]> andersk Git - moira.git/blob - server/qoldsup.qc
Initial revision
[moira.git] / server / qoldsup.qc
1 /*
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.
5  *
6  *      $Source$
7  *      $Author$
8  *      $Header$
9  *
10  *      Copyright (C) 1987 by the Massachusetts Institute of Technology
11  *
12  */
13
14 #ifndef lint
15 static char *rcsid_qsupport_qc = "$Header$";
16 #endif lint
17
18 #include "query.h"
19 #include "sms_server.h"
20 #include <ctype.h>
21
22
23 extern char *whoami;
24
25
26 add_locker() { return(SMS_UNKNOWN_PROC); }
27 add_user_group() { return(SMS_UNKNOWN_PROC); }
28
29
30 /* Specialized Access Routines */
31
32
33 /**
34  ** access_maillist - access_list + disallow adding user-group to maillists
35  **
36  ** Inputs:
37  **   argv[0] - list_id
38  **   cl - client name
39  **
40  **/
41
42 access_maillist(q, argv, cl)
43     struct query *q;
44     char *argv[];
45     client *cl;
46 ##{
47 ##  int list_id;
48 ##  int exists;
49 ##  char list_name[32];
50     int status;
51
52     if ((status = access_list(q, argv, cl)) != SMS_SUCCESS)
53         return(status);
54     if (strcmp(q->name, "add_maillist"))
55         return(status);
56
57     list_id = *(int *)argv[0];
58 ##  range of l is list
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);
65 ##}
66
67
68 \f
69 /* Setup Routines */
70
71
72 \f
73 /* FOLLOWUP ROUTINES */
74
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.
77  *
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
81  * are skipped.
82  *
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
85  * the same.
86  */
87
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)();
93     int actarg;
94     client *cl;
95 ##{
96     char **argv, *p, *index();
97     char *ptype;
98 ##  char mach[129], box[129];
99 ##  int id, rowcount;
100
101     /* for each row */
102     while (sq_get_data(sq, &argv)) {
103         ptype = argv[1];
104         sms_trim_args(2, argv);
105
106         if (!strcmp(ptype, "POP")) {
107             id = atoi(argv[2]);
108 ##          repeat retrieve (mach=machine.name) where machine.mach_id=@id
109             strcpy(box, argv[0]);
110         } else if (!strcmp(ptype, "SMTP")) {
111             id = atoi(argv[3]);
112 ##          repeat retrieve (box=strings.string) where strings.string_id=@id
113 ##          inquire_equel(rowcount = "rowcount")
114             if (rowcount != 1)
115                 return(SMS_STRING);
116             p = index(box, '@');
117             if (p) {
118                 *p++ = 0;
119                 strcpy(mach, p);
120             } else
121                 strcpy(mach, "");
122         } else /* ptype == "NONE" */ {
123             goto skip;
124         }
125
126         free(argv[2]);
127         argv[2] = mach;
128         free(argv[3]);
129         argv[3] = box;
130         (*action)(q->vcnt, argv, actarg);
131     skip:
132         /* free saved data */
133         free(argv[0]);
134         free(argv[1]);
135         free(argv);
136     }
137
138     sq_destroy(sq);
139     return (SMS_SUCCESS);
140 ##}
141
142 \f
143 /* Specialized query routines */
144
145 /* set_user_pobox - this does all of the real work.
146  * argv = user_id, type, machine, box
147  */
148 int set_user_pobox(q, argv, cl)
149     struct query *q;
150     char **argv;
151     client *cl;
152 ##{
153 ##  int user, id, rowcount;
154 ##  char *host;
155 ##  char buffer[256];
156
157     host = argv[2];
158     user = *(int *)argv[0];
159
160     if (!strcmp(argv[1], "POP")) {
161 ##      repeat retrieve (id=machine.mach_id) where machine.name=uppercase(@host)
162 ##      inquire_equel(rowcount = "rowcount")
163         if (rowcount == 0)
164             return(SMS_MACHINE);
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")
171         if (rowcount == 0) {
172 ##          range of v is values
173 ##          repeat retrieve (id = v.value) where v.name = "strings_id"
174             id++;
175 ##          repeat replace v (value = @id) where v.name = "strings_id"
176 ##          append to strings (string_id = id, string = buffer)
177         }
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
182     }
183     set_old_pop_usage(q, argv, 1);
184     set_pobox_modtime(q, argv, cl);
185     return(SMS_SUCCESS);
186 ##}
187
188 followup_delete_pobox(q, argv, cl)
189     struct query *q;
190     char *argv[];
191     client *cl;
192 {
193     set_old_pop_usage(q, argv, -1);
194     set_pobox_modtime(q, argv, cl);
195     return(SMS_SUCCESS);
196 }
197
198 /** set_old_pop_usage - incr/decr usage count for pop server in serverhosts
199  ** table
200  **
201  ** Inputs:
202  **   q->name - "add_pobox" or "delete_pobox"
203  **   argv[1] - type
204  **   argv[2] - mach_id
205  **
206  ** Description:
207  **   - incr/decr value field in serverhosts table for pop/mach_id
208  **
209  **/
210
211 set_old_pop_usage(q, argv, count)
212     struct query *q;
213     char *argv[];
214 ##{
215 ##  int mach_id;
216 ##  int n;
217
218     if (bcmp(argv[1], "POP", 3)) return(SMS_SUCCESS);
219
220     mach_id = *(int *)argv[2];
221     n = count;
222
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
226
227     return(SMS_SUCCESS);
228 ##}
229
230
231 /* Finds "acl_type:acl_name" in the argv (index depends on query) and
232  * replaces it with the list or user name.
233  */
234
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)();
240     int actarg;
241     client *cl;
242 ##{
243     char **argv, *p, *index(), *malloc();
244 ##  char *name, *acl;
245 ##  int id, i, rowcount;
246     int idx;
247
248     if (!strcmp(q->shortname, "gaml"))
249         idx = 1;
250     else if (!strcmp(q->shortname, "gamd"))
251         idx = 1;
252     else
253         idx = 2;
254
255     while (sq_get_data(sq, &argv)) {
256         name = argv[idx];
257         p = index(name, ':');
258         *p++ = 0;
259         id = atoi(p);
260         if ((acl = malloc(33)) == NULL)
261             return(SMS_NO_MEM);
262         if (!strcmp(name, "LIST")) {
263 ##          repeat retrieve (acl = list.#name) where list.list_id = @id
264 ##          inquire_equel(rowcount = "rowcount")
265             if (rowcount != 1)
266                 strcpy(acl, "???");
267         } else if (!strcmp(name, "USER")) {
268 ##          repeat retrieve (acl = users.login) where users.users_id = @id
269 ##          inquire_equel(rowcount = "rowcount")
270             if (rowcount != 1)
271                 strcpy(acl, "???");
272         } else
273           strcpy(acl, "???");
274         free(argv[idx]);
275         argv[idx] = acl;
276
277         /* send the data */
278         (*action)(q->vcnt, argv, actarg);
279
280         /* free saved data */
281         for (i = 0; i < q->vcnt; i++) 
282             free(argv[i]);
283         free(argv);
284     }
285
286     sq_destroy(sq);
287     return (SMS_SUCCESS);
288 ##}
289
290
291 /**
292  ** get_list_is_group
293  ** get_list_is_maillist
294  **
295  ** Inputs:
296  **   argv[0] - list_id
297  **
298  ** Returns:
299  **   {true | false}
300  **
301  **/
302
303 get_list_is_group(q, argv, cl, action, actarg)
304     struct query *q;
305     char *argv[];
306     client *cl;
307     int (*action)();
308     int actarg;
309 ##{
310 ##  int exists, list_id, rowcount;
311     char *result;
312
313     list_id = *(int *)argv[0];
314
315 ##  range of l is list
316 ##  repeat retrieve (exists = l.group) where l.#list_id = @list_id
317 ##  inquire_equel(rowcount = "rowcount")
318     if (rowcount != 1)
319         return(SMS_NOT_UNIQUE);
320
321     result = (exists) ? "true" : "false";
322     (*action)(1, &result, actarg);
323     return(SMS_SUCCESS);
324 ##}
325
326 get_list_is_maillist(q, argv, cl, action, actarg)
327     struct query *q;
328     char *argv[];
329     client *cl;
330     int (*action)();
331     int actarg;
332 ##{
333 ##  int exists, list_id, rowcount;
334     char *result;
335
336     list_id = *(int *)argv[0];
337
338 ##  range of l is list
339 ##  repeat retrieve (exists = l.maillist) where l.#list_id = @list_id
340 ##  inquire_equel(rowcount = "rowcount")
341     if (rowcount != 1)
342         return(SMS_NOT_UNIQUE);
343
344     result = (exists) ? "true" : "false";
345     (*action)(1, &result, actarg);
346     return(SMS_SUCCESS);
347 ##}
348
349
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.
355  */
356
357 get_lists_of_administrator(q, argv, cl, action, actarg)
358     struct query *q;
359     char *argv[];
360     client *cl;
361     int (*action)();
362     int actarg;
363 ##{
364 ##  int user;
365 ##  char name[33];
366     char *args;
367
368 ##  range of l is list
369 ##  range of m is members
370     user  = *(int *) argv[0];
371     args = name;
372
373 ##  repeat retrieve (name = l.#name) 
374 ##      where l.acl_type = "USER" and l.acl_id = @user {
375             (*action)(1, &args, actarg);
376 ##  }
377
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);
382 ##  }
383     return(SMS_SUCCESS);
384 ##}
385
386
387 /**
388  ** Setup routine for add_group
389  **
390  ** Inputs: none
391  **
392  ** Description: allocate next gid and store in values table
393  **
394  **/
395
396 setup_add_group(q, argv, cl)
397     struct query *q;
398     char *argv[];
399     client *cl;
400 ##{
401 ##  int ngid, exists, rowcount, list_id;
402     int status;
403
404 ##  range of l is list
405 ##  range of v is values
406     list_id = *(int *)argv[0];
407
408 ##  repeat retrieve (exists = l.group) where l.#list_id = @list_id
409     if (exists)
410         return(SMS_EXISTS);
411
412 ##  repeat retrieve (ngid = v.value) where v.name = "gid"
413     exists = 1;
414     while (exists) {
415         ngid++;
416 ##      repeat retrieve (exists = any(l.#gid where l.#gid = @ngid))
417     }
418
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);
423 ##}
424
425 /**
426  ** get_groups_of_user - optimized query for retrieval of all groups to
427  **                      which a user belongs
428  **
429  **/
430
431 get_groups_of_user(q, argv, cl, action, actarg)
432     struct query *q;
433     char *argv[];
434     client *cl;
435     int (*action)();
436     int actarg;
437 ##{
438 ##  int users_id;
439 ##  char list_name[33];
440 ##  char gid[11];
441 ##  int rowcount;
442     char *targv[2];
443
444     users_id = *(int *)argv[0];
445     targv[0] = list_name;
446     targv[1] = gid;
447
448 ##  range of m is members
449 ##  range of l is list
450
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
455 ##  {
456          (*action)(2, targv, actarg);
457 ##  }
458 ##  inquire_equel (rowcount = "rowcount")
459
460     return ((rowcount = 0) ? SMS_NO_MATCH : SMS_SUCCESS);
461 ##}
462
463 get_groups_of_all_users(q, argv, cl, action, actarg)
464     struct query *q;
465     char *argv[];
466     client *cl;
467     int (*action)();
468     int actarg;
469 ##{
470 ##  char login[9];
471 ##  char group[33];
472 ##  char gid[11];
473     char *targv[3];
474 ##  int errorno;
475
476     targv[0] = login;
477     targv[1] = group;
478     targv[2] = gid;
479
480 ##  range of u is users
481 ##  range of l is list
482 ##  range of m is members
483
484 ##  set lockmode session where readlock = nolock
485
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
490 ##  {
491          (*action)(3, targv, actarg);
492 ##  }
493
494 ##  inquire_equel (errorno = "errorno")
495 ##  set lockmode session where readlock = system
496
497     return((errorno) ? SMS_INGRES_ERR : SMS_SUCCESS);
498 ##}
499
500
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.
504  */
505 expand_list_flags(q, argv, cl)
506     struct query *q;
507     char **argv;
508     client *cl;
509 ##{
510 ##  int id, flags, active, public, hidden, who;
511 ##  char *entity;
512
513     if (!strcmp(q->shortname, "ulis")) {
514         id = *(int *)argv[0];
515     } else {
516 ##    repeat retrieve (id = values.value) where values.name = "list_id"
517     }
518
519 ##  repeat retrieve (flags = l.#active) where l.list_id = @id
520     active = flags & 1;
521     public = (flags & 2) >> 1;
522     hidden = (flags & 4) >> 2;
523     entity = cl->entity;
524     who = cl->users_id;
525 ##  repeat replace l (#active = @active, #public = @public, #hidden = @hidden,
526 ##      modtime = "now", modby = @who, modwith = @entity)
527 ##       where l.list_id = @id
528     return(SMS_SUCCESS);
529 ##}
530
531
532 /**
533  ** add_new_quota
534  ** delete_current_quota - adjust nfsphys values on xxx_quota queries.
535  **
536  ** Inputs:
537  **   argv[0] - mach_id
538  **   argv[1] - device
539  **   argv[2] - users_id
540  **   argv[3] - quota (add_new_quota only)
541  **
542  ** Description:
543  **   delete_current_quota:
544  **     - find nfsquota entry
545  **     - decrement nfsphys.allocated by nfsquota.quota
546  **   add_new_quota
547  **     - increment nfsphys.allocated by quota
548  **
549  **/
550
551 add_new_quota(q, argv, cl)
552     struct query *q;
553     register char *argv[];
554     client *cl;
555 ##{
556 ##  int mach_id;
557 ##  char *device;
558 ##  int quota;
559
560     mach_id = *(int*)argv[0];
561     device = argv[1];
562     quota = *(int *)argv[3];
563
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
567
568     return(SMS_SUCCESS);
569 ##}
570
571 delete_current_quota(q, argv, cl)
572     struct query *q;
573     register char *argv[];
574     client *cl;
575 ##{
576 ##  int mach_id;
577 ##  int users_id;
578 ##  char *device;
579 ##  int quota;
580
581     mach_id = *(int *)argv[0];
582     device = argv[1];
583     users_id = *(int *)argv[2];
584
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
592  
593     return(SMS_SUCCESS);
594 ##}
595
596
597 /**
598  ** delete_locker - special query routine for deleting a user locker
599  **
600  ** Inputs:
601  **   argv[0] - users_id
602  ** 
603  ** Description:
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
611  **
612  ** Errors:
613  **   - SMS_FILESYS - no filesys exists for user
614  ** 
615  **/
616
617 delete_locker(q, argv)
618     register struct query *q;
619     register char *argv[];
620 ##{
621 ##  int users_id;
622 ##  int mach_id;
623 ##  int quota;
624 ##  int rowcount;
625 ##  char login[9];
626 ##  char lname[64];
627 ##  char ndev[32];
628     char *rindex();
629     register char *c;
630
631     /* copy arguments */
632     users_id = *(int *)argv[0];
633
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
639
640     /* get login name */
641 ##  repeat retrieve (login = u.#login) where u.#users_id = @users_id
642
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
649
650     /* get prefix directory */
651     c = rindex(lname, '/');
652     *c = 0;
653
654     /* get nfs device */
655 ##  repeat retrieve (ndev = np.device) 
656 ##         where np.#mach_id = @mach_id and np.dir = @lname
657
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
664
665     /* decrement nfsphys.allocated */
666 ##  repeat replace np (allocated = np.allocated - @quota)
667 ##         where np.#mach_id = @mach_id and np.#device = @ndev
668
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"
676
677     return(SMS_SUCCESS);
678 ##}
This page took 0.094552 seconds and 5 git commands to generate.