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