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