2 * These are query support routines that are specific to the old version
3 * of the protocol. This file may be removed once support for the old
4 * protocol has been discontinued.
10 * Copyright (C) 1987 by the Massachusetts Institute of Technology
15 static char *rcsid_qsupport_qc = "$Header$";
19 #include "sms_server.h"
26 add_locker() { return(SMS_UNKNOWN_PROC); }
27 add_user_group() { return(SMS_UNKNOWN_PROC); }
30 /* Specialized Access Routines */
34 ** access_maillist - access_list + disallow adding user-group to maillists
42 access_maillist(q, argv, cl)
49 ## char list_name[32];
52 if ((status = access_list(q, argv, cl)) != SMS_SUCCESS)
54 if (strcmp(q->name, "add_maillist"))
57 list_id = *(int *)argv[0];
59 ## repeat retrieve (exists = any(l.#list_id
60 ## where l.group != 0 and l.#list_id = @list_id))
61 if (!exists) return(SMS_SUCCESS);
62 ## repeat retrieve (exists = any(users.login where users.login = l.name and
63 ## l.#list_id = @list_id))
64 return ((exists) ? SMS_USER_GROUP : SMS_SUCCESS);
73 /* FOLLOWUP ROUTINES */
75 /* followup_gpob: fixes argv[2] based on the IDs currently there and the
76 * type in argv[1]. Then completes the upcall to the user.
78 * argv[2] is of the form "123:234" where the first integer is the machine
79 * ID if it is a pop box, and the second is the string ID if it is an SMTP
80 * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE
83 * followup_old_gpob does the same thing for old style queries. The format
84 * is a little different and there is one more argument, but the idea is
88 followup_old_gpob(q, sq, v, action, actarg, cl)
89 register struct query *q;
90 register struct save_queue *sq;
91 register struct validate *v;
92 register int (*action)();
96 char **argv, *p, *index();
98 ## char mach[129], box[129];
102 while (sq_get_data(sq, &argv)) {
104 sms_trim_args(2, argv);
106 if (!strcmp(ptype, "POP")) {
108 ## repeat retrieve (mach=machine.name) where machine.mach_id=@id
109 strcpy(box, argv[0]);
110 } else if (!strcmp(ptype, "SMTP")) {
112 ## repeat retrieve (box=strings.string) where strings.string_id=@id
113 ## inquire_equel(rowcount = "rowcount")
122 } else /* ptype == "NONE" */ {
130 (*action)(q->vcnt, argv, actarg);
132 /* free saved data */
139 return (SMS_SUCCESS);
143 /* Specialized query routines */
145 /* set_user_pobox - this does all of the real work.
146 * argv = user_id, type, machine, box
148 int set_user_pobox(q, argv, cl)
153 ## int user, id, rowcount;
158 user = *(int *)argv[0];
160 if (!strcmp(argv[1], "POP")) {
161 ## repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@host)
162 ## inquire_equel(rowcount = "rowcount")
165 ## replace users (potype="POP", pop_id=id) where users.users_id = user
166 } else if (!strcmp(argv[1], "SMTP")) {
167 sprintf(buffer, "%s@%s", argv[3], host);
168 ## range of s is strings
169 ## repeat retrieve (id = s.string_id) where s.string = @buffer
170 ## inquire_equel (rowcount = "rowcount")
172 ## range of v is values
173 ## repeat retrieve (id = v.value) where v.name = "strings_id"
175 ## repeat replace v (value = @id) where v.name = "strings_id"
176 ## append to strings (string_id = id, string = buffer)
178 ## repeat replace users (potype="SMTP",box_id=@id)
179 ## where users.users_id = @user
180 } else /* argv[1] == "NONE" */ {
181 ## repeat replace users (potype="NONE") where users.users_id = @user
183 set_old_pop_usage(q, argv, 1);
184 set_pobox_modtime(q, argv, cl);
188 followup_delete_pobox(q, argv, cl)
193 set_old_pop_usage(q, argv, -1);
194 set_pobox_modtime(q, argv, cl);
198 /** set_old_pop_usage - incr/decr usage count for pop server in serverhosts
202 ** q->name - "add_pobox" or "delete_pobox"
207 ** - incr/decr value field in serverhosts table for pop/mach_id
211 set_old_pop_usage(q, argv, count)
218 if (bcmp(argv[1], "POP", 3)) return(SMS_SUCCESS);
220 mach_id = *(int *)argv[2];
223 ## range of sh is serverhosts
224 ## repeat replace sh (value1 = sh.value1 + @n)
225 ## where sh.service = "pop" and sh.#mach_id = @mach_id
231 /* Finds "acl_type:acl_name" in the argv (index depends on query) and
232 * replaces it with the list or user name.
235 followup_fix_acl(q, sq, v, action, actarg, cl)
236 register struct query *q;
237 register struct save_queue *sq;
238 register struct validate *v;
239 register int (*action)();
243 char **argv, *p, *index(), *malloc();
245 ## int id, i, rowcount;
248 if (!strcmp(q->shortname, "gaml"))
250 else if (!strcmp(q->shortname, "gamd"))
255 while (sq_get_data(sq, &argv)) {
257 p = index(name, ':');
260 if ((acl = malloc(33)) == NULL)
262 if (!strcmp(name, "LIST")) {
263 ## repeat retrieve (acl = list.#name) where list.list_id = @id
264 ## inquire_equel(rowcount = "rowcount")
267 } else if (!strcmp(name, "USER")) {
268 ## repeat retrieve (acl = users.login) where users.users_id = @id
269 ## inquire_equel(rowcount = "rowcount")
278 (*action)(q->vcnt, argv, actarg);
280 /* free saved data */
281 for (i = 0; i < q->vcnt; i++)
287 return (SMS_SUCCESS);
293 ** get_list_is_maillist
303 get_list_is_group(q, argv, cl, action, actarg)
310 ## int exists, list_id, rowcount;
313 list_id = *(int *)argv[0];
315 ## range of l is list
316 ## repeat retrieve (exists = l.group) where l.#list_id = @list_id
317 ## inquire_equel(rowcount = "rowcount")
319 return(SMS_NOT_UNIQUE);
321 result = (exists) ? "true" : "false";
322 (*action)(1, &result, actarg);
326 get_list_is_maillist(q, argv, cl, action, actarg)
333 ## int exists, list_id, rowcount;
336 list_id = *(int *)argv[0];
338 ## range of l is list
339 ## repeat retrieve (exists = l.maillist) where l.#list_id = @list_id
340 ## inquire_equel(rowcount = "rowcount")
342 return(SMS_NOT_UNIQUE);
344 result = (exists) ? "true" : "false";
345 (*action)(1, &result, actarg);
350 /* implements the get lists of administrator query. It's fairly
351 * straightforward, but too complex for the regular query table.
352 * First retrieve any lists with a USER acl which matches the
353 * specified user. Then retrieve any lists with an acl which is a
354 * list which has the specified user as a member.
357 get_lists_of_administrator(q, argv, cl, action, actarg)
368 ## range of l is list
369 ## range of m is members
370 user = *(int *) argv[0];
373 ## repeat retrieve (name = l.#name)
374 ## where l.acl_type = "USER" and l.acl_id = @user {
375 (*action)(1, &args, actarg);
378 ## repeat retrieve (name = l.#name)
379 ## where l.acl_type = "LIST" and l.acl_id = m.#list_id
380 ## and m.member_type = "USER" and m.member_id = @user {
381 (*action)(1, &args, actarg);
388 ** Setup routine for add_group
392 ** Description: allocate next gid and store in values table
396 setup_add_group(q, argv, cl)
401 ## int ngid, exists, rowcount, list_id;
404 ## range of l is list
405 ## range of v is values
406 list_id = *(int *)argv[0];
408 ## repeat retrieve (exists = l.group) where l.#list_id = @list_id
412 ## repeat retrieve (ngid = v.value) where v.name = "gid"
416 ## repeat retrieve (exists = any(l.#gid where l.#gid = @ngid))
419 ## repeat replace v (value = @ngid) where v.name = "gid"
420 ## inquire_equel (rowcount = "rowcount")
421 if (rowcount != 1) return SMS_INGRES_ERR;
422 else return(SMS_SUCCESS);
426 ** get_groups_of_user - optimized query for retrieval of all groups to
427 ** which a user belongs
431 get_groups_of_user(q, argv, cl, action, actarg)
439 ## char list_name[33];
444 users_id = *(int *)argv[0];
445 targv[0] = list_name;
448 ## range of m is members
449 ## range of l is list
451 ## repeat retrieve (list_name = l.name, gid = text(l.#gid))
452 ## where m.member_id = @users_id and m.member_type = "USER" and
453 ## m.list_id = l.list_id and l.group != 0
454 ## sort by #list_name
456 (*action)(2, targv, actarg);
458 ## inquire_equel (rowcount = "rowcount")
460 return ((rowcount = 0) ? SMS_NO_MATCH : SMS_SUCCESS);
463 get_groups_of_all_users(q, argv, cl, action, actarg)
480 ## range of u is users
481 ## range of l is list
482 ## range of m is members
484 ## set lockmode session where readlock = nolock
486 ## repeat retrieve (login = u.#login, group = l.name, gid = text(l.#gid))
487 ## where m.member_type = "USER" and m.member_id = u.users_id and
488 ## u.status != 0 and m.list_id = l.list_id and l.group != 0
489 ## sort by #login, #group
491 (*action)(3, targv, actarg);
494 ## inquire_equel (errorno = "errorno")
495 ## set lockmode session where readlock = system
497 return((errorno) ? SMS_INGRES_ERR : SMS_SUCCESS);
501 /* expand_list_flags - takes the flag value stuffed into list.active of
502 * the list just created, and expands that value into hidden & public,
503 * then sets the modtime on the list.
505 expand_list_flags(q, argv, cl)
510 ## int id, flags, active, public, hidden, who;
513 if (!strcmp(q->shortname, "ulis")) {
514 id = *(int *)argv[0];
516 ## repeat retrieve (id = values.value) where values.name = "list_id"
519 ## repeat retrieve (flags = l.#active) where l.list_id = @id
521 public = (flags & 2) >> 1;
522 hidden = (flags & 4) >> 2;
525 ## repeat replace l (#active = @active, #public = @public, #hidden = @hidden,
526 ## modtime = "now", modby = @who, modwith = @entity)
527 ## where l.list_id = @id
534 ** delete_current_quota - adjust nfsphys values on xxx_quota queries.
539 ** argv[2] - users_id
540 ** argv[3] - quota (add_new_quota only)
543 ** delete_current_quota:
544 ** - find nfsquota entry
545 ** - decrement nfsphys.allocated by nfsquota.quota
547 ** - increment nfsphys.allocated by quota
551 add_new_quota(q, argv, cl)
553 register char *argv[];
560 mach_id = *(int*)argv[0];
562 quota = *(int *)argv[3];
564 ## range of np is nfsphys
565 ## repeat replace np (allocated = np.allocated + @quota)
566 ## where np.#mach_id = @mach_id and np.#device = @device
571 delete_current_quota(q, argv, cl)
573 register char *argv[];
581 mach_id = *(int *)argv[0];
583 users_id = *(int *)argv[2];
585 ## range of np is nfsphys
586 ## range of nq is nfsquota
587 ## repeat retrieve (quota = nq.#quota)
588 ## where nq.#mach_id = @mach_id and nq.#device = @device and
589 ## nq.#users_id = @users_id
590 ## repeat replace np (allocated = np.allocated - @quota)
591 ## where np.#mach_id = @mach_id and np.#device = @device
598 ** delete_locker - special query routine for deleting a user locker
601 ** argv[0] - users_id
604 ** - get login name from users_id
605 ** - get filesys entry from login
606 ** - use filesys.mach_id and filesys.name to determine machine/device
607 ** pair for nfsphys and nfsquota
608 ** - delete filesys entry (label=<login>)
609 ** - decrement allocated in nfsphys by quota
610 ** - delete nfsquota entry
613 ** - SMS_FILESYS - no filesys exists for user
617 delete_locker(q, argv)
618 register struct query *q;
619 register char *argv[];
632 users_id = *(int *)argv[0];
634 ## range of u is users
635 ## range of f is filesys
636 ## range of np is nfsphys
637 ## range of nq is nfsquota
638 ## range of tbs is tblstats
641 ## repeat retrieve (login = u.#login) where u.#users_id = @users_id
643 /* get mach_id and locker name from filesys entry; then delete it */
644 ## repeat retrieve (mach_id = f.#mach_id, lname = f.#name)
645 ## where f.#label = @login
646 ## inquire_equel (rowcount = "rowcount")
647 if (rowcount == 0) return(SMS_FILESYS);
648 ## repeat delete f where f.#label = @login
650 /* get prefix directory */
651 c = rindex(lname, '/');
655 ## repeat retrieve (ndev = np.device)
656 ## where np.#mach_id = @mach_id and np.dir = @lname
658 /* get quota from nfsquota entry; then delete entry */
659 ## repeat retrieve (quota = nq.#quota)
660 ## where nq.#mach_id = @mach_id and nq.#device = @ndev and
661 ## nq.#users_id = @users_id
662 ## repeat delete nq where nq.#mach_id = @mach_id and nq.#device = @ndev and
663 ## nq.#users_id = @users_id
665 /* decrement nfsphys.allocated */
666 ## repeat replace np (allocated = np.allocated - @quota)
667 ## where np.#mach_id = @mach_id and np.#device = @ndev
669 /* adjust table statistics */
670 ## repeat replace tbs (deletes = tbs.deletes + 1, modtime = "now")
671 ## where tbs.table = "filesys"
672 ## repeat replace tbs (updates = tbs.updates + 1, modtime = "now")
673 ## where tbs.table = "nfsphys"
674 ## repeat replace tbs (deletes = tbs.deletes + 1, modtime = "now")
675 ## where tbs.table = "nfsquota"