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