]> andersk Git - moira.git/blame - server/qsupport.qc
added name<->id cache; new incremental update scheme
[moira.git] / server / qsupport.qc
CommitLineData
05cdd922 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
c801de4c 7 * For copying and distribution information, please see the file
8 * <mit-copyright.h>.
05cdd922 9 *
05cdd922 10 */
11
12#ifndef lint
13static char *rcsid_qsupport_qc = "$Header$";
14#endif lint
15
c801de4c 16#include <mit-copyright.h>
05cdd922 17#include "query.h"
18#include "sms_server.h"
19#include <ctype.h>
20
05cdd922 21
822a6eba 22extern char *whoami, *strsave();
e1795ce1 23extern int ingres_errno, sms_errcode;
822a6eba 24
05cdd922 25
26/* Specialized Access Routines */
27
822a6eba 28/* access_user - verify that client name equals specified login name
29 *
30 * - since field validation routines are called first, a users_id is
31 * now in argv[0] instead of the login name.
32 */
05cdd922 33
34access_user(q, argv, cl)
35 struct query *q;
36 char *argv[];
37 client *cl;
822a6eba 38{
39 if (cl->users_id != *(int *)argv[0])
40 return(SMS_PERM);
41 else
42 return(SMS_SUCCESS);
43}
05cdd922 44
05cdd922 45
30967516 46
822a6eba 47/* access_login - verify that client name equals specified login name
48 *
49 * argv[0...n] contain search info. q->
50 */
51
52access_login(q, argv, cl)
30967516 53 struct query *q;
54 char *argv[];
55 client *cl;
56##{
822a6eba 57## int rowcount, id;
58## char qual[256];
59
60 build_qual(q->qual, q->argc, argv, qual);
711660a5 61## range of u is users
822a6eba 62## retrieve (id = u.users_id) where qual
63## inquire_equel(rowcount = "rowcount")
64 if (rowcount != 1 || id != cl->users_id)
65 return(SMS_PERM);
66 else
67 return(SMS_SUCCESS);
30967516 68##}
69
822a6eba 70
71
72/* access_list - check access for most list operations
73 *
74 * Inputs: argv[0] - list_id
75 * q - query name
76 * argv[2] - member ID (only for queries "amtl" and "dmfl")
4179b9ce 77 * argv[7] - group IID (only for query "ulis")
78 * cl - client name
822a6eba 79 *
80 * - check that client is a member of the access control list
81 * - OR, if the query is add_member_to_list or delete_member_from_list
82 * and the list is public, allow access if client = member
83 */
05cdd922 84
85access_list(q, argv, cl)
86 struct query *q;
87 char *argv[];
88 client *cl;
89##{
4179b9ce 90## int list_id, acl_id, flags, rowcount, gid;
822a6eba 91## char acl_type[9];
05cdd922 92 char *client_type;
822a6eba 93 int client_id, status;
05cdd922 94
95 list_id = *(int *)argv[0];
822a6eba 96## repeat retrieve (acl_id = list.#acl_id, acl_type = list.#acl_type,
4179b9ce 97## gid = list.#gid, flags = list.#public)
05cdd922 98## where list.#list_id = @list_id
822a6eba 99## inquire_equel(rowcount = "rowcount")
100 if (rowcount != 1)
101 return(SMS_INTERNAL);
05cdd922 102
103 /* parse client structure */
822a6eba 104 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
105 return(status);
05cdd922 106
107 /* if amtl or dmfl and list is public allow client to add or delete self */
a6683dad 108 if (((!strcmp("amtl", q->shortname) && flags) ||
109 (!strcmp("dmfl", q->shortname))) &&
110 (!strcmp("USER", argv[1]))) {
822a6eba 111 if (*(int *)argv[2] == client_id) return(SMS_SUCCESS);
4179b9ce 112 /* if update_list, don't allow them to change the GID */
113 } else if (!strcmp("ulis", q->shortname)) {
114 if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) ||
115 (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7]))))
116 return(SMS_PERM);
05cdd922 117 }
118
119 /* check for client in access control list */
822a6eba 120 status = find_member(acl_type, acl_id, client_type, client_id, 0);
121 if (!status) return(SMS_PERM);
05cdd922 122
123 return(SMS_SUCCESS);
124##}
92a943d6 125
a6cb4d4c 126
822a6eba 127/* access_visible_list - allow access to list only if it is not hidden,
128 * or if the client is on the ACL
129 *
130 * Inputs: argv[0] - list_id
131 * cl - client identifier
132 */
133
134access_visible_list(q, argv, cl)
a6cb4d4c 135 struct query *q;
136 char *argv[];
137 client *cl;
138##{
822a6eba 139## int list_id, acl_id, flags, rowcount;
140## char acl_type[9];
141 char *client_type;
142 int client_id, status;
a6cb4d4c 143
144 list_id = *(int *)argv[0];
822a6eba 145## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
146## acl_type = list.#acl_type) where list.#list_id = @list_id
147## inquire_equel(rowcount = "rowcount")
148 if (rowcount != 1)
149 return(SMS_INTERNAL);
150 if (!flags)
151 return(SMS_SUCCESS);
152
711660a5 153
822a6eba 154 /* parse client structure */
155 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
156 return(status);
157
158 /* check for client in access control list */
159 status = find_member(acl_type, acl_id, client_type, client_id, 0);
160 if (!status)
161 return(SMS_PERM);
162
163 return(SMS_SUCCESS);
a6cb4d4c 164##}
165
92a943d6 166
822a6eba 167/* access_vis_list_by_name - allow access to list only if it is not hidden,
168 * or if the client is on the ACL
169 *
170 * Inputs: argv[0] - list name
171 * cl - client identifier
172 */
173
174access_vis_list_by_name(q, argv, cl)
92a943d6 175 struct query *q;
176 char *argv[];
177 client *cl;
92a943d6 178##{
822a6eba 179## int acl_id, flags, rowcount;
180## char acl_type[9], *listname;
181 char *client_type;
182 int client_id, status;
183
184 listname = argv[0];
185## repeat retrieve (flags = list.hidden, acl_id = list.#acl_id,
186## acl_type = list.#acl_type) where list.#name = @listname
187## inquire_equel(rowcount = "rowcount");
188 if (rowcount > 1)
189 return(SMS_WILDCARD);
190 if (rowcount == 0)
191 return(SMS_NO_MATCH);
192 if (!flags)
193 return(SMS_SUCCESS);
92a943d6 194
822a6eba 195 /* parse client structure */
196 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
197 return(status);
198
199 /* check for client in access control list */
200 status = find_member(acl_type, acl_id, client_type, client_id, 0);
201 if (!status)
202 return(SMS_PERM);
203
204 return(SMS_SUCCESS);
92a943d6 205##}
05cdd922 206
822a6eba 207
208/* access_member - allow user to access member of type "USER" and name matches
209 * username, or to access member of type "LIST" and list is one that user is
210 * on the acl of, or the list is visible.
211 */
212
213access_member(q, argv, cl)
05cdd922 214 struct query *q;
822a6eba 215 char *argv[];
05cdd922 216 client *cl;
822a6eba 217{
218 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
219 return(access_visible_list(q, &argv[1], cl));
05cdd922 220
822a6eba 221 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) {
4179b9ce 222 if (cl->users_id == *(int *)argv[1])
822a6eba 223 return(SMS_SUCCESS);
05cdd922 224 }
225
822a6eba 226 return(SMS_PERM);
227}
05cdd922 228
05cdd922 229
822a6eba 230/* access_qgli - special access routine for Qualified_get_lists. Allows
231 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
232 */
233
234access_qgli(q, argv, cl)
235 struct query *q;
236 char *argv[];
237 client *cl;
238{
239 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
240 return(SMS_SUCCESS);
241 return(SMS_PERM);
242}
243
244
245/* access_service - allow access if user is on ACL of service. Don't
246 * allow access if a wildcard is used.
247 */
05cdd922 248
822a6eba 249access_service(q, argv, cl)
05cdd922 250 struct query *q;
251 char *argv[];
822a6eba 252 client *cl;
05cdd922 253##{
822a6eba 254## int acl_id, rowcount;
255## char *name, acl_type[9];
256 int client_id, status;
257 char *client_type;
05cdd922 258
822a6eba 259 name = argv[0];
260## repeat retrieve (acl_id = servers.#acl_id, acl_type = servers.#acl_type)
44bd6f44 261## where servers.#name = uppercase(@name)
822a6eba 262## inquire_equel(rowcount = "rowcount")
263 if (rowcount > 1)
264 return(SMS_PERM);
05cdd922 265
822a6eba 266 /* parse client structure */
267 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
268 return(status);
92a943d6 269
822a6eba 270 /* check for client in access control list */
271 status = find_member(acl_type, acl_id, client_type, client_id, 0);
272 if (!status) return(SMS_PERM);
05cdd922 273
92a943d6 274 return(SMS_SUCCESS);
275##}
276
822a6eba 277
278
279/* access_filesys - verify that client is owner or on owners list of filesystem
280 * named by argv[0]
281 */
282
283access_filesys(q, argv, cl)
92a943d6 284 struct query *q;
285 char *argv[];
822a6eba 286 client *cl;
92a943d6 287##{
822a6eba 288## int rowcount, users_id, list_id;
289## char *name;
290 int status, client_id;
291 char *client_type;
92a943d6 292
822a6eba 293 name = argv[0];
294## repeat retrieve (users_id = filesys.owner, list_id = filesys.owners)
295## where filesys.label = @name
296## inquire_equel(rowcount = "rowcount")
297
298 if (rowcount != 1)
299 return(SMS_PERM);
300 if (users_id == cl->users_id)
301 return(SMS_SUCCESS);
db8a5dda 302 if ((status = get_client(cl, &client_type, &client_id)) != SMS_SUCCESS)
303 return(status);
304 status = find_member("LIST", list_id, client_type, client_id, 0);
305 if (status)
822a6eba 306 return(SMS_SUCCESS);
db8a5dda 307 else
308 return(SMS_PERM);
05cdd922 309##}
822a6eba 310
311
05cdd922 312\f
822a6eba 313/* Setup Routines */
314
315/* Setup routine for add_user
316 *
317 * Inputs: argv[0] - login
318 * argv[1] - uid
319 *
320 * Description:
321 *
322 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
323 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
324 */
c2408bd5 325
822a6eba 326setup_ausr(q, argv, cl)
c2408bd5 327 struct query *q;
822a6eba 328 register char *argv[];
329 client *cl;
330##{
331## int nuid, rowcount;
332
333 if (!strcmp(argv[1], UNIQUE_UID) || atoi(argv[1]) == -1) {
334 if (set_next_object_id("uid", "users"))
335 return(SMS_INGRES_ERR);
336## repeat retrieve (nuid = values.value) where values.name = "uid"
337## inquire_equel(rowcount = "rowcount")
338 if (rowcount != 1)
339 return(SMS_INTERNAL);
340 sprintf(argv[1], "%d", nuid);
341 }
c2408bd5 342
822a6eba 343 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[1]) == -1) {
344 sprintf(argv[0], "#%s", argv[1]);
345 }
c2408bd5 346
822a6eba 347 return(SMS_SUCCESS);
348##}
c2408bd5 349
c2408bd5 350
822a6eba 351/* setup_dusr - verify that the user is no longer being referenced
352 * and may safely be deleted.
353 */
c2408bd5 354
822a6eba 355int setup_dusr(q, argv)
356 struct query *q;
357 char **argv;
358##{
359## int flag, id;
360
361 id = *(int *)argv[0];
331b982e 362
363 /* For now, only allow users to be deleted if their status is 0 */
364## repeat retrieve (flag = u.status) where u.users_id = @id
711660a5 365 if (flag != 0 && flag != 4)
331b982e 366 return(SMS_IN_USE);
367
44bd6f44 368## repeat delete nfsquota where nfsquota.users_id = @id
711660a5 369## repeat delete krbmap where krbmap.users_id = @id
a6683dad 370## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
371## and imembers.member_type = "USER"))
822a6eba 372 if (flag)
373 return(SMS_IN_USE);
374## repeat retrieve (flag = any(filesys.label where filesys.owner=@id))
375 if (flag)
376 return(SMS_IN_USE);
377## repeat retrieve (flag = any(list.name where list.acl_id=@id and
378## list.acl_type = "USER"))
379 if (flag)
380 return(SMS_IN_USE);
381## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
382## servers.acl_type = "USER"))
383 if (flag)
384 return(SMS_IN_USE);
44bd6f44 385## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
386## hostaccess.acl_type = "USER"))
387 if (flag)
388 return(SMS_IN_USE);
02ccf7ad 389 if (ingres_errno)
390 return(sms_errcode);
391 return(SMS_SUCCESS);
822a6eba 392##}
c2408bd5 393
822a6eba 394
395/* setup_spop: verify that there is already a valid POP machine_id in the
396 * pop_id field. Also take care of keeping track of the post office usage.
397 */
398int setup_spop(q, argv)
399struct query *q;
400char **argv;
c2408bd5 401##{
e7fa3293 402## int id, mid, flag;
822a6eba 403## char type[9];
404
405 id = *(int *)argv[0];
e7fa3293 406## repeat retrieve (type = u.potype, mid = u.pop_id,
407## flag = any(machine.name where machine.mach_id = u.pop_id
408## and u.pop_id != 0 and u.users_id = @id))
4f16dc86 409## where u.users_id = @id
822a6eba 410 if (!flag)
411 return(SMS_MACHINE);
e7fa3293 412 if (strcmp(strtrim(type), "POP"))
413 set_pop_usage(mid, 1);
822a6eba 414 return(SMS_SUCCESS);
415##}
c2408bd5 416
c2408bd5 417
822a6eba 418/* setup_dpob: Take care of keeping track of the post office usage.
419 */
420int setup_dpob(q, argv)
421struct query *q;
422char **argv;
423##{
424## int id, user;
425## char type[9];
426
427 user = *(int *)argv[0];
428## repeat retrieve (type = u.potype, id = u.pop_id)
429## where u.users_id = @user
02ccf7ad 430 if (ingres_errno) return(sms_errcode);
c2408bd5 431
e7fa3293 432 if (!strcmp(strtrim(type), "POP"))
822a6eba 433 set_pop_usage(id, -1);
c2408bd5 434 return(SMS_SUCCESS);
435##}
436
c2408bd5 437
822a6eba 438/* setup_dmac - verify that the machine is no longer being referenced
439 * and may safely be deleted.
440 */
c2408bd5 441
822a6eba 442int setup_dmac(q, argv)
05cdd922 443 struct query *q;
822a6eba 444 char **argv;
05cdd922 445##{
822a6eba 446## int flag, id;
447
448 id = *(int *)argv[0];
449## repeat retrieve (flag = any(users.login where users.potype = "POP"
450## and users.pop_id=@id))
451 if (flag)
452 return(SMS_IN_USE);
453## repeat retrieve (flag = any(serverhosts.mach_id
454## where serverhosts.mach_id=@id))
455 if (flag)
456 return(SMS_IN_USE);
457## repeat retrieve (flag = any(nfsphys.mach_id where nfsphys.mach_id=@id))
458 if (flag)
459 return(SMS_IN_USE);
460## repeat retrieve (flag = any(hostaccess.mach_id where hostaccess.mach_id=@id))
461 if (flag)
462 return(SMS_IN_USE);
e7fa3293 463## repeat retrieve (flag = any(printcap.mach_id where printcap.mach_id=@id))
331b982e 464 if (flag)
465 return(SMS_IN_USE);
711660a5 466## repeat retrieve (flag = any(palladium.mach_id where palladium.mach_id=@id))
467 if (flag)
468 return(SMS_IN_USE);
44bd6f44 469
470## repeat delete mcmap where mcmap.mach_id = @id
02ccf7ad 471 if (ingres_errno) return(sms_errcode);
44bd6f44 472 return(SMS_SUCCESS);
05cdd922 473##}
474
05cdd922 475
822a6eba 476/* setup_dclu - verify that the cluster is no longer being referenced
477 * and may safely be deleted.
478 */
05cdd922 479
822a6eba 480int setup_dclu(q, argv)
05cdd922 481 struct query *q;
822a6eba 482 char **argv;
05cdd922 483##{
822a6eba 484## int flag, id;
485
486 id = *(int *)argv[0];
487## repeat retrieve (flag = any(mcmap.mach_id where mcmap.clu_id=@id))
488 if (flag)
489 return(SMS_IN_USE);
490## repeat retrieve (flag = any(svc.clu_id where svc.clu_id=@id))
491 if (flag)
492 return(SMS_IN_USE);
02ccf7ad 493 if (ingres_errno)
494 return(sms_errcode);
495 return(SMS_SUCCESS);
05cdd922 496##}
497
05cdd922 498
822a6eba 499/* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
500 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
501 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
502 * a -1 there. Remember that this is also used for ulis, with the indexes
503 * at 6 & 7.
504 */
05cdd922 505
822a6eba 506int setup_alis(q, argv)
507struct query *q;
508char **argv;
05cdd922 509##{
822a6eba 510## int ngid;
511 char *malloc();
512 int idx;
513
514 if (!strcmp(q->shortname, "alis"))
515 idx = 6;
516 else if (!strcmp(q->shortname, "ulis"))
517 idx = 7;
518
519 if (!strcmp(argv[idx], UNIQUE_GID) || atoi(argv[idx]) == -1) {
520 if (atoi(argv[idx - 1])) {
521 if (set_next_object_id("gid", "list"))
522 return(SMS_INGRES_ERR);
523## repeat retrieve (ngid = values.value) where values.name = "gid"
02ccf7ad 524 if (ingres_errno) return(sms_errcode);
822a6eba 525 sprintf(argv[idx], "%d", ngid);
526 } else {
527 strcpy(argv[idx], "-1");
528 }
529 }
05cdd922 530
05cdd922 531 return(SMS_SUCCESS);
532##}
a6cb4d4c 533
822a6eba 534
535/* setup_dlist - verify that the list is no longer being referenced
536 * and may safely be deleted.
537 */
538
539int setup_dlis(q, argv)
a6cb4d4c 540 struct query *q;
822a6eba 541 char **argv;
a6cb4d4c 542##{
822a6eba 543## int flag, id;
544
545 id = *(int *)argv[0];
a6683dad 546## repeat retrieve (flag = any(imembers.member_id where imembers.member_id=@id
547## and imembers.member_type = "LIST"))
822a6eba 548 if (flag)
549 return(SMS_IN_USE);
a6683dad 550## repeat retrieve (flag = any(imembers.member_id where imembers.list_id=@id))
822a6eba 551 if (flag)
552 return(SMS_IN_USE);
553## repeat retrieve (flag = any(filesys.label where filesys.owners=@id))
554 if (flag)
555 return(SMS_IN_USE);
556## repeat retrieve (flag = any(capacls.tag where capacls.list_id=@id))
557 if (flag)
558 return(SMS_IN_USE);
559## repeat retrieve (flag = any(list.name where list.acl_id=@id and
4f16dc86 560## list.acl_type = "LIST" and list.list_id != @id))
822a6eba 561 if (flag)
562 return(SMS_IN_USE);
563## repeat retrieve (flag = any(servers.name where servers.acl_id=@id and
564## servers.acl_type = "LIST"))
565 if (flag)
566 return(SMS_IN_USE);
44bd6f44 567## repeat retrieve (flag=any(hostaccess.acl_id where hostaccess.acl_id=@id and
568## hostaccess.acl_type = "LIST"))
569 if (flag)
570 return(SMS_IN_USE);
822a6eba 571## repeat retrieve (flag = any(zephyr.class
572## where zephyr.xmt_type = "LIST" and zephyr.xmt_id = @id or
573## zephyr.sub_type = "LIST" and zephyr.sub_id = @id or
574## zephyr.iws_type = "LIST" and zephyr.iws_id = @id or
575## zephyr.iui_type = "LIST" and zephyr.iui_id = @id))
576 if (flag)
577 return(SMS_IN_USE);
02ccf7ad 578 if (ingres_errno)
579 return(sms_errcode);
580 return(SMS_SUCCESS);
822a6eba 581##}
a6cb4d4c 582
a6cb4d4c 583
822a6eba 584/* setup_dsin - verify that the service is no longer being referenced
585 * and may safely be deleted.
586 */
a6cb4d4c 587
822a6eba 588int setup_dsin(q, argv)
589 struct query *q;
590 char **argv;
591##{
592## int flag;
593## char *name;
594
595 name = argv[0];
44bd6f44 596## repeat retrieve (flag = any(serverhosts.service
597## where serverhosts.service=uppercase(@name)))
822a6eba 598 if (flag)
599 return(SMS_IN_USE);
600## repeat retrieve (flag = servers.inprogress) where servers.#name = @name
601 if (flag)
602 return(SMS_IN_USE);
02ccf7ad 603 if (ingres_errno)
604 return(sms_errcode);
605 return(SMS_SUCCESS);
822a6eba 606##}
a6cb4d4c 607
a6cb4d4c 608
822a6eba 609/* setup_dshi - verify that the service-host is no longer being referenced
610 * and may safely be deleted.
611 */
a6cb4d4c 612
822a6eba 613int setup_dshi(q, argv)
614 struct query *q;
615 char **argv;
616##{
617## int flag, id;
618## char *name;
a6cb4d4c 619
822a6eba 620 name = argv[0];
621 id = *(int *)argv[1];
622## repeat retrieve (flag=serverhosts.inprogress)
44bd6f44 623## where serverhosts.service=uppercase(@name) and serverhosts.mach_id=@id
822a6eba 624 if (flag)
625 return(SMS_IN_USE);
02ccf7ad 626 if (ingres_errno)
627 return(sms_errcode);
628 return(SMS_SUCCESS);
a6cb4d4c 629##}
822a6eba 630
631
a6cb4d4c 632/**
822a6eba 633 ** setup_add_filesys - verify existance of referenced file systems
634 **
635 ** Inputs: Add
636 ** argv[1] - type
637 ** argv[2] - mach_id
638 ** argv[3] - name
639 ** argv[5] - access
a6cb4d4c 640 **
641 ** Description:
822a6eba 642 ** - for type = RVD:
643 ** * allow anything
644 ** - for type = NFS:
645 ** * extract directory prefix from name
646 ** * verify mach_id/dir in nfsphys
647 ** * verify access in {r, w, R, W}
648 **
649 ** Side effect: sets variable var_phys_id to the ID of the physical
650 ** filesystem (nfsphys_id for NFS, 0 for RVD)
a6cb4d4c 651 **
822a6eba 652 ** Errors:
653 ** SMS_NFS - specified directory not exported
654 ** SMS_FILESYS_ACCESS - invalid filesys access
a6cb4d4c 655 **
656 **/
657
822a6eba 658##static int var_phys_id;
a6cb4d4c 659
822a6eba 660setup_afil(q, argv)
a6cb4d4c 661 struct query *q;
662 char *argv[];
663{
822a6eba 664 char *type;
665 int mach_id;
666 char *name;
667 char *access;
a6cb4d4c 668
a6cb4d4c 669 type = argv[1];
670 mach_id = *(int *)argv[2];
822a6eba 671 name = argv[3];
672 access = argv[5];
673 var_phys_id = 0;
a6cb4d4c 674
822a6eba 675 if (!strcmp(type, "NFS"))
676 return (check_nfs(mach_id, name, access));
677 else
678 return(SMS_SUCCESS);
679}
05cdd922 680
30967516 681
e7fa3293 682/* Verify the arguments, depending on the FStype. Also, if this is an
683 * NFS filesystem, then update any quotas for that filesystem to reflect
684 * the new phys_id.
685 */
686
822a6eba 687setup_ufil(q, argv)
30967516 688 struct query *q;
689 char *argv[];
e7fa3293 690##{
691 int mach_id, status;
692 char *type, *name, *access;
49189928 693## int fid, total;
30967516 694
822a6eba 695 type = argv[2];
696 mach_id = *(int *)argv[3];
697 name = argv[4];
698 access = argv[6];
699 var_phys_id = 0;
49189928 700 fid = *(int *)argv[0];
a6cb4d4c 701
e7fa3293 702 if (!strcmp(type, "NFS")) {
703 status = check_nfs(mach_id, name, access);
db767e36 704## replace nfsquota (phys_id = var_phys_id) where nfsquota.filsys_id = fid
02ccf7ad 705 if (ingres_errno) return(sms_errcode);
e7fa3293 706 return(status);
49189928 707 } else if (!strcmp(type, "AFS")) {
708 total = 0;
709## retrieve (total = sum(nfsquota.quota where nfsquota.filsys_id = fid))
710 if (ingres_errno) return(sms_errcode);
711 if (total != 0) {
712## delete nfsquota where nfsquota.filsys_id = fid
713 if (ingres_errno) return(sms_errcode);
714## append nfsquota (quota = total, filsys_id = fid,
715## phys_id = 0, users_id = 0)
716 if (ingres_errno) return(sms_errcode);
717 }
718 } else {
719## replace nfsquota (phys_id = 0) where nfsquota.filsys_id = fid
720 if (ingres_errno) return(sms_errcode);
721 }
722 return(SMS_SUCCESS);
e7fa3293 723##}
30967516 724
a6cb4d4c 725
822a6eba 726/* Find the NFS physical partition that the named directory is on.
727 * This is done by comparing the dir against the mount point of the
728 * partition. To make sure we get the correct match when there is
729 * more than one, we sort the query in reverse order by dir name.
730 */
a6cb4d4c 731
822a6eba 732##check_nfs(mach_id, name, access)
a6cb4d4c 733## int mach_id;
822a6eba 734 char *name;
735 char *access;
736##{
a30e1c62 737## char dir[81];
822a6eba 738 char caccess;
739 register int status;
740 register char *cp1;
741 register char *cp2;
a6cb4d4c 742
822a6eba 743 caccess = (isupper(*access)) ? tolower(*access) : *access;
49189928 744 if (caccess != 'r' && caccess != 'w' && caccess != 'n')
745 return(SMS_FILESYS_ACCESS);
a6cb4d4c 746
822a6eba 747 status = SMS_NFS;
748## range of np is nfsphys
749## repeat retrieve (var_phys_id = np.#nfsphys_id, dir = trim(np.#dir))
750## where np.#mach_id = @mach_id sort by #dir:d {
751 cp1 = name;
752 cp2 = dir;
753 while (*cp2) {
754 if (*cp1++ != *cp2) break;
755 cp2++;
756 }
757 if (*cp2 == 0) {
758 status = SMS_SUCCESS;
a6cb4d4c 759## endretrieve
760 }
761## }
02ccf7ad 762 if (ingres_errno)
763 return(sms_errcode);
822a6eba 764 return(status);
30967516 765##}
a6cb4d4c 766
92a943d6 767
f49f997e 768/* setup_dfil: free any quota records and fsgroup info associated with
769 * a filesystem when it is deleted. Also adjust the allocation numbers.
822a6eba 770 */
92a943d6 771
822a6eba 772setup_dfil(q, argv, cl)
773 struct query *q;
774 char **argv;
775 client *cl;
776##{
777## int id;
92a943d6 778
822a6eba 779 id = *(int *)argv[0];
780## range of q is nfsquota
44bd6f44 781## range of fs is filesys
782## range of n is nfsphys
783## repeat replace n (allocated=n.allocated-sum(q.quota where q.filsys_id=@id))
784## where n.nfsphys_id = fs.phys_id and fs.filsys_id = @id
92a943d6 785
822a6eba 786## repeat delete q where q.filsys_id = @id
f49f997e 787## repeat delete fsgroup where fsgroup.filsys_id = @id
788## repeat delete fsgroup where fsgroup.group_id = @id
02ccf7ad 789 if (ingres_errno) return(sms_errcode);
92a943d6 790 return(SMS_SUCCESS);
791##}
30967516 792
822a6eba 793
794/* setup_dnfp: check to see that the nfs physical partition does not have
795 * any filesystems assigned to it before allowing it to be deleted.
796 */
797
798setup_dnfp(q, argv, cl)
799 struct query *q;
800 char **argv;
92a943d6 801 client *cl;
92a943d6 802##{
822a6eba 803## int id, exists;
92a943d6 804
822a6eba 805 id = *(int *)argv[0];
806## repeat retrieve (exists = any(filesys.label where filesys.phys_id = @id))
807 if (exists)
808 return(SMS_IN_USE);
02ccf7ad 809 if (ingres_errno)
810 return(sms_errcode);
92a943d6 811 return(SMS_SUCCESS);
812##}
4b890cc4 813
4b890cc4 814
822a6eba 815/* setup_dnfq: Remove allocation from nfsphys before deleting quota.
816 * argv[0] = filsys_id
817 * argv[1] = users_id
818 */
819
820setup_dnfq(q, argv, cl)
821 struct query *q;
822 char **argv;
823 client *cl;
824##{
825## int quota, fs, user;
826
827 fs = *(int *)argv[0];
828 user = *(int *)argv[1];
829
830## range of q is nfsquota
831## repeat retrieve (quota = q.#quota) where q.users_id = @user and
832## q.filsys_id = @fs
833## repeat replace nfsphys (allocated = nfsphys.allocated - @quota)
834## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
02ccf7ad 835 if (ingres_errno) return(sms_errcode);
822a6eba 836 return(SMS_SUCCESS);
837##}
838
839
67d7b959 840/* setup_sshi: don't exclusive lock the machine table during
841 * set_server_host_internal.
842 */
843
844setup_sshi(q, argv, cl)
845 struct query *q;
846 char **argv;
847 client *cl;
848##{
849## set lockmode session where readlock = system
850##}
851
852
711660a5 853/* setup add_kerberos_user_mapping: add the string to the string
854 * table if necessary.
855 */
856
857setup_akum(q, argv, cl)
858struct query *q;
859char **argv;
860client *cl;
861##{
862## int id, rowcount;
863## char *name;
864
865 name = argv[1];
866## range of s is strings
867## repeat retrieve (id = s.string_id) where s.string = @name
868## inquire_equel (rowcount = "rowcount")
869 if (rowcount == 0) {
870 if (q->type != APPEND) return(SMS_STRING);
871## range of v is values
872## retrieve (id = v.value) where v.#name = "strings_id"
873 id++;
874## replace v (value = id) where v.#name = "strings_id"
875## append to strings (string_id = id, string = name)
876 }
02ccf7ad 877 if (ingres_errno) return(sms_errcode);
711660a5 878 *(int *)argv[1] = id;
02ccf7ad 879 return(SMS_SUCCESS);
711660a5 880##}
881
882
822a6eba 883\f
884/* FOLLOWUP ROUTINES */
885
886/* generic set_modtime routine. This takes the table name from the query,
887 * and will update the modtime, modby, and modwho fields in the entry in
888 * the table whose name field matches argv[0].
889 */
890
891set_modtime(q, argv, cl)
4b890cc4 892 struct query *q;
893 char *argv[];
822a6eba 894 client *cl;
4b890cc4 895##{
822a6eba 896## char *name, *entity, *table;
897## int who;
4b890cc4 898
822a6eba 899 entity = cl->entity;
711660a5 900 who = cl->client_id;
822a6eba 901 table = q->rtable;
902 name = argv[0];
4b890cc4 903
822a6eba 904## replace table (modtime = "now", modby = who, modwith = entity)
905## where table.#name = name
4b890cc4 906 return(SMS_SUCCESS);
907##}
908
822a6eba 909/* generic set_modtime_by_id routine. This takes the table name from
910 * the query, and the id name from the validate record,
911 * and will update the modtime, modby, and modwho fields in the entry in
912 * the table whose id matches argv[0].
913 */
914
915set_modtime_by_id(q, argv, cl)
4b890cc4 916 struct query *q;
822a6eba 917 char **argv;
918 client *cl;
4b890cc4 919##{
822a6eba 920## char *entity, *table, *id_name;
921## int who, id;
922
923 entity = cl->entity;
711660a5 924 who = cl->client_id;
822a6eba 925 table = q->rtable;
926 id_name = q->validate->object_id;
4b890cc4 927
822a6eba 928 id = *(int *)argv[0];
929## replace table (modtime = "now", modby = who, modwith = entity)
930## where table.id_name = id
4b890cc4 931 return(SMS_SUCCESS);
932##}
933
822a6eba 934
935/* Sets the finger modtime on a user record. The users_id will be in argv[0].
936 */
937
938set_finger_modtime(q, argv, cl)
4b890cc4 939 struct query *q;
940 char *argv[];
822a6eba 941 client *cl;
4b890cc4 942##{
822a6eba 943## int users_id, who;
944## char *entity;
945
946 entity = cl->entity;
711660a5 947 who = cl->client_id;
822a6eba 948 users_id = *(int *)argv[0];
4b890cc4 949
822a6eba 950## repeat replace u (fmodtime = "now", fmodby = @who, fmodwith = @entity)
951## where u.#users_id = @users_id
4b890cc4 952 return(SMS_SUCCESS);
953##}
05cdd922 954
822a6eba 955
956/* Sets the pobox modtime on a user record. The users_id will be in argv[0].
957 */
958
959set_pobox_modtime(q, argv, cl)
05cdd922 960 struct query *q;
822a6eba 961 char **argv;
962 client *cl;
05cdd922 963##{
822a6eba 964## int users_id, who;
965## char *entity;
05cdd922 966
822a6eba 967 entity = cl->entity;
711660a5 968 who = cl->client_id;
822a6eba 969 users_id = *(int *)argv[0];
05cdd922 970
822a6eba 971## repeat replace users (pmodtime = "now", pmodby = @who, pmodwith = @entity)
972## where users.#users_id = @users_id
973 return(SMS_SUCCESS);
974##}
05cdd922 975
05cdd922 976
3c7c4a07 977/* Like set_modtime, but uppercases the name first.
822a6eba 978 */
979
3c7c4a07 980set_uppercase_modtime(q, argv, cl)
822a6eba 981 struct query *q;
982 char **argv;
983 client *cl;
984##{
3c7c4a07 985## char *name, *entity, *table;
822a6eba 986## int who;
987
988 entity = cl->entity;
711660a5 989 who = cl->client_id;
3c7c4a07 990 table = q->rtable;
991 name = argv[0];
05cdd922 992
3c7c4a07 993## replace table (modtime = "now", modby = who, modwith = entity)
994## where table.#name = uppercase(name)
05cdd922 995 return(SMS_SUCCESS);
996##}
05cdd922 997
822a6eba 998
999/* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
1000 * is necessary for add_machine_to_cluster becuase the table that query
1001 * operates on is "mcm", not "machine".
1002 */
1003
1004set_mach_modtime_by_id(q, argv, cl)
05cdd922 1005 struct query *q;
05cdd922 1006 char **argv;
822a6eba 1007 client *cl;
1008##{
1009## char *entity;
1010## int who, id;
05cdd922 1011
822a6eba 1012 entity = cl->entity;
711660a5 1013 who = cl->client_id;
05cdd922 1014
822a6eba 1015 id = *(int *)argv[0];
1016## range of m is machine
1017## repeat replace m (modtime = "now", modby = @who, modwith = @entity)
1018## where m.mach_id = @id
1019 return(SMS_SUCCESS);
1020##}
05cdd922 1021
05cdd922 1022
822a6eba 1023/* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
1024 * is necessary for add_cluster_data and delete_cluster_data becuase the
1025 * table that query operates on is "svc", not "cluster".
1026 */
1027
1028set_cluster_modtime_by_id(q, argv, cl)
1029 struct query *q;
1030 char **argv;
1031 client *cl;
1032##{
1033## char *entity;
1034## int who, id;
1035
1036 entity = cl->entity;
711660a5 1037 who = cl->client_id;
822a6eba 1038
1039 id = *(int *)argv[0];
1040## range of c is cluster
1041## repeat replace c (modtime = "now", modby = @who, modwith = @entity)
1042## where c.clu_id = @id
05cdd922 1043 return(SMS_SUCCESS);
1044##}
1045
822a6eba 1046
1047/* sets the modtime on the serverhost where the service name is in argv[0]
1048 * and the mach_id is in argv[1].
1049 */
1050
1051set_serverhost_modtime(q, argv, cl)
92a943d6 1052 struct query *q;
822a6eba 1053 char **argv;
1054 client *cl;
92a943d6 1055##{
822a6eba 1056## char *entity, *serv;
1057## int who, id;
1058
1059 entity = cl->entity;
711660a5 1060 who = cl->client_id;
822a6eba 1061
1062 serv = argv[0];
1063 id = *(int *)argv[1];
1064## repeat replace sh (modtime = "now", modby = @who, modwith = @entity)
44bd6f44 1065## where sh.service = uppercase(@serv) and sh.mach_id = @id
822a6eba 1066 return(SMS_SUCCESS);
1067##}
1068
1069
1070/* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
1071 * directory name is in argv[1].
1072 */
1073
1074set_nfsphys_modtime(q, argv, cl)
1075 struct query *q;
92a943d6 1076 char **argv;
822a6eba 1077 client *cl;
1078##{
1079## char *entity, *dir;
1080## int who, id;
92a943d6 1081
822a6eba 1082 entity = cl->entity;
711660a5 1083 who = cl->client_id;
92a943d6 1084
822a6eba 1085 id = *(int *)argv[0];
1086 dir = argv[1];
1087## repeat replace np (modtime = "now", modby = @who, modwith = @entity)
1088## where np.#dir = @dir and np.mach_id = @id
1089 return(SMS_SUCCESS);
1090##}
92a943d6 1091
92a943d6 1092
822a6eba 1093/* sets the modtime on a filesystem, where argv[0] contains the filesys
1094 * label.
1095 */
1096
1097set_filesys_modtime(q, argv, cl)
1098 struct query *q;
1099 char *argv[];
1100 client *cl;
1101##{
1102## char *label, *entity;
1103## int who;
1104
1105 entity = cl->entity;
711660a5 1106 who = cl->client_id;
822a6eba 1107
1108 label = argv[0];
1109 if (!strcmp(q->shortname, "ufil"))
1110 label = argv[1];
1111
1112## repeat replace fs (modtime = "now", modby = @who, modwith = @entity,
1113## #phys_id = @var_phys_id) where fs.#label = @label
92a943d6 1114 return(SMS_SUCCESS);
1115##}
05cdd922 1116
822a6eba 1117
1118/* sets the modtime on a zephyr class, where argv[0] contains the class
1119 * name.
1120 */
1121
1122set_zephyr_modtime(q, argv, cl)
1123 struct query *q;
1124 char *argv[];
1125 client *cl;
05cdd922 1126##{
822a6eba 1127## char *class, *entity;
1128## int who;
1129
1130 entity = cl->entity;
711660a5 1131 who = cl->client_id;
822a6eba 1132
1133 class = argv[0];
1134
1135## repeat replace z (modtime = "now", modby = @who, modwith = @entity)
1136## where z.#class = @class
1137 return(SMS_SUCCESS);
1138##}
1139
1140
1141/* fixes the modby field. This will be the second to last thing in the
1142 * argv, the argv length is determined from the query structure. It is
1143 * passed as a pointer to an integer. This will either turn it into a
1144 * username, or # + the users_id.
1145 */
1146followup_fix_modby(q, sq, v, action, actarg, cl)
1147 struct query *q;
1148 register struct save_queue *sq;
1149 struct validate *v;
1150 register int (*action)();
1151 register int actarg;
1152 client *cl;
1153##{
1154 register int i, j;
1155 char **argv, *malloc();
1156## int id, rowcount;
05cdd922 1157## char *name;
05cdd922 1158
822a6eba 1159 i = q->vcnt - 2;
1160 while (sq_get_data(sq, &argv)) {
1161 id = atoi(argv[i]);
1162 free(argv[i]);
711660a5 1163 argv[i] = malloc(256);
822a6eba 1164 name = argv[i];
711660a5 1165 if (id > 0)
1166## repeat retrieve (name = users.login) where users.users_id = @id
1167 else {
1168 id = -id;
1169## repeat retrieve (name = strings.string) where strings.string_id = @id
1170 id = -id;
1171 }
822a6eba 1172## inquire_equel(rowcount = "rowcount")
1173 if (rowcount != 1) {
1174 sprintf(argv[i], "#%d", id);
1175 }
1176 (*action)(q->vcnt, argv, actarg);
1177 for (j = 0; j < q->vcnt; j++)
1178 free(argv[j]);
1179 free(argv);
1180 }
1181 sq_destroy(sq);
02ccf7ad 1182 if (ingres_errno) return(sms_errcode);
822a6eba 1183 return(SMS_SUCCESS);
30967516 1184##}
1185
822a6eba 1186
30967516 1187/**
822a6eba 1188 ** followup_ausr - add finger and pobox entries, set_user_modtime
30967516 1189 **
1190 ** Inputs:
822a6eba 1191 ** argv[0] - login (add_user)
1192 ** argv[3] - last name
1193 ** argv[4] - first name
1194 ** argv[5] - middle name
30967516 1195 **
1196 **/
1197
822a6eba 1198followup_ausr(q, argv, cl)
30967516 1199 struct query *q;
822a6eba 1200 char *argv[];
1201 client *cl;
30967516 1202##{
822a6eba 1203## int who;
1204## char *login, *entity;
1205## char fullname[129];
30967516 1206
822a6eba 1207 login = argv[0];
711660a5 1208 who = cl->client_id;
822a6eba 1209 entity = cl->entity;
30967516 1210
822a6eba 1211 /* build fullname */
1212 if (strlen(argv[4]) && strlen(argv[5]))
1213 sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]);
1214 else if (strlen(argv[4]))
1215 sprintf(fullname, "%s %s", argv[4], argv[3]);
1216 else
1217 sprintf(fullname, "%s", argv[3]);
30967516 1218
822a6eba 1219 /* create finger entry, pobox & set modtime on user */
1220## repeat replace u (modtime = "now", modby=@who, modwith=@entity,
1221## #fullname=@fullname, mit_affil = u.mit_year,
1222## fmodtime="now", fmodby=@who, fmodwith=@entity,
1223## potype="NONE", pmodtime="now", pmodby=@who, pmodwith=@entity)
1224## where u.#login = @login
30967516 1225
05cdd922 1226 return(SMS_SUCCESS);
1227##}
1228
822a6eba 1229
1230/* followup_gpob: fixes argv[2] based on the IDs currently there and the
1231 * type in argv[1]. Then completes the upcall to the user.
1232 *
1233 * argv[2] is of the form "123:234" where the first integer is the machine
1234 * ID if it is a pop box, and the second is the string ID if it is an SMTP
1235 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
1236 * are skipped.
1237 */
1238
1239followup_gpob(q, sq, v, action, actarg, cl)
1240 register struct query *q;
1241 register struct save_queue *sq;
1242 register struct validate *v;
1243 register int (*action)();
1244 int actarg;
1245 client *cl;
1246##{
1247 char **argv, *index();
1248 char *ptype, *p;
1249## char box[129], *name;
1250## int mid, sid, rowcount;
1251
1252 /* for each row */
1253 while (sq_get_data(sq, &argv)) {
1254 sms_trim_args(2, argv);
1255 ptype = argv[1];
1256 p = index(argv[2], ':');
1257 *p++ = 0;
1258 mid = atoi(argv[2]);
1259 sid = atoi(p);
1260 free(argv[2]);
1261
1262 if (!strcmp(ptype, "POP")) {
1263## repeat retrieve (box=machine.#name) where machine.mach_id=@mid
1264## inquire_equel(rowcount = "rowcount")
1265 if (rowcount != 1)
1266 return(SMS_MACHINE);
1267 } else if (!strcmp(ptype, "SMTP")) {
1268## repeat retrieve (box=strings.string) where strings.string_id=@sid
1269## inquire_equel(rowcount = "rowcount")
1270 if (rowcount != 1)
1271 return(SMS_STRING);
1272 } else /* ptype == "NONE" */ {
1273 goto skip;
1274 }
1275
1276 if (!strcmp(q->shortname, "gpob")) {
1277 sid = atoi(argv[4]);
1278 free(argv[4]);
711660a5 1279 argv[4] = malloc(256);
822a6eba 1280 name = argv[4];
711660a5 1281 if (sid > 0)
1282## repeat retrieve (name = users.login) where users.users_id = @sid
1283 else {
1284 sid = -sid;
1285## repeat retrieve (name = strings.string)
1286## where strings.string_id = @sid
1287 sid = -sid;
1288 }
822a6eba 1289## inquire_equel(rowcount = "rowcount")
1290 if (rowcount != 1)
1291 sprintf(name, "#%d", sid);
1292 }
1293
1294 argv[2] = box;
1295 (*action)(q->vcnt, argv, actarg);
1296 skip:
1297 /* free saved data */
1298 free(argv[0]);
1299 free(argv[1]);
711660a5 1300 free(argv[4]);
822a6eba 1301 free(argv);
1302 }
1303
1304 sq_destroy(sq);
1305 return (SMS_SUCCESS);
1306##}
1307
1308
44bd6f44 1309/* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the
1310 * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the
822a6eba 1311 * proper name based on the type, and repace that string in the argv.
1312 * Also fixes the modby field by called followup_fix_modby.
1313 */
1314
1315followup_glin(q, sq, v, action, actarg, cl)
1316 register struct query *q;
1317 register struct save_queue *sq;
1318 register struct validate *v;
1319 register int (*action)();
1320 int actarg;
1321 client *cl;
1322##{
1323 char **argv, *malloc(), *realloc(), *type;
1324## char *name;
1325## int id, rowcount;
1326 int i, idx;
1327
1328 idx = 8;
1329 if (!strcmp(q->shortname, "gsin"))
4f16dc86 1330 idx = 12;
822a6eba 1331
1332 while (sq_get_data(sq, &argv)) {
1333 sms_trim_args(q->vcnt, argv);
1334
1335 id = atoi(argv[i = q->vcnt - 2]);
1336 free(argv[i]);
711660a5 1337 name = argv[i] = malloc(256);
1338 if (id > 0)
1339## repeat retrieve (name = users.login) where users.users_id = @id
1340 else {
1341 id = -id;
1342## repeat retrieve (name = strings.string) where strings.string_id = @id
1343 id = -id;
1344 }
822a6eba 1345## inquire_equel(rowcount = "rowcount")
1346 if (rowcount != 1)
1347 sprintf(argv[i], "#%d", id);
1348
1349 id = atoi(argv[idx]);
1350 type = argv[idx - 1];
1351 if ((name = malloc(33)) == NULL)
1352 return(SMS_NO_MEM);
1353
1354 if (!strcmp(type, "LIST")) {
1355## repeat retrieve (name = list.#name) where list.list_id = @id
1356## inquire_equel(rowcount = "rowcount")
1357 if (rowcount != 1)
1358 strcpy(name, "???");
1359 } else if (!strcmp(type, "USER")) {
1360## repeat retrieve (name = users.login) where users.users_id = @id
f0516942 1361## inquire_equel(rowcount = "rowcount")
1362 if (rowcount != 1)
1363 strcpy(name, "???");
1364 } else if (!strcmp(type, "KERBEROS")) {
1365## repeat retrieve (name = strings.string) where strings.string_id = @id
822a6eba 1366## inquire_equel(rowcount = "rowcount")
1367 if (rowcount != 1)
1368 strcpy(name, "???");
1369 } else if (!strcmp(type, "NONE")) {
1370 strcpy(name, "NONE");
1371 } else
1372 strcpy(name, "???");
1373 free(argv[idx]);
1374 argv[idx] = name;
1375
1376 if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) {
1377 argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1);
1378 strcpy(argv[6], UNIQUE_GID);
1379 }
1380
1381 /* send the data */
1382 (*action)(q->vcnt, argv, actarg);
1383
1384 /* free saved data */
1385 for (i = 0; i < q->vcnt; i++)
1386 free(argv[i]);
1387 free(argv);
1388 }
1389
1390 sq_destroy(sq);
1391 return (SMS_SUCCESS);
1392##}
1393
1394
711660a5 1395/* followup_gnfq: Fix the directory name & modby fields
1396 * argv[0] = filsys_id
1397 * argv[2] = ascii(quota)
1398 */
1399
1400followup_gnfq(q, sq, v, action, actarg, cl)
1401 struct query *q;
1402 register struct save_queue *sq;
1403 struct validate *v;
1404 register int (*action)();
1405 register int actarg;
1406 client *cl;
1407##{
1408 register int j;
1409 char **argv, *malloc();
1410## int id, rowcount;
1411## char *name, *label;
1412
1413 while (sq_get_data(sq, &argv)) {
1414 id = atoi(argv[3]);
1415 free(argv[3]);
1416 argv[3] = malloc(256);
1417 name = argv[3];
1418 if (id == 0) {
1419 label = argv[0];
1420## repeat retrieve (name = filesys.#name) where filesys.#label = @label
1421 } else {
1422## repeat retrieve (name = nfsphys.dir) where nfsphys.nfsphys_id = @id
1423 }
1424## inquire_equel(rowcount = "rowcount")
1425 if (rowcount != 1) {
1426 sprintf(argv[3], "#%d", id);
1427 }
1428
1429 id = atoi(argv[6]);
1430 free(argv[6]);
1431 argv[6] = malloc(256);
1432 name = argv[6];
1433 if (id > 0)
1434## repeat retrieve (name = users.login) where users.users_id = @id
1435 else {
1436 id = -id;
1437## repeat retrieve (name = strings.string) where strings.string_id = @id
1438 id = -id;
1439 }
1440## inquire_equel(rowcount = "rowcount")
1441 if (rowcount != 1) {
1442 sprintf(argv[6], "#%d", id);
1443 }
1444 (*action)(q->vcnt, argv, actarg);
1445 for (j = 0; j < q->vcnt; j++)
1446 free(argv[j]);
1447 free(argv);
1448 }
1449 sq_destroy(sq);
1450 return(SMS_SUCCESS);
1451##}
1452
1453
822a6eba 1454/* followup_anfq: Add allocation to nfsphys after creating quota.
1455 * argv[0] = filsys_id
1456 * argv[2] = ascii(quota)
1457 */
1458
1459followup_anfq(q, argv, cl)
1460 struct query *q;
1461 char **argv;
1462 client *cl;
1463##{
1464## int quota, user, fs, who;
1465## char *entity;
1466
1467 fs = *(int *)argv[0];
1468 user = *(int *)argv[1];
1469 quota = atoi(argv[2]);
711660a5 1470 who = cl->client_id;
822a6eba 1471 entity = cl->entity;
1472
1473## repeat replace nq (modtime = "now", modby = @who, modwith = @entity)
1474## where nq.filsys_id = @fs and nq.users_id = @user
1475## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
1476## where nfsphys.nfsphys_id = filesys.#phys_id and filesys.filsys_id = @fs
02ccf7ad 1477 if (ingres_errno) return(sms_errcode);
822a6eba 1478 return(SMS_SUCCESS);
1479##}
1480
1481
1482/* followup_gzcl:
1483 */
1484
1485followup_gzcl(q, sq, v, action, actarg, cl)
1486 register struct query *q;
1487 register struct save_queue *sq;
1488 register struct validate *v;
1489 register int (*action)();
92a943d6 1490 int actarg;
822a6eba 1491 client *cl;
92a943d6 1492##{
822a6eba 1493## char *name;
1494## int rowcount, id;
1495 char **argv;
1496 int i;
92a943d6 1497
822a6eba 1498 while (sq_get_data(sq, &argv)) {
1499 sms_trim_args(q->vcnt, argv);
92a943d6 1500
822a6eba 1501 id = atoi(argv[i = q->vcnt - 2]);
1502 free(argv[i]);
711660a5 1503 name = argv[i] = malloc(256);
1504 if (id > 0)
1505## repeat retrieve (name = users.login) where users.users_id = @id
1506 else {
1507 id = -id;
1508## repeat retrieve (name = strings.string) where strings.string_id = @id
1509 id = -id;
1510 }
822a6eba 1511## inquire_equel(rowcount = "rowcount")
1512 if (rowcount != 1)
1513 sprintf(argv[i], "#%d", id);
1514
1515 for (i = 1; i < 8; i+=2) {
1516 id = atoi(argv[i+1]);
1517 free(argv[i+1]);
1518 if ((name = argv[i+1] = malloc(33)) == NULL)
1519 return(SMS_NO_MEM);
1520 if (!strcmp(argv[i], "LIST")) {
1521## repeat retrieve (name = list.#name) where list.list_id = @id
1522## inquire_equel(rowcount = "rowcount")
1523 if (rowcount != 1)
1524 strcpy(name, "???");
1525 } else if (!strcmp(argv[i], "USER")) {
1526## repeat retrieve (name = users.login) where users.users_id = @id
f0516942 1527## inquire_equel(rowcount = "rowcount")
1528 if (rowcount != 1)
1529 strcpy(name, "???");
1530 } else if (!strcmp(argv[i], "KERBEROS")) {
1531## repeat retrieve (name = strings.string) where strings.string_id = @id
822a6eba 1532## inquire_equel(rowcount = "rowcount")
1533 if (rowcount != 1)
1534 strcpy(name, "???");
1535 } else if (!strcmp(argv[i], "NONE")) {
1536 strcpy(name, "NONE");
1537 } else {
1538 strcpy(name, "???");
1539 }
1540 }
92a943d6 1541
822a6eba 1542 /* send the data */
1543 (*action)(q->vcnt, argv, actarg);
1544
1545 /* free saved data */
1546 for (i = 0; i < q->vcnt; i++)
1547 free(argv[i]);
1548 free(argv);
1549 }
1550 sq_destroy(sq);
92a943d6 1551 return(SMS_SUCCESS);
1552##}
1553
05cdd922 1554
822a6eba 1555/* followup_gsha:
1556 */
1557
1558followup_gsha(q, sq, v, action, actarg, cl)
05cdd922 1559 register struct query *q;
822a6eba 1560 register struct save_queue *sq;
1561 register struct validate *v;
1562 register int (*action)();
1563 int actarg;
1564 client *cl;
05cdd922 1565##{
822a6eba 1566## char *name;
1567## int rowcount, id;
1568 char **argv;
1569 int i;
05cdd922 1570
822a6eba 1571 while (sq_get_data(sq, &argv)) {
1572 sms_trim_args(q->vcnt, argv);
05cdd922 1573
822a6eba 1574 id = atoi(argv[4]);
1575 free(argv[4]);
711660a5 1576 name = argv[4] = malloc(256);
1577 if (id > 0)
1578## repeat retrieve (name = users.login) where users.users_id = @id
1579 else {
1580 id = -id;
1581## repeat retrieve (name = strings.string) where strings.string_id = @id
1582 id = -id;
1583 }
822a6eba 1584## inquire_equel(rowcount = "rowcount")
1585 if (rowcount != 1)
1586 sprintf(argv[4], "#%d", id);
1587
1588 id = atoi(argv[2]);
1589 free(argv[2]);
1590 if ((name = argv[2] = malloc(33)) == NULL)
1591 return(SMS_NO_MEM);
1592 if (!strcmp(argv[1], "LIST")) {
1593## repeat retrieve (name = list.#name) where list.list_id = @id
1594## inquire_equel(rowcount = "rowcount")
1595 if (rowcount != 1)
1596 strcpy(name, "???");
1597 } else if (!strcmp(argv[1], "USER")) {
1598## repeat retrieve (name = users.login) where users.users_id = @id
f0516942 1599## inquire_equel(rowcount = "rowcount")
1600 if (rowcount != 1)
1601 strcpy(name, "???");
1602 } else if (!strcmp(argv[1], "KERBEROS")) {
1603## repeat retrieve (name = strings.string) where strings.string_id = @id
822a6eba 1604## inquire_equel(rowcount = "rowcount")
1605 if (rowcount != 1)
1606 strcpy(name, "???");
1607 } else if (!strcmp(argv[1], "NONE")) {
1608 strcpy(name, "NONE");
1609 } else {
1610 strcpy(name, "???");
1611 }
05cdd922 1612
822a6eba 1613 /* send the data */
1614 (*action)(q->vcnt, argv, actarg);
1615
1616 /* free saved data */
1617 for (i = 0; i < q->vcnt; i++)
1618 free(argv[i]);
1619 free(argv);
1620 }
1621 sq_destroy(sq);
1622 return(SMS_SUCCESS);
1623##}
05cdd922 1624
05cdd922 1625
822a6eba 1626\f
1627/* Special query routines */
30967516 1628
822a6eba 1629/* set_pobox - this does all of the real work.
1630 * argv = user_id, type, box
1631 * if type is POP, then box should be a machine, and its ID should be put in
1632 * pop_id. If type is SMTP, then box should be a string and its ID should
1633 * be put in box_id. If type is NONE, then box doesn't matter.
1634 */
1635
1636int set_pobox(q, argv, cl)
1637 struct query *q;
1638 char **argv;
1639 client *cl;
1640##{
1641## int user, id, rowcount;
1642## char *box, potype[9];
1643
1644 box = argv[2];
1645 user = *(int *)argv[0];
1646
1647## repeat retrieve (id = users.pop_id, potype = users.#potype)
1648## where users.users_id = @user
02ccf7ad 1649 if (ingres_errno) return(sms_errcode);
e7fa3293 1650 if (!strcmp(strtrim(potype), "POP"))
822a6eba 1651 set_pop_usage(id, -1);
1652
1653 if (!strcmp(argv[1], "POP")) {
1654## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@box)
1655## inquire_equel(rowcount = "rowcount")
1656 if (rowcount != 1)
1657 return(SMS_MACHINE);
1658## repeat replace users (#potype = "POP", pop_id = @id)
1659## where users.users_id = @user
1660 set_pop_usage(id, 1);
1661 } else if (!strcmp(argv[1], "SMTP")) {
353cb0da 1662 if (index(box, '/') || index(box, '|'))
1663 return(SMS_BAD_CHAR);
822a6eba 1664## range of s is strings
1665## repeat retrieve (id = s.string_id) where s.string = @box
1666## inquire_equel (rowcount = "rowcount")
1667 if (rowcount == 0) {
1668## range of v is values
1669## repeat retrieve (id = v.value) where v.name = "strings_id"
1670 id++;
1671## repeat replace v (value = @id) where v.name = "strings_id"
1672## append to strings (string_id = id, string = box)
1673 }
1674## repeat replace users (#potype = "SMTP", box_id = @id)
1675## where users.users_id = @user
1676 } else /* argv[1] == "NONE" */ {
1677## repeat replace users (#potype = "NONE") where users.users_id = @user
1678 }
1679
1680 set_pobox_modtime(q, argv, cl);
1681## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
1682## where tblstats.#table = "users"
02ccf7ad 1683 if (ingres_errno) return(sms_errcode);
30967516 1684 return(SMS_SUCCESS);
1685##}
1686
30967516 1687
822a6eba 1688/* get_list_info: passed a wildcard list name, returns lots of stuff about
1689 * each list. This is tricky: first build a queue of all requested
44bd6f44 1690 * data. Rest of processing consists of fixing gid, ace_name, and modby.
822a6eba 1691 */
1692
1693get_list_info(q, aargv, cl, action, actarg)
30967516 1694 register struct query *q;
822a6eba 1695 char **aargv;
1696 client *cl;
1697 register int (*action)();
1698 int actarg;
30967516 1699##{
822a6eba 1700 char *argv[13], *malloc(), *realloc();
1701## char *name, acl_type[9], listname[33], active[5], public[5], hidden[5];
49189928 1702## char maillist[5], group[5], gid[6], acl_name[256], desc[256], modtime[27];
711660a5 1703## char modby[256], modwith[9];
822a6eba 1704## int id, rowcount, acl_id, hid, modby_id;
1705 int returned;
1706 struct save_queue *sq, *sq_create();
30967516 1707
822a6eba 1708 returned = rowcount = 0;
1709 name = aargv[0];
30967516 1710
822a6eba 1711 sq = sq_create();
1712## range of l is list
1713## repeat retrieve (id = l.list_id) where l.#name = @name {
1714 sq_save_data(sq, id);
1715 rowcount++;
1716## }
711660a5 1717 if (ingres_errno) return(sms_errcode);
822a6eba 1718 if (rowcount == 0)
1719 return(SMS_NO_MATCH);
1720
1721 argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden;
1722 argv[4] = maillist; argv[5] = group; argv[6] = gid; argv[7] = acl_type;
1723 argv[8] = acl_name; argv[9] = desc; argv[10] = modtime; argv[11] = modby;
1724 argv[12] = modwith;
1725
1726 while (sq_get_data(sq, &id)) {
1727 if (id == 0)
1728 continue;
1729 argv[6] = gid;
1730## repeat retrieve (listname = l.#name, active = text(l.#active),
1731## public = text(l.#public), hidden = text(l.#hidden),
1732## hid = l.#hidden, maillist = text(l.#maillist),
1733## group = text(l.#group), gid = text(l.#gid),
1734## acl_type = trim(l.#acl_type), acl_id = l.#acl_id,
1735## desc = l.#desc, modtime = l.#modtime, modby_id = l.#modby,
1736## modwith =l.#modwith)
1737## where l.list_id = @id
711660a5 1738 if (ingres_errno) return(sms_errcode);
822a6eba 1739
1740 if (atoi(gid) == -1)
1741 argv[6] = UNIQUE_GID;
1742
1743 if (!strcmp(acl_type, "LIST")) {
1744## repeat retrieve (acl_name = l.#name) where l.list_id = @acl_id
1745## inquire_equel(rowcount = "rowcount")
1746 if (rowcount != 1)
1747 strcpy(acl_name, "???");
1748 } else if (!strcmp(acl_type, "USER")) {
1749## repeat retrieve (acl_name = users.#login)
1750## where users.users_id = @acl_id
f0516942 1751## inquire_equel(rowcount = "rowcount")
1752 if (rowcount != 1)
1753 strcpy(acl_name, "???");
1754 } else if (!strcmp(acl_type, "KERBEROS")) {
1755## repeat retrieve (acl_name = strings.string)
1756## where strings.string_id = @acl_id
822a6eba 1757## inquire_equel(rowcount = "rowcount")
1758 if (rowcount != 1)
1759 strcpy(acl_name, "???");
1760 } else if (!strcmp(acl_type, "NONE")) {
1761 strcpy(acl_name, "NONE");
1762 } else
1763 strcpy(acl_name, "???");
1764
711660a5 1765 if (modby_id > 0)
1766## repeat retrieve (modby = users.login) where users.users_id = @modby_id
1767 else {
1768 modby_id = -modby_id;
1769## repeat retrieve (modby = strings.string)
1770## where strings.string_id = @modby_id
1771 modby_id = -modby_id;
1772 }
822a6eba 1773## inquire_equel(rowcount = "rowcount")
1774 if (rowcount != 1)
711660a5 1775 sprintf(modby, "#%d", modby_id);
1776 if (ingres_errno) return(sms_errcode);
822a6eba 1777
1778 sms_trim_args(q->vcnt, argv);
1779 returned++;
1780 (*action)(q->vcnt, argv, actarg);
1781 }
30967516 1782
822a6eba 1783 sq_destroy(sq);
02ccf7ad 1784 if (ingres_errno) return(sms_errcode);
822a6eba 1785## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
1786## where tblstats.#table = "list"
5e06ce45 1787
822a6eba 1788 return (SMS_SUCCESS);
1789##}
1790
1791
a6683dad 1792/* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is
1793 * how many different ancestors a member is allowed to have.
1794 */
1795
1796#define MAXLISTDEPTH 100
1797
1798int add_member_to_list(q, argv, cl)
1799 struct query *q;
1800 char **argv;
1801 client *cl;
1802##{
49189928 1803## int id, lid, mid, exists, error, who, ref;
189bd6e7 1804## char *mtype, dtype[9], buf[256], *entity;
49189928 1805 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
1806 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
a6683dad 1807 char *dtypes[MAXLISTDEPTH];
711660a5 1808 char *iargv[3];
a6683dad 1809
1810## range of m is imembers
1811 lid = *(int *)argv[0];
1812 mtype = argv[1];
1813 mid = *(int *)argv[2];
49189928 1814 /* if the member is already a direct member of the list, punt */
a6683dad 1815## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1816## m.member_id = @mid and m.member_type = @mtype
1817## and m.direct = 1))
1818 if (exists)
1819 return(SMS_EXISTS);
353cb0da 1820 if (!strcasecmp(mtype, "STRING")) {
1821## repeat retrieve (buf = strings.string) where strings.string_id = @mid
1822 if (index(buf, '/') || index(buf, '|'))
1823 return(SMS_BAD_CHAR);
1824 }
1825
a6683dad 1826 ancestors[0] = lid;
49189928 1827 aref[0] = 1;
a6683dad 1828 acount = 1;
49189928 1829## repeat retrieve (id = m.list_id, ref = m.ref_count)
a6683dad 1830## where m.member_id = @lid and m.member_type = "LIST" {
49189928 1831 aref[acount] = ref;
a6683dad 1832 ancestors[acount++] = id;
1833 if (acount >= MAXLISTDEPTH) {
1834## endretrieve
1835 }
1836## }
711660a5 1837 if (ingres_errno) return(sms_errcode);
a6683dad 1838 if (acount >= MAXLISTDEPTH) {
1839 return(SMS_INTERNAL);
1840 }
1841 descendants[0] = mid;
1842 dtypes[0] = mtype;
49189928 1843 dref[0] = 1;
a6683dad 1844 dcount = 1;
1845 error = 0;
1846 if (!strcmp(mtype, "LIST")) {
49189928 1847## repeat retrieve (id = m.member_id, dtype = m.member_type,
1848## ref = m.ref_count)
a6683dad 1849## where m.list_id = @mid {
1850 switch (dtype[0]) {
1851 case 'L':
1852 dtypes[dcount] = "LIST";
1853 break;
1854 case 'U':
1855 dtypes[dcount] = "USER";
1856 break;
1857 case 'S':
1858 dtypes[dcount] = "STRING";
1859 break;
1860 case 'K':
1861 dtypes[dcount] = "KERBEROS";
1862 break;
1863 default:
1864 error++;
1865## endretrieve
1866 }
49189928 1867 dref[dcount] = ref;
a6683dad 1868 descendants[dcount++] = id;
1869 if (dcount >= MAXLISTDEPTH) {
1870 error++;
1871## endretrieve
1872 }
1873## }
711660a5 1874 if (ingres_errno) return(sms_errcode);
a6683dad 1875 if (error)
1876 return(SMS_INTERNAL);
1877 }
1878 for (a = 0; a < acount; a++) {
1879 lid = ancestors[a];
1880 for (d = 0; d < dcount; d++) {
1881 mid = descendants[d];
1882 mtype = dtypes[d];
1883 if (mid == lid && !strcmp(mtype, "LIST")) {
1884 return(SMS_LISTLOOP);
1885 }
1886## repeat retrieve (exists = any(m.ref_count where m.list_id = @lid
1887## and m.member_id = @mid
1888## and m.member_type = @mtype))
49189928 1889 ref = aref[a] * dref[d];
a6683dad 1890 if (exists) {
1891 if (a == 0 && d == 0)
49189928 1892## replace m (ref_count = m.ref_count+ref, direct = 1)
a6683dad 1893## where m.list_id = lid and m.member_id = mid and
1894## m.member_type = mtype
1895 else
49189928 1896## replace m (ref_count = m.ref_count+ref)
a6683dad 1897## where m.list_id = lid and m.member_id = mid and
1898## m.member_type = mtype
1899 } else {
711660a5 1900 incremental_clear_before();
a6683dad 1901 if (a == 0 && d == 0)
1902## append imembers (list_id=lid, member_id = mid, direct = 1,
1903## member_type=mtype, ref_count = 1)
1904 else
1905## append imembers (list_id=lid, member_id = mid,
49189928 1906## member_type=mtype, ref_count = ref)
711660a5 1907 iargv[0] = (char *)lid;
1908 iargv[1] = mtype;
1909 iargv[2] = (char *)mid;
1910 incremental_after("members", 0, iargv);
a6683dad 1911 }
1912 }
1913 }
189bd6e7 1914 lid = *(int *)argv[0];
1915 entity = cl->entity;
1916 who = cl->client_id;
1917## repeat replace list (modtime = "now", modby = @who, modwith = @entity)
1918## where list.#list_id = @lid
711660a5 1919 if (ingres_errno) return(sms_errcode);
a6683dad 1920 return(SMS_SUCCESS);
1921##}
1922
1923
1924/* Delete_member_from_list: do list flattening as we go!
1925 */
1926
1927int delete_member_from_list(q, argv, cl)
1928 struct query *q;
1929 char **argv;
1930 client *cl;
1931##{
49189928 1932## int id, lid, mid, cnt, exists, error, who, ref;
189bd6e7 1933## char *mtype, dtype[9], *entity;
49189928 1934 int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a;
1935 int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d;
a6683dad 1936 char *dtypes[MAXLISTDEPTH];
711660a5 1937 char *iargv[3];
a6683dad 1938
1939## range of m is imembers
1940 lid = *(int *)argv[0];
1941 mtype = argv[1];
1942 mid = *(int *)argv[2];
49189928 1943 /* if the member is not a direct member of the list, punt */
a6683dad 1944## repeat retrieve (exists = any(m.list_id where m.list_id=@lid and
1945## m.member_id = @mid and m.member_type = @mtype
1946## and m.direct = 1))
711660a5 1947 if (ingres_errno) return(sms_errcode);
a6683dad 1948 if (!exists)
1949 return(SMS_NO_MATCH);
1950 ancestors[0] = lid;
49189928 1951 aref[0] = 1;
a6683dad 1952 acount = 1;
49189928 1953## repeat retrieve (id = m.list_id, ref = m.ref_count)
a6683dad 1954## where m.member_id = @lid and m.member_type = "LIST" {
49189928 1955 aref[acount] = ref;
a6683dad 1956 ancestors[acount++] = id;
1957 if (acount >= MAXLISTDEPTH)
1958## endretrieve
1959## }
711660a5 1960 if (ingres_errno) return(sms_errcode);
a6683dad 1961 if (acount >= MAXLISTDEPTH)
1962 return(SMS_INTERNAL);
1963 descendants[0] = mid;
1964 dtypes[0] = mtype;
49189928 1965 dref[0] = 1;
a6683dad 1966 dcount = 1;
1967 error = 0;
1968 if (!strcmp(mtype, "LIST")) {
49189928 1969## repeat retrieve (id = m.member_id, dtype = m.member_type,
1970## ref = m.ref_count)
a6683dad 1971## where m.list_id = @mid {
1972 switch (dtype[0]) {
1973 case 'L':
1974 dtypes[dcount] = "LIST";
1975 break;
1976 case 'U':
1977 dtypes[dcount] = "USER";
1978 break;
1979 case 'S':
1980 dtypes[dcount] = "STRING";
1981 break;
1982 case 'K':
1983 dtypes[dcount] = "KERBEROS";
1984 break;
1985 default:
1986 error++;
1987## endretrieve
1988 }
49189928 1989 dref[dcount] = ref;
a6683dad 1990 descendants[dcount++] = id;
1991 if (dcount >= MAXLISTDEPTH)
1992## endretrieve
1993## }
711660a5 1994 if (ingres_errno) return(sms_errcode);
a6683dad 1995 if (error)
1996 return(SMS_INTERNAL);
1997 }
1998 for (a = 0; a < acount; a++) {
1999 lid = ancestors[a];
2000 for (d = 0; d < dcount; d++) {
2001 mid = descendants[d];
2002 mtype = dtypes[d];
2003 if (mid == lid && !strcmp(mtype, "LIST")) {
2004 return(SMS_LISTLOOP);
2005 }
2006## repeat retrieve (cnt = m.ref_count)
2007## where m.list_id = @lid and m.member_id = @mid
2008## and m.member_type = @mtype
49189928 2009 ref = aref[a] * dref[d];
2010 if (cnt <= ref) {
711660a5 2011 iargv[0] = (char *)lid;
2012 iargv[1] = mtype;
2013 iargv[2] = (char *)mid;
2014 incremental_before("members", 0, iargv);
a6683dad 2015## delete m where m.list_id = lid and m.member_id = mid and
2016## m.member_type = mtype
711660a5 2017 incremental_clear_after();
a6683dad 2018 } else if (a == 0 && d == 0) {
49189928 2019## replace m (ref_count = m.ref_count-ref, direct = 0)
a6683dad 2020## where m.list_id = lid and m.member_id = mid and
2021## m.member_type = mtype
2022 } else {
49189928 2023## replace m (ref_count = m.ref_count-ref)
353cb0da 2024## where m.list_id = lid and m.member_id = mid and
a6683dad 2025## m.member_type = mtype
2026 }
2027 }
2028 }
189bd6e7 2029 lid = *(int *)argv[0];
2030 entity = cl->entity;
2031 who = cl->client_id;
2032## repeat replace list (modtime = "now", modby = @who, modwith = @entity)
2033## where list.#list_id = @lid
711660a5 2034 if (ingres_errno) return(sms_errcode);
a6683dad 2035 return(SMS_SUCCESS);
2036##}
2037
2038
44bd6f44 2039/* get_ace_use - given a type and a name, return a type and a name.
2040 * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0],
822a6eba 2041 * and argv[1] will contain the ID of the entity in question. The R*
2042 * types mean to recursively look at every containing list, not just
2043 * when the object in question is a direct member. On return, the
2044 * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR.
2045 */
2046
44bd6f44 2047int get_ace_use(q, argv, cl, action, actarg)
822a6eba 2048 struct query *q;
2049 char *argv[];
2050 client *cl;
2051 int (*action)();
2052 int actarg;
2053##{
2054 int found = 0;
2055## char *atype;
2056## int aid, listid, id;
2057 struct save_queue *sq, *sq_create();
2058
a6683dad 2059## range of m is imembers
822a6eba 2060 atype = argv[0];
2061 aid = *(int *)argv[1];
f0516942 2062 if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") ||
2063 !strcmp(atype, "KERBEROS")) {
44bd6f44 2064 return(get_ace_internal(atype, aid, action, actarg));
822a6eba 2065 }
2066
2067 sq = sq_create();
2068 if (!strcmp(atype, "RLIST")) {
2069 sq_save_data(sq, aid);
2070 /* get all the list_id's of containing lists */
a6683dad 2071## range of m is imembers
2072## repeat retrieve (listid = m.list_id)
822a6eba 2073## where m.member_type = "LIST" and m.member_id = @id {
a6683dad 2074 sq_save_unique_data(sq, listid);
2075## }
822a6eba 2076 /* now process each one */
2077 while (sq_get_data(sq, &id)) {
44bd6f44 2078 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
822a6eba 2079 found++;
2080 }
2081 }
2082
2083 if (!strcmp(atype, "RUSER")) {
822a6eba 2084## repeat retrieve (listid = m.list_id)
2085## where m.member_type = "USER" and m.member_id = @aid {
2086 sq_save_data(sq, listid);
2087## }
822a6eba 2088 /* now process each one */
2089 while (sq_get_data(sq, &id)) {
44bd6f44 2090 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
822a6eba 2091 found++;
2092 }
44bd6f44 2093 if (get_ace_internal("USER", aid, action, actarg) == SMS_SUCCESS)
822a6eba 2094 found++;
2095 }
05cdd922 2096
f0516942 2097 if (!strcmp(atype, "RKERBERO")) {
f0516942 2098## repeat retrieve (listid = m.list_id)
2099## where m.member_type = "KERBEROS" and m.member_id = @aid {
2100 sq_save_data(sq, listid);
2101## }
f0516942 2102 /* now process each one */
2103 while (sq_get_data(sq, &id)) {
2104 if (get_ace_internal("LIST", id, action, actarg) == SMS_SUCCESS)
2105 found++;
2106 }
2107 if (get_ace_internal("KERBEROS", aid, action, actarg) == SMS_SUCCESS)
2108 found++;
2109 }
2110
822a6eba 2111 sq_destroy(sq);
02ccf7ad 2112 if (ingres_errno) return(sms_errcode);
822a6eba 2113 if (!found) return(SMS_NO_MATCH);
05cdd922 2114 return(SMS_SUCCESS);
2115##}
92a943d6 2116
822a6eba 2117
44bd6f44 2118/* This looks up a single list or user for ace use. atype must be "USER"
822a6eba 2119 * or "LIST", and aid is the ID of the corresponding object. This is used
44bd6f44 2120 * by get_ace_use above.
822a6eba 2121 */
2122
44bd6f44 2123##get_ace_internal(atype, aid, action, actarg)
822a6eba 2124## char *atype;
2125## int aid;
2126 int (*action)();
2127 int actarg;
2128##{
2129 char *rargv[2];
2130 int found = 0;
2131## char name[33];
2132
2133 rargv[1] = name;
2134 if (!strcmp(atype, "LIST")) {
2135 rargv[0] = "FILESYS";
2136## repeat retrieve (name = filesys.label)
2137## where filesys.owners = @aid {
2138 (*action)(2, rargv, actarg);
2139 found++;
2140## }
2141
2142 rargv[0] = "QUERY";
2143## repeat retrieve (name = capacls.capability)
2144## where capacls.list_id = @aid {
2145 (*action)(2, rargv, actarg);
2146 found++;
2147## }
2148 } else if (!strcmp(atype, "USER")) {
2149 rargv[0] = "FILESYS";
2150## repeat retrieve (name = filesys.label)
2151## where filesys.owner = @aid {
2152 (*action)(2, rargv, actarg);
2153 found++;
2154## }
2155 }
2156
2157 rargv[0] = "LIST";
2158## repeat retrieve (name = list.#name)
2159## where list.acl_type = @atype and list.acl_id = @aid {
2160 (*action)(2, rargv, actarg);
2161 found++;
2162## }
2163
2164 rargv[0] = "SERVICE";
2165## repeat retrieve (name = servers.#name)
2166## where servers.acl_type = @atype and servers.acl_id = @aid {
2167 (*action)(2, rargv, actarg);
2168 found++;
2169## }
2170
2171 rargv[0] = "HOSTACCESS";
2172## repeat retrieve (name = machine.#name)
2173## where machine.mach_id = hostaccess.mach_id and
2174## hostaccess.acl_type = @atype and hostaccess.acl_id = @aid {
2175 (*action)(2, rargv, actarg);
2176 found++;
2177## }
2178 rargv[0] = "ZEPHYR";
2179## repeat retrieve (name = zephyr.class)
2180## where zephyr.xmt_type = @atype and zephyr.xmt_id = @aid or
2181## zephyr.sub_type = @atype and zephyr.sub_id = @aid or
2182## zephyr.iws_type = @atype and zephyr.iws_id = @aid or
2183## zephyr.iui_type = @atype and zephyr.iui_id = @aid {
2184 (*action)(2, rargv, actarg);
2185 found++;
2186## }
2187
2188 if (!found) return(SMS_NO_MATCH);
2189 return(SMS_SUCCESS);
2190##}
2191
2192
2193/* get_lists_of_member - given a type and a name, return the name and flags
2194 * of all of the lists of the given member. The member_type is one of
2195 * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0],
2196 * and argv[1] will contain the ID of the entity in question. The R*
2197 * types mean to recursively look at every containing list, not just
2198 * when the object in question is a direct member.
2199 */
2200
2201int get_lists_of_member(q, argv, cl, action, actarg)
92a943d6 2202 struct query *q;
2203 char *argv[];
822a6eba 2204 client *cl;
2205 int (*action)();
2206 int actarg;
92a943d6 2207##{
a6683dad 2208 int found = 0, direct = 1;
2209 char *rargv[6];
822a6eba 2210## char *atype;
2211## int aid, listid, id;
a6683dad 2212## char name[33], active[5], public[5], hidden[5], maillist[5], group[5];
822a6eba 2213
2214 atype = argv[0];
2215 aid = *(int *)argv[1];
822a6eba 2216 if (!strcmp(atype, "RLIST")) {
a6683dad 2217 atype = "LIST";
2218 direct = 0;
822a6eba 2219 }
822a6eba 2220 if (!strcmp(atype, "RUSER")) {
a6683dad 2221 atype = "USER";
2222 direct = 0;
822a6eba 2223 }
822a6eba 2224 if (!strcmp(atype, "RSTRING")) {
a6683dad 2225 atype = "STRING";
2226 direct = 0;
92a943d6 2227 }
a6683dad 2228 if (!strcmp(atype, "RKERBEROS")) {
2229 atype = "KERBEROS";
2230 direct = 0;
f0516942 2231 }
2232
822a6eba 2233 rargv[0] = name;
2234 rargv[1] = active;
2235 rargv[2] = public;
2236 rargv[3] = hidden;
2237 rargv[4] = maillist;
2238 rargv[5] = group;
9bcb4bf5 2239## range of m is imembers
a6683dad 2240 if (direct) {
2241## repeat retrieve (name = list.#name, active = text(list.#active),
2242## public = text(list.#public), hidden = text(list.#hidden),
2243## maillist = text(list.#maillist), group = text(list.#group))
2244## where list.list_id = m.list_id and m.direct = 1 and
2245## m.member_type = @atype and m.member_id = @aid {
2246 (*action)(6, rargv, actarg);
2247 found++;
2248## }
2249 } else {
2250## repeat retrieve (name = list.#name, active = text(list.#active),
822a6eba 2251## public = text(list.#public), hidden = text(list.#hidden),
2252## maillist = text(list.#maillist), group = text(list.#group))
2253## where list.list_id = m.list_id and
2254## m.member_type = @atype and m.member_id = @aid {
2255 (*action)(6, rargv, actarg);
2256 found++;
a6683dad 2257## }
2258 }
92a943d6 2259
02ccf7ad 2260 if (ingres_errno) return(sms_errcode);
822a6eba 2261 if (!found) return(SMS_NO_MATCH);
92a943d6 2262 return(SMS_SUCCESS);
2263##}
2264
822a6eba 2265
2266/* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of
2267 * the five flags associated with each list. It will return the name of
2268 * each list that meets the quailifications. It does this by building a
2269 * where clause based on the arguments, then doing a retrieve.
2270 */
2271
2272static char *lflags[5] = { "active", "public", "hidden", "maillist", "group" };
2273
2274int qualified_get_lists(q, argv, cl, action, actarg)
2275 struct query *q;
2276 char *argv[];
2277 client *cl;
2278 int (*action)();
2279 int actarg;
2280{
2281 return(qualified_get(q, argv, action, actarg, "l.list_id != 0",
2282 "l", "name", lflags));
2283}
2284
2285
2286/** get_members_of_list - optimized query for retrieval of list members
c2408bd5 2287 **
2288 ** Inputs:
2289 ** argv[0] - list_id
2290 **
2291 ** Description:
2292 ** - retrieve USER members, then LIST members, then STRING members
c2408bd5 2293 **/
2294
822a6eba 2295get_members_of_list(q, argv, cl, action, actarg)
c2408bd5 2296 struct query *q;
2297 char *argv[];
822a6eba 2298 client *cl;
c2408bd5 2299 int (*action)();
2300 int actarg;
2301##{
2302## int list_id;
2303## char member_name[129];
2304 char *targv[2];
2305
2306 list_id = *(int *)argv[0];
2307 targv[0] = "USER";
2308 targv[1] = member_name;
2309
a6683dad 2310## range of m is imembers
c2408bd5 2311## repeat retrieve (member_name = users.login)
2312## where m.#list_id = @list_id and m.member_type = "USER"
a6683dad 2313## and m.member_id = users.users_id and m.direct = 1
92a943d6 2314## sort by #member_name
c2408bd5 2315## {
2316 (*action)(2, targv, actarg);
2317## }
02ccf7ad 2318 if (ingres_errno) return(sms_errcode);
c2408bd5 2319
2320 targv[0] = "LIST";
2321## repeat retrieve (member_name = list.name)
2322## where m.#list_id = @list_id and m.member_type = "LIST"
a6683dad 2323## and m.member_id = list.#list_id and m.direct = 1
92a943d6 2324## sort by #member_name
c2408bd5 2325## {
2326 (*action)(2, targv, actarg);
2327## }
02ccf7ad 2328 if (ingres_errno) return(sms_errcode);
c2408bd5 2329
2330 targv[0] = "STRING";
2331## repeat retrieve (member_name = strings.string)
2332## where m.#list_id = @list_id and m.member_type = "STRING"
a6683dad 2333## and m.member_id = strings.string_id and m.direct = 1
92a943d6 2334## sort by #member_name
f0516942 2335## {
2336 (*action)(2, targv, actarg);
2337## }
02ccf7ad 2338 if (ingres_errno) return(sms_errcode);
f0516942 2339
2340 targv[0] = "KERBEROS";
2341## repeat retrieve (member_name = strings.string)
2342## where m.#list_id = @list_id and m.member_type = "KERBEROS"
a6683dad 2343## and m.member_id = strings.string_id and m.direct = 1
f0516942 2344## sort by #member_name
c2408bd5 2345## {
2346 (*action)(2, targv, actarg);
2347## }
02ccf7ad 2348 if (ingres_errno) return(sms_errcode);
c2408bd5 2349
2350 return(SMS_SUCCESS);
2351##}
2352
92a943d6 2353
822a6eba 2354/* count_members_of_list: this is a simple query, but it cannot be done
2355 * through the dispatch table.
2356 */
2357
2358int count_members_of_list(q, argv, cl, action, actarg)
92a943d6 2359 struct query *q;
2360 char *argv[];
822a6eba 2361 client *cl;
92a943d6 2362 int (*action)();
2363 int actarg;
2364##{
822a6eba 2365## int list, ct = 0;
2366 char *rargv[1], countbuf[5];
2367
2368 list = *(int *)argv[0];
2369 rargv[0] = countbuf;
a6683dad 2370## repeat retrieve (ct = count(imembers.list_id
2371## where imembers.list_id = @list and
2372## imembers.direct = 1))
02ccf7ad 2373 if (ingres_errno) return(sms_errcode);
822a6eba 2374 sprintf(countbuf, "%d", ct);
2375 (*action)(1, rargv, actarg);
822a6eba 2376 return(SMS_SUCCESS);
2377##}
92a943d6 2378
92a943d6 2379
822a6eba 2380/* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of
2381 * the three flags associated with each service. It will return the name of
2382 * each service that meets the quailifications. It does this by building a
2383 * where clause based on the arguments, then doing a retrieve.
2384 */
92a943d6 2385
822a6eba 2386static char *sflags[3] = { "enable", "inprogress", "harderror" };
a6cb4d4c 2387
822a6eba 2388int qualified_get_server(q, argv, cl, action, actarg)
a6cb4d4c 2389 struct query *q;
2390 char *argv[];
822a6eba 2391 client *cl;
a6cb4d4c 2392 int (*action)();
2393 int actarg;
822a6eba 2394{
2395 return(qualified_get(q, argv, action, actarg, "s.name != \"\"",
2396 "s", "name", sflags));
2397}
a6cb4d4c 2398
a6cb4d4c 2399
822a6eba 2400/* generic qualified get routine, used by qualified_get_lists,
2401 * qualified_get_server, and qualified_get_serverhost.
2402 * Args:
2403 * start - a simple where clause, must not be empty
2404 * range - the name of the range variable
2405 * field - the field to return
2406 * flags - an array of strings, names of the flag variables
2407 */
c2408bd5 2408
822a6eba 2409int qualified_get(q, argv, action, actarg, start, range, field, flags)
c2408bd5 2410 struct query *q;
2411 char *argv[];
2412 int (*action)();
2413 int actarg;
822a6eba 2414 char *start;
2415 char *range;
2416 char *field;
2417 char *flags[];
c2408bd5 2418##{
822a6eba 2419## char name[33], qual[256], *rvar, *rtbl, *rfield;
2420 char *rargv[1], buf[32];
2421## int rowcount, i;
2422
2423 strcpy(qual, start);
2424 for (i = 0; i < q->argc; i++) {
2425 if (!strcmp(argv[i], "TRUE")) {
2426 sprintf(buf, " and %s.%s != 0", range, flags[i]);
2427 (void) strcat(qual, buf);
2428 } else if (!strcmp(argv[i], "FALSE")) {
2429 sprintf(buf, " and %s.%s = 0", range, flags[i]);
2430 (void) strcat(qual, buf);
2431 }
2432 }
2433
2434 rargv[0] = name;
2435 rvar = range;
2436 rtbl = q->rtable;
2437 rfield = field;
2438## range of rvar is rtbl
2439## retrieve (name = rvar.rfield) where qual {
2440 (*action)(1, rargv, actarg);
c2408bd5 2441## }
02ccf7ad 2442 if (ingres_errno) return(sms_errcode);
822a6eba 2443## inquire_equel(rowcount = "rowcount")
2444## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2445## where tblstats.#table = @rtbl
2446 if (rowcount == 0)
2447 return(SMS_NO_MATCH);
2448 return(SMS_SUCCESS);
2449##}
c2408bd5 2450
c2408bd5 2451
822a6eba 2452/* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of
2453 * the five flags associated with each serverhost. It will return the name of
2454 * each service and host that meets the quailifications. It does this by
2455 * building a where clause based on the arguments, then doing a retrieve.
2456 */
c2408bd5 2457
822a6eba 2458static char *shflags[6] = { "service", "enable", "override", "success",
2459 "inprogress", "hosterror" };
a6cb4d4c 2460
822a6eba 2461int qualified_get_serverhost(q, argv, cl, action, actarg)
a6cb4d4c 2462 struct query *q;
2463 char *argv[];
822a6eba 2464 client *cl;
a6cb4d4c 2465 int (*action)();
2466 int actarg;
2467##{
822a6eba 2468## char sname[33], mname[33], qual[256];
2469 char *rargv[2], buf[32];
2470## int rowcount, i;
2471
44bd6f44 2472 sprintf(qual, "machine.mach_id = sh.mach_id and sh.service = uppercase(\"%s\")",
822a6eba 2473 argv[0]);
2474 for (i = 1; i < q->argc; i++) {
2475 if (!strcmp(argv[i], "TRUE")) {
2476 sprintf(buf, " and sh.%s != 0", shflags[i]);
2477 strcat(qual, buf);
2478 } else if (!strcmp(argv[i], "FALSE")) {
2479 sprintf(buf, " and sh.%s = 0", shflags[i]);
2480 strcat(qual, buf);
2481 }
2482 }
2483
2484 rargv[0] = sname;
2485 rargv[1] = mname;
2486## range of sh is serverhosts
2487## retrieve (sname = sh.service, mname = machine.name) where qual {
2488 (*action)(2, rargv, actarg);
a6cb4d4c 2489## }
02ccf7ad 2490 if (ingres_errno) return(sms_errcode);
822a6eba 2491## inquire_equel(rowcount = "rowcount")
2492## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
2493## where tblstats.#table = "serverhosts"
2494 if (rowcount == 0)
2495 return(SMS_NO_MATCH);
2496 return(SMS_SUCCESS);
2497##}
a6cb4d4c 2498
a6cb4d4c 2499
822a6eba 2500/* register_user - change user's login name and allocate a pobox, group,
2501 * filesystem, and quota for them. The user's status must start out as 0,
2502 * and is left as 2. Arguments are: user's UID, new login name, and user's
2503 * type for filesystem allocation (SMS_FS_STUDENT, SMS_FS_FACULTY,
2504 * SMS_FS_STAFF, SMS_FS_MISC).
2505 */
2506
2507register_user(q, argv, cl)
2508 struct query *q;
2509 char **argv;
2510 client *cl;
2511##{
2512## char *login, dir[65], *entity, *directory, machname[33];
2513## int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota;
2514## int size, alloc, pid, m_id;
711660a5 2515 char buffer[256], *aargv[3];
822a6eba 2516 int maxsize;
2517
2518 entity = cl->entity;
711660a5 2519 who = cl->client_id;
822a6eba 2520
2521 uid = atoi(argv[0]);
2522 login = argv[1];
2523 utype = atoi(argv[2]);
2524
2525## range of u is users
2526## range of l is list
2527## range of sh is serverhosts
2528## range of n is nfsphys
2529## range of m is machine
2530
2531 /* find user */
2532## repeat retrieve (users_id = u.#users_id)
711660a5 2533## where u.#uid = @uid and (u.status = 0 or u.status = 5)
822a6eba 2534## inquire_equel(rowcount = "rowcount");
2535 if (rowcount == 0)
2536 return(SMS_NO_MATCH);
2537 if (rowcount > 1)
2538 return(SMS_NOT_UNIQUE);
2539
2540 /* check new login name */
711660a5 2541## repeat retrieve (flag = any(u.#login where u.#login = @login and
2542## u.#users_id != users_id))
e1795ce1 2543 if (ingres_errno) return(sms_errcode);
2544 if (flag) return(SMS_IN_USE);
4f16dc86 2545## repeat retrieve (flag = any(l.#name where l.#name = @login))
e1795ce1 2546 if (ingres_errno) return(sms_errcode);
2547 if (flag) return(SMS_IN_USE);
99a288b9 2548## repeat retrieve (flag = any(filesys.#label where filesys.#label = @login))
e1795ce1 2549 if (ingres_errno) return(sms_errcode);
2550 if (flag) return(SMS_IN_USE);
822a6eba 2551 com_err(whoami, 0, "new login name OK");
2552
2553 /* choose place for pobox, put in mid */
2554## repeat retrieve (mid = sh.mach_id, machname = m.name)
44bd6f44 2555## where sh.service = "POP" and m.mach_id = sh.mach_id and
2556## sh.value2 - sh.value1 = max(sh.value2-sh.value1 where sh.service="POP")
02ccf7ad 2557 if (ingres_errno) return(sms_errcode);
8ac9ee7a 2558## inquire_equel(rowcount = "rowcount");
822a6eba 2559 if (rowcount == 0)
44bd6f44 2560 return(SMS_NO_POBOX);
822a6eba 2561
2562 /* change login name, set pobox */
711660a5 2563 sprintf(buffer, "u.users_id = %d", users_id);
2564 incremental_before("users", buffer, 0);
822a6eba 2565## repeat replace u (#login = @login, status = 2, modtime = "now",
2566## modby = @who, modwith = @entity, potype="POP",
2567## pop_id = @mid, pmodtime="now", pmodby=@who,
2568## pmodwith=@entity)
2569## where u.#users_id = @users_id
8ac9ee7a 2570## inquire_equel(rowcount = "rowcount");
02ccf7ad 2571 if (ingres_errno) return(sms_errcode);
822a6eba 2572 if (rowcount != 1)
2573 return(SMS_INTERNAL);
2574 set_pop_usage(mid, 1);
2575 com_err(whoami, 0, "set login name to %s and pobox to %s", login,
711660a5 2576 strtrim(machname));
2577 incremental_after("users", buffer, 0);
822a6eba 2578
2579 /* create group list */
2580 if (set_next_object_id("gid", "list"))
44bd6f44 2581 return(SMS_NO_ID);
822a6eba 2582 if (set_next_object_id("list_id", "list"))
44bd6f44 2583 return(SMS_NO_ID);
822a6eba 2584## repeat retrieve (list_id = values.value) where values.name = "list_id"
02ccf7ad 2585 if (ingres_errno) return(sms_errcode);
8ac9ee7a 2586## inquire_equel(rowcount = "rowcount");
822a6eba 2587 if (rowcount != 1)
2588 return(SMS_INTERNAL);
711660a5 2589 incremental_clear_before();
822a6eba 2590## repeat append list (name = @login, #list_id = @list_id, active = 1,
2591## public = 0, hidden = 0, maillist = 0, group = 1,
2592## #gid = values.value, desc = "User Group",
2593## acl_type = "USER", acl_id = @users_id, modtime = "now",
2594## modby = @who, modwith = @entity)
2595## where values.name = "gid"
02ccf7ad 2596 if (ingres_errno) return(sms_errcode);
8ac9ee7a 2597## inquire_equel(rowcount = "rowcount");
44bd6f44 2598 if (rowcount != 1)
2599 return(SMS_INTERNAL);
711660a5 2600 sprintf(buffer, "l.list_id = %d", list_id);
2601 incremental_after("list", buffer, 0);
2602 aargv[0] = (char *) list_id;
2603 aargv[1] = "USER";
2604 aargv[2] = (char *) users_id;
2605 incremental_clear_before();
a6683dad 2606## repeat append imembers (#list_id = @list_id, member_type = "USER",
2607## member_id = @users_id, ref_count = 1, direct = 1)
02ccf7ad 2608 if (ingres_errno) return(sms_errcode);
8ac9ee7a 2609## inquire_equel(rowcount = "rowcount");
822a6eba 2610 if (rowcount != 1)
2611 return(SMS_INTERNAL);
60610bc7 2612 incremental_after("members", 0, aargv);
822a6eba 2613 com_err(whoami, 0, "group list created");
2614
2615 /* decide where to put filesystem */
2616 maxsize = 0;
2617 directory = NULL;
2618## repeat retrieve (mid = n.mach_id, dir = trim(n.#dir), nid = n.nfsphys_id,
2619## flag = n.status, size = n.#size, alloc = n.allocated) {
2620 if ((flag & utype) && (size != 0) && (size - alloc > maxsize)) {
2621 maxsize = size - alloc;
2622 if (directory)
2623 free(directory);
2624 directory = strsave(dir);
2625 pid = nid;
2626 m_id = mid;
2627 }
a6cb4d4c 2628## }
02ccf7ad 2629 if (ingres_errno) return(sms_errcode);
822a6eba 2630 if (maxsize == 0)
44bd6f44 2631 return(SMS_NO_FILESYS);
822a6eba 2632
2633 /* create filesystem */
2634 if (set_next_object_id("filsys_id", "filesys"))
44bd6f44 2635 return(SMS_NO_ID);
711660a5 2636 incremental_clear_before();
822a6eba 2637## repeat append filesys (filsys_id = values.value, phys_id = @pid,
2638## label = @login, type = "NFS", mach_id = @m_id,
4f16dc86 2639## name = @directory + "/" + @login,
2640## mount = "/mit/" + @login,
822a6eba 2641## access = "w", comments = "User Locker",
2642## owner = @users_id, owners = @list_id, createflg = 1,
2643## lockertype = "HOMEDIR", modtime = "now",
2644## modby = @who, modwith = @entity)
2645## where values.name = "filsys_id"
02ccf7ad 2646 if (ingres_errno) return(sms_errcode);
8ac9ee7a 2647## inquire_equel(rowcount = "rowcount");
822a6eba 2648 if (rowcount != 1)
2649 return(SMS_INTERNAL);
711660a5 2650 incremental_after("filesys",
2651 "fs.filsys_id = values.value and values.name = \"filsys_id\"",
2652 0);
822a6eba 2653 com_err(whoami, 0, "filesys created on mach %d in %s/%s", m_id,
4f16dc86 2654 directory, login);
822a6eba 2655
2656 /* set quota */
2657## repeat retrieve (quota = values.value) where values.name = "def_quota"
02ccf7ad 2658 if (ingres_errno) return(sms_errcode);
8ac9ee7a 2659## inquire_equel(rowcount = "rowcount");
822a6eba 2660 if (rowcount != 1)
44bd6f44 2661 return(SMS_NO_QUOTA);
711660a5 2662 incremental_clear_before();
822a6eba 2663## repeat append nfsquota (#users_id = @users_id, filsys_id = values.value,
e7fa3293 2664## #quota = @quota, phys_id = @pid, modtime = "now",
2665## modby = @who, modwith = @entity)
822a6eba 2666## where values.name = "filsys_id"
02ccf7ad 2667 if (ingres_errno) return(sms_errcode);
8ac9ee7a 2668## inquire_equel(rowcount = "rowcount");
822a6eba 2669 if (rowcount != 1)
2670 return(SMS_INTERNAL);
2671## repeat replace nfsphys (allocated = nfsphys.allocated + @quota)
2672## where nfsphys.nfsphys_id = filesys.#phys_id and
2673## filesys.filsys_id = values.value and values.name = "filsys_id"
02ccf7ad 2674 if (ingres_errno) return(sms_errcode);
8ac9ee7a 2675## inquire_equel(rowcount = "rowcount");
822a6eba 2676 if (rowcount != 1)
2677 return(SMS_INTERNAL);
711660a5 2678 aargv[0] = login;
2679 aargv[1] = login;
2680 sprintf(buffer, "nq.users_id = %d and nq.filsys_id = values.value and values.name = \"filsys_id\"", users_id);
60610bc7 2681 incremental_after("nfsquota", buffer, aargv);
822a6eba 2682 com_err(whoami, 0, "quota of %d assigned", quota);
02ccf7ad 2683 if (ingres_errno) return(sms_errcode);
822a6eba 2684
4f16dc86 2685## repeat replace tblstats (updates = tblstats.updates + 1, modtime = "now")
2686## where tblstats.table = "users"
2687## repeat replace tblstats (appends = tblstats.appends + 1, modtime = "now")
2688## where tblstats.table = "list" or tblstats.table = "filesys" or
2689## tblstats.table = "nfsquota"
02ccf7ad 2690 if (ingres_errno) return(sms_errcode);
822a6eba 2691 return(SMS_SUCCESS);
2692##}
2693
2694
2695
2696/** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
2697 **
2698 ** Inputs:
2699 ** id of machine
2700 ** delta (will be +/- 1)
2701 **
2702 ** Description:
2703 ** - incr/decr value field in serverhosts table for pop/mach_id
2704 **
2705 **/
2706
2707static int set_pop_usage(id, count)
2708int id;
2709int count;
2710##{
2711## int mach_id = id;
2712## int n = count;
2713
2714## range of sh is serverhosts
2715## repeat replace sh (value1 = sh.value1 + @n)
44bd6f44 2716## where sh.service = "POP" and sh.#mach_id = @mach_id
a6cb4d4c 2717
02ccf7ad 2718 if (ingres_errno) return(sms_errcode);
a6cb4d4c 2719 return(SMS_SUCCESS);
2720##}
822a6eba 2721
2722
c2408bd5 2723\f
05cdd922 2724/* Validation Routines */
2725
2726validate_row(q, argv, v)
2727 register struct query *q;
2728 char *argv[];
2729 register struct validate *v;
2730##{
2731## char *rvar;
2732## char *table;
2733## char *name;
2734## char qual[128];
2735## int rowcount;
2736
2737 /* build where clause */
2738 build_qual(v->qual, v->argc, argv, qual);
2739
2740 /* setup ingres variables */
2741 rvar = q->rvar;
2742 table = q->rtable;
2743 name = v->field;
2744
6388c51a 2745 if (log_flags & LOG_VALID)
b4182127 2746 /* tell the logfile what we're doing */
2747 com_err(whoami, 0, "validating row: %s", qual);
2748
05cdd922 2749 /* look for the record */
2750## range of rvar is table
2751## retrieve (rowcount = count(rvar.name where qual))
e1795ce1 2752 if (ingres_errno) return(sms_errcode);
05cdd922 2753 if (rowcount == 0) return(SMS_NO_MATCH);
2754 if (rowcount > 1) return(SMS_NOT_UNIQUE);
2755 return(SMS_EXISTS);
2756##}
2757
2758validate_fields(q, argv, vo, n)
2759 struct query *q;
2760 register char *argv[];
2761 register struct valobj *vo;
2762 register int n;
2763{
2764 register int status;
05cdd922 2765
2766 while (--n >= 0) {
2767 switch (vo->type) {
2768 case V_NAME:
6388c51a 2769 if (log_flags & LOG_VALID)
b4182127 2770 com_err(whoami, 0, "validating %s in %s: %s",
05cdd922 2771 vo->namefield, vo->table, argv[vo->index]);
05cdd922 2772 status = validate_name(argv, vo);
2773 break;
2774
2775 case V_ID:
6388c51a 2776 if (log_flags & LOG_VALID)
b4182127 2777 com_err(whoami, 0, "validating %s in %s: %s",
05cdd922 2778 vo->idfield, vo->table, argv[vo->index]);
05cdd922 2779 status = validate_id(argv, vo);
2780 break;
2781
92a943d6 2782 case V_DATE:
6388c51a 2783 if (log_flags & LOG_VALID)
92a943d6 2784 com_err(whoami, 0, "validating date: %s", argv[vo->index]);
2785 status = validate_date(argv, vo);
2786 break;
2787
05cdd922 2788 case V_TYPE:
6388c51a 2789 if (log_flags & LOG_VALID)
b4182127 2790 com_err(whoami, 0, "validating %s type: %s",
05cdd922 2791 vo->table, argv[vo->index]);
05cdd922 2792 status = validate_type(argv, vo);
2793 break;
2794
2795 case V_TYPEDATA:
6388c51a 2796 if (log_flags & LOG_VALID)
92a943d6 2797 com_err(whoami, 0, "validating typed data (%s): %s",
2798 argv[vo->index - 1], argv[vo->index]);
05cdd922 2799 status = validate_typedata(q, argv, vo);
2800 break;
2801
822a6eba 2802 case V_RENAME:
6388c51a 2803 if (log_flags & LOG_VALID)
822a6eba 2804 com_err(whoami, 0, "validating rename %s in %s",
2805 argv[vo->index], vo->table);
2806 status = validate_rename(argv, vo);
2807 break;
2808
2809 case V_CHAR:
6388c51a 2810 if (log_flags & LOG_VALID)
822a6eba 2811 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
2812 status = validate_chars(argv[vo->index]);
05cdd922 2813 break;
2814
92a943d6 2815 case V_SORT:
2816 status = SMS_EXISTS;
2817 break;
2818
e1795ce1 2819 case V_LOCK:
2820 status = lock_table(vo);
2821 break;
05cdd922 2822 }
2823
2824 if (status != SMS_EXISTS) return(status);
2825 vo++;
2826 }
2827
02ccf7ad 2828 if (ingres_errno) return(sms_errcode);
05cdd922 2829 return(SMS_SUCCESS);
2830}
2831
822a6eba 2832
2833/* validate_chars: verify that there are no illegal characters in
2834 * the string. Legal characters are printing chars other than
331b982e 2835 * ", *, ?, \, [ and ].
822a6eba 2836 */
2837static int illegalchars[] = {
2838 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2839 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2840 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
2841 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
2842 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
331b982e 2843 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
822a6eba 2844 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2845 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
2846 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2847 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2848 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2849 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2850 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2851 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2852 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2853 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2854};
2855
2856validate_chars(s)
2857register char *s;
2858{
2859 while (*s)
2860 if (illegalchars[*s++])
2861 return(SMS_BAD_CHAR);
2862 return(SMS_EXISTS);
2863}
2864
2865
05cdd922 2866validate_id(argv, vo)
2867 char *argv[];
2868 register struct valobj *vo;
2869##{
2870## char *name;
2871## char *table;
2872## char *namefield;
2873## char *idfield;
2874## int id;
2875## int rowcount;
122ec372 2876 register char *c;
05cdd922 2877
2878 name = argv[vo->index];
2879 table = vo->table;
122ec372 2880 /* minor kludge to upcasify machine names */
822a6eba 2881 if (!strcmp(table, "machine"))
122ec372 2882 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
05cdd922 2883 namefield = vo->namefield;
2884 idfield = vo->idfield;
822a6eba 2885 if (!strcmp(namefield, "uid")) {
9119288e 2886## retrieve (id = table.idfield) where table.namefield = int4(name)
e1795ce1 2887 if (ingres_errno) return(sms_errcode);
9119288e 2888## inquire_equel (rowcount = "rowcount")
2889 } else {
2890## retrieve (id = table.idfield) where table.namefield = name
e1795ce1 2891 if (ingres_errno) return(sms_errcode);
9119288e 2892## inquire_equel (rowcount = "rowcount")
2893 }
05cdd922 2894 if (rowcount != 1) return(vo->error);
2895 *(int *)argv[vo->index] = id;
2896 return(SMS_EXISTS);
2897##}
2898
2899validate_name(argv, vo)
2900 char *argv[];
2901 register struct valobj *vo;
2902##{
2903## char *name;
2904## char *table;
2905## char *namefield;
2906## int rowcount;
44bd6f44 2907 register char *c;
05cdd922 2908
2909 name = argv[vo->index];
2910 table = vo->table;
2911 namefield = vo->namefield;
44bd6f44 2912 if (!strcmp(table, "servers") && !strcmp(namefield, "name")) {
2913 for (c = name; *c; c++)
2914 if (islower(*c))
2915 *c = toupper(*c);
2916 }
05cdd922 2917## retrieve (rowcount = countu(table.namefield
2918## where table.namefield = name))
e1795ce1 2919 if (ingres_errno) return(sms_errcode);
05cdd922 2920 return ((rowcount == 1) ? SMS_EXISTS : vo->error);
2921##}
2922
92a943d6 2923validate_date(argv, vo)
2924 char *argv[];
2925 struct valobj *vo;
2926##{
2927## char *idate;
2928## double dd;
2929## int errorno;
2930
2931 idate = argv[vo->index];
2932
2933## retrieve (dd = interval("years", date(idate) - date("today")))
2934## inquire_equel (errorno = "errorno")
2935 if (errorno != 0 || dd > 5.0) return(SMS_DATE);
44bd6f44 2936 return(SMS_EXISTS);
92a943d6 2937##}
2938
822a6eba 2939
2940validate_rename(argv, vo)
2941char *argv[];
2942struct valobj *vo;
2943##{
2944## char *name, *table, *namefield, *idfield;
2945## int id;
2946 register char *c;
2947
2948 c = name = argv[vo->index];
2949 while (*c)
2950 if (illegalchars[*c++])
2951 return(SMS_BAD_CHAR);
2952 table = vo->table;
2953 /* minor kludge to upcasify machine names */
2954 if (!strcmp(table, "machine"))
2955 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
2956 namefield = vo->namefield;
2957 idfield = vo->idfield;
2958 id = -1;
2959 if (idfield == 0) {
2960 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
2961 return(SMS_EXISTS);
2962## retrieve (id = any(table.namefield where table.namefield = name))
e1795ce1 2963 if (ingres_errno) return(sms_errcode);
822a6eba 2964 if (id)
2965 return(vo->error);
2966 else
2967 return(SMS_EXISTS);
2968 }
2969## retrieve (id = table.idfield) where table.namefield = name
e1795ce1 2970 if (ingres_errno) return(sms_errcode);
822a6eba 2971 if (id == -1 || id == *(int *)argv[vo->index - 1])
2972 return(SMS_EXISTS);
2973 else
2974 return(vo->error);
2975##}
2976
2977
05cdd922 2978validate_type(argv, vo)
2979 char *argv[];
2980 register struct valobj *vo;
2981##{
2982## char *typename;
2983## char *value;
822a6eba 2984## int exists;
05cdd922 2985 register char *c;
2986
2987 typename = vo->table;
822a6eba 2988 c = value = argv[vo->index];
2989 while (*c)
2990 if (illegalchars[*c++])
2991 return(SMS_BAD_CHAR);
05cdd922 2992
2993 /* uppercase type fields */
2994 for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
2995
2996## range of a is alias
822a6eba 2997## repeat retrieve (exists = any(a.trans where a.name = @typename and
05cdd922 2998## a.type = "TYPE" and
2999## a.trans = @value))
e1795ce1 3000 if (ingres_errno) return(sms_errcode);
822a6eba 3001 return (exists ? SMS_EXISTS : vo->error);
05cdd922 3002##}
3003
3004/* validate member or type-specific data field */
3005
3006validate_typedata(q, argv, vo)
3007 register struct query *q;
3008 register char *argv[];
3009 register struct valobj *vo;
3010##{
3011## char *name;
3012## char *field_type;
822a6eba 3013## char data_type[129];
05cdd922 3014## int id;
05cdd922 3015## int rowcount;
822a6eba 3016 char *index();
a6cb4d4c 3017 register char *c;
05cdd922 3018
3019 /* get named object */
3020 name = argv[vo->index];
3021
3022 /* get field type string (known to be at index-1) */
3023 field_type = argv[vo->index-1];
3024
3025 /* get corresponding data type associated with field type name */
3026## repeat retrieve (data_type = alias.trans)
3027## where alias.#name = @field_type and alias.type = "TYPEDATA"
e1795ce1 3028 if (ingres_errno) return(sms_errcode);
05cdd922 3029## inquire_equel (rowcount = "rowcount")
3030 if (rowcount != 1) return(SMS_TYPE);
3031
3032 /* now retrieve the record id corresponding to the named object */
822a6eba 3033 if (index(data_type, ' '))
3034 *index(data_type, ' ') = 0;
05cdd922 3035 if (!strcmp(data_type, "user")) {
3036 /* USER */
3037## repeat retrieve (id = users.users_id) where users.login = @name
3038## inquire_equel (rowcount = "rowcount")
3039 if (rowcount != 1) return(SMS_USER);
3040
3041 } else if (!strcmp(data_type, "list")) {
3042 /* LIST */
3043## repeat retrieve (id = list.list_id) where list.#name = @name
3044## inquire_equel (rowcount = "rowcount")
822a6eba 3045 if (rowcount != 1) {
3046 /* if idfield is non-zero, then if argv[0] matches the string
3047 * that we're trying to resolve, we should get the value of
3048 * values.[idfield] for the id.
3049 */
3050 if (vo->idfield && !strcmp(argv[0], argv[vo->index])) {
4f16dc86 3051 set_next_object_id(q->validate->object_id, q->rtable);
822a6eba 3052 name = vo->idfield;
4f16dc86 3053## repeat retrieve (id = values.value) where values.#name = @name
822a6eba 3054## inquire_equel(rowcount = "rowcount")
3055 if (rowcount != 1) return(SMS_LIST);
3056 } else
3057 return(SMS_LIST);
3058 }
05cdd922 3059 } else if (!strcmp(data_type, "machine")) {
3060 /* MACHINE */
a6cb4d4c 3061 for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c);
05cdd922 3062## repeat retrieve (id = machine.mach_id) where machine.#name = @name
3063## inquire_equel (rowcount = "rowcount")
3064 if (rowcount != 1) return(SMS_MACHINE);
3065
3066 } else if (!strcmp(data_type, "string")) {
3067 /* STRING */
3068## range of s is strings
822a6eba 3069## repeat retrieve (id = s.string_id) where s.string = @name
05cdd922 3070## inquire_equel (rowcount = "rowcount")
3071 if (rowcount == 0) {
49189928 3072 if (q->type != APPEND && q->type != UPDATE) return(SMS_STRING);
05cdd922 3073## range of v is values
3074## retrieve (id = v.value) where v.#name = "strings_id"
3075 id++;
3076## replace v (value = id) where v.#name = "strings_id"
822a6eba 3077## append to strings (string_id = id, string = name)
05cdd922 3078 }
822a6eba 3079 } else if (!strcmp(data_type, "none")) {
3080 id = 0;
05cdd922 3081 } else {
3082 return(SMS_TYPE);
3083 }
3084
3085 /* now set value in argv */
3086 *(int *)argv[vo->index] = id;
3087
3088 return (SMS_EXISTS);
3089##}
3090
05cdd922 3091
e1795ce1 3092/* Lock the table named by the validation object */
3093
3094lock_table(vo)
3095struct valobj *vo;
3096##{
3097## char *table, *idfield;
3098## int rowcount;
3099
3100 table = vo->table;
3101 idfield = vo->idfield;
3102## replace table (modtime = "now") where table.idfield = 0
3103 if (ingres_errno) return(sms_errcode);
3104## inquire_equel (rowcount = "rowcount")
3105 if (rowcount != 1)
3106 return(vo->error);
3107 else
3108 return(SMS_EXISTS);
3109##}
3110
3111
822a6eba 3112/* Check the database at startup time. For now this just resets the
3113 * inprogress flags that the DCM uses.
3114 */
05cdd922 3115
822a6eba 3116sanity_check_database()
3117##{
05cdd922 3118##}
This page took 0.649082 seconds and 5 git commands to generate.