]>
Commit | Line | Data |
---|---|---|
7ac48069 | 1 | /* $Id$ |
b070f8a1 | 2 | * |
7ac48069 | 3 | * Special query routines |
b070f8a1 | 4 | * |
7ac48069 | 5 | * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology |
6 | * For copying and distribution information, please see the file | |
7 | * <mit-copyright.h>. | |
b070f8a1 | 8 | */ |
9 | ||
b070f8a1 | 10 | #include <mit-copyright.h> |
b070f8a1 | 11 | #include "mr_server.h" |
03c05291 | 12 | #include "query.h" |
7ac48069 | 13 | #include "qrtn.h" |
14 | ||
b070f8a1 | 15 | #include <ctype.h> |
7ac48069 | 16 | #include <stdlib.h> |
03c05291 | 17 | #include <string.h> |
7ac48069 | 18 | |
5d677c81 | 19 | EXEC SQL INCLUDE sqlca; |
7ac48069 | 20 | |
21 | RCSID("$Header$"); | |
b070f8a1 | 22 | |
03c05291 | 23 | extern char *whoami, *table_name[]; |
24 | extern int dbms_errno, mr_errcode; | |
b070f8a1 | 25 | |
0fc7ab46 | 26 | EXEC SQL BEGIN DECLARE SECTION; |
45bf7573 | 27 | extern char stmt_buf[]; |
0fc7ab46 | 28 | EXEC SQL END DECLARE SECTION; |
5d677c81 | 29 | |
03c05291 | 30 | EXEC SQL WHENEVER SQLERROR DO dbmserr(); |
31 | ||
7ac48069 | 32 | int get_ace_internal(char *atypex, int aid, |
33 | int (*action)(int, char *[], void *), void *actarg); | |
7ac48069 | 34 | int qualified_get(struct query *q, char *argv[], |
35 | int (*action)(int, char *[], void *), void *actarg, | |
03c05291 | 36 | char *start, char *range, char *field, char *flags[]); |
453b99fe | 37 | |
0fc7ab46 | 38 | |
0659551f | 39 | /* set_pobox - this does all of the real work. |
40 | * argv = user_id, type, box | |
41 | * if type is POP, then box should be a machine, and its ID should be put in | |
17cb3de8 | 42 | * pop_id. If type is IMAP, then box should be a filesys, and its ID should |
43 | * be put in pop_id. If type is SMTP, then box should be a string and its | |
44 | * ID should be put in box_id. If type is NONE, then box doesn't matter. | |
0fc7ab46 | 45 | */ |
b070f8a1 | 46 | |
5eaef520 | 47 | int set_pobox(struct query *q, char **argv, client *cl) |
5d677c81 | 48 | { |
5eaef520 | 49 | EXEC SQL BEGIN DECLARE SECTION; |
50 | int user, id; | |
e688520a | 51 | char *box, potype[USERS_POTYPE_SIZE]; |
5eaef520 | 52 | EXEC SQL END DECLARE SECTION; |
53 | int status; | |
54 | ||
55 | box = argv[2]; | |
56 | user = *(int *)argv[0]; | |
57 | ||
58 | EXEC SQL SELECT pop_id, potype INTO :id, :potype FROM users | |
59 | WHERE users_id = :user; | |
60 | if (dbms_errno) | |
61 | return mr_errcode; | |
62 | if (!strcmp(strtrim(potype), "POP")) | |
63 | set_pop_usage(id, -1); | |
64 | ||
65 | if (!strcmp(argv[1], "POP")) | |
66 | { | |
67 | status = name_to_id(box, MACHINE_TABLE, &id); | |
68 | if (status == MR_NO_MATCH) | |
69 | return MR_MACHINE; | |
70 | else if (status) | |
71 | return status; | |
17cb3de8 | 72 | EXEC SQL UPDATE users SET potype = 'POP', pop_id = :id, imap_id = 0 |
5eaef520 | 73 | WHERE users_id = :user; |
74 | set_pop_usage(id, 1); | |
75 | } | |
76 | else if (!strcmp(argv[1], "SMTP")) | |
77 | { | |
78 | if (strchr(box, '/') || strchr(box, '|')) | |
79 | return MR_BAD_CHAR; | |
80 | status = name_to_id(box, STRINGS_TABLE, &id); | |
81 | if (status == MR_NO_MATCH) | |
82 | id = add_string(box); | |
83 | else if (status) | |
84 | return status; | |
85 | EXEC SQL UPDATE users SET potype = 'SMTP', box_id = :id | |
86 | WHERE users_id = :user; | |
87 | } | |
7b3eb008 | 88 | else if (!strcmp(argv[1], "IMAP")) |
89 | { | |
17cb3de8 | 90 | EXEC SQL SELECT filsys_id INTO :id FROM filesys |
91 | WHERE label = :box AND type = 'IMAP'; | |
92 | if (sqlca.sqlcode) | |
7b3eb008 | 93 | return MR_FILESYS; |
17cb3de8 | 94 | EXEC SQL UPDATE users SET potype = 'IMAP', imap_id = :id, pop_id = 0 |
7b3eb008 | 95 | WHERE users_id = :user; |
96 | } | |
5eaef520 | 97 | else /* argv[1] == "NONE" */ |
98 | { | |
99 | EXEC SQL UPDATE users SET potype = 'NONE' | |
100 | WHERE users_id = :user; | |
b070f8a1 | 101 | } |
102 | ||
5eaef520 | 103 | set_pobox_modtime(q, argv, cl); |
104 | EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE | |
105 | WHERE table_name = 'users'; | |
106 | if (dbms_errno) | |
107 | return mr_errcode; | |
108 | return MR_SUCCESS; | |
5d677c81 | 109 | } |
b070f8a1 | 110 | |
17cb3de8 | 111 | /* set_pobox_pop: Revert to existing POP or IMAP pobox. |
112 | * Also take care of keeping track of the post office usage. | |
113 | */ | |
114 | int set_pobox_pop(struct query *q, char **argv, client *cl) | |
115 | { | |
116 | EXEC SQL BEGIN DECLARE SECTION; | |
117 | int id, pid, iid, mid; | |
118 | char type[USERS_POTYPE_SIZE]; | |
119 | EXEC SQL END DECLARE SECTION; | |
120 | ||
121 | id = *(int *)argv[0]; | |
122 | EXEC SQL SELECT potype, pop_id, imap_id INTO :type, :pid, :iid | |
123 | FROM users WHERE users_id = :id; | |
124 | if (sqlca.sqlerrd[2] == 0 || (pid == 0 && iid == 0)) | |
125 | return MR_MACHINE; | |
126 | ||
127 | if (pid) | |
128 | { | |
129 | EXEC SQL SELECT mach_id INTO :mid FROM machine | |
130 | WHERE mach_id = :pid; | |
131 | if (sqlca.sqlerrd[2] == 0) | |
132 | return MR_MACHINE; | |
133 | EXEC SQL UPDATE users SET potype = 'POP' WHERE users_id = :id; | |
134 | if (strcmp(strtrim(type), "POP")) | |
135 | set_pop_usage(mid, 1); | |
136 | } | |
137 | else | |
138 | { | |
139 | EXEC SQL SELECT filsys_id INTO :mid FROM filesys | |
140 | WHERE filsys_id = :iid; | |
141 | if (sqlca.sqlerrd[2] == 0) | |
142 | return MR_MACHINE; | |
143 | EXEC SQL UPDATE users SET potype = 'IMAP' WHERE users_id = :id; | |
144 | } | |
145 | ||
146 | set_pobox_modtime(q, argv, cl); | |
147 | EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE | |
148 | WHERE table_name = 'users'; | |
149 | if (dbms_errno) | |
150 | return mr_errcode; | |
151 | return MR_SUCCESS; | |
152 | } | |
153 | ||
154 | ||
0659551f | 155 | /* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is |
156 | * how many different ancestors a member is allowed to have. | |
b070f8a1 | 157 | */ |
158 | ||
0659551f | 159 | #define MAXLISTDEPTH 1024 |
b070f8a1 | 160 | |
5eaef520 | 161 | int add_member_to_list(struct query *q, char **argv, client *cl) |
5d677c81 | 162 | { |
5eaef520 | 163 | EXEC SQL BEGIN DECLARE SECTION; |
46b6f1f6 | 164 | int id, lid, mid, tag, error, who, ref, rowcnt; |
e688520a | 165 | char *mtype, dtype[IMEMBERS_MEMBER_TYPE_SIZE], *entity; |
5eaef520 | 166 | EXEC SQL END DECLARE SECTION; |
167 | int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a; | |
168 | int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d; | |
169 | int status; | |
170 | char *dtypes[MAXLISTDEPTH]; | |
171 | char *iargv[3], *buf; | |
172 | ||
173 | lid = *(int *)argv[0]; | |
174 | mtype = argv[1]; | |
175 | mid = *(int *)argv[2]; | |
46b6f1f6 | 176 | tag = !strcmp(q->shortname, "atml") ? *(int *)argv[3] : 0; |
a37b0b99 | 177 | |
178 | if (acl_access_check(lid, cl)) | |
179 | return MR_PERM; | |
180 | ||
5eaef520 | 181 | /* if the member is already a direct member of the list, punt */ |
182 | EXEC SQL SELECT COUNT(list_id) INTO :rowcnt FROM imembers | |
183 | WHERE list_id = :lid AND member_id = :mid | |
184 | AND member_type = :mtype AND direct = 1; | |
185 | if (rowcnt > 0) | |
186 | return MR_EXISTS; | |
187 | if (!strcasecmp(mtype, "STRING")) | |
188 | { | |
189 | buf = malloc(0); | |
190 | status = id_to_name(mid, STRINGS_TABLE, &buf); | |
191 | if (status) | |
192 | return status; | |
193 | if (strchr(buf, '/') || strchr(buf, '|')) | |
194 | { | |
195 | free(buf); | |
196 | return MR_BAD_CHAR; | |
0659551f | 197 | } |
5eaef520 | 198 | free(buf); |
0659551f | 199 | } |
b070f8a1 | 200 | |
5eaef520 | 201 | ancestors[0] = lid; |
202 | aref[0] = 1; | |
203 | acount = 1; | |
204 | EXEC SQL DECLARE csr103 CURSOR FOR | |
205 | SELECT list_id, ref_count FROM imembers | |
206 | WHERE member_id = :lid AND member_type = 'LIST'; | |
207 | if (dbms_errno) | |
208 | return mr_errcode; | |
209 | EXEC SQL OPEN csr103; | |
210 | if (dbms_errno) | |
211 | return mr_errcode; | |
212 | while (1) | |
213 | { | |
214 | EXEC SQL FETCH csr103 INTO :id, :ref; | |
215 | if (sqlca.sqlcode) | |
216 | break; | |
217 | aref[acount] = ref; | |
218 | ancestors[acount++] = id; | |
219 | if (acount >= MAXLISTDEPTH) | |
220 | break; | |
0659551f | 221 | } |
5eaef520 | 222 | EXEC SQL CLOSE csr103; |
223 | if (dbms_errno) | |
224 | return mr_errcode; | |
225 | if (acount >= MAXLISTDEPTH) | |
226 | return MR_INTERNAL; | |
227 | descendants[0] = mid; | |
228 | dtypes[0] = mtype; | |
229 | dref[0] = 1; | |
230 | dcount = 1; | |
231 | error = 0; | |
232 | if (!strcmp(mtype, "LIST")) | |
233 | { | |
234 | EXEC SQL DECLARE csr104 CURSOR FOR | |
235 | SELECT member_id, member_type, ref_count | |
236 | FROM imembers | |
237 | WHERE list_id = :mid; | |
238 | if (dbms_errno) | |
239 | return mr_errcode; | |
240 | EXEC SQL OPEN csr104; | |
241 | if (dbms_errno) | |
242 | return mr_errcode; | |
243 | while (1) | |
244 | { | |
245 | EXEC SQL FETCH csr104 INTO :id, :dtype, :ref; | |
246 | if (sqlca.sqlcode) | |
247 | break; | |
248 | switch (dtype[0]) | |
249 | { | |
0659551f | 250 | case 'L': |
5eaef520 | 251 | dtypes[dcount] = "LIST"; |
252 | break; | |
0659551f | 253 | case 'U': |
5eaef520 | 254 | dtypes[dcount] = "USER"; |
255 | break; | |
0659551f | 256 | case 'S': |
5eaef520 | 257 | dtypes[dcount] = "STRING"; |
258 | break; | |
0659551f | 259 | case 'K': |
5eaef520 | 260 | dtypes[dcount] = "KERBEROS"; |
261 | break; | |
0659551f | 262 | default: |
5eaef520 | 263 | error++; |
264 | break; | |
0659551f | 265 | } |
5eaef520 | 266 | dref[dcount] = ref; |
267 | descendants[dcount++] = id; | |
268 | if (dcount >= MAXLISTDEPTH) | |
269 | { | |
270 | error++; | |
271 | break; | |
0659551f | 272 | } |
273 | } | |
5eaef520 | 274 | EXEC SQL CLOSE csr104; |
275 | if (dbms_errno) | |
276 | return mr_errcode; | |
277 | if (error) | |
278 | return MR_INTERNAL; | |
b070f8a1 | 279 | } |
5eaef520 | 280 | for (a = 0; a < acount; a++) |
281 | { | |
282 | lid = ancestors[a]; | |
283 | for (d = 0; d < dcount; d++) | |
284 | { | |
285 | mid = descendants[d]; | |
286 | mtype = dtypes[d]; | |
287 | if (mid == lid && !strcmp(mtype, "LIST")) | |
288 | return MR_LISTLOOP; | |
289 | EXEC SQL SELECT COUNT(ref_count) INTO :rowcnt | |
290 | FROM imembers | |
291 | WHERE list_id = :lid AND member_id = :mid | |
292 | AND member_type = :mtype; | |
293 | ref = aref[a] * dref[d]; | |
294 | if (rowcnt > 0) | |
295 | { | |
296 | if (a == 0 && d == 0) | |
297 | { | |
298 | EXEC SQL UPDATE imembers | |
46b6f1f6 | 299 | SET ref_count = ref_count + :ref, direct = 1, tag = :tag |
5eaef520 | 300 | WHERE list_id = :lid AND member_id = :mid |
301 | AND member_type = :mtype; | |
0659551f | 302 | } |
5eaef520 | 303 | else |
304 | { | |
305 | EXEC SQL UPDATE imembers | |
306 | SET ref_count = ref_count + :ref | |
307 | WHERE list_id = :lid AND member_id = :mid | |
308 | AND member_type = :mtype; | |
309 | } | |
310 | } | |
311 | else | |
312 | { | |
313 | incremental_clear_before(); | |
314 | if (a == 0 && d == 0) | |
315 | { | |
03c05291 | 316 | EXEC SQL INSERT INTO imembers |
46b6f1f6 | 317 | (list_id, member_type, member_id, tag, direct, ref_count) |
318 | VALUES (:lid, :mtype, :mid, :tag, 1, 1); | |
5eaef520 | 319 | } |
320 | else | |
321 | { | |
03c05291 | 322 | EXEC SQL INSERT INTO imembers |
46b6f1f6 | 323 | (list_id, member_type, member_id, tag, direct, ref_count) |
324 | VALUES (:lid, :mtype, :mid, :tag, 0, 1); | |
0659551f | 325 | } |
5eaef520 | 326 | iargv[0] = (char *)lid; |
327 | iargv[1] = mtype; | |
328 | iargv[2] = (char *)mid; | |
329 | incremental_after(IMEMBERS_TABLE, 0, iargv); | |
0659551f | 330 | } |
331 | } | |
b070f8a1 | 332 | } |
5eaef520 | 333 | lid = *(int *)argv[0]; |
334 | entity = cl->entity; | |
335 | who = cl->client_id; | |
336 | EXEC SQL UPDATE list | |
337 | SET modtime = SYSDATE, modby = :who, modwith = :entity | |
338 | WHERE list_id = :lid; | |
339 | if (dbms_errno) | |
340 | return mr_errcode; | |
341 | return MR_SUCCESS; | |
5d677c81 | 342 | } |
b070f8a1 | 343 | |
344 | ||
0659551f | 345 | /* Delete_member_from_list: do list flattening as we go! |
b070f8a1 | 346 | */ |
347 | ||
5eaef520 | 348 | int delete_member_from_list(struct query *q, char **argv, client *cl) |
5d677c81 | 349 | { |
5eaef520 | 350 | EXEC SQL BEGIN DECLARE SECTION; |
351 | int id, lid, mid, cnt, error, who, ref; | |
e688520a | 352 | char *mtype, dtype[IMEMBERS_MEMBER_TYPE_SIZE], *entity; |
5eaef520 | 353 | EXEC SQL END DECLARE SECTION; |
354 | int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a; | |
355 | int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d; | |
356 | char *dtypes[MAXLISTDEPTH]; | |
357 | char *iargv[3]; | |
358 | ||
359 | lid = *(int *)argv[0]; | |
360 | mtype = argv[1]; | |
361 | mid = *(int *)argv[2]; | |
a37b0b99 | 362 | |
363 | if (acl_access_check(lid, cl)) | |
364 | return MR_PERM; | |
365 | ||
5eaef520 | 366 | /* if the member is not a direct member of the list, punt */ |
367 | EXEC SQL SELECT COUNT(list_id) INTO :cnt FROM imembers | |
368 | WHERE list_id = :lid AND member_id = :mid | |
369 | AND member_type = :mtype AND direct = 1; | |
370 | if (dbms_errno) | |
371 | return mr_errcode; | |
372 | if (cnt == 0) | |
373 | return MR_NO_MATCH; | |
374 | ancestors[0] = lid; | |
375 | aref[0] = 1; | |
376 | acount = 1; | |
377 | EXEC SQL DECLARE csr105 CURSOR FOR | |
378 | SELECT list_id, ref_count FROM imembers | |
379 | WHERE member_id = :lid AND member_type = 'LIST'; | |
380 | if (dbms_errno) | |
381 | return mr_errcode; | |
382 | EXEC SQL OPEN csr105; | |
383 | if (dbms_errno) | |
384 | return mr_errcode; | |
385 | while (1) | |
386 | { | |
387 | EXEC SQL FETCH csr105 INTO :id, :ref; | |
388 | if (sqlca.sqlcode) | |
389 | break; | |
390 | aref[acount] = ref; | |
391 | ancestors[acount++] = id; | |
392 | if (acount >= MAXLISTDEPTH) | |
393 | break; | |
b070f8a1 | 394 | } |
5eaef520 | 395 | EXEC SQL CLOSE csr105; |
396 | if (dbms_errno) | |
397 | return mr_errcode; | |
398 | if (acount >= MAXLISTDEPTH) | |
399 | return MR_INTERNAL; | |
400 | descendants[0] = mid; | |
401 | dtypes[0] = mtype; | |
402 | dref[0] = 1; | |
403 | dcount = 1; | |
404 | error = 0; | |
405 | if (!strcmp(mtype, "LIST")) | |
406 | { | |
407 | EXEC SQL DECLARE csr106 CURSOR FOR | |
408 | SELECT member_id, member_type, ref_count FROM imembers | |
409 | WHERE list_id = :mid; | |
410 | if (dbms_errno) | |
411 | return mr_errcode; | |
412 | EXEC SQL OPEN csr106; | |
413 | if (dbms_errno) | |
414 | return mr_errcode; | |
415 | while (1) | |
416 | { | |
417 | EXEC SQL FETCH csr106 INTO :id, :dtype, :ref; | |
418 | if (sqlca.sqlcode) | |
419 | break; | |
420 | switch (dtype[0]) | |
421 | { | |
0659551f | 422 | case 'L': |
5eaef520 | 423 | dtypes[dcount] = "LIST"; |
424 | break; | |
0659551f | 425 | case 'U': |
5eaef520 | 426 | dtypes[dcount] = "USER"; |
427 | break; | |
0659551f | 428 | case 'S': |
5eaef520 | 429 | dtypes[dcount] = "STRING"; |
430 | break; | |
0659551f | 431 | case 'K': |
5eaef520 | 432 | dtypes[dcount] = "KERBEROS"; |
433 | break; | |
0659551f | 434 | default: |
5eaef520 | 435 | error++; |
436 | break; | |
0659551f | 437 | } |
5eaef520 | 438 | dref[dcount] = ref; |
439 | descendants[dcount++] = id; | |
440 | if (dcount >= MAXLISTDEPTH) | |
441 | break; | |
0659551f | 442 | } |
5eaef520 | 443 | EXEC SQL CLOSE csr106; |
444 | if (dbms_errno) | |
445 | return mr_errcode; | |
446 | if (error) | |
447 | return MR_INTERNAL; | |
3beadd83 | 448 | } |
5eaef520 | 449 | for (a = 0; a < acount; a++) |
450 | { | |
451 | lid = ancestors[a]; | |
452 | for (d = 0; d < dcount; d++) | |
453 | { | |
454 | mid = descendants[d]; | |
455 | mtype = dtypes[d]; | |
456 | if (mid == lid && !strcmp(mtype, "LIST")) | |
457 | return MR_LISTLOOP; | |
458 | EXEC SQL SELECT ref_count INTO :cnt FROM imembers | |
459 | WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype; | |
460 | ref = aref[a] * dref[d]; | |
461 | if (cnt <= ref) | |
462 | { | |
463 | iargv[0] = (char *)lid; | |
464 | iargv[1] = mtype; | |
465 | iargv[2] = (char *)mid; | |
466 | incremental_before(IMEMBERS_TABLE, 0, iargv); | |
467 | EXEC SQL DELETE FROM imembers | |
468 | WHERE list_id = :lid AND member_id = :mid | |
469 | AND member_type= :mtype; | |
470 | incremental_clear_after(); | |
0659551f | 471 | } |
5eaef520 | 472 | else if (a == 0 && d == 0) |
473 | { | |
474 | EXEC SQL UPDATE imembers | |
475 | SET ref_count = ref_count - :ref, direct = 0 | |
476 | WHERE list_id = :lid AND member_id = :mid | |
477 | AND member_type = :mtype; | |
478 | } | |
479 | else | |
480 | { | |
481 | EXEC SQL UPDATE imembers | |
482 | SET ref_count = ref_count - :ref | |
483 | WHERE list_id = :lid AND member_id = :mid | |
484 | AND member_type = :mtype; | |
0659551f | 485 | } |
486 | } | |
3beadd83 | 487 | } |
5eaef520 | 488 | lid = *(int *)argv[0]; |
489 | entity = cl->entity; | |
490 | who = cl->client_id; | |
491 | EXEC SQL UPDATE list SET modtime = SYSDATE, modby = :who, modwith = :entity | |
492 | WHERE list_id = :lid; | |
493 | if (dbms_errno) | |
494 | return mr_errcode; | |
495 | return MR_SUCCESS; | |
5d677c81 | 496 | } |
b070f8a1 | 497 | |
498 | ||
7f6ea9fd | 499 | /* Don't allow someone to add someone to a list which is the acl of a |
500 | * query unless they're on the list acl, even if they're on the amtl | |
501 | * query acl! Also, don't allow someone proxying to add someone to a | |
502 | * capacl. | |
503 | */ | |
a37b0b99 | 504 | int acl_access_check(int list_id, client *cl) |
505 | { | |
506 | EXEC SQL BEGIN DECLARE SECTION; | |
507 | int c1, c2, lid = list_id, acl_id; | |
508 | char acl_type[LIST_ACL_TYPE_SIZE]; | |
509 | EXEC SQL END DECLARE SECTION; | |
510 | ||
511 | /* Check if the list is directly a capacl */ | |
512 | EXEC SQL SELECT COUNT(list_id) INTO :c1 FROM capacls WHERE list_id=:lid; | |
513 | ||
514 | /* Check if the list is a member (direct or indirect) of a list that | |
515 | is a capacl */ | |
516 | EXEC SQL SELECT COUNT(l1.list_id) INTO :c2 FROM list l1, list l2, | |
517 | imembers im, capacls c WHERE c.list_id = l2.list_id AND | |
518 | im.list_id = l2.list_id AND im.member_type = 'LIST' AND | |
519 | im.member_id = l1.list_id AND l1.list_id = :lid; | |
520 | ||
521 | if (c1 == 0 && c2 == 0) | |
522 | return 0; | |
523 | ||
7f6ea9fd | 524 | if (cl->proxy_id) |
525 | return 1; | |
526 | ||
a37b0b99 | 527 | EXEC SQL SELECT acl_type, acl_id INTO :acl_type, :acl_id |
528 | FROM list WHERE list_id=:lid; | |
529 | return !find_member(acl_type, acl_id, cl); | |
530 | } | |
531 | ||
532 | ||
0659551f | 533 | /* get_ace_use - given a type and a name, return a type and a name. |
534 | * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0], | |
535 | * and argv[1] will contain the ID of the entity in question. The R* | |
536 | * types mean to recursively look at every containing list, not just | |
537 | * when the object in question is a direct member. On return, the | |
538 | * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR. | |
b070f8a1 | 539 | */ |
540 | ||
5eaef520 | 541 | int get_ace_use(struct query *q, char *argv[], client *cl, |
7ac48069 | 542 | int (*action)(int, char *[], void *), void *actarg) |
5d677c81 | 543 | { |
5eaef520 | 544 | int found = 0; |
545 | EXEC SQL BEGIN DECLARE SECTION; | |
546 | char *atype; | |
547 | int aid, listid, id; | |
548 | EXEC SQL END DECLARE SECTION; | |
7ac48069 | 549 | struct save_queue *sq; |
5eaef520 | 550 | |
551 | atype = argv[0]; | |
552 | aid = *(int *)argv[1]; | |
553 | if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") || | |
554 | !strcmp(atype, "KERBEROS")) | |
555 | return get_ace_internal(atype, aid, action, actarg); | |
556 | ||
557 | sq = sq_create(); | |
558 | if (!strcmp(atype, "RLIST")) | |
559 | { | |
7ac48069 | 560 | sq_save_data(sq, (void *)aid); |
5eaef520 | 561 | /* get all the list_id's of containing lists */ |
562 | EXEC SQL DECLARE csr107 CURSOR FOR | |
563 | SELECT list_id FROM imembers | |
564 | WHERE member_type = 'LIST' AND member_id = :aid; | |
565 | if (dbms_errno) | |
566 | return mr_errcode; | |
567 | EXEC SQL OPEN csr107; | |
568 | if (dbms_errno) | |
569 | return mr_errcode; | |
570 | while (1) | |
571 | { | |
572 | EXEC SQL FETCH csr107 INTO :listid; | |
573 | if (sqlca.sqlcode) | |
574 | break; | |
7ac48069 | 575 | sq_save_unique_data(sq, (void *)listid); |
0659551f | 576 | } |
5eaef520 | 577 | EXEC SQL CLOSE csr107; |
578 | /* now process each one */ | |
579 | while (sq_get_data(sq, &id)) | |
580 | { | |
581 | if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS) | |
582 | found++; | |
0659551f | 583 | } |
584 | } | |
b070f8a1 | 585 | |
5eaef520 | 586 | if (!strcmp(atype, "RUSER")) |
587 | { | |
588 | EXEC SQL DECLARE csr108 CURSOR FOR | |
589 | SELECT list_id FROM imembers | |
590 | WHERE member_type = 'USER' AND member_id = :aid; | |
591 | if (dbms_errno) | |
592 | return mr_errcode; | |
593 | EXEC SQL OPEN csr108; | |
594 | if (dbms_errno) | |
595 | return mr_errcode; | |
596 | while (1) | |
597 | { | |
598 | EXEC SQL FETCH csr108 INTO :listid; | |
599 | if (sqlca.sqlcode) | |
600 | break; | |
7ac48069 | 601 | sq_save_data(sq, (void *)listid); |
0659551f | 602 | } |
5eaef520 | 603 | EXEC SQL CLOSE csr108; |
604 | /* now process each one */ | |
605 | while (sq_get_data(sq, &id)) | |
606 | { | |
607 | if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS) | |
608 | found++; | |
0659551f | 609 | } |
5eaef520 | 610 | if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS) |
611 | found++; | |
0659551f | 612 | } |
45bf7573 | 613 | |
5eaef520 | 614 | if (!strcmp(atype, "RKERBEROS")) |
615 | { | |
616 | EXEC SQL DECLARE csr109 CURSOR FOR | |
617 | SELECT list_id FROM imembers | |
618 | WHERE member_type = 'KERBEROS' AND member_id = :aid; | |
619 | if (dbms_errno) | |
620 | return mr_errcode; | |
621 | EXEC SQL OPEN csr109; | |
622 | if (dbms_errno) | |
623 | return mr_errcode; | |
624 | while (1) | |
625 | { | |
626 | EXEC SQL FETCH csr109 INTO :listid; | |
627 | if (sqlca.sqlcode) | |
628 | break; | |
7ac48069 | 629 | sq_save_data(sq, (void *)listid); |
0659551f | 630 | } |
5eaef520 | 631 | EXEC SQL CLOSE csr109; |
632 | /* now process each one */ | |
633 | while (sq_get_data(sq, &id)) | |
634 | { | |
635 | if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS) | |
636 | found++; | |
0659551f | 637 | } |
5eaef520 | 638 | if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS) |
639 | found++; | |
0659551f | 640 | } |
b3ce33fe | 641 | |
5eaef520 | 642 | sq_destroy(sq); |
643 | if (dbms_errno) | |
644 | return mr_errcode; | |
645 | if (!found) | |
646 | return MR_NO_MATCH; | |
647 | return MR_SUCCESS; | |
5d677c81 | 648 | } |
b070f8a1 | 649 | |
650 | ||
0659551f | 651 | /* This looks up a single list or user for ace use. atype must be "USER" |
652 | * or "LIST", and aid is the ID of the corresponding object. This is used | |
653 | * by get_ace_use above. | |
b070f8a1 | 654 | */ |
655 | ||
7ac48069 | 656 | int get_ace_internal(char *atype, int aid, |
657 | int (*action)(int, char *[], void *), void *actarg) | |
5d677c81 | 658 | { |
5eaef520 | 659 | char *rargv[2]; |
660 | int found = 0; | |
661 | EXEC SQL BEGIN DECLARE SECTION; | |
e688520a | 662 | char name[LIST_NAME_SIZE], *type = atype; |
5eaef520 | 663 | int id = aid; |
664 | EXEC SQL END DECLARE SECTION; | |
665 | ||
666 | rargv[1] = name; | |
667 | if (!strcmp(atype, "LIST")) | |
668 | { | |
669 | rargv[0] = "FILESYS"; | |
670 | EXEC SQL DECLARE csr110 CURSOR FOR | |
671 | SELECT label FROM filesys | |
672 | WHERE owners = :id; | |
673 | if (dbms_errno) | |
674 | return mr_errcode; | |
675 | EXEC SQL OPEN csr110; | |
676 | if (dbms_errno) | |
677 | return mr_errcode; | |
678 | while (1) | |
679 | { | |
680 | EXEC SQL FETCH csr110 INTO :name; | |
681 | if (sqlca.sqlcode) | |
682 | break; | |
683 | (*action)(2, rargv, actarg); | |
684 | found++; | |
b070f8a1 | 685 | } |
5eaef520 | 686 | EXEC SQL CLOSE csr110; |
687 | ||
688 | rargv[0] = "QUERY"; | |
689 | EXEC SQL DECLARE csr111 CURSOR FOR | |
690 | SELECT capability FROM capacls | |
691 | WHERE list_id = :id; | |
692 | if (dbms_errno) | |
693 | return mr_errcode; | |
694 | EXEC SQL OPEN csr111; | |
695 | if (dbms_errno) | |
696 | return mr_errcode; | |
697 | while (1) | |
698 | { | |
699 | EXEC SQL FETCH csr111 INTO :name; | |
700 | if (sqlca.sqlcode) | |
701 | break; | |
702 | (*action)(2, rargv, actarg); | |
703 | found++; | |
b070f8a1 | 704 | } |
5eaef520 | 705 | EXEC SQL CLOSE csr111; |
706 | } | |
707 | else if (!strcmp(atype, "USER")) | |
708 | { | |
709 | rargv[0] = "FILESYS"; | |
710 | EXEC SQL DECLARE csr112 CURSOR FOR | |
711 | SELECT label FROM filesys | |
712 | WHERE owner = :id; | |
713 | if (dbms_errno) | |
714 | return mr_errcode; | |
715 | EXEC SQL OPEN csr112; | |
716 | if (dbms_errno) | |
717 | return mr_errcode; | |
718 | while (1) | |
719 | { | |
720 | EXEC SQL FETCH csr112 INTO :name; | |
721 | if (sqlca.sqlcode) | |
722 | break; | |
723 | (*action)(2, rargv, actarg); | |
724 | found++; | |
b070f8a1 | 725 | } |
5eaef520 | 726 | EXEC SQL CLOSE csr112; |
b070f8a1 | 727 | } |
0fc7ab46 | 728 | |
5eaef520 | 729 | rargv[0] = "LIST"; |
730 | EXEC SQL DECLARE csr113 CURSOR FOR | |
731 | SELECT name FROM list | |
732 | WHERE acl_type = :type AND acl_id = :id; | |
733 | if (dbms_errno) | |
734 | return mr_errcode; | |
735 | EXEC SQL OPEN csr113; | |
736 | if (dbms_errno) | |
737 | return mr_errcode; | |
738 | while (1) | |
739 | { | |
740 | EXEC SQL FETCH csr113 INTO :name; | |
741 | if (sqlca.sqlcode) | |
742 | break; | |
743 | (*action)(2, rargv, actarg); | |
744 | found++; | |
5d677c81 | 745 | } |
5eaef520 | 746 | EXEC SQL CLOSE csr113; |
747 | ||
748 | rargv[0] = "SERVICE"; | |
749 | EXEC SQL DECLARE csr114 CURSOR FOR | |
750 | SELECT name FROM servers | |
751 | WHERE acl_type = :type AND acl_id = :id; | |
752 | if (dbms_errno) | |
753 | return mr_errcode; | |
754 | EXEC SQL OPEN csr114; | |
755 | if (dbms_errno) | |
756 | return mr_errcode; | |
757 | while (1) | |
758 | { | |
759 | EXEC SQL FETCH csr114 INTO :name; | |
760 | if (sqlca.sqlcode) | |
761 | break; | |
762 | (*action)(2, rargv, actarg); | |
763 | found++; | |
0fc7ab46 | 764 | } |
5eaef520 | 765 | EXEC SQL CLOSE csr114; |
b070f8a1 | 766 | |
5eaef520 | 767 | rargv[0] = "HOSTACCESS"; |
768 | EXEC SQL DECLARE csr115 CURSOR FOR | |
769 | SELECT name FROM machine m, hostaccess ha | |
770 | WHERE m.mach_id = ha.mach_id AND ha.acl_type = :type | |
771 | AND ha.acl_id = :id; | |
03c05291 | 772 | if (dbms_errno) |
5eaef520 | 773 | return mr_errcode; |
0659551f | 774 | EXEC SQL OPEN csr115; |
03c05291 | 775 | if (dbms_errno) |
5eaef520 | 776 | return mr_errcode; |
777 | while (1) | |
778 | { | |
0659551f | 779 | EXEC SQL FETCH csr115 INTO :name; |
5eaef520 | 780 | if (sqlca.sqlcode) |
781 | break; | |
0659551f | 782 | (*action)(2, rargv, actarg); |
783 | found++; | |
5eaef520 | 784 | } |
0659551f | 785 | EXEC SQL CLOSE csr115; |
b070f8a1 | 786 | |
0659551f | 787 | rargv[0] = "ZEPHYR"; |
788 | EXEC SQL DECLARE csr116 CURSOR FOR | |
789 | SELECT class FROM zephyr z | |
5eaef520 | 790 | WHERE z.xmt_type = :type AND z.xmt_id = :id |
791 | OR z.sub_type = :type AND z.sub_id = :id | |
792 | OR z.iws_type = :type AND z.iws_id = :id | |
793 | OR z.iui_type = :type AND z.iui_id = :id; | |
03c05291 | 794 | if (dbms_errno) |
5eaef520 | 795 | return mr_errcode; |
0659551f | 796 | EXEC SQL OPEN csr116; |
03c05291 | 797 | if (dbms_errno) |
5eaef520 | 798 | return mr_errcode; |
799 | while (1) | |
800 | { | |
0659551f | 801 | EXEC SQL FETCH csr116 INTO :name; |
5eaef520 | 802 | if (sqlca.sqlcode) |
803 | break; | |
0659551f | 804 | (*action)(2, rargv, actarg); |
805 | found++; | |
5eaef520 | 806 | } |
0659551f | 807 | EXEC SQL CLOSE csr116; |
b070f8a1 | 808 | |
5eaef520 | 809 | if (!found) |
810 | return MR_NO_MATCH; | |
811 | return MR_SUCCESS; | |
5d677c81 | 812 | } |
b070f8a1 | 813 | |
814 | ||
0659551f | 815 | /* get_lists_of_member - given a type and a name, return the name and flags |
816 | * of all of the lists of the given member. The member_type is one of | |
817 | * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0], | |
818 | * and argv[1] will contain the ID of the entity in question. The R* | |
819 | * types mean to recursively look at every containing list, not just | |
820 | * when the object in question is a direct member. | |
821 | */ | |
b070f8a1 | 822 | |
5eaef520 | 823 | int get_lists_of_member(struct query *q, char *argv[], client *cl, |
7ac48069 | 824 | int (*action)(int, char *[], void *), void *actarg) |
0659551f | 825 | { |
5eaef520 | 826 | int found = 0, direct = 1; |
827 | char *rargv[6]; | |
828 | EXEC SQL BEGIN DECLARE SECTION; | |
829 | char *atype; | |
830 | int aid; | |
e688520a | 831 | char name[LIST_NAME_SIZE]; |
832 | char active[5], public[5], hidden[5], maillist[5], grouplist[5]; | |
5eaef520 | 833 | EXEC SQL END DECLARE SECTION; |
834 | ||
835 | atype = argv[0]; | |
836 | aid = *(int *)argv[1]; | |
837 | if (!strcmp(atype, "RLIST")) | |
838 | { | |
839 | atype = "LIST"; | |
840 | direct = 0; | |
0659551f | 841 | } |
5eaef520 | 842 | if (!strcmp(atype, "RUSER")) |
843 | { | |
844 | atype = "USER"; | |
845 | direct = 0; | |
0659551f | 846 | } |
5eaef520 | 847 | if (!strcmp(atype, "RSTRING")) |
848 | { | |
849 | atype = "STRING"; | |
850 | direct = 0; | |
0659551f | 851 | } |
5eaef520 | 852 | if (!strcmp(atype, "RKERBEROS")) |
853 | { | |
854 | atype = "KERBEROS"; | |
855 | direct = 0; | |
0659551f | 856 | } |
b070f8a1 | 857 | |
5eaef520 | 858 | rargv[0] = name; |
859 | rargv[1] = active; | |
860 | rargv[2] = public; | |
861 | rargv[3] = hidden; | |
862 | rargv[4] = maillist; | |
863 | rargv[5] = grouplist; | |
864 | if (direct) | |
865 | { | |
866 | EXEC SQL DECLARE csr117a CURSOR FOR | |
867 | SELECT l.name, l.active, l.publicflg, l.hidden, l.maillist, l.grouplist | |
868 | FROM list l, imembers im | |
869 | WHERE l.list_id = im.list_id AND im.direct = 1 | |
870 | AND im.member_type = :atype AND im.member_id = :aid; | |
871 | if (dbms_errno) | |
872 | return mr_errcode; | |
873 | EXEC SQL OPEN csr117a; | |
874 | if (dbms_errno) | |
875 | return mr_errcode; | |
876 | while (1) | |
877 | { | |
878 | EXEC SQL FETCH csr117a | |
879 | INTO :name, :active, :public, :hidden, :maillist, :grouplist; | |
880 | if (sqlca.sqlcode) | |
881 | break; | |
882 | (*action)(6, rargv, actarg); | |
883 | found++; | |
0659551f | 884 | } |
5eaef520 | 885 | EXEC SQL CLOSE csr117a; |
886 | } | |
887 | else | |
888 | { | |
889 | EXEC SQL DECLARE csr117b CURSOR FOR | |
890 | SELECT l.name, l.active, l.publicflg, l.hidden, l.maillist, l.grouplist | |
891 | FROM list l, imembers im | |
892 | WHERE l.list_id = im.list_id | |
893 | AND im.member_type = :atype AND im.member_id = :aid; | |
894 | if (dbms_errno) | |
895 | return mr_errcode; | |
896 | EXEC SQL OPEN csr117b; | |
897 | if (dbms_errno) | |
898 | return mr_errcode; | |
899 | while (1) | |
900 | { | |
901 | EXEC SQL FETCH csr117b | |
902 | INTO :name, :active, :public, :hidden, :maillist, :grouplist; | |
903 | if (sqlca.sqlcode) | |
904 | break; | |
905 | (*action)(6, rargv, actarg); | |
906 | found++; | |
0659551f | 907 | } |
5eaef520 | 908 | EXEC SQL CLOSE csr117b; |
038fd8a4 | 909 | } |
0659551f | 910 | |
5eaef520 | 911 | if (dbms_errno) |
912 | return mr_errcode; | |
913 | if (!found) | |
914 | return MR_NO_MATCH; | |
915 | return MR_SUCCESS; | |
038fd8a4 | 916 | } |
917 | ||
b070f8a1 | 918 | |
0659551f | 919 | /* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of |
920 | * the five flags associated with each list. It will return the name of | |
921 | * each list that meets the quailifications. It does this by building a | |
922 | * where clause based on the arguments, then doing a retrieve. | |
923 | */ | |
924 | ||
925 | static char *lflags[5] = { "active", "publicflg", "hidden", "maillist", "grouplist" }; | |
b070f8a1 | 926 | |
5eaef520 | 927 | int qualified_get_lists(struct query *q, char *argv[], client *cl, |
7ac48069 | 928 | int (*action)(int, char *[], void *), void *actarg) |
5d677c81 | 929 | { |
5eaef520 | 930 | return qualified_get(q, argv, action, actarg, "l.list_id != 0", |
931 | "l", "name", lflags); | |
0659551f | 932 | } |
0fc7ab46 | 933 | |
5d677c81 | 934 | |
5eaef520 | 935 | int get_members_of_list(struct query *q, char *argv[], client *cl, |
7ac48069 | 936 | int (*action)(int, char *[], void *), void *actarg) |
0659551f | 937 | { |
5eaef520 | 938 | EXEC SQL BEGIN DECLARE SECTION; |
7ac48069 | 939 | int list_id, direct; |
46b6f1f6 | 940 | char member_name[MAX_FIELD_WIDTH], tag[STRINGS_STRING_SIZE]; |
5eaef520 | 941 | EXEC SQL END DECLARE SECTION; |
46b6f1f6 | 942 | char *targv[3]; |
943 | int targc; | |
5eaef520 | 944 | |
46b6f1f6 | 945 | /* For gmol or gtml, only get direct members. For geml, get all. */ |
946 | if (!strcmp(q->shortname, "geml")) | |
947 | direct = -1; | |
948 | else | |
5eaef520 | 949 | direct = 0; |
46b6f1f6 | 950 | |
951 | /* For gmol or geml, only return type and name. For gtml, return tag too. */ | |
952 | if (!strcmp(q->shortname, "gtml")) | |
953 | targc = 3; | |
5eaef520 | 954 | else |
46b6f1f6 | 955 | targc = 2; |
5eaef520 | 956 | |
957 | list_id = *(int *)argv[0]; | |
958 | ||
959 | targv[1] = member_name; | |
46b6f1f6 | 960 | targv[2] = tag; |
961 | ||
5eaef520 | 962 | targv[0] = "USER"; |
963 | EXEC SQL DECLARE csr119 CURSOR FOR | |
46b6f1f6 | 964 | SELECT u.login, s.string FROM users u, imembers im, strings s |
5eaef520 | 965 | WHERE im.list_id = :list_id AND im.member_type = 'USER' |
966 | AND im.member_id = u.users_id AND im.direct > :direct | |
46b6f1f6 | 967 | AND s.string_id = im.tag ORDER BY 1; |
5eaef520 | 968 | if (dbms_errno) |
969 | return mr_errcode; | |
970 | EXEC SQL OPEN csr119; | |
971 | if (dbms_errno) | |
972 | return mr_errcode; | |
973 | while (1) | |
974 | { | |
46b6f1f6 | 975 | EXEC SQL FETCH csr119 INTO :member_name, :tag; |
5eaef520 | 976 | if (sqlca.sqlcode) |
977 | break; | |
46b6f1f6 | 978 | (*action)(targc, targv, actarg); |
b070f8a1 | 979 | } |
5eaef520 | 980 | EXEC SQL CLOSE csr119; |
981 | if (dbms_errno) | |
982 | return mr_errcode; | |
983 | ||
984 | targv[0] = "LIST"; | |
985 | EXEC SQL DECLARE csr120 CURSOR FOR | |
46b6f1f6 | 986 | SELECT l.name, s.string FROM list l, imembers im, strings s |
5eaef520 | 987 | WHERE im.list_id = :list_id AND im.member_type = 'LIST' |
988 | AND im.member_id = l.list_id AND im.direct > :direct | |
46b6f1f6 | 989 | AND s.string_id = im.tag ORDER BY 1; |
5eaef520 | 990 | if (dbms_errno) |
991 | return mr_errcode; | |
992 | EXEC SQL OPEN csr120; | |
993 | if (dbms_errno) | |
994 | return mr_errcode; | |
995 | while (1) | |
996 | { | |
46b6f1f6 | 997 | EXEC SQL FETCH csr120 INTO :member_name, :tag; |
5eaef520 | 998 | if (sqlca.sqlcode) |
999 | break; | |
46b6f1f6 | 1000 | (*action)(targc, targv, actarg); |
b070f8a1 | 1001 | } |
5eaef520 | 1002 | EXEC SQL CLOSE csr120; |
1003 | if (dbms_errno) | |
1004 | return mr_errcode; | |
1005 | ||
1006 | targv[0] = "STRING"; | |
1007 | EXEC SQL DECLARE csr121 CURSOR FOR | |
46b6f1f6 | 1008 | SELECT str.string, s.string FROM strings str, imembers im, strings s |
5eaef520 | 1009 | WHERE im.list_id = :list_id AND im.member_type = 'STRING' |
1010 | AND im.member_id = str.string_id AND im.direct > :direct | |
46b6f1f6 | 1011 | AND s.string_id = im.tag ORDER BY 1; |
5eaef520 | 1012 | if (dbms_errno) |
1013 | return mr_errcode; | |
1014 | EXEC SQL OPEN csr121; | |
1015 | if (dbms_errno) | |
1016 | return mr_errcode; | |
1017 | while (1) | |
1018 | { | |
46b6f1f6 | 1019 | EXEC SQL FETCH csr121 INTO :member_name, :tag; |
5eaef520 | 1020 | if (sqlca.sqlcode) |
1021 | break; | |
46b6f1f6 | 1022 | (*action)(targc, targv, actarg); |
b070f8a1 | 1023 | } |
5eaef520 | 1024 | EXEC SQL CLOSE csr121; |
1025 | if (dbms_errno) | |
1026 | return mr_errcode; | |
1027 | ||
1028 | targv[0] = "KERBEROS"; | |
1029 | EXEC SQL DECLARE csr122 CURSOR FOR | |
46b6f1f6 | 1030 | SELECT str.string, s.string FROM strings str, imembers im, strings s |
5eaef520 | 1031 | WHERE im.list_id = :list_id AND im.member_type = 'KERBEROS' |
46b6f1f6 | 1032 | AND im.member_id = str.string_id AND im.direct > :direct |
1033 | AND s.string_id = im.tag ORDER BY 1; | |
5eaef520 | 1034 | if (dbms_errno) |
1035 | return mr_errcode; | |
1036 | EXEC SQL OPEN csr122; | |
1037 | if (dbms_errno) | |
1038 | return mr_errcode; | |
1039 | while (1) | |
1040 | { | |
46b6f1f6 | 1041 | EXEC SQL FETCH csr122 INTO :member_name, :tag; |
5eaef520 | 1042 | if (sqlca.sqlcode) |
1043 | break; | |
46b6f1f6 | 1044 | (*action)(targc, targv, actarg); |
0659551f | 1045 | } |
5eaef520 | 1046 | EXEC SQL CLOSE csr122; |
1047 | if (dbms_errno) | |
1048 | return mr_errcode; | |
b070f8a1 | 1049 | |
5eaef520 | 1050 | return MR_SUCCESS; |
5d677c81 | 1051 | } |
b070f8a1 | 1052 | |
1053 | ||
0659551f | 1054 | /* count_members_of_list: this is a simple query, but it cannot be done |
1055 | * through the dispatch table. | |
1056 | */ | |
b070f8a1 | 1057 | |
5eaef520 | 1058 | int count_members_of_list(struct query *q, char *argv[], client *cl, |
7ac48069 | 1059 | int (*action)(int, char *[], void *), void *actarg) |
5d677c81 | 1060 | { |
5eaef520 | 1061 | EXEC SQL BEGIN DECLARE SECTION; |
1062 | int list, ct = 0; | |
1063 | EXEC SQL END DECLARE SECTION; | |
1064 | char *rargv[1], countbuf[5]; | |
1065 | ||
1066 | list = *(int *)argv[0]; | |
1067 | rargv[0] = countbuf; | |
1068 | EXEC SQL SELECT count (*) INTO :ct FROM imembers | |
1069 | WHERE list_id = :list AND direct = 1; | |
1070 | if (dbms_errno) | |
1071 | return mr_errcode; | |
1072 | sprintf(countbuf, "%d", ct); | |
1073 | (*action)(1, rargv, actarg); | |
1074 | return MR_SUCCESS; | |
5d677c81 | 1075 | } |
b070f8a1 | 1076 | |
b070f8a1 | 1077 | |
0659551f | 1078 | /* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of |
1079 | * the three flags associated with each service. It will return the name of | |
1080 | * each service that meets the quailifications. It does this by building a | |
1081 | * where clause based on the arguments, then doing a retrieve. | |
1082 | */ | |
b070f8a1 | 1083 | |
0659551f | 1084 | static char *sflags[3] = { "enable", "inprogress", "harderror" }; |
b070f8a1 | 1085 | |
5eaef520 | 1086 | int qualified_get_server(struct query *q, char *argv[], client *cl, |
7ac48069 | 1087 | int (*action)(int, char *[], void *), void *actarg) |
5d677c81 | 1088 | { |
5eaef520 | 1089 | return qualified_get(q, argv, action, actarg, "s.name is not null", |
1090 | "s", "name", sflags); | |
1091 | /* of course, name will never be null, but we need something there | |
1092 | to make qualified_get happy */ | |
5d677c81 | 1093 | } |
b070f8a1 | 1094 | |
1095 | ||
0659551f | 1096 | /* generic qualified get routine, used by qualified_get_lists, |
1097 | * qualified_get_server, and qualified_get_serverhost. | |
1098 | * Args: | |
1099 | * start - a simple where clause, must not be empty | |
1100 | * range - the name of the range variable | |
1101 | * field - the field to return | |
1102 | * flags - an array of strings, names of the flag variables | |
b070f8a1 | 1103 | */ |
1104 | ||
7ac48069 | 1105 | int qualified_get(struct query *q, char *argv[], |
1106 | int (*action)(int, char *[], void *), void *actarg, | |
5eaef520 | 1107 | char *start, char *range, char *field, char *flags[]) |
453b99fe | 1108 | { |
5eaef520 | 1109 | char qual[256]; |
1110 | int i; | |
1111 | char buf[32]; | |
1112 | ||
1113 | strcpy(qual, start); | |
1114 | for (i = 0; i < q->argc; i++) | |
1115 | { | |
1116 | if (!strcmp(argv[i], "TRUE")) | |
1117 | { | |
1118 | sprintf(buf, " AND %s.%s != 0", range, flags[i]); | |
1119 | strcat(qual, buf); | |
1120 | } | |
1121 | else if (!strcmp(argv[i], "FALSE")) | |
1122 | { | |
1123 | sprintf(buf, " AND %s.%s = 0", range, flags[i]); | |
1124 | strcat(qual, buf); | |
0659551f | 1125 | } |
453b99fe | 1126 | } |
1127 | ||
5eaef520 | 1128 | sprintf(stmt_buf, "SELECT %s.%s FROM %s %s WHERE %s", range, field, |
1129 | table_name[q->rtable], range, qual); | |
1130 | return do_for_all_rows(stmt_buf, 1, action, actarg); | |
453b99fe | 1131 | } |
1132 | ||
1133 | ||
0659551f | 1134 | /* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of |
1135 | * the five flags associated with each serverhost. It will return the name of | |
1136 | * each service and host that meets the quailifications. It does this by | |
1137 | * building a where clause based on the arguments, then doing a retrieve. | |
45bf7573 | 1138 | */ |
45bf7573 | 1139 | |
0659551f | 1140 | static char *shflags[6] = { "service", "enable", "override", "success", |
1141 | "inprogress", "hosterror" }; | |
45bf7573 | 1142 | |
5eaef520 | 1143 | int qualified_get_serverhost(struct query *q, char *argv[], client *cl, |
7ac48069 | 1144 | int (*action)(int, char *[], void *), |
1145 | void *actarg) | |
45bf7573 | 1146 | { |
5eaef520 | 1147 | char qual[256], buf[32]; |
1148 | int i; | |
1149 | ||
1150 | sprintf(qual, "m.mach_id = sh.mach_id AND sh.service = UPPER('%s')", | |
1151 | argv[0]); | |
1152 | for (i = 1; i < q->argc; i++) | |
1153 | { | |
1154 | if (!strcmp(argv[i], "TRUE")) | |
1155 | { | |
1156 | sprintf(buf, " AND sh.%s != 0", shflags[i]); | |
1157 | strcat(qual, buf); | |
1158 | } | |
1159 | else if (!strcmp(argv[i], "FALSE")) | |
1160 | { | |
1161 | sprintf(buf, " AND sh.%s = 0", shflags[i]); | |
1162 | strcat(qual, buf); | |
0659551f | 1163 | } |
1164 | } | |
45bf7573 | 1165 | |
5eaef520 | 1166 | sprintf(stmt_buf, "SELECT sh.service, m.name FROM serverhosts sh, " |
1167 | "machine m WHERE %s", qual); | |
1168 | return do_for_all_rows(stmt_buf, 2, action, actarg); | |
45bf7573 | 1169 | } |
1170 | ||
0659551f | 1171 | |
1172 | /* register_user - change user's login name and allocate a pobox, group, | |
1173 | * filesystem, and quota for them. The user's status must start out as 0, | |
1174 | * and is left as 2. Arguments are: user's UID, new login name, and user's | |
1175 | * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY, | |
1176 | * MR_FS_STAFF, MR_FS_MISC). | |
99e09b48 | 1177 | */ |
0659551f | 1178 | |
5eaef520 | 1179 | int register_user(struct query *q, char **argv, client *cl) |
99e09b48 | 1180 | { |
5eaef520 | 1181 | EXEC SQL BEGIN DECLARE SECTION; |
e688520a | 1182 | char *login, *entity; |
1183 | char directory[FILESYS_NAME_SIZE], machname[MACHINE_NAME_SIZE]; | |
5eaef520 | 1184 | int who, rowcount, mid, uid, users_id, utype, list_id; |
7ac48069 | 1185 | int ostatus, nstatus, fsidval; |
5eaef520 | 1186 | static int m_id = 0, def_quota = 0; |
1187 | EXEC SQL END DECLARE SECTION; | |
1188 | char buffer[256], *aargv[3]; | |
1189 | ||
1190 | entity = cl->entity; | |
1191 | who = cl->client_id; | |
1192 | ||
1193 | uid = atoi(argv[0]); | |
1194 | login = argv[1]; | |
1195 | utype = atoi(argv[2]); | |
1196 | ||
1197 | /* find user */ | |
1198 | EXEC SQL SELECT users_id, status INTO :users_id, :ostatus | |
1199 | FROM users | |
1200 | WHERE unix_uid = :uid AND (status = 0 OR status = 5 OR status = 6); | |
1201 | ||
1202 | if (sqlca.sqlerrd[2] == 0) | |
1203 | return MR_NO_MATCH; | |
1204 | if (sqlca.sqlerrd[2] > 1) | |
1205 | return MR_NOT_UNIQUE; | |
1206 | ||
1207 | /* check new login name */ | |
1208 | EXEC SQL SELECT COUNT(login) INTO :rowcount FROM users | |
1209 | WHERE login = :login AND users_id != :users_id; | |
1210 | if (dbms_errno) | |
1211 | return mr_errcode; | |
1212 | if (rowcount > 0) | |
1213 | return MR_IN_USE; | |
1214 | EXEC SQL SELECT COUNT(name) INTO :rowcount FROM list | |
ec0b8003 | 1215 | WHERE LOWER(name) = :login; |
5eaef520 | 1216 | if (dbms_errno) |
1217 | return mr_errcode; | |
1218 | if (rowcount > 0) | |
1219 | return MR_IN_USE; | |
1220 | EXEC SQL SELECT COUNT(label) INTO :rowcount FROM filesys | |
1221 | WHERE label = :login; | |
1222 | if (dbms_errno) | |
1223 | return mr_errcode; | |
1224 | if (rowcount > 0) | |
1225 | return MR_IN_USE; | |
1226 | EXEC SQL SELECT COUNT(name) INTO :rowcount FROM alias | |
1227 | WHERE name = :login AND type = 'FILESYS'; | |
1228 | if (dbms_errno) | |
1229 | return mr_errcode; | |
1230 | if (rowcount > 0) | |
1231 | return MR_IN_USE; | |
1232 | com_err(whoami, 0, "login name OK"); | |
1233 | ||
1234 | /* choose place for pobox, put in mid */ | |
1235 | EXEC SQL DECLARE csr130 CURSOR FOR | |
1236 | SELECT sh.mach_id, m.name FROM serverhosts sh, machine m | |
1237 | WHERE sh.service = 'POP' AND sh.mach_id = m.mach_id | |
1238 | AND sh.value2 - sh.value1 = (SELECT MAX(value2 - value1) FROM serverhosts | |
1239 | WHERE service = 'POP'); | |
1240 | if (dbms_errno) | |
1241 | return mr_errcode; | |
1242 | EXEC SQL OPEN csr130; | |
1243 | if (dbms_errno) | |
1244 | return mr_errcode; | |
1245 | EXEC SQL FETCH csr130 INTO :mid, :machname; | |
1246 | if (sqlca.sqlerrd[2] == 0) | |
1247 | { | |
1248 | EXEC SQL CLOSE csr130; | |
1249 | if (dbms_errno) | |
1250 | return mr_errcode; | |
1251 | return MR_NO_POBOX; | |
1252 | } | |
1253 | else | |
1254 | { | |
1255 | EXEC SQL CLOSE csr130; | |
1256 | if (dbms_errno) | |
1257 | return mr_errcode; | |
99e09b48 | 1258 | } |
99e09b48 | 1259 | |
5eaef520 | 1260 | /* change login name, set pobox */ |
1261 | sprintf(buffer, "u.users_id = %d", users_id); | |
1262 | incremental_before(USERS_TABLE, buffer, 0); | |
1263 | nstatus = 2; | |
1264 | if (ostatus == 5 || ostatus == 6) | |
1265 | nstatus = 1; | |
1266 | EXEC SQL UPDATE users SET login = :login, status = :nstatus, | |
1267 | modtime = SYSDATE, modby = :who, modwith = :entity, potype = 'POP', | |
1268 | pop_id = :mid, pmodtime = SYSDATE, pmodby = :who, pmodwith = :entity | |
1269 | WHERE users_id = :users_id; | |
1270 | ||
1271 | if (dbms_errno) | |
1272 | return mr_errcode; | |
1273 | if (sqlca.sqlerrd[2] != 1) | |
1274 | return MR_INTERNAL; | |
1275 | set_pop_usage(mid, 1); | |
1276 | com_err(whoami, 0, "set login name to %s and pobox to %s", login, | |
1277 | strtrim(machname)); | |
1278 | incremental_after(USERS_TABLE, buffer, 0); | |
1279 | ||
1280 | if (m_id == 0) | |
1281 | { | |
1282 | /* Cell Name (I know, it shouldn't be hard coded...) */ | |
1283 | strcpy(machname, "ATHENA.MIT.EDU"); | |
1284 | EXEC SQL SELECT mach_id INTO :m_id FROM machine | |
1285 | WHERE name = :machname; | |
0659551f | 1286 | } |
3beadd83 | 1287 | |
5eaef520 | 1288 | EXEC SQL SELECT list_id INTO :list_id FROM list |
1289 | WHERE name = 'wheel'; | |
1290 | ||
1291 | /* create filesystem */ | |
1292 | if (set_next_object_id("filsys_id", FILESYS_TABLE, 0)) | |
1293 | return MR_NO_ID; | |
1294 | incremental_clear_before(); | |
1295 | if (islower(login[0]) && islower(login[1])) | |
1296 | { | |
1297 | sprintf(directory, "/afs/athena.mit.edu/user/%c/%c/%s", | |
1298 | login[0], login[1], login); | |
0659551f | 1299 | } |
5eaef520 | 1300 | else |
1301 | sprintf(directory, "/afs/athena.mit.edu/user/other/%s", login); | |
1302 | ||
1303 | EXEC SQL SELECT value INTO :fsidval FROM numvalues | |
1304 | WHERE numvalues.name = 'filsys_id'; | |
1305 | EXEC SQL INSERT INTO filesys | |
1306 | (filsys_id, phys_id, label, type, mach_id, name, | |
1307 | mount, rwaccess, comments, owner, owners, createflg, | |
1308 | lockertype, modtime, modby, modwith) | |
1309 | VALUES | |
1310 | (:fsidval, 0, :login, 'AFS', :m_id, :directory, | |
1311 | '/mit/' || :login, 'w', 'User Locker', :users_id, :list_id, 1, | |
1312 | 'HOMEDIR', SYSDATE, :who, :entity); | |
1313 | ||
1314 | if (dbms_errno) | |
1315 | return mr_errcode; | |
1316 | if (sqlca.sqlerrd[2] != 1) | |
1317 | return MR_INTERNAL; | |
1318 | sprintf(buffer, "fs.filsys_id = %d", fsidval); | |
1319 | incremental_after(FILESYS_TABLE, buffer, 0); | |
1320 | ||
1321 | /* set quota */ | |
1322 | if (def_quota == 0) | |
1323 | { | |
1324 | EXEC SQL SELECT value INTO :def_quota FROM numvalues | |
1325 | WHERE name = 'def_quota'; | |
1326 | if (dbms_errno) | |
1327 | return mr_errcode; | |
1328 | if (sqlca.sqlerrd[2] != 1) | |
1329 | return MR_NO_QUOTA; | |
0659551f | 1330 | } |
5eaef520 | 1331 | incremental_clear_before(); |
1332 | EXEC SQL INSERT INTO quota | |
1333 | (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith) | |
1334 | VALUES (0, :fsidval, 'ANY', :def_quota, 0, SYSDATE, :who, :entity); | |
1335 | if (dbms_errno) | |
1336 | return mr_errcode; | |
1337 | if (sqlca.sqlerrd[2] != 1) | |
1338 | return MR_INTERNAL; | |
1339 | aargv[0] = login; | |
1340 | aargv[1] = "ANY"; | |
1341 | aargv[2] = login; | |
1342 | sprintf(buffer, "q.entity_id = 0 and q.filsys_id = %d and q.type = 'ANY'", | |
1343 | fsidval); | |
1344 | incremental_after(QUOTA_TABLE, buffer, aargv); | |
1345 | com_err(whoami, 0, "quota of %d assigned", def_quota); | |
1346 | if (dbms_errno) | |
1347 | return mr_errcode; | |
1348 | ||
1349 | cache_entry(login, USERS_TABLE, users_id); | |
1350 | ||
1351 | EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE | |
1352 | WHERE table_name = 'users'; | |
1353 | EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = SYSDATE | |
1354 | WHERE table_name = 'filesys' OR table_name = 'quota'; | |
1355 | if (dbms_errno) | |
1356 | return mr_errcode; | |
1357 | return MR_SUCCESS; | |
3afb5524 | 1358 | } |
1359 | ||
835aabee | 1360 | |
1361 | ||
0659551f | 1362 | /** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe |
1363 | ** | |
1364 | ** Inputs: | |
1365 | ** id of machine | |
1366 | ** delta (will be +/- 1) | |
1367 | ** | |
1368 | ** Description: | |
1369 | ** - incr/decr value field in serverhosts table for pop/mach_id | |
1370 | ** | |
1371 | **/ | |
1372 | ||
1373 | int set_pop_usage(id, cnt) | |
03c05291 | 1374 | int id, cnt; |
0659551f | 1375 | { |
5eaef520 | 1376 | EXEC SQL BEGIN DECLARE SECTION; |
1377 | int iid = id, icnt = cnt; | |
1378 | EXEC SQL END DECLARE SECTION; | |
03c05291 | 1379 | |
5eaef520 | 1380 | EXEC SQL UPDATE serverhosts SET value1 = value1 + :icnt |
1381 | WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :iid; | |
835aabee | 1382 | |
5eaef520 | 1383 | if (dbms_errno) |
1384 | return mr_errcode; | |
1385 | return MR_SUCCESS; | |
835aabee | 1386 | } |
1387 |