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