1 | /* $Id$ |
---|
2 | * |
---|
3 | * Query setup routines |
---|
4 | * |
---|
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>. |
---|
8 | */ |
---|
9 | |
---|
10 | #include <mit-copyright.h> |
---|
11 | #include "mr_server.h" |
---|
12 | #include "query.h" |
---|
13 | #include "qrtn.h" |
---|
14 | |
---|
15 | #include <arpa/inet.h> |
---|
16 | #include <netinet/in.h> |
---|
17 | |
---|
18 | #include <ctype.h> |
---|
19 | #include <stdlib.h> |
---|
20 | #include <string.h> |
---|
21 | |
---|
22 | EXEC SQL INCLUDE sqlca; |
---|
23 | |
---|
24 | RCSID("$Header$"); |
---|
25 | |
---|
26 | extern char *whoami; |
---|
27 | extern int dbms_errno, mr_errcode; |
---|
28 | |
---|
29 | EXEC SQL BEGIN DECLARE SECTION; |
---|
30 | extern char stmt_buf[]; |
---|
31 | EXEC SQL END DECLARE SECTION; |
---|
32 | |
---|
33 | EXEC SQL WHENEVER SQLERROR DO dbmserr(); |
---|
34 | |
---|
35 | int hostname_check(char *name); |
---|
36 | int hostinfo_check(char *name, int num); |
---|
37 | int prefetch_value(struct query *q, char **argv, client *cl); |
---|
38 | int check_nfs(int mach_idx, char *name, char *access); |
---|
39 | int check_mailman_listname(char *name, const char *suffix); |
---|
40 | |
---|
41 | /* Setup Routines */ |
---|
42 | |
---|
43 | /* Setup routine for add_user |
---|
44 | * |
---|
45 | * Inputs: argv[0] - login |
---|
46 | * argv[1] - uid |
---|
47 | * |
---|
48 | * Description: |
---|
49 | * |
---|
50 | * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid) |
---|
51 | * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>" |
---|
52 | */ |
---|
53 | |
---|
54 | int setup_ausr(struct query *q, char *argv[], client *cl) |
---|
55 | { |
---|
56 | int row, err; |
---|
57 | EXEC SQL BEGIN DECLARE SECTION; |
---|
58 | int nuid; |
---|
59 | EXEC SQL END DECLARE SECTION; |
---|
60 | |
---|
61 | if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac")) |
---|
62 | row = 2; |
---|
63 | else |
---|
64 | row = 1; |
---|
65 | |
---|
66 | if (q->version > 2) |
---|
67 | { |
---|
68 | if (strlen(argv[row + 3]) + strlen(argv[row + 4]) + |
---|
69 | strlen(argv[row + 5]) + 2 > USERS_FULLNAME_SIZE) |
---|
70 | return MR_ARG_TOO_LONG; |
---|
71 | } |
---|
72 | else |
---|
73 | { |
---|
74 | if (strlen(argv[row + 2]) + strlen(argv[row + 3]) + |
---|
75 | strlen(argv[row + 4]) + 2 > USERS_FULLNAME_SIZE) |
---|
76 | return MR_ARG_TOO_LONG; |
---|
77 | } |
---|
78 | |
---|
79 | if (q->version > 10) |
---|
80 | { |
---|
81 | /* For both winhomedir and winprofiledir, we allow values of the |
---|
82 | * following forms: |
---|
83 | * |
---|
84 | * [AFS] - Magic token for AFS home directory. |
---|
85 | * [LOCAL] - Magic token for AD default local values, i.e. C:\<mumble> |
---|
86 | * [DFS] - Magic token for DFS home directory |
---|
87 | * UNC pathname - \\<something> |
---|
88 | * local pathname - <drive letter>:<something> |
---|
89 | */ |
---|
90 | |
---|
91 | if ((strcasecmp(argv[row + 12], "[AFS]")) && |
---|
92 | (strcasecmp(argv[row + 12], "[LOCAL]")) && |
---|
93 | (strcasecmp(argv[row + 12], "[DFS]")) && |
---|
94 | (!(argv[row + 12][0] == '\\' && argv[row + 12][1] == '\\')) && |
---|
95 | (!(isalpha(*argv[row + 12]) && (argv[row + 12][1] == ':')))) |
---|
96 | return MR_BAD_CHAR; |
---|
97 | |
---|
98 | if ((strcasecmp(argv[row + 13], "[AFS]")) && |
---|
99 | (strcasecmp(argv[row + 13], "[LOCAL]")) && |
---|
100 | (strcasecmp(argv[row + 13], "[DFS]")) && |
---|
101 | (!(argv[row + 13][0] == '\\' && argv[row + 13][1] == '\\')) && |
---|
102 | (!(isalpha(*argv[row + 13]) && (argv[row + 13][1] == ':')))) |
---|
103 | return MR_BAD_CHAR; |
---|
104 | } |
---|
105 | |
---|
106 | if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1) |
---|
107 | { |
---|
108 | if ((err = set_next_object_id("unix_uid", USERS_TABLE, 1))) |
---|
109 | return err; |
---|
110 | EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'unix_uid'; |
---|
111 | if (sqlca.sqlerrd[2] != 1) |
---|
112 | return MR_INTERNAL; |
---|
113 | sprintf(argv[row], "%d", nuid); |
---|
114 | } |
---|
115 | |
---|
116 | if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1) |
---|
117 | sprintf(argv[0], "#%s", argv[row]); |
---|
118 | |
---|
119 | if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS) |
---|
120 | return mr_errcode; |
---|
121 | |
---|
122 | /* If this is an MR_Q_UPDATE query, we're done. */ |
---|
123 | if (row == 2) |
---|
124 | return MR_SUCCESS; |
---|
125 | |
---|
126 | /* For an add query, we need to fill in the creator id. */ |
---|
127 | sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id); |
---|
128 | return MR_SUCCESS; |
---|
129 | } |
---|
130 | |
---|
131 | |
---|
132 | /* setup_dusr - verify that the user is no longer being referenced |
---|
133 | * and may safely be deleted. |
---|
134 | */ |
---|
135 | |
---|
136 | int setup_dusr(struct query *q, char *argv[], client *cl) |
---|
137 | { |
---|
138 | EXEC SQL BEGIN DECLARE SECTION; |
---|
139 | int flag, id, cnt; |
---|
140 | char resv[USERS_RESERVATIONS_SIZE]; |
---|
141 | EXEC SQL END DECLARE SECTION; |
---|
142 | |
---|
143 | id = *(int *)argv[0]; |
---|
144 | |
---|
145 | /* For now, only allow users to be deleted if their status is |
---|
146 | * one of 0, 4, or 8 (the various registerable statuses) |
---|
147 | * and we have no reservations about deleting them. |
---|
148 | */ |
---|
149 | EXEC SQL SELECT status, reservations INTO :flag, :resv |
---|
150 | FROM users WHERE users_id = :id; |
---|
151 | if ((flag != 0 && flag != 4 && flag != 8) || *resv) |
---|
152 | return MR_IN_USE; |
---|
153 | |
---|
154 | EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers |
---|
155 | WHERE member_id = :id AND member_type = 'USER'; |
---|
156 | if (cnt > 0) |
---|
157 | return MR_IN_USE; |
---|
158 | EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys |
---|
159 | WHERE owner = :id; |
---|
160 | if (cnt > 0) |
---|
161 | return MR_IN_USE; |
---|
162 | EXEC SQL SELECT COUNT(name) INTO :cnt FROM list |
---|
163 | WHERE acl_id = :id AND acl_type = 'USER'; |
---|
164 | if (cnt > 0) |
---|
165 | return MR_IN_USE; |
---|
166 | EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers |
---|
167 | WHERE acl_id = :id AND acl_type = 'USER'; |
---|
168 | if (cnt > 0) |
---|
169 | return MR_IN_USE; |
---|
170 | EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess |
---|
171 | WHERE acl_id = :id AND acl_type = 'USER'; |
---|
172 | if (cnt > 0) |
---|
173 | return MR_IN_USE; |
---|
174 | if (dbms_errno) |
---|
175 | return mr_errcode; |
---|
176 | |
---|
177 | EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER'; |
---|
178 | EXEC SQL DELETE FROM krbmap WHERE users_id = :id; |
---|
179 | return MR_SUCCESS; |
---|
180 | } |
---|
181 | |
---|
182 | |
---|
183 | /* setup_dpob: Take care of keeping track of the post office usage. |
---|
184 | */ |
---|
185 | int setup_dpob(struct query *q, char *argv[], client *cl) |
---|
186 | { |
---|
187 | EXEC SQL BEGIN DECLARE SECTION; |
---|
188 | int id, user; |
---|
189 | char type[USERS_POTYPE_SIZE]; |
---|
190 | EXEC SQL END DECLARE SECTION; |
---|
191 | |
---|
192 | user = *(int *)argv[0]; |
---|
193 | EXEC SQL SELECT potype, pop_id INTO :type, :id FROM users |
---|
194 | WHERE users_id = :user; |
---|
195 | if (dbms_errno) |
---|
196 | return mr_errcode; |
---|
197 | |
---|
198 | if (!strcmp(strtrim(type), "POP")) |
---|
199 | set_pop_usage(id, -1); |
---|
200 | return MR_SUCCESS; |
---|
201 | } |
---|
202 | |
---|
203 | |
---|
204 | /* setup_dmac - verify that the machine is no longer being referenced |
---|
205 | * and may safely be deleted. |
---|
206 | */ |
---|
207 | |
---|
208 | int setup_dmac(struct query *q, char *argv[], client *cl) |
---|
209 | { |
---|
210 | EXEC SQL BEGIN DECLARE SECTION; |
---|
211 | int flag, id, cnt; |
---|
212 | EXEC SQL END DECLARE SECTION; |
---|
213 | |
---|
214 | id = *(int *)argv[0]; |
---|
215 | |
---|
216 | EXEC SQL SELECT status INTO :flag FROM machine |
---|
217 | WHERE mach_id = :id; |
---|
218 | if (flag != 3) |
---|
219 | return MR_IN_USE; |
---|
220 | EXEC SQL SELECT COUNT(login) INTO :cnt FROM users |
---|
221 | WHERE potype = 'POP' AND pop_id = :id; |
---|
222 | if (cnt > 0) |
---|
223 | return MR_IN_USE; |
---|
224 | EXEC SQL SELECT COUNT(login) INTO :cnt FROM users |
---|
225 | WHERE potype = 'EXCHANGE' and exchange_id = :id; |
---|
226 | if (cnt > 0) |
---|
227 | return MR_IN_USE; |
---|
228 | EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM serverhosts |
---|
229 | WHERE mach_id = :id; |
---|
230 | if (cnt > 0) |
---|
231 | return MR_IN_USE; |
---|
232 | EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM nfsphys |
---|
233 | WHERE mach_id = :id; |
---|
234 | if (cnt > 0) |
---|
235 | return MR_IN_USE; |
---|
236 | EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostaccess |
---|
237 | WHERE mach_id = :id; |
---|
238 | if (cnt > 0) |
---|
239 | return MR_IN_USE; |
---|
240 | EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printers |
---|
241 | WHERE mach_id = :id; |
---|
242 | if (cnt > 0) |
---|
243 | return MR_IN_USE; |
---|
244 | EXEC SQL SELECT COUNT(rm) INTO :cnt FROM printers |
---|
245 | WHERE rm = :id; |
---|
246 | if (cnt > 0) |
---|
247 | return MR_IN_USE; |
---|
248 | EXEC SQL SELECT COUNT(rq) INTO :cnt FROM printers |
---|
249 | WHERE rq = :id; |
---|
250 | if (cnt > 0) |
---|
251 | return MR_IN_USE; |
---|
252 | EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printservers |
---|
253 | WHERE mach_id = :id; |
---|
254 | if (cnt > 0) |
---|
255 | return MR_IN_USE; |
---|
256 | EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostalias |
---|
257 | WHERE mach_id = :id; |
---|
258 | if (cnt > 0) |
---|
259 | return MR_IN_USE; |
---|
260 | EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers |
---|
261 | WHERE member_type = 'MACHINE' and member_id = :id; |
---|
262 | if (cnt > 0) |
---|
263 | return MR_IN_USE; |
---|
264 | |
---|
265 | EXEC SQL DELETE FROM mcmap WHERE mach_id = :id; |
---|
266 | if (dbms_errno) |
---|
267 | return mr_errcode; |
---|
268 | |
---|
269 | EXEC SQL DELETE FROM mcntmap WHERE mach_id = :id; |
---|
270 | if (dbms_errno) |
---|
271 | return mr_errcode; |
---|
272 | return MR_SUCCESS; |
---|
273 | } |
---|
274 | |
---|
275 | /* setup_asnt - verify that the data entered for the subnet is sane. |
---|
276 | * In particular, make sure that the "low" and "high" addresses are |
---|
277 | * correctly ordered, i.e., high > low. |
---|
278 | */ |
---|
279 | |
---|
280 | int setup_asnt(struct query *q, char *argv[], client *cl) |
---|
281 | { |
---|
282 | int high, low, row, status; |
---|
283 | char *account_number; |
---|
284 | |
---|
285 | /* Check for asnt or usnt. */ |
---|
286 | if (q->type == MR_Q_APPEND) |
---|
287 | row = 0; |
---|
288 | else |
---|
289 | row = 1; |
---|
290 | |
---|
291 | low = atoi(argv[row + 7]); |
---|
292 | high = atoi(argv[row + 8]); |
---|
293 | status = atoi(argv[row + 2]); |
---|
294 | account_number = argv[row + 4]; |
---|
295 | |
---|
296 | /* Don't allow Private subnets to be created without a valid billing |
---|
297 | * number. |
---|
298 | */ |
---|
299 | if (status == SNET_STATUS_PRIVATE_10MBPS || |
---|
300 | status == SNET_STATUS_PRIVATE_100MBPS || |
---|
301 | status == SNET_STATUS_PRIVATE_1000MBPS) |
---|
302 | { |
---|
303 | EXEC SQL SELECT account_number FROM accountnumbers |
---|
304 | WHERE account_number = :account_number; |
---|
305 | if (sqlca.sqlcode == SQL_NO_MATCH) |
---|
306 | return MR_ACCOUNT_NUMBER; |
---|
307 | } |
---|
308 | |
---|
309 | /* Special case 0.0.0.0 and 255.255.255.255 */ |
---|
310 | if (!(low == 0 || low == -1 || high == 0 || high == -1)) |
---|
311 | if (low > high) |
---|
312 | return MR_ADDRESS; |
---|
313 | |
---|
314 | /* If this is update_subnet, we're done. */ |
---|
315 | if (row == 1) |
---|
316 | return MR_SUCCESS; |
---|
317 | |
---|
318 | /* For an add_subnet query, allocate and fill in a new snet_id */ |
---|
319 | if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS) |
---|
320 | return mr_errcode; |
---|
321 | |
---|
322 | return MR_SUCCESS; |
---|
323 | } |
---|
324 | |
---|
325 | /* setup_dsnt - verify that the subnet is no longer being referenced |
---|
326 | * and may safely be deleted. |
---|
327 | */ |
---|
328 | |
---|
329 | int setup_dsnt(struct query *q, char *argv[], client *cl) |
---|
330 | { |
---|
331 | EXEC SQL BEGIN DECLARE SECTION; |
---|
332 | int id, cnt = 0; |
---|
333 | EXEC SQL END DECLARE SECTION; |
---|
334 | |
---|
335 | id = *(int *)argv[0]; |
---|
336 | EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM machine |
---|
337 | WHERE snet_id = :id; |
---|
338 | if (cnt > 0) |
---|
339 | return MR_IN_USE; |
---|
340 | return MR_SUCCESS; |
---|
341 | } |
---|
342 | |
---|
343 | |
---|
344 | /* setup_dclu - verify that the cluster is no longer being referenced |
---|
345 | * and may safely be deleted. |
---|
346 | */ |
---|
347 | |
---|
348 | int setup_dclu(struct query *q, char *argv[], client *cl) |
---|
349 | { |
---|
350 | EXEC SQL BEGIN DECLARE SECTION; |
---|
351 | int id, cnt; |
---|
352 | EXEC SQL END DECLARE SECTION; |
---|
353 | |
---|
354 | id = *(int *)argv[0]; |
---|
355 | EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcmap |
---|
356 | WHERE clu_id = :id; |
---|
357 | if (cnt > 0) |
---|
358 | return MR_IN_USE; |
---|
359 | EXEC SQL SELECT COUNT(clu_id) INTO :cnt FROM svc |
---|
360 | WHERE clu_id = :id; |
---|
361 | if (cnt > 0) |
---|
362 | return MR_IN_USE; |
---|
363 | if (dbms_errno) |
---|
364 | return mr_errcode; |
---|
365 | return MR_SUCCESS; |
---|
366 | } |
---|
367 | |
---|
368 | |
---|
369 | /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate |
---|
370 | * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but |
---|
371 | * argv[5] is not, then remember that UNIQUE_ID is being stored by putting |
---|
372 | * a -1 there. Remember that this is also used for ulis, with the indexes |
---|
373 | * at 6 & 7. Also check that the list name does not contain uppercase |
---|
374 | * characters, control characters, @, or :. |
---|
375 | * |
---|
376 | * Newlines in list descriptions do bad things to the aliases file |
---|
377 | * moira generates, so make sure the description doesn't contain any, too. |
---|
378 | */ |
---|
379 | |
---|
380 | static int badlistchars[] = { |
---|
381 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */ |
---|
382 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */ |
---|
383 | 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */ |
---|
384 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */ |
---|
385 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */ |
---|
386 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */ |
---|
387 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */ |
---|
388 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */ |
---|
389 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
---|
390 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
---|
391 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
---|
392 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
---|
393 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
---|
394 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
---|
395 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
---|
396 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
---|
397 | }; |
---|
398 | |
---|
399 | static const char *mailman_suffixes[] = { "-admin", "-owner", "-request", |
---|
400 | "-bounces", "-confirm", "-join", |
---|
401 | "-leave", "-subscribe", |
---|
402 | "-unsubscribe", NULL }; |
---|
403 | |
---|
404 | int setup_alis(struct query *q, char *argv[], client *cl) |
---|
405 | { |
---|
406 | EXEC SQL BEGIN DECLARE SECTION; |
---|
407 | int ngid, cnt, mailman, mailman_id, lid; |
---|
408 | char *name, *desc; |
---|
409 | EXEC SQL END DECLARE SECTION; |
---|
410 | unsigned char *p; |
---|
411 | int idx, err, best = -1, usage, i; |
---|
412 | |
---|
413 | if (!strcmp(q->shortname, "alis")) |
---|
414 | idx = 0; |
---|
415 | else if (!strcmp(q->shortname, "ulis")) |
---|
416 | idx = 1; |
---|
417 | name = argv[idx]; |
---|
418 | |
---|
419 | if (q->version == 2) |
---|
420 | desc = argv[9 + idx]; |
---|
421 | else if (q->version == 3) |
---|
422 | desc = argv[10 + idx]; |
---|
423 | else if (q->version == 4) |
---|
424 | desc = argv[12 + idx]; |
---|
425 | else if (q->version >= 10) |
---|
426 | desc = argv[14 + idx]; |
---|
427 | |
---|
428 | if (idx == 1) |
---|
429 | { |
---|
430 | lid = *(int *)argv[0]; |
---|
431 | |
---|
432 | if (acl_access_check(lid, cl)) |
---|
433 | return MR_PERM; |
---|
434 | } |
---|
435 | |
---|
436 | for (p = (unsigned char *) name; *p; p++) |
---|
437 | { |
---|
438 | if (badlistchars[*p]) |
---|
439 | return MR_BAD_CHAR; |
---|
440 | } |
---|
441 | |
---|
442 | for (p = (unsigned char *) desc; *p; p++) |
---|
443 | { |
---|
444 | if (*p == '\n') |
---|
445 | return MR_BAD_CHAR; |
---|
446 | } |
---|
447 | |
---|
448 | /* Check that it doesn't conflict with a pre-existing weirdly-cased |
---|
449 | * name. */ |
---|
450 | EXEC SQL SELECT COUNT(name) INTO :cnt FROM list |
---|
451 | WHERE LOWER(name) = :name AND name != :name; |
---|
452 | if (cnt) |
---|
453 | return MR_EXISTS; |
---|
454 | |
---|
455 | if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1) |
---|
456 | { |
---|
457 | if (atoi(argv[5 + idx])) |
---|
458 | { |
---|
459 | if ((err = set_next_object_id("gid", LIST_TABLE, 1))) |
---|
460 | return err; |
---|
461 | EXEC SQL SELECT value INTO :ngid FROM numvalues |
---|
462 | WHERE name = 'gid'; |
---|
463 | if (dbms_errno) |
---|
464 | return mr_errcode; |
---|
465 | sprintf(argv[6 + idx], "%d", ngid); |
---|
466 | } |
---|
467 | else |
---|
468 | strcpy(argv[6 + idx], "-1"); |
---|
469 | } |
---|
470 | |
---|
471 | /* Don't let someone rename a list to one of the magic mailman names |
---|
472 | * (foo-admin, etc) if foo already exists as a mailman list. |
---|
473 | */ |
---|
474 | for (i = 0; mailman_suffixes[i]; i++) |
---|
475 | { |
---|
476 | if ((err = check_mailman_listname(name, mailman_suffixes[i])) |
---|
477 | != MR_SUCCESS) |
---|
478 | return err; |
---|
479 | } |
---|
480 | |
---|
481 | if (q->version >= 10) |
---|
482 | { |
---|
483 | /* Don't let them take this name for a mailman list if we can't |
---|
484 | * reserve the -admin, -owner, and -request names. |
---|
485 | */ |
---|
486 | if (atoi(argv[8 + idx])) |
---|
487 | { |
---|
488 | EXEC SQL SELECT COUNT(name) INTO :cnt FROM list |
---|
489 | WHERE (name = :name || '-admin' OR name = :name || '-owner' OR |
---|
490 | name = :name || '-request'); |
---|
491 | if (cnt) |
---|
492 | return MR_EXISTS; |
---|
493 | } |
---|
494 | |
---|
495 | /* Handle the [ANY] case for mailman server. */ |
---|
496 | mailman_id = *(int *)argv[9 + idx]; |
---|
497 | if (mailman_id == -1) |
---|
498 | { |
---|
499 | EXEC SQL DECLARE csr_mailman CURSOR FOR |
---|
500 | SELECT mach_id FROM serverhosts WHERE service = 'MAILMAN' |
---|
501 | AND enable = 1; |
---|
502 | if (dbms_errno) |
---|
503 | return mr_errcode; |
---|
504 | EXEC SQL OPEN csr_mailman; |
---|
505 | if (dbms_errno) |
---|
506 | return mr_errcode; |
---|
507 | |
---|
508 | while (1) |
---|
509 | { |
---|
510 | EXEC SQL FETCH csr_mailman INTO :mailman_id; |
---|
511 | if (sqlca.sqlcode) |
---|
512 | break; |
---|
513 | |
---|
514 | EXEC SQL SELECT COUNT(name) INTO :usage FROM list |
---|
515 | WHERE mailman_id = :mailman_id; |
---|
516 | |
---|
517 | if (best < 0 || usage < best) |
---|
518 | { |
---|
519 | best = usage; |
---|
520 | *(int *)argv[9 + idx] = mailman_id; |
---|
521 | break; |
---|
522 | } |
---|
523 | } |
---|
524 | EXEC SQL CLOSE csr_mailman; |
---|
525 | if (dbms_errno) |
---|
526 | return mr_errcode; |
---|
527 | |
---|
528 | if (best == -1) |
---|
529 | return MR_SERVICE; |
---|
530 | } |
---|
531 | } |
---|
532 | else |
---|
533 | { |
---|
534 | /* Client too old to know about the mailman code. |
---|
535 | * Use existing value of mailman boolean in the table. |
---|
536 | * Don't do this for add_list from an old client, since the row |
---|
537 | * they're creating won't exist yet, and there's no way for them to |
---|
538 | * create a list with the mailman bit set, anyway. |
---|
539 | */ |
---|
540 | if (idx == 1) |
---|
541 | { |
---|
542 | EXEC SQL SELECT mailman INTO :mailman FROM list WHERE list_id = :lid; |
---|
543 | if (mailman) |
---|
544 | { |
---|
545 | EXEC SQL SELECT COUNT(name) INTO :cnt FROM list |
---|
546 | WHERE (name = :name || '-admin' OR name = :name || '-owner' OR |
---|
547 | name = :name || '-request'); |
---|
548 | if (cnt) |
---|
549 | return MR_EXISTS; |
---|
550 | } |
---|
551 | } |
---|
552 | } |
---|
553 | |
---|
554 | if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS) |
---|
555 | return mr_errcode; |
---|
556 | |
---|
557 | return MR_SUCCESS; |
---|
558 | } |
---|
559 | |
---|
560 | |
---|
561 | /* setup_dlis - verify that the list is no longer being referenced |
---|
562 | * and may safely be deleted. |
---|
563 | */ |
---|
564 | |
---|
565 | int setup_dlis(struct query *q, char *argv[], client *cl) |
---|
566 | { |
---|
567 | int id; |
---|
568 | EXEC SQL BEGIN DECLARE SECTION; |
---|
569 | int cnt; |
---|
570 | EXEC SQL END DECLARE SECTION; |
---|
571 | |
---|
572 | id = *(int *)argv[0]; |
---|
573 | |
---|
574 | EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers |
---|
575 | WHERE member_id = :id AND member_type = 'LIST'; |
---|
576 | if (cnt > 0) |
---|
577 | return MR_IN_USE; |
---|
578 | |
---|
579 | EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers |
---|
580 | WHERE member_id = :id AND member_type = 'LIST'; |
---|
581 | if (cnt > 0) |
---|
582 | return MR_IN_USE; |
---|
583 | |
---|
584 | EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers |
---|
585 | WHERE list_id = :id; |
---|
586 | if (cnt > 0) |
---|
587 | return MR_IN_USE; |
---|
588 | |
---|
589 | EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys WHERE owners = :id; |
---|
590 | if (cnt > 0) |
---|
591 | return MR_IN_USE; |
---|
592 | |
---|
593 | EXEC SQL SELECT COUNT(tag) INTO :cnt FROM capacls WHERE list_id = :id; |
---|
594 | if (cnt > 0) |
---|
595 | return MR_IN_USE; |
---|
596 | |
---|
597 | EXEC SQL SELECT COUNT(name) INTO :cnt FROM list |
---|
598 | WHERE acl_id = :id AND acl_type = 'LIST' AND list_id != :id; |
---|
599 | if (cnt > 0) |
---|
600 | return MR_IN_USE; |
---|
601 | |
---|
602 | EXEC SQL SELECT COUNT(name) INTO :cnt FROM list |
---|
603 | WHERE memacl_id = :id AND memacl_type = 'LIST' AND list_id != :id; |
---|
604 | if (cnt > 0) |
---|
605 | return MR_IN_USE; |
---|
606 | |
---|
607 | EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers |
---|
608 | WHERE acl_id = :id AND acl_type = 'LIST'; |
---|
609 | if (cnt > 0) |
---|
610 | return MR_IN_USE; |
---|
611 | |
---|
612 | EXEC SQL SELECT COUNT(entity_id) INTO :cnt FROM quota |
---|
613 | WHERE entity_id = :id AND type = 'GROUP'; |
---|
614 | if (cnt > 0) |
---|
615 | return MR_IN_USE; |
---|
616 | |
---|
617 | EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess |
---|
618 | WHERE acl_id = :id AND acl_type = 'LIST'; |
---|
619 | if (cnt > 0) |
---|
620 | return MR_IN_USE; |
---|
621 | |
---|
622 | EXEC SQL SELECT COUNT(class) INTO :cnt FROM zephyr z |
---|
623 | WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id |
---|
624 | OR z.sub_type = 'LIST' AND z.sub_id = :id |
---|
625 | OR z.iws_type = 'LIST' AND z.iws_id = :id |
---|
626 | OR z.iui_type = 'LIST' AND z.iui_id = :id |
---|
627 | OR z.owner_type = 'LIST' and z.owner_id = :id; |
---|
628 | if (cnt > 0) |
---|
629 | return MR_IN_USE; |
---|
630 | |
---|
631 | EXEC SQL SELECT COUNT(name) INTO :cnt FROM printers |
---|
632 | WHERE lpc_acl = :id OR ac = :id; |
---|
633 | if (cnt > 0) |
---|
634 | return MR_IN_USE; |
---|
635 | |
---|
636 | EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printservers |
---|
637 | WHERE owner_type = 'LIST' AND owner_id = :id |
---|
638 | OR lpc_acl = :id; |
---|
639 | if (cnt > 0) |
---|
640 | return MR_IN_USE; |
---|
641 | |
---|
642 | EXEC SQL SELECT count(name) INTO :cnt FROM containers |
---|
643 | WHERE acl_id = :id AND acl_type = 'LIST'; |
---|
644 | if (cnt > 0) |
---|
645 | return MR_IN_USE; |
---|
646 | |
---|
647 | EXEC SQL SELECT count(name) INTO :cnt FROM containers |
---|
648 | WHERE memacl_id = :id AND memacl_type = 'LIST'; |
---|
649 | if (cnt > 0) |
---|
650 | return MR_IN_USE; |
---|
651 | |
---|
652 | return MR_SUCCESS; |
---|
653 | } |
---|
654 | |
---|
655 | |
---|
656 | /* setup_dsin - verify that the service is no longer being referenced |
---|
657 | * and may safely be deleted. |
---|
658 | */ |
---|
659 | |
---|
660 | int setup_dsin(struct query *q, char *argv[], client *cl) |
---|
661 | { |
---|
662 | EXEC SQL BEGIN DECLARE SECTION; |
---|
663 | int ec, cnt; |
---|
664 | char *svrname; |
---|
665 | EXEC SQL END DECLARE SECTION; |
---|
666 | |
---|
667 | svrname = argv[0]; |
---|
668 | EXEC SQL SELECT COUNT(service) INTO :cnt FROM serverhosts |
---|
669 | WHERE service = UPPER(:svrname); |
---|
670 | if (cnt > 0) |
---|
671 | return MR_IN_USE; |
---|
672 | |
---|
673 | EXEC SQL SELECT inprogress INTO :ec FROM servers |
---|
674 | WHERE name = UPPER(:svrname); |
---|
675 | if (dbms_errno) |
---|
676 | return mr_errcode; |
---|
677 | if (ec) |
---|
678 | return MR_IN_USE; |
---|
679 | |
---|
680 | return MR_SUCCESS; |
---|
681 | } |
---|
682 | |
---|
683 | |
---|
684 | /* setup_dshi - verify that the service-host is no longer being referenced |
---|
685 | * and may safely be deleted. |
---|
686 | */ |
---|
687 | |
---|
688 | int setup_dshi(struct query *q, char *argv[], client *cl) |
---|
689 | { |
---|
690 | EXEC SQL BEGIN DECLARE SECTION; |
---|
691 | int id, ec; |
---|
692 | char *svrname; |
---|
693 | EXEC SQL END DECLARE SECTION; |
---|
694 | |
---|
695 | svrname = argv[0]; |
---|
696 | id = *(int *)argv[1]; |
---|
697 | |
---|
698 | EXEC SQL SELECT inprogress INTO :ec FROM serverhosts |
---|
699 | WHERE service = UPPER(:svrname) AND mach_id = :id; |
---|
700 | if (dbms_errno) |
---|
701 | return mr_errcode; |
---|
702 | if (ec) |
---|
703 | return MR_IN_USE; |
---|
704 | |
---|
705 | return MR_SUCCESS; |
---|
706 | } |
---|
707 | |
---|
708 | |
---|
709 | /** |
---|
710 | ** setup_add_filesys - verify existance of referenced file systems |
---|
711 | ** |
---|
712 | ** Inputs: Add |
---|
713 | ** argv[1] - type |
---|
714 | ** argv[2] - mach_id |
---|
715 | ** argv[3] - name |
---|
716 | ** argv[5] - rwaccess |
---|
717 | ** |
---|
718 | ** Description: |
---|
719 | ** - for type = RVD: |
---|
720 | ** * allow anything |
---|
721 | ** - for type = NFS/IMAP: |
---|
722 | ** * extract directory prefix from name |
---|
723 | ** * verify mach_id/dir in nfsphys |
---|
724 | ** * verify rwaccess in {r, w, R, W} |
---|
725 | ** |
---|
726 | ** Side effect: sets variable _var_phys_id to the ID of the physical |
---|
727 | ** filesystem (nfsphys_id for NFS, 0 for RVD) |
---|
728 | ** |
---|
729 | ** Errors: |
---|
730 | ** MR_NFS - specified directory not exported |
---|
731 | ** MR_FILESYS_ACCESS - invalid filesys access |
---|
732 | ** |
---|
733 | **/ |
---|
734 | |
---|
735 | EXEC SQL BEGIN DECLARE SECTION; |
---|
736 | int _var_phys_id; |
---|
737 | EXEC SQL END DECLARE SECTION; |
---|
738 | |
---|
739 | int setup_afil(struct query *q, char *argv[], client *cl) |
---|
740 | { |
---|
741 | char *type, *name; |
---|
742 | int mach_id; |
---|
743 | EXEC SQL BEGIN DECLARE SECTION; |
---|
744 | int ok; |
---|
745 | char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess; |
---|
746 | EXEC SQL END DECLARE SECTION; |
---|
747 | |
---|
748 | type = argv[1]; |
---|
749 | mach_id = *(int *)argv[2]; |
---|
750 | name = argv[3]; |
---|
751 | rwaccess = argv[5]; |
---|
752 | _var_phys_id = 0; |
---|
753 | |
---|
754 | sprintf(ftype, "fs_access_%s", type); |
---|
755 | EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias |
---|
756 | WHERE name = :ftype AND type = 'TYPE' and trans = :rwaccess; |
---|
757 | if (dbms_errno) |
---|
758 | return mr_errcode; |
---|
759 | if (ok == 0) |
---|
760 | return MR_FILESYS_ACCESS; |
---|
761 | |
---|
762 | if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS) |
---|
763 | return mr_errcode; |
---|
764 | |
---|
765 | if (!strcmp(type, "NFS") || !strcmp(type, "IMAP")) |
---|
766 | return check_nfs(mach_id, name, rwaccess); |
---|
767 | |
---|
768 | return MR_SUCCESS; |
---|
769 | } |
---|
770 | |
---|
771 | |
---|
772 | /* Verify the arguments, depending on the FStype. Also, if this is an |
---|
773 | * NFS filesystem, then update any quotas for that filesystem to reflect |
---|
774 | * the new phys_id. |
---|
775 | */ |
---|
776 | |
---|
777 | int setup_ufil(struct query *q, char *argv[], client *cl) |
---|
778 | { |
---|
779 | int mach_id, status; |
---|
780 | char *type, *name; |
---|
781 | EXEC SQL BEGIN DECLARE SECTION; |
---|
782 | int fid, total, who, ok; |
---|
783 | char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access; |
---|
784 | short int total_null; |
---|
785 | EXEC SQL END DECLARE SECTION; |
---|
786 | |
---|
787 | _var_phys_id = 0; |
---|
788 | type = argv[2]; |
---|
789 | mach_id = *(int *)argv[3]; |
---|
790 | name = argv[4]; |
---|
791 | access = argv[6]; |
---|
792 | fid = *(int *)argv[0]; |
---|
793 | who = cl->client_id; |
---|
794 | entity = cl->entity; |
---|
795 | |
---|
796 | sprintf(ftype, "fs_access_%s", type); |
---|
797 | EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias |
---|
798 | WHERE name = :ftype AND type = 'TYPE' AND trans = :access; |
---|
799 | if (dbms_errno) |
---|
800 | return mr_errcode; |
---|
801 | if (ok == 0) |
---|
802 | return MR_FILESYS_ACCESS; |
---|
803 | |
---|
804 | EXEC SQL SELECT type INTO :ftype FROM filesys |
---|
805 | WHERE filsys_id = :fid; |
---|
806 | if (dbms_errno) |
---|
807 | return mr_errcode; |
---|
808 | |
---|
809 | if (!strcmp(type, "NFS") || !strcmp(type, "IMAP")) |
---|
810 | { |
---|
811 | status = check_nfs(mach_id, name, access); |
---|
812 | EXEC SQL UPDATE quota SET phys_id = :_var_phys_id |
---|
813 | WHERE filsys_id = :fid; |
---|
814 | if (dbms_errno) |
---|
815 | return mr_errcode; |
---|
816 | return status; |
---|
817 | } |
---|
818 | else if (!strcmp(type, "AFS") && strcmp(strtrim(ftype), "AFS") |
---|
819 | && strcmp(strtrim(ftype), "ERR")) |
---|
820 | { |
---|
821 | total = 0; |
---|
822 | EXEC SQL DELETE FROM quota |
---|
823 | WHERE type = 'ANY' AND filsys_id = :fid; |
---|
824 | EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota |
---|
825 | WHERE filsys_id = :fid AND phys_id != 0; |
---|
826 | if (dbms_errno) |
---|
827 | return mr_errcode; |
---|
828 | if (!total_null && (total != 0)) |
---|
829 | { |
---|
830 | EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id, |
---|
831 | type, modtime, modby, modwith) |
---|
832 | VALUES (:total, :fid, 0, 0, 'ANY', SYSDATE, :who, :entity); |
---|
833 | if (dbms_errno) |
---|
834 | return mr_errcode; |
---|
835 | } |
---|
836 | } |
---|
837 | else |
---|
838 | { |
---|
839 | EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid; |
---|
840 | if (dbms_errno) |
---|
841 | return mr_errcode; |
---|
842 | } |
---|
843 | return MR_SUCCESS; |
---|
844 | } |
---|
845 | |
---|
846 | |
---|
847 | /* Find the NFS physical partition that the named directory is on. |
---|
848 | * This is done by comparing the dir against the mount point of the |
---|
849 | * partition. To make sure we get the correct match when there is |
---|
850 | * more than one, we sort the query in reverse order by dir name. |
---|
851 | */ |
---|
852 | |
---|
853 | int check_nfs(int mach_id, char *name, char *access) |
---|
854 | { |
---|
855 | EXEC SQL BEGIN DECLARE SECTION; |
---|
856 | char dir[NFSPHYS_DIR_SIZE]; |
---|
857 | int mid = mach_id; |
---|
858 | EXEC SQL END DECLARE SECTION; |
---|
859 | int status; |
---|
860 | char *cp1; |
---|
861 | char *cp2; |
---|
862 | |
---|
863 | status = MR_NFS; |
---|
864 | EXEC SQL DECLARE csr101 CURSOR FOR |
---|
865 | SELECT nfsphys_id, dir FROM nfsphys |
---|
866 | WHERE mach_id = :mid |
---|
867 | ORDER BY 2 DESC; |
---|
868 | if (dbms_errno) |
---|
869 | return mr_errcode; |
---|
870 | EXEC SQL OPEN csr101; |
---|
871 | if (dbms_errno) |
---|
872 | return mr_errcode; |
---|
873 | while (1) |
---|
874 | { |
---|
875 | EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir; |
---|
876 | if (sqlca.sqlcode) |
---|
877 | break; |
---|
878 | cp1 = name; |
---|
879 | cp2 = strtrim(dir); |
---|
880 | while (*cp2) |
---|
881 | { |
---|
882 | if (*cp1++ != *cp2) |
---|
883 | break; |
---|
884 | cp2++; |
---|
885 | } |
---|
886 | if (!*cp2) |
---|
887 | { |
---|
888 | status = MR_SUCCESS; |
---|
889 | break; |
---|
890 | } |
---|
891 | } |
---|
892 | EXEC SQL CLOSE csr101; |
---|
893 | if (dbms_errno) |
---|
894 | return mr_errcode; |
---|
895 | return status; |
---|
896 | } |
---|
897 | |
---|
898 | |
---|
899 | /* setup_dfil: free any quota records and fsgroup info associated with |
---|
900 | * a filesystem when it is deleted. Also adjust the allocation numbers. |
---|
901 | */ |
---|
902 | |
---|
903 | int setup_dfil(struct query *q, char **argv, client *cl) |
---|
904 | { |
---|
905 | EXEC SQL BEGIN DECLARE SECTION; |
---|
906 | int id, total, phys_id; |
---|
907 | short int none; |
---|
908 | EXEC SQL END DECLARE SECTION; |
---|
909 | |
---|
910 | id = *(int *)argv[0]; |
---|
911 | EXEC SQL SELECT SUM (quota) INTO :total:none FROM quota |
---|
912 | WHERE filsys_id = :id; |
---|
913 | |
---|
914 | if (none) |
---|
915 | total = 0; |
---|
916 | |
---|
917 | /** What if there are multiple phys_id's per f/s? (bad data) **/ |
---|
918 | EXEC SQL SELECT phys_id INTO :phys_id FROM filesys |
---|
919 | WHERE filsys_id = :id; |
---|
920 | EXEC SQL UPDATE nfsphys SET allocated = allocated - :total |
---|
921 | WHERE nfsphys_id = :phys_id; |
---|
922 | |
---|
923 | if (!none) |
---|
924 | EXEC SQL DELETE FROM quota WHERE filsys_id = :id; |
---|
925 | EXEC SQL DELETE FROM fsgroup WHERE filsys_id = :id; |
---|
926 | EXEC SQL DELETE FROM fsgroup WHERE group_id = :id; |
---|
927 | if (dbms_errno) |
---|
928 | return mr_errcode; |
---|
929 | return MR_SUCCESS; |
---|
930 | } |
---|
931 | |
---|
932 | |
---|
933 | /* setup_dnfp: check to see that the nfs physical partition does not have |
---|
934 | * any filesystems assigned to it before allowing it to be deleted. |
---|
935 | */ |
---|
936 | |
---|
937 | int setup_dnfp(struct query *q, char **argv, client *cl) |
---|
938 | { |
---|
939 | EXEC SQL BEGIN DECLARE SECTION; |
---|
940 | int id, cnt; |
---|
941 | char *dir; |
---|
942 | EXEC SQL END DECLARE SECTION; |
---|
943 | |
---|
944 | id = *(int *)argv[0]; |
---|
945 | dir = argv[1]; |
---|
946 | EXEC SQL SELECT count(fs.rowid) INTO :cnt FROM filesys fs, nfsphys np |
---|
947 | WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id |
---|
948 | AND np.mach_id = :id AND np.dir = :dir; |
---|
949 | if (cnt > 0) |
---|
950 | return MR_IN_USE; |
---|
951 | if (dbms_errno) |
---|
952 | return mr_errcode; |
---|
953 | return MR_SUCCESS; |
---|
954 | } |
---|
955 | |
---|
956 | |
---|
957 | /* setup_dqot: Remove allocation from nfsphys before deleting quota. |
---|
958 | * argv[0] = filsys_id |
---|
959 | * argv[1] = type if "update_quota" or "delete_quota" |
---|
960 | * argv[2 or 1] = users_id or list_id |
---|
961 | */ |
---|
962 | |
---|
963 | int setup_dqot(struct query *q, char **argv, client *cl) |
---|
964 | { |
---|
965 | EXEC SQL BEGIN DECLARE SECTION; |
---|
966 | int quota, fs, id, physid; |
---|
967 | char *qtype; |
---|
968 | EXEC SQL END DECLARE SECTION; |
---|
969 | |
---|
970 | fs = *(int *)argv[0]; |
---|
971 | if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) |
---|
972 | { |
---|
973 | qtype = argv[1]; |
---|
974 | id = *(int *)argv[2]; |
---|
975 | } |
---|
976 | else |
---|
977 | { |
---|
978 | qtype = "USER"; |
---|
979 | id = *(int *)argv[1]; |
---|
980 | } |
---|
981 | |
---|
982 | EXEC SQL SELECT quota INTO :quota FROM quota |
---|
983 | WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs; |
---|
984 | EXEC SQL SELECT phys_id INTO :physid FROM filesys |
---|
985 | WHERE filsys_id = :fs; |
---|
986 | EXEC SQL UPDATE nfsphys SET allocated = allocated - :quota |
---|
987 | WHERE nfsphys_id = :physid; |
---|
988 | |
---|
989 | if (dbms_errno) |
---|
990 | return mr_errcode; |
---|
991 | return MR_SUCCESS; |
---|
992 | } |
---|
993 | |
---|
994 | |
---|
995 | /* prefetch_value(): |
---|
996 | * This routine fetches an appropriate value from the numvalues table. |
---|
997 | * It is a little hack to get around the fact that SQL doesn't let you |
---|
998 | * do something like INSERT INTO table (foo) VALUES (other_table.bar). |
---|
999 | * |
---|
1000 | * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or |
---|
1001 | * from within a setup_...() routine with the appropriate arguments. |
---|
1002 | * |
---|
1003 | * Correct functioning of this routine may depend on the assumption |
---|
1004 | * that this query is an MR_Q_APPEND. |
---|
1005 | */ |
---|
1006 | |
---|
1007 | int prefetch_value(struct query *q, char **argv, client *cl) |
---|
1008 | { |
---|
1009 | EXEC SQL BEGIN DECLARE SECTION; |
---|
1010 | char *name = q->validate->object_id; |
---|
1011 | int value; |
---|
1012 | EXEC SQL END DECLARE SECTION; |
---|
1013 | int status, limit, argc; |
---|
1014 | |
---|
1015 | /* set next object id, limiting it if necessary */ |
---|
1016 | if (!strcmp(name, "unix_uid") || !strcmp(name, "gid")) |
---|
1017 | limit = 1; /* So far as I know, this isn't needed. Just CMA. */ |
---|
1018 | else |
---|
1019 | limit = 0; |
---|
1020 | if ((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS) |
---|
1021 | return status; |
---|
1022 | |
---|
1023 | /* fetch object id */ |
---|
1024 | EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :name; |
---|
1025 | if (dbms_errno) |
---|
1026 | return mr_errcode; |
---|
1027 | if (sqlca.sqlerrd[2] != 1) |
---|
1028 | return MR_INTERNAL; |
---|
1029 | |
---|
1030 | argc = q->argc + q->vcnt; /* end of Argv for MR_Q_APPENDs */ |
---|
1031 | sprintf(argv[argc], "%d", value); |
---|
1032 | |
---|
1033 | return MR_SUCCESS; |
---|
1034 | } |
---|
1035 | |
---|
1036 | /* prefetch_filesys(): |
---|
1037 | * Fetches the phys_id from filesys based on the filsys_id in argv[0]. |
---|
1038 | * Appends the filsys_id and the phys_id to the argv so they can be |
---|
1039 | * referenced in an INSERT into a table other than filesys. Also |
---|
1040 | * see comments at prefetch_value(). |
---|
1041 | * |
---|
1042 | * Assumes the existence of a row where filsys_id = argv[0], since a |
---|
1043 | * filesys label has already been resolved to a filsys_id. |
---|
1044 | */ |
---|
1045 | int prefetch_filesys(struct query *q, char **argv, client *cl) |
---|
1046 | { |
---|
1047 | EXEC SQL BEGIN DECLARE SECTION; |
---|
1048 | int fid, phid; |
---|
1049 | EXEC SQL END DECLARE SECTION; |
---|
1050 | int argc; |
---|
1051 | |
---|
1052 | fid = *(int *)argv[0]; |
---|
1053 | EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid; |
---|
1054 | if (dbms_errno) |
---|
1055 | return mr_errcode; |
---|
1056 | |
---|
1057 | argc = q->argc + q->vcnt; |
---|
1058 | sprintf(argv[argc++], "%d", phid); |
---|
1059 | sprintf(argv[argc], "%d", fid); |
---|
1060 | |
---|
1061 | return MR_SUCCESS; |
---|
1062 | } |
---|
1063 | |
---|
1064 | |
---|
1065 | /* setup_ghst(): |
---|
1066 | */ |
---|
1067 | |
---|
1068 | int setup_ghst(struct query *q, char **argv, client *cl) |
---|
1069 | { |
---|
1070 | if (strcmp(argv[0], "*") || strcmp(argv[1], "*") || |
---|
1071 | strcmp(argv[2], "*") || strcmp(argv[3], "*")) |
---|
1072 | return MR_SUCCESS; |
---|
1073 | else |
---|
1074 | return MR_PERM; |
---|
1075 | } |
---|
1076 | |
---|
1077 | /* setup_ahst(): |
---|
1078 | */ |
---|
1079 | |
---|
1080 | int setup_ahst(struct query *q, char **argv, client *cl) |
---|
1081 | { |
---|
1082 | EXEC SQL BEGIN DECLARE SECTION; |
---|
1083 | char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE]; |
---|
1084 | char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE]; |
---|
1085 | int value, id, ssaddr, smask, shigh, slow, cnt; |
---|
1086 | unsigned int saddr, mask, high, low; |
---|
1087 | EXEC SQL END DECLARE SECTION; |
---|
1088 | int row, idx; |
---|
1089 | struct in_addr addr; |
---|
1090 | |
---|
1091 | id = *(int *)argv[0]; |
---|
1092 | |
---|
1093 | if (!strcmp(q->shortname, "uhst")) |
---|
1094 | { |
---|
1095 | row = 1; |
---|
1096 | EXEC SQL SELECT name, vendor, model, os |
---|
1097 | INTO :oldname, :vendor, :model, :os |
---|
1098 | FROM machine WHERE mach_id = :id; |
---|
1099 | } |
---|
1100 | else |
---|
1101 | row = 0; |
---|
1102 | |
---|
1103 | if (q->version < 6) |
---|
1104 | idx = 0; |
---|
1105 | else if (q->version >= 6 && q->version < 8) |
---|
1106 | idx = 1; |
---|
1107 | else |
---|
1108 | idx = 2; |
---|
1109 | |
---|
1110 | /* Sanity check name, vendor, model, and os. */ |
---|
1111 | if ((row == 0 || strcasecmp(argv[1], oldname)) && |
---|
1112 | !hostname_check(argv[row])) |
---|
1113 | return MR_BAD_CHAR; |
---|
1114 | if ((row == 0 || strcasecmp(argv[2], vendor)) && |
---|
1115 | !hostinfo_check(argv[row + 1], 0)) |
---|
1116 | return MR_BAD_CHAR; |
---|
1117 | if ((row == 0 || strcasecmp(argv[3], model)) && |
---|
1118 | !hostinfo_check(argv[row + 2], 1)) |
---|
1119 | return MR_BAD_CHAR; |
---|
1120 | if ((row == 0 || strcasecmp(argv[4], os)) && |
---|
1121 | !hostinfo_check(argv[row + 3], 0)) |
---|
1122 | return MR_BAD_CHAR; |
---|
1123 | |
---|
1124 | /* check for duplicate name */ |
---|
1125 | name = argv[row]; |
---|
1126 | EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias |
---|
1127 | WHERE name = UPPER(:name); |
---|
1128 | if (dbms_errno) |
---|
1129 | return mr_errcode; |
---|
1130 | if (cnt != 0) |
---|
1131 | return MR_EXISTS; |
---|
1132 | |
---|
1133 | /* check address */ |
---|
1134 | if (!strcmp(argv[9 + row + idx], "unassigned")) |
---|
1135 | value = -1; |
---|
1136 | else if (!strcmp(argv[9 + row + idx], "unique")) |
---|
1137 | { |
---|
1138 | if (*(int *)argv[8 + row + idx] == 0) |
---|
1139 | value = -1; |
---|
1140 | else |
---|
1141 | value = -2; |
---|
1142 | } |
---|
1143 | else |
---|
1144 | { |
---|
1145 | value = ntohl(inet_addr(argv[9 + row + idx])); |
---|
1146 | if (value == -1) |
---|
1147 | return MR_ADDRESS; |
---|
1148 | } |
---|
1149 | if (value == 0) |
---|
1150 | return MR_ADDRESS; |
---|
1151 | if (value != -1) |
---|
1152 | { |
---|
1153 | /* |
---|
1154 | * an address or unique was specified. |
---|
1155 | */ |
---|
1156 | id = *(int *)argv[8 + row + idx]; |
---|
1157 | EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask, |
---|
1158 | :shigh, :slow FROM subnet WHERE snet_id = :id; |
---|
1159 | if (dbms_errno) |
---|
1160 | return mr_errcode; |
---|
1161 | saddr = (unsigned) ssaddr; |
---|
1162 | mask = (unsigned) smask; |
---|
1163 | high = (unsigned) shigh; |
---|
1164 | low = (unsigned) slow; |
---|
1165 | if (value != -2) |
---|
1166 | { |
---|
1167 | /* |
---|
1168 | * someone specified an IP address for the host record |
---|
1169 | */ |
---|
1170 | if ((value & mask) != saddr || value < low || value > high) |
---|
1171 | return MR_ADDRESS; |
---|
1172 | /* |
---|
1173 | * run the address argument through inet_addr(). This |
---|
1174 | * has the effect that any out of bounds host addrs will |
---|
1175 | * be converted to a valid host addr. We do this now |
---|
1176 | * so that the uniqueness check works. We should also |
---|
1177 | * link in an inet_addr() that returns an error for |
---|
1178 | * this case. |
---|
1179 | */ |
---|
1180 | addr.s_addr = inet_addr(argv[9 + row + idx]); |
---|
1181 | name = inet_ntoa(addr); |
---|
1182 | EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine |
---|
1183 | WHERE address = :name; |
---|
1184 | if (dbms_errno) |
---|
1185 | return mr_errcode; |
---|
1186 | if (cnt > 0) |
---|
1187 | { |
---|
1188 | /* |
---|
1189 | * make IP address is unique. If this a modify request |
---|
1190 | * (row == 1), then we expect one record to exist. |
---|
1191 | */ |
---|
1192 | if (row == 0 || (row == 1 && cnt > 1)) |
---|
1193 | return MR_ADDRESS; |
---|
1194 | if (row == 1 && cnt == 1) |
---|
1195 | { |
---|
1196 | EXEC SQL SELECT mach_id INTO :id FROM machine |
---|
1197 | WHERE address = :name; |
---|
1198 | if (id != *(int *)argv[0]) |
---|
1199 | return MR_ADDRESS; |
---|
1200 | } |
---|
1201 | } |
---|
1202 | } |
---|
1203 | else |
---|
1204 | { |
---|
1205 | /* |
---|
1206 | * a "unique" address was specified. Walk through the |
---|
1207 | * range specified in the network record, return |
---|
1208 | * error if no room left. |
---|
1209 | */ |
---|
1210 | for (id = low; id <= high; id++) |
---|
1211 | { |
---|
1212 | if (((id & 0xff) == 0) || ((id & 0xff) == 255)) |
---|
1213 | continue; |
---|
1214 | addr.s_addr = htonl(id); |
---|
1215 | name = inet_ntoa(addr); |
---|
1216 | EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine |
---|
1217 | WHERE address = :name; |
---|
1218 | if (dbms_errno) |
---|
1219 | return mr_errcode; |
---|
1220 | if (cnt == 0) |
---|
1221 | break; |
---|
1222 | } |
---|
1223 | if (cnt != 0) |
---|
1224 | return MR_NO_ID; |
---|
1225 | else |
---|
1226 | value = htonl(id); |
---|
1227 | } |
---|
1228 | /* |
---|
1229 | * we have an address in value. Convert it to a string and store it. |
---|
1230 | */ |
---|
1231 | addr.s_addr = htonl(value); |
---|
1232 | strcpy(argv[9 + row + idx], inet_ntoa(addr)); |
---|
1233 | } |
---|
1234 | else |
---|
1235 | strcpy(argv[9 + row + idx], "unassigned"); |
---|
1236 | |
---|
1237 | /* status checking */ |
---|
1238 | value = atoi(argv[7 + row + idx]); |
---|
1239 | if (row == 0 && !(value == 1 || value == 0)) |
---|
1240 | return MR_TYPE; |
---|
1241 | if (row == 1) |
---|
1242 | { |
---|
1243 | id = *(int *)argv[0]; |
---|
1244 | EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id; |
---|
1245 | if (dbms_errno) |
---|
1246 | return mr_errcode; |
---|
1247 | if (value != cnt) |
---|
1248 | { |
---|
1249 | EXEC SQL UPDATE machine SET statuschange = SYSDATE |
---|
1250 | WHERE mach_id = :id; |
---|
1251 | } |
---|
1252 | } |
---|
1253 | |
---|
1254 | /* |
---|
1255 | * If this is an update_host query, we're done. |
---|
1256 | */ |
---|
1257 | if (row == 1) |
---|
1258 | return MR_SUCCESS; |
---|
1259 | |
---|
1260 | /* |
---|
1261 | * For an add_host query, allocate and fill in a new machine id, |
---|
1262 | * and then insert the creator id. |
---|
1263 | */ |
---|
1264 | if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS) |
---|
1265 | return mr_errcode; |
---|
1266 | |
---|
1267 | sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id); |
---|
1268 | return MR_SUCCESS; |
---|
1269 | } |
---|
1270 | |
---|
1271 | |
---|
1272 | /* setup_ahal(): |
---|
1273 | */ |
---|
1274 | |
---|
1275 | int setup_ahal(struct query *q, char **argv, client *cl) |
---|
1276 | { |
---|
1277 | EXEC SQL BEGIN DECLARE SECTION; |
---|
1278 | char *name; |
---|
1279 | int cnt; |
---|
1280 | EXEC SQL END DECLARE SECTION; |
---|
1281 | char *p; |
---|
1282 | |
---|
1283 | name = argv[0]; |
---|
1284 | if (!hostname_check(argv[0])) |
---|
1285 | return MR_BAD_CHAR; |
---|
1286 | |
---|
1287 | EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE |
---|
1288 | name = UPPER(:name); |
---|
1289 | if (dbms_errno) |
---|
1290 | return mr_errcode; |
---|
1291 | if (cnt > 0) |
---|
1292 | return MR_EXISTS; |
---|
1293 | |
---|
1294 | return MR_SUCCESS; |
---|
1295 | } |
---|
1296 | |
---|
1297 | /* setup_uhha(): Check characters in hwaddr, and make sure it's not |
---|
1298 | * a duplicate. |
---|
1299 | */ |
---|
1300 | int setup_uhha(struct query *q, char **argv, client *cl) |
---|
1301 | { |
---|
1302 | EXEC SQL BEGIN DECLARE SECTION; |
---|
1303 | char *hwaddr = argv[1]; |
---|
1304 | int count; |
---|
1305 | EXEC SQL END DECLARE SECTION; |
---|
1306 | char *p; |
---|
1307 | |
---|
1308 | if (*hwaddr && strcasecmp(hwaddr, "unknown")) |
---|
1309 | { |
---|
1310 | for (p = hwaddr; *p; p++) |
---|
1311 | { |
---|
1312 | if (isupper(*p)) |
---|
1313 | *p = tolower(*p); |
---|
1314 | if (!isxdigit(*p)) |
---|
1315 | return MR_BAD_CHAR; |
---|
1316 | } |
---|
1317 | if (p != hwaddr + 12) |
---|
1318 | return MR_ADDRESS; |
---|
1319 | |
---|
1320 | EXEC SQL SELECT COUNT(hwaddr) INTO :count |
---|
1321 | FROM machine WHERE hwaddr = :hwaddr; |
---|
1322 | if (count) |
---|
1323 | return MR_NOT_UNIQUE; |
---|
1324 | } |
---|
1325 | |
---|
1326 | return MR_SUCCESS; |
---|
1327 | } |
---|
1328 | |
---|
1329 | /* setup_aprn(): Make sure name/duplexname don't conflict with |
---|
1330 | * anything. If [ANY] was specified for the spooling host, pick the |
---|
1331 | * least loaded print server that serves this kind of printer. |
---|
1332 | */ |
---|
1333 | int setup_aprn(struct query *q, char **argv, client *cl) |
---|
1334 | { |
---|
1335 | int best = -1, row; |
---|
1336 | char *p; |
---|
1337 | EXEC SQL BEGIN DECLARE SECTION; |
---|
1338 | int mid, usage, count; |
---|
1339 | char types[STRINGS_STRING_SIZE], *hwaddr, *name, *duplexname, *oldname; |
---|
1340 | EXEC SQL END DECLARE SECTION; |
---|
1341 | |
---|
1342 | /* Check for aprn or uprn. */ |
---|
1343 | if (q->type == MR_Q_APPEND) |
---|
1344 | row = 0; |
---|
1345 | else |
---|
1346 | row = 1; |
---|
1347 | |
---|
1348 | name = argv[PRN_NAME + row]; |
---|
1349 | duplexname = argv[PRN_DUPLEXNAME + row]; |
---|
1350 | oldname = argv[0]; |
---|
1351 | |
---|
1352 | if (!*name) |
---|
1353 | return MR_BAD_CHAR; |
---|
1354 | else |
---|
1355 | { |
---|
1356 | if (q->type == MR_Q_APPEND) |
---|
1357 | { |
---|
1358 | EXEC SQL SELECT COUNT(name) INTO :count FROM printers |
---|
1359 | WHERE name = :name OR duplexname = :name; |
---|
1360 | } |
---|
1361 | else |
---|
1362 | { |
---|
1363 | EXEC SQL SELECT COUNT(name) INTO :count FROM printers |
---|
1364 | WHERE ( name = :name OR duplexname = :name ) |
---|
1365 | AND name != :oldname; |
---|
1366 | } |
---|
1367 | if (dbms_errno) |
---|
1368 | return mr_errcode; |
---|
1369 | if (count) |
---|
1370 | return MR_NOT_UNIQUE; |
---|
1371 | } |
---|
1372 | |
---|
1373 | if (*duplexname) |
---|
1374 | { |
---|
1375 | if (q->type == MR_Q_APPEND) |
---|
1376 | { |
---|
1377 | EXEC SQL SELECT COUNT(name) INTO :count FROM printers |
---|
1378 | WHERE name = :duplexname OR duplexname = :duplexname; |
---|
1379 | } |
---|
1380 | else |
---|
1381 | { |
---|
1382 | EXEC SQL SELECT COUNT(name) INTO :count FROM printers |
---|
1383 | WHERE ( name = :duplexname OR duplexname = :duplexname ) |
---|
1384 | AND name != :oldname; |
---|
1385 | } |
---|
1386 | |
---|
1387 | if (dbms_errno) |
---|
1388 | return mr_errcode; |
---|
1389 | if (count) |
---|
1390 | return MR_NOT_UNIQUE; |
---|
1391 | } |
---|
1392 | |
---|
1393 | if (!strcmp(name, duplexname)) |
---|
1394 | return MR_NOT_UNIQUE; |
---|
1395 | |
---|
1396 | mid = *(int *)argv[PRN_RM + row]; |
---|
1397 | if (mid == -1) |
---|
1398 | { |
---|
1399 | EXEC SQL DECLARE csr_rm CURSOR FOR |
---|
1400 | SELECT ps.mach_id, s.string FROM printservers ps, strings s |
---|
1401 | WHERE ps.mach_id IN |
---|
1402 | ( SELECT mach_id FROM serverhosts WHERE service = 'PRINT' |
---|
1403 | AND enable = 1 ) |
---|
1404 | AND ps.printer_types = s.string_id; |
---|
1405 | if (dbms_errno) |
---|
1406 | return mr_errcode; |
---|
1407 | EXEC SQL OPEN csr_rm; |
---|
1408 | if (dbms_errno) |
---|
1409 | return mr_errcode; |
---|
1410 | |
---|
1411 | while (1) |
---|
1412 | { |
---|
1413 | EXEC SQL FETCH csr_rm INTO :mid, :types; |
---|
1414 | if (sqlca.sqlcode) |
---|
1415 | break; |
---|
1416 | |
---|
1417 | for (p = strtok(types, ", "); p; p = strtok(NULL, ", ")) |
---|
1418 | { |
---|
1419 | if (!strcasecmp(argv[PRN_TYPE + row], p)) |
---|
1420 | { |
---|
1421 | EXEC SQL SELECT COUNT(name) INTO :usage |
---|
1422 | FROM printers WHERE rm = :mid; |
---|
1423 | |
---|
1424 | if (best < 0 || usage < best) |
---|
1425 | { |
---|
1426 | best = usage; |
---|
1427 | *(int *)argv[PRN_RM + row] = mid; |
---|
1428 | break; |
---|
1429 | } |
---|
1430 | } |
---|
1431 | } |
---|
1432 | } |
---|
1433 | EXEC SQL CLOSE csr_rm; |
---|
1434 | if (dbms_errno) |
---|
1435 | return mr_errcode; |
---|
1436 | |
---|
1437 | if (best == -1) |
---|
1438 | return MR_SERVICE; |
---|
1439 | } |
---|
1440 | else |
---|
1441 | { |
---|
1442 | EXEC SQL SELECT mach_id INTO :mid FROM printservers |
---|
1443 | WHERE mach_id = :mid; |
---|
1444 | if (sqlca.sqlcode) |
---|
1445 | return MR_SERVICE; |
---|
1446 | } |
---|
1447 | |
---|
1448 | return MR_SUCCESS; |
---|
1449 | } |
---|
1450 | |
---|
1451 | int setup_dpsv(struct query *q, char **argv, client *cl) |
---|
1452 | { |
---|
1453 | int id; |
---|
1454 | EXEC SQL BEGIN DECLARE SECTION; |
---|
1455 | int cnt; |
---|
1456 | EXEC SQL END DECLARE SECTION; |
---|
1457 | |
---|
1458 | id = *(int *)argv[0]; |
---|
1459 | |
---|
1460 | EXEC SQL SELECT COUNT(rm) INTO :cnt FROM printers |
---|
1461 | WHERE rm = :id; |
---|
1462 | if (cnt > 0) |
---|
1463 | return MR_IN_USE; |
---|
1464 | |
---|
1465 | return MR_SUCCESS; |
---|
1466 | } |
---|
1467 | |
---|
1468 | int setup_dcon(struct query *q, char *argv[], client *cl) |
---|
1469 | { |
---|
1470 | EXEC SQL BEGIN DECLARE SECTION; |
---|
1471 | int id, cnt; |
---|
1472 | char containername[CONTAINERS_NAME_SIZE]; |
---|
1473 | EXEC SQL END DECLARE SECTION; |
---|
1474 | |
---|
1475 | id = *(int *)argv[0]; |
---|
1476 | /* check to see if there are machines in this container */ |
---|
1477 | EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcntmap |
---|
1478 | WHERE cnt_id = :id; |
---|
1479 | if (cnt > 0) |
---|
1480 | return MR_IN_USE; |
---|
1481 | |
---|
1482 | /* check to see if there are subcontainers in this container */ |
---|
1483 | |
---|
1484 | /* get the container name */ |
---|
1485 | |
---|
1486 | EXEC SQL SELECT name INTO :containername |
---|
1487 | FROM containers |
---|
1488 | WHERE cnt_id = :id; |
---|
1489 | |
---|
1490 | /* trim off the trailing spaces */ |
---|
1491 | strcpy(containername, strtrim(containername)); |
---|
1492 | |
---|
1493 | EXEC SQL SELECT COUNT(cnt_id) INTO :cnt FROM containers |
---|
1494 | WHERE LOWER(name) LIKE LOWER(:containername || '/' || '%'); |
---|
1495 | |
---|
1496 | if (cnt > 0) |
---|
1497 | return MR_IN_USE; |
---|
1498 | |
---|
1499 | if (dbms_errno) |
---|
1500 | return mr_errcode; |
---|
1501 | return MR_SUCCESS; |
---|
1502 | } |
---|
1503 | |
---|
1504 | int setup_scli(struct query *q, char *argv[], client *cl) |
---|
1505 | { |
---|
1506 | EXEC SQL BEGIN DECLARE SECTION; |
---|
1507 | int cnt_id, list_id; |
---|
1508 | EXEC SQL END DECLARE SECTION; |
---|
1509 | |
---|
1510 | cnt_id = *(int *)argv[0]; |
---|
1511 | /* Check if someone has already set the list for this container */ |
---|
1512 | EXEC SQL SELECT list_id INTO :list_id FROM containers |
---|
1513 | WHERE cnt_id = :cnt_id; |
---|
1514 | if (list_id != 0) |
---|
1515 | return MR_EXISTS; |
---|
1516 | |
---|
1517 | if (dbms_errno) |
---|
1518 | return mr_errcode; |
---|
1519 | |
---|
1520 | return MR_SUCCESS; |
---|
1521 | } |
---|
1522 | |
---|
1523 | /* hostname_check() |
---|
1524 | * validate the rfc1035/rfc1123-ness of a hostname |
---|
1525 | */ |
---|
1526 | |
---|
1527 | int hostname_check(char *name) |
---|
1528 | { |
---|
1529 | char *p; |
---|
1530 | int count; |
---|
1531 | |
---|
1532 | /* Sanity check name: must contain only letters, numerals, and |
---|
1533 | * hyphen, and not start or end with a hyphen. Also make sure no |
---|
1534 | * label (the thing the .s seperate) is longer than 63 characters, |
---|
1535 | * or empty. |
---|
1536 | */ |
---|
1537 | |
---|
1538 | for (p = name, count = 0; *p; p++) |
---|
1539 | { |
---|
1540 | count++; |
---|
1541 | if ((!isalnum(*p) && *p != '-' && *p != '.') || |
---|
1542 | (*p == '-' && p[1] == '.')) |
---|
1543 | return 0; |
---|
1544 | if (*p == '.') |
---|
1545 | { |
---|
1546 | if (count == 1) |
---|
1547 | return 0; |
---|
1548 | count = 0; |
---|
1549 | } |
---|
1550 | if (count == 64) |
---|
1551 | return 0; |
---|
1552 | } |
---|
1553 | if (*(p - 1) == '-') |
---|
1554 | return 0; |
---|
1555 | return 1; |
---|
1556 | } |
---|
1557 | |
---|
1558 | int hostinfo_check(char *info, int num) |
---|
1559 | { |
---|
1560 | char *p; |
---|
1561 | |
---|
1562 | if (!*info) |
---|
1563 | return 1; |
---|
1564 | |
---|
1565 | /* Sanity check host hostinfo: must start with a letter (or number |
---|
1566 | * if num is true), contain only letters, numerals, and hyphen, and |
---|
1567 | * not end with a hyphen. |
---|
1568 | */ |
---|
1569 | |
---|
1570 | if (!isalpha(*info) && (!num || !isdigit(*info))) |
---|
1571 | return 0; |
---|
1572 | for (p = info; *p; p++) |
---|
1573 | { |
---|
1574 | if ((!isalnum(*p) && *p != '-' && *p != '.') || |
---|
1575 | (*p == '-' && p[1] == '.')) |
---|
1576 | return 0; |
---|
1577 | } |
---|
1578 | if (!isalnum(*(p - 1))) |
---|
1579 | return 1; |
---|
1580 | } |
---|
1581 | |
---|
1582 | int setup_acon(struct query *q, char *argv[], client *cl) |
---|
1583 | { |
---|
1584 | EXEC SQL BEGIN DECLARE SECTION; |
---|
1585 | char containername[CONTAINERS_NAME_SIZE]; |
---|
1586 | EXEC SQL END DECLARE SECTION; |
---|
1587 | |
---|
1588 | char* ptr; |
---|
1589 | |
---|
1590 | memset(containername, 0, sizeof(containername)); |
---|
1591 | strcpy(containername, argv[0]); |
---|
1592 | ptr = strrchr(containername, '/'); |
---|
1593 | /* sub container, check for parents */ |
---|
1594 | if (ptr) |
---|
1595 | { |
---|
1596 | *ptr = '\0'; |
---|
1597 | EXEC SQL SELECT * FROM containers |
---|
1598 | WHERE lower(name) = lower(:containername); |
---|
1599 | if (sqlca.sqlerrd[2] != 1) |
---|
1600 | return MR_CONTAINER_NO_PARENT; |
---|
1601 | } |
---|
1602 | |
---|
1603 | if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS) |
---|
1604 | return mr_errcode; |
---|
1605 | |
---|
1606 | return MR_SUCCESS; |
---|
1607 | } |
---|
1608 | |
---|
1609 | int check_mailman_listname(char *name, const char *suffix) |
---|
1610 | { |
---|
1611 | char *p; |
---|
1612 | EXEC SQL BEGIN DECLARE SECTION; |
---|
1613 | int i, cnt; |
---|
1614 | EXEC SQL END DECLARE SECTION; |
---|
1615 | |
---|
1616 | p = strstr(name, suffix); |
---|
1617 | if (p) |
---|
1618 | { |
---|
1619 | if (strlen(name) == (p - name + strlen(suffix))) |
---|
1620 | { |
---|
1621 | /* list is of the form "name-suffix" */ |
---|
1622 | i = (p - name); |
---|
1623 | EXEC SQL SELECT COUNT(name) INTO :cnt FROM list |
---|
1624 | WHERE name = SUBSTR(:name, 1, :i) AND mailman = 1; |
---|
1625 | if (cnt > 0) |
---|
1626 | return MR_EXISTS; |
---|
1627 | } |
---|
1628 | } |
---|
1629 | |
---|
1630 | return MR_SUCCESS; |
---|
1631 | } |
---|