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