]> andersk Git - moira.git/blob - server/qsupport.qc
add Password_input
[moira.git] / server / qsupport.qc
1 /*
2  *      $Source$
3  *      $Author$
4  *      $Header$
5  *
6  *      Copyright (C) 1987 by the Massachusetts Institute of Technology
7  *
8  *      $Log$
9  *      Revision 1.7  1987-08-04 01:49:41  wesommer
10  *      Rearranged messages.
11  *
12 Revision 1.6  87/08/04  01:10:02  wesommer
13 Changes by mike; checked in prior to my hacking.
14
15 Revision 1.5  87/07/30  14:54:13  wesommer
16 Added debugging code in an attempt to catch a flakey problem.
17
18 Revision 1.4  87/07/30  00:30:21  wesommer
19 replaced appends = appends+1 with appends = tbs.appends+1
20
21 Revision 1.3  87/07/30  00:26:11  wesommer
22 Changes by mike prior to "appends" fix.
23
24 Revision 1.2  87/07/29  16:00:39  wesommer
25 Fixed add_locker.
26
27 Revision 1.1  87/07/29  15:13:57  wesommer
28 Initial revision
29
30  */
31
32 #ifndef lint
33 static char *rcsid_qsupport_qc = "$Header$";
34 #endif lint
35
36 #include "query.h"
37 #include "sms_server.h"
38 #include <ctype.h>
39
40 #define SMS_SUCCESS 0
41
42 extern char *whoami;
43
44 /* Specialized Access Routines */
45
46 /**
47  ** access_user - verify that client name equals specified login name
48  **
49  ** Used by: update_user_shell
50  **          update_finger_by_login
51  **
52  **  - since field validation routines are called first, a users_id is
53  **    now in argv[0] instead of the login name.  Therefore, we must 
54  **    convert the client name to a users_id.
55  **/
56
57 access_user(q, argv, cl)
58     struct query *q;
59     char *argv[];
60     client *cl;
61 ##{
62     register struct krbname *krb;
63 ##  int client_id;
64 ##  char *client_name;
65 ##  int rowcount;
66
67     client_name = cl->kname.name;
68 ##  repeat retrieve (client_id = users.users_id) 
69 ##         where users.login = @client_name
70 ##  inquire_equel (rowcount = "rowcount")
71     if (rowcount != 1) return(SMS_PERM);
72     if (client_id != *(int *)argv[0]) return(SMS_PERM);
73
74     return(SMS_SUCCESS);
75 ##}
76     
77 /**
78  ** access_pop - same as access_user plus verifies that a user has only one
79  **              mailbox of type "POP"
80  **
81  ** Inputs:
82  **   argv[0] - users_id
83  **   argv[1] - type
84  **   argv[2] - mach_id
85  **   argv[3] - box
86  **
87  ** Description:
88  **   - if q->name = "add_pobox" and type = "POP", 
89  **        verify that no POP box already exists for user
90  **   - call access_user
91  **
92  **/
93
94 access_pop(q, argv, cl)
95     struct query *q;
96     char *argv[];
97     client *cl;
98 ##{
99 ##  int users_id;
100 ##  int mach_id;
101 ##  char *box;
102 ##  int exists;
103
104     if (!bcmp(q->name, "add_pobox", 10) && !bcmp(argv[1], "POP", 4)) {
105         users_id = *(int *)argv[0];
106         mach_id = *(int *)argv[2];
107         box = argv[3];
108 ##      range of p is pobox
109 ##      repeat retrieve (exists = any(p.#box where p.#users_id = @users_id
110 ##                                    and p.type = "POP" 
111 ##                                    and p.#mach_id = @mach_id
112 ##                                    and p.#box = @box))
113         if (exists) return(SMS_EXISTS);
114     }
115
116     return(access_user(q, argv, cl));
117 ##}
118
119 /**
120  ** access_list - check access for adding or deleting list members
121  **
122  ** Inputs: argv[0] - list_id
123  **         cl->krb.name - client name
124  **
125  ** - check that client is a member of the access control list
126  ** - OR, if q->shortname == {amtl | dfml} and
127  **       if list.flags & LF_PUBLIC, allow access if client = member
128  **
129  **/ 
130
131 access_list(q, argv, cl)
132     struct query *q;
133     char *argv[];
134     client *cl;
135 ##{
136 ##  int list_id;
137 ##  int acl_id;
138 ##  int flags;
139     int member_id;
140     char *client_type;
141     int client_id;
142     int status;
143     int exists;
144
145     list_id = *(int *)argv[0];
146 ##  repeat retrieve (acl_id = list.#acl_id, flags = list.#flags) 
147 ##         where list.#list_id = @list_id
148
149     /* parse client structure */
150     status = get_client(cl, &client_type, &client_id);
151     if (status != SMS_SUCCESS) return(status);
152
153     /* if amtl or dmfl and list is public allow client to add or delete self */
154     if (!bcmp("amtl", q->shortname, 4) || !bcmp("dmfl", q->shortname, 4)) {
155         if ((flags & LF_PUBLIC) && !bcmp("USER", argv[1], 4)) {
156             member_id = *(int *)argv[2];
157             if (member_id == client_id) return(SMS_SUCCESS);
158         }
159     }
160
161     /* check for client in access control list */
162     exists = find_member(acl_id, client_type, client_id, 0);
163     if (!exists) return(SMS_PERM);
164
165     return(SMS_SUCCESS);
166 ##}
167 \f
168 /**
169  ** Setup routine for add_user
170  **
171  ** Inputs: argv[0] - login
172  **         argv[1] - uid
173  **
174  ** Description:
175  **
176  ** - if argv[1] == "#" then set argv[1] = next(uid)
177  ** - if argv[0] == "#" then set argv[0] = "#<uid>"
178  **
179  **/
180
181 setup_add_user(q, argv, cl, access_check)
182     struct query *q;
183     register char *argv[];
184     client *cl;
185     int access_check;
186 ##{
187 ##  int nuid;
188 ##  int exists;
189
190     if (access_check) return(SMS_SUCCESS);
191
192     if (!bcmp(argv[1], "#", 2)) {
193 ##      range of u is users
194 ##      range of v is values
195 ##      repeat retrieve (nuid = v.value) where v.name = "uid"
196         exists = 1;
197         while (exists) {
198             nuid++;
199 ##          repeat retrieve (exists = any(u.#uid where u.#uid = @nuid))
200         }
201 ##      repeat replace v (value = @nuid) where v.name = "uid"
202         sprintf(argv[1], "%d", nuid);
203     }
204
205     if (!bcmp(argv[0], "#", 2)) {
206         sprintf(argv[0], "#%s", argv[1]);
207     }
208
209     return(SMS_SUCCESS);
210 ##}
211
212 /**
213  ** Setup routine for add_group
214  **
215  ** Inputs: none
216  **
217  ** Description: allocate next gid and store in values table
218  **
219  **/
220
221 setup_add_group(q, argv, cl, access_check)
222     struct query *q;
223     char *argv[];
224     client *cl;
225     int access_check;
226 ##{
227 ##  int ngid;
228 ##  int exists;
229
230     if (access_check) return(SMS_SUCCESS);
231
232 ##  range of g is groups
233 ##  range of v is values
234 ##  repeat retrieve (ngid = v.value) where v.name = "gid"
235     exists = 1;
236     while (exists) {
237         ngid++;
238 ##      repeat retrieve (exists = any(g.#gid where g.#gid = @ngid))
239     }
240
241 ##  repeat replace v (value = @ngid) where v.name = "gid"
242     return(SMS_SUCCESS);
243 ##}
244 \f
245 /**
246  ** setup_add_filesys - verify existance of referenced file systems
247  ** setup_update_filesys - same, except argv[1..5] --> argv[2..6]
248  **
249  ** Inputs:     Add         Update
250  **   argv[0] - label       label
251  **   argv[1] - type        new label
252  **   argv[2] - mach_id     type
253  **   argv[3] - name        mach_id
254  **   argv[4] - mount       name
255  **   argv[5] - access      mount
256  **   argv[6] -             access
257  **
258  ** Description:
259  **   - for type = RVD:
260  **        * verify mach_id/name in rvdvirt
261  **        * verify access in {r, x, R, X}
262  **   - for type = NFS:
263  **        * extract directory prefix from name
264  **        * verify mach_id/dir in nfsphys
265  **        * verify access in {r, w, R, W}
266  **
267  ** Errors:
268  **   SMS_RVD - no such rvd
269  **   SMS_NFS - specified directory not exported
270  **   SMS_FILESYS_ACCESS - invalid filesys access
271  **
272  **/
273
274 setup_add_filesys(q, argv)
275     struct query *q;
276     char *argv[];
277 {
278     char *type;
279     int mach_id;
280     char *name;
281     char *access;  
282
283     type = argv[1];
284     mach_id = *(int *)argv[2];
285     name = argv[3];
286     access = argv[5];
287
288     if (!bcmp(type, "RVD", 3))
289         return (check_rvd(mach_id, name, access));
290     else if (!bcmp(type, "NFS", 3))
291         return (check_nfs(mach_id, name, access));
292     else
293         return(SMS_SUCCESS);
294 }
295
296 setup_update_filesys(q, argv)
297     struct query *q;
298     char *argv[];
299 {
300     char *type;
301     int mach_id;
302     char *name;
303     char *access;  
304
305     type = argv[2];
306     mach_id = *(int *)argv[3];
307     name = argv[4];
308     access = argv[6];
309
310     if (!bcmp(type, "RVD", 3))
311         return (check_rvd(mach_id, name, access));
312     else if (!bcmp(type, "NFS", 3))
313         return (check_nfs(mach_id, name, access));
314     else
315         return(SMS_SUCCESS);
316 }
317
318 ##check_rvd(mach_id, name, access)
319 ##  int mach_id;
320 ##  char *name;
321     char *access;
322 ##{
323 ##  int rowcount;
324     char caccess;
325
326 ##  range of rv is rvdvirt
327 ##  retrieve (rowcount = any(rv.#name where rv.#mach_id = mach_id and
328 ##                           rv.#name = name))
329     if (rowcount == 0) return(SMS_RVD);
330
331     caccess = (isupper(*access)) ? tolower(*access) : *access;
332     if (caccess != 'r' && caccess != 'x') return(SMS_FILESYS_ACCESS);
333
334     return(SMS_SUCCESS);
335 ##}
336
337 ##check_nfs(mach_id, name, access)
338 ##  int mach_id;
339     char *name;
340     char *access;
341 ##{
342 ##  int rowcount;
343 ##  char dir[32];
344     char caccess;
345     register char *cp1;
346     register char *cp2;
347
348     caccess = (isupper(*access)) ? tolower(*access) : *access;
349     if (caccess != 'r' && caccess != 'w') return(SMS_FILESYS_ACCESS);
350
351 ##  range of np is nfsphys
352 ##  retrieve (dir = np.#dir) where np.#mach_id = mach_id
353 ##  {
354          cp1 = name;
355          cp2 = dir;
356          while (*cp2) {
357              if (*cp1++ != *cp2) break;
358              cp2++;
359          }
360          if (*cp2 == 0) return(SMS_SUCCESS);
361 ##  }
362
363     return(SMS_NFS);
364 ##}
365 \f
366 /* Followup Routines */
367
368 set_user_modtime(q, argv)
369     struct query *q;
370     char *argv[];
371 ##{
372 ##  char *login;
373
374     login = argv[0];
375 ##  repeat replace u (modtime = "now") where u.#login = @login
376     return(SMS_SUCCESS);
377 ##}
378
379 set_user_modtime_by_id(q, argv)
380     struct query *q;
381     char *argv[];
382 ##{
383 ##  int users_id;
384
385     users_id = *(int *)argv[0];
386 ##  repeat replace users (modtime = "now") where users.#users_id = @users_id
387     return(SMS_SUCCESS);
388 ##}
389
390 set_list_modtime(q, argv)
391     struct query *q;
392     char *argv[];
393 ##{
394 ##  char *list_name;
395
396     list_name = argv[0];
397 ##  repeat replace list (modtime = "now") where list.name = @list_name
398     return(SMS_SUCCESS);
399 ##}
400
401 set_list_modtime_by_id(q, argv)
402     struct query *q;
403     char *argv[];
404 ##{
405 ##  int list_id;
406
407     list_id = *(int *)argv[0];
408 ##  repeat replace list (modtime = "now") where list.#list_id = @list_id
409     return(SMS_SUCCESS);
410 ##}
411
412 set_finger_modtime(q, argv)
413     struct query *q;
414     char *argv[];
415 ##{
416 ##  int users_id;
417
418     users_id = *(int *)argv[0];
419 ##  repeat replace f (modtime = "now") where f.#users_id = @users_id
420     return(SMS_SUCCESS);
421 ##}
422
423 /**
424  ** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe
425  **
426  ** Inputs:
427  **   q->name - "add_pobox" or "delete_pobox"
428  **   argv[2] - mach_id
429  **
430  ** Description:
431  **   - incr/decr value field in serverhosts table for pop/mach_id
432  **
433  **/
434
435 set_pop_usage(q, argv)
436     struct query *q;
437     char *argv[];
438 ##{
439 ##  int mach_id;
440
441     mach_id = *(int *)argv[2];
442 ##  range of sh is serverhosts
443
444     if (!bcmp(q->name, "add_pobox", 10)) {
445 ##      repeat replace sh (value1 = sh.value1 + 1)
446 ##             where sh.service = "pop" and sh.#mach_id = @mach_id
447     } else if (!bcmp(q->name, "delete_pobox", 13)) {
448 ##      repeat replace sh (value1 = sh.value1 - 1)
449 ##             where sh.service = "pop" and sh.#mach_id = @mach_id
450     }
451
452     return(SMS_SUCCESS);
453 ##}
454
455 /**
456  ** delete_list_members - called after the delete_list query to clean up
457  **                       members table.
458  **
459  ** Inputs: argv[0] - list_id
460  **
461  ** Description:
462  **   - foreach string member: decr string refc; ifzero, delete string
463  **   - delete all members entries for this list_id
464  **
465  **/
466
467 delete_list_members(q, argv)
468     struct query *q;
469     register char *argv[];
470 ##{
471 ##  int list_id;
472 ##  int string_id;
473 ##  int refc;
474 ##  int rowcount;
475     struct save_queue *sq;
476     struct save_queue *sq_create();
477
478     list_id = *(int *)argv[0];
479     sq = sq_create();
480
481 ##  range of m is members
482 ##  repeat retrieve (string_id = m.member_id)
483 ##         where m.#list_id = @list_id and m.member_type = "STRING"
484 ##  {
485          sq_save_data(sq, string_id);
486 ##  }
487
488     while (sq_get_data(sq, &string_id)) {
489 ##      range of s is strings
490 ##      repeat retrieve (refc = s.#refc) where s.#string_id = @string_id
491 ##      inquire_equel (rowcount = "rowcount")
492         if (rowcount == 0) continue;
493         if (--refc == 0) {
494 ##          repeat delete s where s.#string_id = @string_id
495         } else {
496 ##          repeat replace s (#refc = @refc) where s.#string_id = @string_id
497         }
498     }
499     sq_destroy(sq);
500
501 ##  repeat delete m where m.#list_id = @list_id
502
503     return(SMS_SUCCESS);
504 ##}
505
506 /**
507  ** grvd_support - Support routine for get_rvd_servers query
508  **
509  ** Inputs:
510  **    q     - grvd query structure
511  **    sq    - save_queue struture: contains list of {machine, oper_acl_id,
512  **            admin_acl_id, shutdown_acl_id} records.
513  **    v     - validate structure (not used)
514  **    action - action routine
515  **    actarg - action routine argument
516  **
517  ** Description:
518  **   - translate acl_ids to list names
519  **
520  **/
521
522 grvd_support(q, sq, v, action, actarg)
523     struct query *q;
524     struct save_queue *sq;
525     struct validate *v;
526     int (*action)();
527     int actarg;
528 ##{
529     char **argv;
530     char *targv[4];
531 ##  char oper[33];
532 ##  char admin[33];
533 ##  char shutdown[33];
534 ##  int list_id;
535
536     targv[0] = oper;
537     targv[1] = admin;
538     targv[2] = shutdown;
539
540 ##  range of l is list
541
542     while (sq_get_data(sq, &argv)) {
543         sscanf(argv[0], "%d", &list_id);
544 ##      repeat retrieve (oper = l.name) where l.#list_id = @list_id
545         sscanf(argv[1], "%d", &list_id);
546 ##      repeat retrieve (admin = l.name) where l.#list_id = @list_id
547         sscanf(argv[2], "%d", &list_id);
548 ##      repeat retrieve (shutdown = l.name) where l.#list_id = @list_id
549         
550         (*action)(3, targv, actarg);
551         free(argv[0]);
552         free(argv[1]);
553         free(argv[2]);
554     }
555
556     sq_destroy(sq);
557     return(SMS_SUCCESS);
558 ##}
559
560 /**
561  ** set_next_object_id - set next object id in values table
562  **
563  ** Inputs: object - object name in values table
564  **
565  ** - called before an APPEND operation to set the next object id to
566  **   be used for the new record
567  **
568  **/
569
570 set_next_object_id(object)
571     char *object;
572 ##{
573 ##  char *name;
574
575     name = object;
576 ##  range of v is values
577 ##  repeat replace v (value = v.value + 1) where v.#name = @name
578     return(SMS_SUCCESS);
579 ##}
580
581 /**
582  ** get_query_need - check modtime of query's associated table against given
583  **                  time and return true if greater (false if not)
584  **
585  ** Inputs:
586  **   argv[0] - query name
587  **   argv[1] - time to compare against
588  **
589  **/
590
591 get_query_need(q, argv, action, actarg)
592     struct query *q;
593     register char *argv[];
594     int (*action)();
595 ##{
596     struct query *q1;
597 ##  char *last_get_time;
598 ##  char *table;
599 ##  int need;
600     char *result;
601     struct query *get_query_by_name();
602
603     q1 = get_query_by_name(argv[0]);
604
605     last_get_time = argv[1];
606     table = q1->rtable;
607
608     if (q1->type != RETRIEVE || table == (char *)0) return(SMS_NO_MATCH);
609
610 ##  range of tbs is tblstats
611 ##  repeat retrieve (need = any(tbs.modtime where tbs.#table = @table and
612 ##                              tbs.modtime > @last_get_time))
613     
614     result = (need) ? "true" : "false";
615     (*action)(1, &result, actarg);
616     return(SMS_SUCCESS);
617 ##}
618
619 \f
620 /**
621  ** add_locker - special query routine for creating a user locker
622  **
623  ** Inputs:
624  **   argv[0] - users_id
625  **   argv[1] - machine_id
626  **   argv[2] - device
627  **   argv[3] - initial quota
628  ** 
629  ** Description:
630  **   - get prefix directory (dir) for mount point on specified machine/device
631  **   - create filesys entry (label=<login>, type=NFS, machine=<machine>,
632  **     mount=<dir>/<login>, access=w, acl=dbadmin)
633  **   - increment allocated in nfsphys by quota
634  **   - create nfsquota entry
635  **
636  ** Errors:
637  **   - SMS_NFSPHYS - machine/device does not exist in nfsphys
638  **   - SMS_FILESYS_EXISTS - file system already exists
639  ** 
640  **/
641
642 add_locker(q, argv)
643     register struct query *q;
644     char *argv[];
645 ##{
646 ##  int users_id;
647 ##  int mach_id;
648 ##  char *device;
649 ##  int quota;
650 ##  int rowcount;
651 ##  char login[9];
652 ##  char dir[32];
653 ##  int allocated;
654 ##  char locker[64];
655 ##  char mount[64];
656 ##  int user_acl;
657
658     /* copy arguments */
659     users_id = *(int *)argv[0];
660     mach_id = *(int *)argv[1];
661     device = argv[2];
662     sscanf(argv[3], "%d", &quota);
663
664 ##  range of u is users
665 ##  range of f is filesys
666 ##  range of np is nfsphys
667 ##  range of tbs is tblstats
668
669     /* get login name */
670 ##  repeat retrieve (login = u.#login) where u.#users_id = @users_id
671
672     /* get user's acl id */
673 ##  repeat retrieve (user_acl = list.list_id) where list.name = @login
674
675     /* get filesystem directory prefix; give error if machine/device
676        pair not in nfsphys table */
677     printf("np.mach_id = %d and np.device = %s\n", mach_id, device);
678     
679 ##  repeat retrieve (dir = np.#dir, allocated = np.#allocated) 
680 ##         where np.#mach_id = @mach_id and np.#device = device
681 ##  inquire_equel (rowcount = "rowcount")
682     if (rowcount == 0) return(SMS_NFSPHYS);
683
684     /* make sure a filesys with user's name does not already exist */
685 ##  repeat retrieve (rowcount = any(f.label where f.label = @login))
686     if (rowcount != 0) return(SMS_FILESYS_EXISTS);
687
688     /* create a new filesys */
689     sprintf(locker, "%s/%s", dir, login);
690     sprintf(mount, "/mit/%s", login);
691 ##  repeat append filesys 
692 ##             (#label = @login, type = "NFS", #mach_id = @mach_id,
693 ##              name = @locker, access = "w", order = 1, #mount = @mount,
694 ##              acl_id = @user_acl)
695 ##  repeat replace tbs (appends = tbs.appends + 1, modtime = "now")
696 ##             where tbs.table = "filesys"
697
698     /* increment usage count in nfsphys table */
699     allocated += quota;
700 ##  replace np (#allocated = allocated) 
701 ##          where np.#mach_id = mach_id and np.#device = device
702 ##  repeat replace tbs (updates = tbs.updates + 1, modtime = "now")
703 ##             where tbs.table = "nfsphys"
704
705     /* create nfsquota entry */
706 ##  append nfsquota (#users_id = users_id, #mach_id = mach_id,
707 ##                   #device = device, #quota = quota)
708 ##  repeat replace tbs (appends = tbs.appends + 1, modtime = "now")
709 ##             where tbs.table = "nfsquota"
710
711     return(SMS_SUCCESS);
712 ##}
713
714 /**
715  ** delete_locker - special query routine for deleting a user locker
716  **
717  ** Inputs:
718  **   argv[0] - users_id
719  **   argv[1] - machine_id
720  **   argv[2] - device
721  **   argv[3] - quota
722  ** 
723  ** Description:
724  **   - delete filesys entry (label=<login>)
725  **   - decrement allocated in nfsphys by quota
726  **   - delete nfsquota entry
727  **
728  ** Errors:
729  **   - SMS_FILESYS - no filesys exists for user
730  ** 
731  **/
732
733 delete_locker(q, argv)
734     register struct query *q;
735     register char *argv[];
736 ##{
737 ##  int users_id;
738 ##  int mach_id;
739 ##  char *device;
740 ##  int quota;
741 ##  int rowcount;
742 ##  char login[9];
743
744     /* copy arguments */
745     users_id = *(int *)argv[0];
746     mach_id = *(int *)argv[1];
747     device = argv[2];
748     sscanf(argv[3], "%d", &quota);
749
750 ##  range of u is users
751 ##  range of f is filesys
752 ##  range of np is nfsphys
753 ##  range of nq is nfsquota
754 ##  range of tbs is tblstats
755
756     /* get login name */
757 ##  repeat retrieve (login = u.#login) where u.#users_id = @users_id
758
759     /* delete the filesys entry */
760 ##  repeat delete f where f.label = @login
761 ##  inquire_equel (rowcount = "rowcount")
762     if (rowcount == 0) return(SMS_FILESYS);
763 ##  repeat replace tbs (deletes = tbs.deletes + 1, modtime = "now")
764 ##             where tbs.table = "filesys"
765
766     /* decrement usage count in nfsphys table */
767 ##  replace np (#allocated = np.#allocated - quota) 
768 ##          where np.#mach_id = mach_id and np.#device = device
769 ##  repeat replace tbs (updates = tbs.updates + 1, modtime = "now")
770 ##             where tbs.table = "nfsphys"
771
772     /* delete nfsquota entry */
773 ##  delete nq where nq.#users_id = users_id and nq.#mach_id = mach_id and
774 ##                  nq.#device = device
775 ##  repeat replace tbs (deletes = tbs.deletes + 1, modtime = "now")
776 ##             where tbs.table = "nfsquota"
777
778     return(SMS_SUCCESS);
779 ##}
780 \f
781 /**
782  ** get_members_of_list - optimized query for retrieval of list members
783  **
784  ** Inputs:
785  **   argv[0] - list_id
786  **
787  ** Description:
788  **   - retrieve USER members, then LIST members, then STRING members
789  **
790  **/
791
792 get_members_of_list(q, argv, action, actarg)
793     struct query *q;
794     char *argv[];
795     int (*action)();
796     int actarg;
797 ##{
798 ##  int list_id;
799 ##  char member_name[129];
800     char *targv[2];
801
802     list_id = *(int *)argv[0];
803     targv[0] = "USER";
804     targv[1] = member_name;
805
806 ##  range of m is members
807 ##  repeat retrieve (member_name = users.login)
808 ##             where m.#list_id = @list_id and m.member_type = "USER"
809 ##                   and m.member_id = users.users_id
810 ##  {
811          (*action)(2, targv, actarg);
812 ##  }
813
814     targv[0] = "LIST";
815 ##  repeat retrieve (member_name = list.name)
816 ##             where m.#list_id = @list_id and m.member_type = "LIST"
817 ##                   and m.member_id = list.#list_id
818 ##  {
819          (*action)(2, targv, actarg);
820 ##  }
821
822     targv[0] = "STRING";
823 ##  repeat retrieve (member_name = strings.string)
824 ##             where m.#list_id = @list_id and m.member_type = "STRING"
825 ##                   and m.member_id = strings.string_id
826 ##  {
827          (*action)(2, targv, actarg);
828 ##  }
829
830     return(SMS_SUCCESS);
831 ##}
832
833 /**
834  ** get_all_poboxes - optimize query for retrieval of all poboxes
835  **
836  ** Description:
837  **   - retrieve LOCAL boxes, then POP boxes, then FOREIGN boxes
838  **
839  **/
840
841 get_all_poboxes(q, argv, action, actarg)
842     struct query *q;
843     char *argv[];
844     int (*action)();
845     int actarg;
846 ##{
847 ##  char login[9];
848 ##  char machine[129];
849 ##  char box[129];
850     char *targv[4];
851
852     targv[0] = login;
853     targv[2] = machine;
854     targv[3] = box;
855
856     targv[1] = "LOCAL";
857 ##  range of p is pobox
858 ##  repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
859 ##             where p.type = "LOCAL" and p.users_id = users.users_id
860 ##                   and p.mach_id = #machine.mach_id
861 ##  {
862          (*action)(4, targv, actarg);
863 ##  }
864
865     targv[1] = "POP";
866 ##  repeat retrieve (login=users.#login, machine = #machine.name, box=p.#box)
867 ##             where p.type = "POP" and p.users_id = users.users_id
868 ##                   and p.mach_id = #machine.mach_id
869 ##  {
870          (*action)(4, targv, actarg);
871 ##  }
872
873     targv[1] = "FOREIGN";
874 ##  repeat retrieve (login=users.#login, machine=strings.string, box=p.#box)
875 ##             where p.type = "FOREIGN" and p.users_id = users.users_id
876 ##                   and p.mach_id = strings.string_id
877 ##  {
878          (*action)(4, targv, actarg);
879 ##  }
880
881     return(SMS_SUCCESS);
882 ##}
883 \f
884 /* Validation Routines */
885
886 validate_row(q, argv, v)
887     register struct query *q;
888     char *argv[];
889     register struct validate *v;
890 ##{
891 ##  char *rvar;
892 ##  char *table;
893 ##  char *name;
894 ##  char qual[128];
895 ##  int rowcount;
896
897     /* build where clause */
898     build_qual(v->qual, v->argc, argv, qual);
899
900     /* setup ingres variables */
901     rvar = q->rvar;
902     table = q->rtable;
903     name = v->field;
904
905     if (log_flags & LOG_RES)
906         /* tell the logfile what we're doing */
907         com_err(whoami, 0, "validating row: %s", qual);
908     
909     /* look for the record */
910 ##  range of rvar is table
911 ##  retrieve (rowcount = count(rvar.name where qual))
912     if (rowcount == 0) return(SMS_NO_MATCH);
913     if (rowcount > 1) return(SMS_NOT_UNIQUE);
914     return(SMS_EXISTS);
915 ##}
916
917 validate_fields(q, argv, vo, n)
918     struct query *q;
919     register char *argv[];
920     register struct valobj *vo;
921     register int n;
922 {
923     register int status;
924     char buf[64];
925
926     while (--n >= 0) {
927         switch (vo->type) {
928         case V_NAME:
929             if (log_flags&LOG_RES)
930                 com_err(whoami, 0, "validating %s in %s: %s", 
931                     vo->namefield, vo->table, argv[vo->index]);
932             status = validate_name(argv, vo);
933             break;
934
935         case V_ID:
936             if (log_flags&LOG_RES)
937                 com_err(whoami, 0, "validating %s in %s: %s", 
938                     vo->idfield, vo->table, argv[vo->index]);
939             status = validate_id(argv, vo);
940             break;
941
942         case V_TYPE:
943             if (log_flags&LOG_RES)
944                 com_err(whoami, 0, "validating %s type: %s",
945                     vo->table, argv[vo->index]);
946             status = validate_type(argv, vo);
947             break;
948
949         case V_TYPEDATA:
950             if (log_flags&LOG_RES)
951                 com_err(whoami, 0, "validating type-specific data: %s",
952                     argv[vo->index]);
953             status = validate_typedata(q, argv, vo);
954             break;
955
956         case V_FOLLOWUP:
957             status = SMS_EXISTS;
958             break;
959
960         }
961
962         if (status != SMS_EXISTS) return(status);
963         vo++;
964     }
965
966     return(SMS_SUCCESS);
967 }
968
969 validate_id(argv, vo)
970     char *argv[];
971     register struct valobj *vo;
972 ##{
973 ##  char *name;
974 ##  char *table;
975 ##  char *namefield;
976 ##  char *idfield;
977 ##  int id;
978 ##  int rowcount;
979
980     name = argv[vo->index];
981     table = vo->table;
982     namefield = vo->namefield;
983     idfield = vo->idfield;
984 ##  retrieve (id = table.idfield) where table.namefield = name
985 ##  inquire_equel (rowcount = "rowcount")
986     if (rowcount != 1) return(vo->error);
987     *(int *)argv[vo->index] = id;
988     return(SMS_EXISTS);
989 ##}
990
991 validate_name(argv, vo)
992     char *argv[];
993     register struct valobj *vo;
994 ##{
995 ##  char *name;
996 ##  char *table;
997 ##  char *namefield;
998 ##  int rowcount;
999
1000     name = argv[vo->index];
1001     table = vo->table;
1002     namefield = vo->namefield;
1003 ##  retrieve (rowcount = countu(table.namefield 
1004 ##            where table.namefield = name))
1005     return ((rowcount == 1) ? SMS_EXISTS : vo->error);
1006 ##}
1007
1008 validate_type(argv, vo)
1009     char *argv[];
1010     register struct valobj *vo;
1011 ##{
1012 ##  char *typename;
1013 ##  char *value;
1014 ##  int rowcount;
1015     register char *c;
1016
1017     typename = vo->table;
1018     value = argv[vo->index];
1019
1020     /* uppercase type fields */
1021     for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c);
1022
1023 ##  range of a is alias
1024 ##  repeat retrieve (rowcount = count(a.trans where a.name = @typename and
1025 ##                                    a.type = "TYPE" and
1026 ##                                    a.trans = @value))
1027     return ((rowcount == 1) ? SMS_EXISTS : vo->error);
1028 ##}
1029
1030 /* validate member or type-specific data field */
1031
1032 validate_typedata(q, argv, vo)
1033     register struct query *q;
1034     register char *argv[];
1035     register struct valobj *vo;
1036 ##{
1037 ##  char *name;
1038 ##  char *field_type;
1039 ##  char data_type[17];
1040 ##  int id;
1041 ##  int refc;
1042 ##  int rowcount;
1043
1044     /* get named object */
1045     name = argv[vo->index];
1046
1047     /* get field type string (known to be at index-1) */
1048     field_type = argv[vo->index-1];
1049
1050     /* get corresponding data type associated with field type name */
1051 ##  repeat retrieve (data_type = alias.trans) 
1052 ##         where alias.#name = @field_type and alias.type = "TYPEDATA"
1053 ##  inquire_equel (rowcount = "rowcount")
1054     if (rowcount != 1) return(SMS_TYPE);
1055
1056     /* now retrieve the record id corresponding to the named object */
1057
1058     if (!strcmp(data_type, "user")) {
1059         /* USER */
1060 ##      repeat retrieve (id = users.users_id) where users.login = @name
1061 ##      inquire_equel (rowcount = "rowcount")
1062         if (rowcount != 1) return(SMS_USER);
1063
1064     } else if (!strcmp(data_type, "list")) {
1065         /* LIST */
1066 ##      repeat retrieve (id = list.list_id) where list.#name = @name
1067 ##      inquire_equel (rowcount = "rowcount")
1068         if (rowcount != 1) return(SMS_LIST);
1069
1070     } else if (!strcmp(data_type, "machine")) {
1071         /* MACHINE */
1072 ##      repeat retrieve (id = machine.mach_id) where machine.#name = @name
1073 ##      inquire_equel (rowcount = "rowcount")
1074         if (rowcount != 1) return(SMS_MACHINE);
1075
1076     } else if (!strcmp(data_type, "string")) {
1077         /* STRING */
1078 ##      range of s is strings
1079 ##      repeat retrieve (id = s.string_id, refc = s.#refc) 
1080 ##             where s.string = @name
1081 ##      inquire_equel (rowcount = "rowcount")
1082         if (rowcount == 0) {
1083             if (q->type != APPEND) return(SMS_STRING);
1084 ##          range of v is values
1085 ##          retrieve (id = v.value) where v.#name = "strings_id"
1086             id++;
1087 ##          replace v (value = id) where v.#name = "strings_id"
1088 ##          append to strings (string_id = id, string = name, #refc = 1)
1089         } else if (rowcount == 1) {
1090             if (q->type == APPEND || q->type == DELETE) {
1091                 refc += (q->type == APPEND) ? 1 : -1;
1092                 if (refc > 0) {
1093 ##                  replace s (#refc = refc) where s.string_id = id
1094                 } else {
1095 ##                  delete s where s.string_id = id
1096                 }
1097             }
1098         }
1099     } else {
1100         return(SMS_TYPE);
1101     }
1102
1103     /* now set value in argv */
1104     *(int *)argv[vo->index] = id;
1105     
1106     return (SMS_EXISTS);
1107 ##}
1108
1109 \f
1110 translate_ids(q, sq, v, action, actarg)
1111     register struct query *q;
1112     register struct save_queue *sq;
1113     register struct validate *v;
1114     register int (*action)();
1115     int actarg;
1116 ##{
1117 ##  char *name;
1118 ##  char *field_type;
1119 ##  char data_type[17];
1120 ##  int id;
1121 ##  int rowcount;
1122     register int i;
1123     struct valobj *vo;
1124     char **argv;
1125
1126     for (i = 0; i < v->objcnt; i++) {
1127         vo = &v->valobj[i];
1128         if (vo->type == V_FOLLOWUP) break;
1129     }
1130
1131     /* for each row */
1132     while (sq_get_data(sq, &argv)) {
1133
1134         /* get object id */
1135         i = vo->index;
1136         sscanf(argv[i], "%d", &id);
1137         free(argv[i]);
1138         name = (char *)malloc(129);
1139         argv[i] = name;
1140
1141         /* get field type string (known to be at index-1) */
1142         field_type = argv[vo->index-1];
1143
1144         /* get corresponding data type associated with field type name */
1145 ##      repeat retrieve (data_type = alias.trans) 
1146 ##             where alias.#name = @field_type and alias.type = "TYPEDATA"
1147 ##      inquire_equel (rowcount = "rowcount")
1148         if (rowcount != 1) {
1149             sprintf(name, "%d", id);
1150             (*action)(q->vcnt, argv, actarg);
1151             continue;
1152         }
1153
1154         /* retrieve object name */
1155
1156         if (!strcmp(data_type, "user")) {
1157             /* USER */
1158 ##          repeat retrieve (name = users.login) where users.users_id = @id
1159 ##          inquire_equel (rowcount = "rowcount")
1160
1161         } else if (!strcmp(data_type, "list")) {
1162             /* LIST */
1163 ##          repeat retrieve (name = list.#name) where list.list_id = @id
1164 ##          inquire_equel (rowcount = "rowcount")
1165
1166         } else if (!strcmp(data_type, "machine")) {
1167             /* MACHINE */
1168 ##          repeat retrieve (name = machine.#name) where machine.mach_id = @id
1169 ##          inquire_equel (rowcount = "rowcount")
1170
1171         } else if (!strcmp(data_type, "string")) {
1172             /* STRING */
1173 ##          repeat retrieve (name = strings.string) 
1174 ##                 where strings.string_id = @id
1175 ##          inquire_equel (rowcount = "rowcount")
1176
1177         } else {
1178             rowcount = 0;
1179         }
1180
1181         /* if there wasn't a corresponding object name, then use the id */
1182         if (rowcount != 1) sprintf(name, "%d", id);
1183
1184         /* send the data */
1185         (*action)(q->vcnt, argv, actarg);
1186
1187         /* free saved data */
1188         for (i = 0; i < q->vcnt; i++) 
1189             free(argv[i]);
1190         free(argv);
1191     }
1192
1193     sq_destroy(sq);
1194     return (SMS_SUCCESS);
1195 ##}
1196 \f
1197 /*
1198  * Local Variables:
1199  * mode: c
1200  * c-indent-level: 4
1201  * c-continued-statement-offset: 4
1202  * c-brace-offset: -4
1203  * c-argdecl-indent: 4
1204  * c-label-offset: -4
1205  * End:
1206  */
This page took 0.13174 seconds and 5 git commands to generate.