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