]> andersk Git - moira.git/blame_incremental - server/qvalidate.pc
Command line printer manipulation client, and build goo.
[moira.git] / server / qvalidate.pc
... / ...
CommitLineData
1/* $Id$
2 *
3 * Argument validation 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 <ctype.h>
16#include <stdlib.h>
17#include <string.h>
18#include <unistd.h>
19
20EXEC SQL INCLUDE sqlca;
21EXEC SQL INCLUDE sqlda;
22
23RCSID("$Header$");
24
25extern char *whoami, *table_name[], *sqlbuffer[QMAXARGS];
26extern int dbms_errno, mr_errcode;
27
28EXEC SQL BEGIN DECLARE SECTION;
29extern char stmt_buf[];
30EXEC SQL END DECLARE SECTION;
31
32int validate_chars(char *argv[], struct valobj *vo);
33int validate_id(struct query *, char *argv[], struct valobj *vo);
34int validate_name(char *argv[], struct valobj *vo);
35int validate_rename(char *argv[], struct valobj *vo);
36int validate_type(char *argv[], struct valobj *vo);
37int validate_typedata(struct query *, char *argv[], struct valobj *vo);
38int validate_len(char *argv[], struct valobj *vo);
39int validate_num(char *argv[], struct valobj *vo);
40
41extern SQLDA *sqlald(int, int, int);
42SQLDA *mr_alloc_sqlda(void);
43
44EXEC SQL WHENEVER SQLERROR DO dbmserr();
45
46/* Validation Routines */
47
48int validate_row(struct query *q, char *argv[], struct validate *v)
49{
50 EXEC SQL BEGIN DECLARE SECTION;
51 int rowcount;
52 EXEC SQL END DECLARE SECTION;
53 char *qual;
54
55 /* build where clause */
56 qual = build_qual(v->qual, v->argc, argv);
57
58 /* look for the record */
59 sprintf(stmt_buf, "SELECT COUNT (*) FROM %s WHERE %s",
60 table_name[q->rtable], qual);
61 dosql(sqlbuffer);
62 free(qual);
63 if (dbms_errno)
64 return mr_errcode;
65
66 rowcount = atoi(sqlbuffer[0]);
67 if (rowcount == 0)
68 return MR_NO_MATCH;
69 if (rowcount > 1)
70 return MR_NOT_UNIQUE;
71 return MR_EXISTS;
72}
73
74int validate_fields(struct query *q, char *argv[], struct valobj *vo, int n)
75{
76 int status;
77
78 while (--n >= 0)
79 {
80 switch (vo->type)
81 {
82 case V_NAME:
83 status = validate_name(argv, vo);
84 break;
85
86 case V_ID:
87 status = validate_id(q, argv, vo);
88 break;
89
90 case V_TYPE:
91 status = validate_type(argv, vo);
92 break;
93
94 case V_TYPEDATA:
95 status = validate_typedata(q, argv, vo);
96 break;
97
98 case V_RENAME:
99 status = validate_rename(argv, vo);
100 break;
101
102 case V_CHAR:
103 status = validate_chars(argv, vo);
104 break;
105
106 case V_LEN:
107 status = validate_len(argv, vo);
108 break;
109
110 case V_NUM:
111 status = validate_num(argv, vo);
112 break;
113 }
114
115 if (status != MR_EXISTS)
116 return status;
117 vo++;
118 }
119
120 if (dbms_errno)
121 return mr_errcode;
122 return MR_SUCCESS;
123}
124
125
126/* validate_chars: verify that there are no illegal characters in
127 * the string. Legal characters are printing chars other than
128 * ", *, ?, \, [ and ].
129 */
130static int illegalchars[] = {
131 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
132 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
133 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
137 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
139 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
140 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
141 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
142 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
143 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
144 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
145 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
146 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
147};
148
149int validate_chars(char *argv[], struct valobj *vo)
150{
151 char *s = argv[vo->index];
152 EXEC SQL BEGIN DECLARE SECTION;
153 int len;
154 char *tname, *cname;
155 EXEC SQL END DECLARE SECTION;
156
157 /* check for bad characters */
158 while (*s)
159 {
160 if (illegalchars[(int)*s++])
161 return MR_BAD_CHAR;
162 }
163
164 /* check for length */
165 tname = table_name[vo->table];
166 cname = vo->namefield;
167 EXEC SQL SELECT data_length INTO :len FROM user_tab_columns
168 WHERE table_name = UPPER(:tname) AND column_name = UPPER(:cname);
169
170 if ((strlen(argv[vo->index]) > len) &&
171 strcmp(argv[vo->index], UNIQUE_LOGIN)) /* kludge... sigh */
172 return MR_ARG_TOO_LONG;
173
174 return MR_EXISTS;
175}
176
177
178int validate_id(struct query *q, char *argv[], struct valobj *vo)
179{
180 EXEC SQL BEGIN DECLARE SECTION;
181 char *name, *namefield, *idfield;
182 int id, rowcount, tbl;
183 EXEC SQL END DECLARE SECTION;
184 int status;
185 char *c;
186
187 name = argv[vo->index];
188 tbl = vo->table;
189 namefield = vo->namefield;
190 idfield = vo->idfield;
191
192 if (tbl == MACHINE_TABLE || tbl == SUBNET_TABLE)
193 {
194 for (c = name; *c; c++)
195 {
196 if (islower(*c))
197 *c = toupper(*c);
198 }
199 }
200 status = name_to_id(name, tbl, &id);
201 if (status == 0)
202 {
203 *(int *)argv[vo->index] = id;
204 return MR_EXISTS;
205 }
206 else if (status == MR_NO_MATCH && tbl == STRINGS_TABLE &&
207 (q->type == MR_Q_APPEND || q->type == MR_Q_UPDATE))
208 {
209 if (strlen(name) >= STRINGS_STRING_SIZE)
210 return MR_ARG_TOO_LONG;
211 id = add_string(name);
212 *(int *)argv[vo->index] = id;
213 return MR_EXISTS;
214 }
215 else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
216 return vo->error;
217 else
218 return status;
219}
220
221int validate_name(char *argv[], struct valobj *vo)
222{
223 char *name, *namefield;
224 char *c;
225
226 name = argv[vo->index];
227 namefield = vo->namefield;
228 if (vo->table == SERVERS_TABLE && !strcmp(namefield, "name"))
229 {
230 for (c = name; *c; c++)
231 {
232 if (islower(*c))
233 *c = toupper(*c);
234 }
235 }
236 if (!*name)
237 return MR_RESERVED;
238 sprintf(stmt_buf, "SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
239 table_name[vo->table], table_name[vo->table], namefield, name);
240 dosql(sqlbuffer);
241
242 if (dbms_errno)
243 return mr_errcode;
244 return (atoi(sqlbuffer[0]) == 1) ? MR_EXISTS : vo->error;
245}
246
247int validate_rename(char *argv[], struct valobj *vo)
248{
249 EXEC SQL BEGIN DECLARE SECTION;
250 char *name, *namefield, *idfield;
251 int id;
252 EXEC SQL END DECLARE SECTION;
253 int status;
254 char *c;
255
256 status = validate_chars(argv, vo);
257 if (status != MR_EXISTS)
258 return status;
259 name = argv[vo->index];
260 /* minor kludge to upcasify machine names */
261 if (vo->table == MACHINE_TABLE)
262 {
263 for (c = name; *c; c++)
264 {
265 if (islower(*c))
266 *c = toupper(*c);
267 }
268 }
269 if (!*name)
270 return MR_RESERVED;
271 namefield = vo->namefield;
272 idfield = vo->idfield;
273 id = -1;
274 if (idfield == 0)
275 {
276 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
277 return MR_EXISTS;
278 sprintf(stmt_buf, "SELECT %s FROM %s WHERE %s = '%s'",
279 namefield, table_name[vo->table], namefield, name);
280 dosql(sqlbuffer);
281
282 if (dbms_errno)
283 return mr_errcode;
284 if (sqlca.sqlcode == SQL_NO_MATCH)
285 return MR_EXISTS; /* how's _that_ for intuitive? */
286 else
287 return vo->error;
288 }
289 status = name_to_id(name, vo->table, &id);
290 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
291 return MR_EXISTS;
292 else
293 return vo->error;
294}
295
296
297int validate_type(char *argv[], struct valobj *vo)
298{
299 EXEC SQL BEGIN DECLARE SECTION;
300 char *typename;
301 char *val;
302 int cnt;
303 EXEC SQL END DECLARE SECTION;
304 char *c;
305
306 typename = vo->namefield;
307 c = val = argv[vo->index];
308 while (*c)
309 {
310 if (illegalchars[(int)*c++])
311 return MR_BAD_CHAR;
312 }
313
314 /* uppercase type fields */
315 for (c = val; *c; c++)
316 {
317 if (islower(*c))
318 *c = toupper(*c);
319 }
320
321 EXEC SQL SELECT COUNT(trans) INTO :cnt FROM alias
322 WHERE name = :typename AND type = 'TYPE' AND trans = :val;
323 if (dbms_errno)
324 return mr_errcode;
325 return cnt ? MR_EXISTS : vo->error;
326}
327
328/* validate member or type-specific data field */
329
330int validate_typedata(struct query *q, char *argv[], struct valobj *vo)
331{
332 EXEC SQL BEGIN DECLARE SECTION;
333 char *name;
334 char *field_type;
335 char data_type[129];
336 int id;
337 EXEC SQL END DECLARE SECTION;
338 int status;
339 char *c;
340
341 /* get named object */
342 name = argv[vo->index];
343
344 /* get field type string (known to be at index-1) */
345 field_type = argv[vo->index - 1];
346
347 /* get corresponding data type associated with field type name */
348 EXEC SQL SELECT trans INTO :data_type FROM alias
349 WHERE name = :field_type AND type = 'TYPEDATA';
350 if (dbms_errno)
351 return mr_errcode;
352 if (sqlca.sqlerrd[2] != 1)
353 return MR_TYPE;
354
355 /* now retrieve the record id corresponding to the named object */
356 if (strchr(data_type, ' '))
357 *strchr(data_type, ' ') = '\0';
358 if (!strcmp(data_type, "user"))
359 {
360 /* USER */
361 if (strchr(name, '@'))
362 return MR_USER;
363 status = name_to_id(name, USERS_TABLE, &id);
364 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
365 return MR_USER;
366 if (status)
367 return status;
368 }
369 else if (!strcmp(data_type, "list"))
370 {
371 /* LIST */
372 status = name_to_id(name, LIST_TABLE, &id);
373 if (status && status == MR_NOT_UNIQUE)
374 return MR_LIST;
375 if (status == MR_NO_MATCH)
376 {
377 /* if idfield is non-zero, then if argv[0] matches the string
378 * that we're trying to resolve, we should get the value of
379 * numvalues.[idfield] for the id.
380 */
381 if (vo->idfield && (*(int *)argv[0] == *(int *)argv[vo->index]))
382 {
383 set_next_object_id(q->validate->object_id, q->rtable, 0);
384 name = vo->idfield;
385 EXEC SQL SELECT value INTO :id FROM numvalues
386 WHERE name = :name;
387 if (sqlca.sqlerrd[2] != 1)
388 return MR_LIST;
389 }
390 else
391 return MR_LIST;
392 }
393 else if (status)
394 return status;
395 }
396 else if (!strcmp(data_type, "machine"))
397 {
398 /* MACHINE */
399 for (c = name; *c; c++)
400 {
401 if (islower(*c))
402 *c = toupper(*c);
403 }
404 status = name_to_id(name, MACHINE_TABLE, &id);
405 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
406 return MR_MACHINE;
407 if (status)
408 return status;
409 }
410 else if (!strcmp(data_type, "string"))
411 {
412 /* STRING */
413 status = name_to_id(name, STRINGS_TABLE, &id);
414 if (status && status == MR_NOT_UNIQUE)
415 return MR_STRING;
416 if (status == MR_NO_MATCH)
417 {
418 if (q->type != MR_Q_APPEND && q->type != MR_Q_UPDATE)
419 return MR_STRING;
420 if (strlen(name) >= STRINGS_STRING_SIZE)
421 return MR_ARG_TOO_LONG;
422 id = add_string(name);
423 }
424 else if (status)
425 return status;
426 }
427 else if (!strcmp(data_type, "none") || !strcmp(data_type, "all"))
428 id = 0;
429 else
430 return MR_TYPE;
431
432 /* now set value in argv */
433 *(int *)argv[vo->index] = id;
434
435 return MR_EXISTS;
436}
437
438
439/* Make sure the data fits in the field */
440int validate_len(char *argv[], struct valobj *vo)
441{
442 EXEC SQL BEGIN DECLARE SECTION;
443 int len;
444 char *tname, *cname;
445 EXEC SQL END DECLARE SECTION;
446
447 tname = table_name[vo->table];
448 cname = vo->namefield;
449 EXEC SQL SELECT data_length INTO :len FROM user_tab_columns
450 WHERE table_name = UPPER(:tname) AND column_name = UPPER(:cname);
451
452 if ((strlen(argv[vo->index]) > len) &&
453 strcmp(argv[vo->index], UNIQUE_LOGIN)) /* kludge... sigh */
454 return MR_ARG_TOO_LONG;
455
456 return MR_EXISTS;
457}
458
459/* Make sure the data is numeric */
460int validate_num(char *argv[], struct valobj *vo)
461{
462 char *p = argv[vo->index];
463
464 if (!strcmp(p, UNIQUE_GID) || !strcmp(p, UNIQUE_UID))
465 {
466 strcpy(p, "-1");
467 return MR_EXISTS;
468 }
469
470 if (*p == '-')
471 p++;
472 if (!*p)
473 return MR_INTEGER;
474
475 for (; *p; p++)
476 {
477 if (*p < '0' || *p > '9')
478 return MR_INTEGER;
479 }
480
481 return MR_EXISTS;
482}
483
484/* Check the database at startup time. */
485
486void sanity_check_database(void)
487{
488 EXEC SQL BEGIN DECLARE SECTION;
489 int oid, id;
490 EXEC SQL END DECLARE SECTION;
491
492 /* Sometimes a crash can leave strings_id in numvalues in an
493 incorrect state. Check for that and fix it. */
494
495 EXEC SQL SELECT value INTO :oid FROM numvalues WHERE name = 'strings_id';
496
497 for (id = oid + 1; sqlca.sqlcode == 0; id++)
498 {
499 EXEC SQL SELECT string_id INTO :id FROM strings
500 WHERE string_id = :id;
501 }
502
503 if (id != oid + 1)
504 EXEC SQL UPDATE numvalues SET value = :id - 1 WHERE name = 'strings_id';
505}
506
507
508char *sqlbuffer[QMAXARGS];
509
510/* Dynamic SQL support routines */
511SQLDA *mr_alloc_sqlda(void)
512{
513 SQLDA *it;
514 int j;
515
516 it = sqlald(QMAXARGS, ARGLEN, 0);
517 if (!it)
518 {
519 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
520 exit(1);
521 }
522
523 for (j = 0; j < QMAXARGS; j++)
524 {
525 it->V[j] = sqlbuffer[j] = xmalloc(ARGLEN);
526 it->T[j] = 97; /* 97 = CHARZ = null-terminated string */
527 it->L[j] = ARGLEN;
528 }
529
530 return it;
531}
532
533/* Adds a string to the string table. Returns the id number.
534 *
535 */
536int add_string(char *nm)
537{
538 EXEC SQL BEGIN DECLARE SECTION;
539 char *name = nm;
540 int id;
541 EXEC SQL END DECLARE SECTION;
542
543 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
544 id++;
545 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
546
547 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
548
549 return id;
550}
This page took 0.297764 seconds and 5 git commands to generate.