]> andersk Git - moira.git/blame - server/qvalidate.pc
Code style cleanup. (No functional changes)
[moira.git] / server / qvalidate.pc
CommitLineData
73cf66ba 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
13static char *rcsid_qsupport_dc = "$Header$";
14#endif lint
15
16#include <mit-copyright.h>
17#include <unistd.h>
73cf66ba 18#include "mr_server.h"
03c05291 19#include "query.h"
73cf66ba 20#include <ctype.h>
03c05291 21#include <string.h>
73cf66ba 22EXEC SQL INCLUDE sqlca;
23EXEC SQL INCLUDE sqlda;
24#include "qrtn.h"
25
03c05291 26extern char *whoami, *table_name[], *sqlbuffer[QMAXARGS];
27extern int dbms_errno, mr_errcode;
73cf66ba 28
29EXEC SQL BEGIN DECLARE SECTION;
30extern char stmt_buf[];
31EXEC SQL END DECLARE SECTION;
32
03c05291 33int validate_chars(char *argv[], struct valobj *vo);
34int validate_id(struct query *, char *argv[], struct valobj *vo);
35int validate_name(char *argv[], struct valobj *vo);
36int validate_rename(char *argv[], struct valobj *vo);
37int validate_type(char *argv[], struct valobj *vo);
38int validate_typedata(struct query *, char *argv[], struct valobj *vo);
39int validate_len(char *argv[], struct valobj *vo);
40int lock_table(struct valobj *vo);
41int readlock_table(struct valobj *vo);
42int convert_wildcards_uppercase(char *arg);
73cf66ba 43
5eaef520 44extern SQLDA *sqlald(int, int, int);
960b073b 45
03c05291 46EXEC SQL WHENEVER SQLERROR DO dbmserr();
73cf66ba 47
48/* Validation Routines */
49
5eaef520 50int validate_row(register struct query *q, char *argv[], register struct validate *v)
73cf66ba 51{
5eaef520 52 EXEC SQL BEGIN DECLARE SECTION;
53 char qual[128];
54 int rowcount;
55 EXEC SQL END DECLARE SECTION;
56
57 /* build where clause */
58 build_qual(v->qual, v->argc, argv, qual);
59
60 if (log_flags & LOG_VALID)
61 /* tell the logfile what we're doing */
62 com_err(whoami, 0, "validating row: %s", qual);
63
64 /* look for the record */
65 sprintf(stmt_buf, "SELECT COUNT (*) FROM %s WHERE %s",
66 table_name[q->rtable], qual);
67 dosql(sqlbuffer);
68 if (dbms_errno)
69 return mr_errcode;
70
71 rowcount = atoi(sqlbuffer[0]);
72 if (rowcount == 0)
73 return MR_NO_MATCH;
74 if (rowcount > 1)
75 return MR_NOT_UNIQUE;
76 return MR_EXISTS;
73cf66ba 77}
78
5eaef520 79int validate_fields(struct query *q, register char *argv[],
80 register struct valobj *vo, register int n)
73cf66ba 81{
5eaef520 82 register int status;
73cf66ba 83
5eaef520 84 while (--n >= 0)
85 {
86 switch (vo->type)
87 {
73cf66ba 88 case V_NAME:
5eaef520 89 if (log_flags & LOG_VALID)
90 {
91 com_err(whoami, 0, "validating %s in %s: %s",
92 vo->namefield, table_name[vo->table], argv[vo->index]);
93 }
94 status = validate_name(argv, vo);
95 break;
73cf66ba 96
97 case V_ID:
5eaef520 98 if (log_flags & LOG_VALID)
99 {
100 com_err(whoami, 0, "validating %s in %s: %s",
101 vo->idfield, table_name[vo->table], argv[vo->index]);
102 }
103 status = validate_id(q, argv, vo);
104 break;
73cf66ba 105
106 case V_TYPE:
5eaef520 107 if (log_flags & LOG_VALID)
108 {
109 com_err(whoami, 0, "validating %s type: %s",
110 table_name[vo->table], argv[vo->index]);
111 }
112 status = validate_type(argv, vo);
113 break;
73cf66ba 114
115 case V_TYPEDATA:
5eaef520 116 if (log_flags & LOG_VALID)
117 {
118 com_err(whoami, 0, "validating typed data (%s): %s",
119 argv[vo->index - 1], argv[vo->index]);
120 }
121 status = validate_typedata(q, argv, vo);
122 break;
73cf66ba 123
124 case V_RENAME:
5eaef520 125 if (log_flags & LOG_VALID)
126 {
127 com_err(whoami, 0, "validating rename %s in %s",
128 argv[vo->index], table_name[vo->table]);
129 }
130 status = validate_rename(argv, vo);
131 break;
73cf66ba 132
133 case V_CHAR:
5eaef520 134 if (log_flags & LOG_VALID)
135 com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
136 status = validate_chars(argv, vo);
137 break;
03c05291 138
139 case V_LEN:
5eaef520 140 if (log_flags & LOG_VALID)
141 com_err(whoami, 0, "validating length: %s", argv[vo->index]);
142 status = validate_len(argv, vo);
143 break;
73cf66ba 144
145 case V_SORT:
5eaef520 146 status = MR_EXISTS;
147 break;
73cf66ba 148
149 case V_LOCK:
5eaef520 150 status = lock_table(vo);
151 break;
73cf66ba 152
03c05291 153 case V_RLOCK:
5eaef520 154 status = readlock_table(vo);
155 break;
03c05291 156
157 case V_WILD:
5eaef520 158 status = convert_wildcards(argv[vo->index]);
159 break;
73cf66ba 160
161 case V_UPWILD:
5eaef520 162 status = convert_wildcards_uppercase(argv[vo->index]);
163 break;
73cf66ba 164
165 }
166
5eaef520 167 if (status != MR_EXISTS)
168 return status;
169 vo++;
73cf66ba 170 }
171
5eaef520 172 if (dbms_errno)
173 return mr_errcode;
174 return MR_SUCCESS;
73cf66ba 175}
176
177
178/* validate_chars: verify that there are no illegal characters in
179 * the string. Legal characters are printing chars other than
180 * ", *, ?, \, [ and ].
181 */
182static int illegalchars[] = {
5eaef520 183 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
184 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
185 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
186 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
187 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
188 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
190 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
191 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
192 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
193 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
194 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
195 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
196 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
197 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
198 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
73cf66ba 199};
200
5eaef520 201int validate_chars(char *argv[], register struct valobj *vo)
73cf66ba 202{
5eaef520 203 char *s = argv[vo->index];
204 int arg;
205 EXEC SQL BEGIN DECLARE SECTION;
206 int len;
207 char *tname, *cname;
208 EXEC SQL END DECLARE SECTION;
209
210 /* check for bad characters */
211 while (*s)
212 {
73cf66ba 213 if (illegalchars[*s++])
5eaef520 214 return MR_BAD_CHAR;
215 }
03c05291 216
5eaef520 217 /* check for length */
218 tname = table_name[vo->table];
219 cname = vo->namefield;
220 EXEC SQL SELECT data_length INTO :len FROM user_tab_columns
221 WHERE table_name = UPPER(:tname) AND column_name = UPPER(:cname);
03c05291 222
5eaef520 223 if ((strlen(argv[vo->index]) > len) &&
224 strcmp(argv[vo->index], UNIQUE_LOGIN)) /* kludge... sigh */
225 argv[vo->index][len] = '\0'; /* truncate */
03c05291 226
5eaef520 227 return MR_EXISTS;
73cf66ba 228}
229
230
5eaef520 231int validate_id(struct query *q, char *argv[], register struct valobj *vo)
73cf66ba 232{
5eaef520 233 EXEC SQL BEGIN DECLARE SECTION;
234 char *name, *namefield, *idfield;
235 int id, rowcount, tbl;
236 EXEC SQL END DECLARE SECTION;
237 int status;
238 register char *c;
239
240 name = argv[vo->index];
241 tbl = vo->table;
242 namefield = vo->namefield;
243 idfield = vo->idfield;
244
245 if ((tbl == USERS_TABLE && !strcmp(namefield, "login")) ||
246 tbl == MACHINE_TABLE || tbl == SUBNET_TABLE || tbl == FILESYS_TABLE ||
247 tbl == LIST_TABLE || tbl == CLUSTER_TABLE || tbl == STRINGS_TABLE)
248 {
249 if (tbl == MACHINE_TABLE || tbl == SUBNET_TABLE)
250 {
251 for (c = name; *c; c++)
252 {
253 if (islower(*c))
254 *c = toupper(*c);
255 }
256 }
03c05291 257 status = name_to_id(name, tbl, &id);
5eaef520 258 if (status == 0)
259 {
260 *(int *)argv[vo->index] = id;
261 return MR_EXISTS;
262 }
263 else if (status == MR_NO_MATCH && tbl == STRINGS_TABLE &&
264 (q->type == APPEND || q->type == UPDATE))
265 {
266 id = add_string(name);
267 cache_entry(name, STRINGS_TABLE, id);
268 *(int *)argv[vo->index] = id;
269 return MR_EXISTS;
270 }
271 else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
272 return vo->error;
03c05291 273 else
5eaef520 274 return status;
275 }
276 else
277 {
03c05291 278 /* else, it's `dubu', which uses unix_uid from users */
279 EXEC SQL SELECT COUNT(*) INTO :rowcount FROM users
280 WHERE unix_uid = :name;
5eaef520 281 if (dbms_errno)
282 return mr_errcode;
283 if (rowcount != 1)
284 return vo->error;
03c05291 285 EXEC SQL SELECT users_id INTO :id FROM users
286 WHERE unix_uid = :name;
287 *(int *)argv[vo->index] = id;
5eaef520 288 return MR_EXISTS;
73cf66ba 289 }
73cf66ba 290}
291
5eaef520 292int validate_name(char *argv[], register struct valobj *vo)
73cf66ba 293{
5eaef520 294 char *name, *namefield;
295 register char *c;
296
297 name = argv[vo->index];
298 namefield = vo->namefield;
299 if (vo->table == SERVERS_TABLE && !strcmp(namefield, "name"))
300 {
301 for (c = name; *c; c++)
302 {
73cf66ba 303 if (islower(*c))
304 *c = toupper(*c);
5eaef520 305 }
73cf66ba 306 }
5eaef520 307 sprintf(stmt_buf, "SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
308 table_name[vo->table], table_name[vo->table], namefield, name);
309 dosql(sqlbuffer);
03c05291 310
5eaef520 311 if (dbms_errno)
312 return mr_errcode;
313 return (atoi(sqlbuffer[0]) == 1) ? MR_EXISTS : vo->error;
73cf66ba 314}
315
5eaef520 316int validate_rename(char *argv[], struct valobj *vo)
73cf66ba 317{
5eaef520 318 EXEC SQL BEGIN DECLARE SECTION;
319 char *name, *namefield, *idfield;
320 int id;
321 EXEC SQL END DECLARE SECTION;
322 int status;
323 register char *c;
324
325 status = validate_chars(argv, vo);
326 if (status != MR_EXISTS)
327 return status;
328 name = argv[vo->index];
329 /* minor kludge to upcasify machine names */
330 if (vo->table == MACHINE_TABLE)
331 {
332 for (c = name; *c; c++)
333 {
334 if (islower(*c))
335 *c = toupper(*c);
336 }
337 }
338 namefield = vo->namefield;
339 idfield = vo->idfield;
340 id = -1;
341 if (idfield == 0)
342 {
343 if (!strcmp(argv[vo->index], argv[vo->index - 1]))
344 return MR_EXISTS;
345 sprintf(stmt_buf, "SELECT %s FROM %s WHERE %s = '%s'",
346 namefield, table_name[vo->table], namefield, name);
347 dosql(sqlbuffer);
348
349 if (dbms_errno)
350 return mr_errcode;
351 if (sqlca.sqlcode == SQL_NO_MATCH)
352 return MR_EXISTS; /* how's _that_ for intuitive? */
353 else
354 return vo->error;
73cf66ba 355 }
5eaef520 356 status = name_to_id(name, vo->table, &id);
357 if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
358 return MR_EXISTS;
359 else
360 return vo->error;
73cf66ba 361}
362
363
5eaef520 364int validate_type(char *argv[], register struct valobj *vo)
73cf66ba 365{
5eaef520 366 EXEC SQL BEGIN DECLARE SECTION;
367 char *typename;
368 char *val;
369 int cnt;
370 EXEC SQL END DECLARE SECTION;
371 register char *c;
372
373 typename = vo->namefield;
374 c = val = argv[vo->index];
375 while (*c)
376 {
377 if (illegalchars[*c++])
378 return MR_BAD_CHAR;
73cf66ba 379 }
380
5eaef520 381 /* uppercase type fields */
382 for (c = val; *c; c++)
383 {
384 if (islower(*c))
385 *c = toupper(*c);
386 }
73cf66ba 387
5eaef520 388 EXEC SQL SELECT COUNT(trans) INTO :cnt FROM alias
389 WHERE name = :typename AND type = 'TYPE' AND trans = :val;
390 if (dbms_errno)
391 return mr_errcode;
392 return cnt ? MR_EXISTS : vo->error;
73cf66ba 393}
394
395/* validate member or type-specific data field */
396
5eaef520 397int validate_typedata(register struct query *q, register char *argv[], register struct valobj *vo)
73cf66ba 398{
5eaef520 399 EXEC SQL BEGIN DECLARE SECTION;
400 char *name;
401 char *field_type;
402 char data_type[129];
403 int id;
404 EXEC SQL END DECLARE SECTION;
405 int status;
406 register char *c;
407
408 /* get named object */
409 name = argv[vo->index];
410
411 /* get field type string (known to be at index-1) */
412 field_type = argv[vo->index - 1];
413
414 /* get corresponding data type associated with field type name */
415 EXEC SQL SELECT trans INTO :data_type FROM alias
416 WHERE name = :field_type AND type = 'TYPEDATA';
417 if (dbms_errno)
418 return mr_errcode;
419 if (sqlca.sqlerrd[2] != 1)
420 return MR_TYPE;
421
422 /* now retrieve the record id corresponding to the named object */
423 if (strchr(data_type, ' '))
424 *strchr(data_type, ' ') = '\0';
425 if (!strcmp(data_type, "user"))
426 {
427 /* USER */
428 if (strchr(name, '@'))
429 return MR_USER;
430 status = name_to_id(name, USERS_TABLE, &id);
431 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
432 return MR_USER;
433 if (status)
434 return status;
435 }
436 else if (!strcmp(data_type, "list"))
437 {
438 /* LIST */
439 status = name_to_id(name, LIST_TABLE, &id);
440 if (status && status == MR_NOT_UNIQUE)
441 return MR_LIST;
442 if (status == MR_NO_MATCH)
443 {
444 /* if idfield is non-zero, then if argv[0] matches the string
445 * that we're trying to resolve, we should get the value of
446 * numvalues.[idfield] for the id.
447 */
448 if (vo->idfield && !strcmp(argv[0], argv[vo->index]))
449 {
450 set_next_object_id(q->validate->object_id, q->rtable, 0);
451 name = vo->idfield;
452 EXEC SQL SELECT value INTO :id FROM numvalues
453 WHERE name = :name;
454 if (sqlca.sqlerrd[2] != 1)
455 return MR_LIST;
456 }
457 else
458 return MR_LIST;
459 }
460 else if (status)
461 return status;
462 }
463 else if (!strcmp(data_type, "machine"))
464 {
465 /* MACHINE */
466 for (c = name; *c; c++)
467 {
468 if (islower(*c))
469 *c = toupper(*c);
470 }
471 status = name_to_id(name, MACHINE_TABLE, &id);
472 if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
473 return MR_MACHINE;
474 if (status)
475 return status;
476 }
477 else if (!strcmp(data_type, "string"))
478 {
479 /* STRING */
480 status = name_to_id(name, STRINGS_TABLE, &id);
481 if (status && status == MR_NOT_UNIQUE)
482 return MR_STRING;
483 if (status == MR_NO_MATCH)
484 {
485 if (q->type != APPEND && q->type != UPDATE)
486 return MR_STRING;
487 id = add_string(name);
488 cache_entry(name, STRINGS_TABLE, id);
489 }
490 else if (status)
491 return status;
73cf66ba 492 }
5eaef520 493 else if (!strcmp(data_type, "none"))
494 id = 0;
495 else
496 return MR_TYPE;
73cf66ba 497
5eaef520 498 /* now set value in argv */
499 *(int *)argv[vo->index] = id;
73cf66ba 500
5eaef520 501 return MR_EXISTS;
73cf66ba 502}
503
504
03c05291 505/* Make sure the data fits in the field */
5eaef520 506int validate_len(register char *argv[], register struct valobj *vo)
03c05291 507{
5eaef520 508 EXEC SQL BEGIN DECLARE SECTION;
509 int len;
510 char *tname, *cname;
511 EXEC SQL END DECLARE SECTION;
03c05291 512
5eaef520 513 tname = table_name[vo->table];
514 cname = vo->namefield;
515 EXEC SQL SELECT data_length INTO :len FROM user_tab_columns
516 WHERE table_name = UPPER(:tname) AND column_name = UPPER(:cname);
03c05291 517
5eaef520 518 if ((strlen(argv[vo->index]) > len) &&
519 strcmp(argv[vo->index], UNIQUE_LOGIN)) /* kludge... sigh */
520 argv[vo->index][len] = '\0'; /* truncate */
03c05291 521
5eaef520 522 return MR_EXISTS;
03c05291 523}
524
73cf66ba 525/* Lock the table named by the validation object */
526
5eaef520 527int lock_table(struct valobj *vo)
73cf66ba 528{
03c05291 529#ifdef DO_LOCKING
5eaef520 530 sprintf(stmt_buf, "LOCK TABLE %s IN EXCLUSIVE MODE", table_name[vo->table]);
531 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
532 if (dbms_errno)
533 return mr_errcode;
534 else
03c05291 535#endif
5eaef520 536 return MR_EXISTS;
73cf66ba 537}
538
03c05291 539/*
540 * Get a read lock on the table by accessing the magic lock
541 * record. Certain tables are constructed so that they contain
5eaef520 542 * an id field whose value is zero and a modtime field. We
543 * manipulate the modtime field of the id 0 record to effect
03c05291 544 * locking of the table
73cf66ba 545 */
546
5eaef520 547int readlock_table(struct valobj *vo)
73cf66ba 548{
03c05291 549#ifdef DO_LOCKING
5eaef520 550 sprintf(stmt_buf, "LOCK TABLE %s IN SHARE MODE", table_name[vo->table]);
551 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
03c05291 552
5eaef520 553 if (dbms_errno)
554 return mr_errcode;
555 if (sqlca.sqlcode)
556 return vo->error;
03c05291 557#endif
5eaef520 558 return MR_EXISTS; /* validate_fields expects us to return
559 * this value if everything went okay
560 */
73cf66ba 561}
562
695afd0d 563/* Check the database at startup time. */
03c05291 564
565void sanity_check_database(void)
566{
5eaef520 567 EXEC SQL BEGIN DECLARE SECTION;
568 int oid, id;
569 EXEC SQL END DECLARE SECTION;
695afd0d 570
5eaef520 571 /* Sometimes a crash can leave strings_id in numvalues in an
572 incorrect state. Check for that and fix it. */
695afd0d 573
5eaef520 574 EXEC SQL SELECT value INTO :oid FROM numvalues WHERE name = 'strings_id';
695afd0d 575
5eaef520 576 for (id = oid + 1; sqlca.sqlcode == 0; id++)
577 {
578 EXEC SQL SELECT string_id INTO :id FROM strings
579 WHERE string_id = :id;
580 }
695afd0d 581
5eaef520 582 if (id != oid + 1)
583 EXEC SQL UPDATE numvalues SET value = :id - 1 WHERE name = 'strings_id';
03c05291 584}
585
586
587char *sqlbuffer[QMAXARGS];
73cf66ba 588
589/* Dynamic SQL support routines */
03c05291 590SQLDA *mr_alloc_sqlda()
73cf66ba 591{
5eaef520 592 SQLDA *it;
593 register int j;
594
595 it = sqlald(QMAXARGS, ARGLEN, 0);
596 if (!it)
597 {
598 com_err(whoami, MR_NO_MEM, "setting up SQLDA");
599 exit(1);
73cf66ba 600 }
601
5eaef520 602 for (j = 0; j < QMAXARGS; j++)
603 {
604 it->V[j] = sqlbuffer[j] = malloc(ARGLEN);
605 it->T[j] = 97; /* 97 = CHARZ = null-terminated string */
606 it->L[j] = ARGLEN;
73cf66ba 607 }
03c05291 608
5eaef520 609 return it;
73cf66ba 610}
611
612
73cf66ba 613/* Convert normal Unix-style wildcards to SQL voodoo */
5eaef520 614int convert_wildcards(char *arg)
73cf66ba 615{
5eaef520 616 static char buffer[ARGLEN];
617 register char *s, *d;
618
619 for (d = buffer, s = arg; *s; s++)
620 {
621 switch (*s)
622 {
623 case '*':
624 *d++ = '%';
625 *d++ = '%';
626 break;
627 case '?':
628 *d++ = '_';
629 break;
630 case '_':
631 *d++ = '*';
632 *d++ = *s;
633 break;
634 case '%':
635 *d++ = '*';
636 *d++ = '%';
637 *d++ = '%';
638 break;
639 default:
640 *d++ = *s;
641 break;
73cf66ba 642 }
643 }
5eaef520 644 *d = '\0';
73cf66ba 645
5eaef520 646 /* Copy back into argv */
647 strcpy(arg, buffer);
73cf66ba 648
5eaef520 649 return MR_EXISTS;
73cf66ba 650}
651
652/* This version includes uppercase conversion, for things like gmac.
653 * This is necessary because "LIKE" doesn't work with "uppercase()".
654 * Including it in a wildcard routine saves making two passes over
655 * the argument string.
656 */
5eaef520 657int convert_wildcards_uppercase(char *arg)
73cf66ba 658{
5eaef520 659 static char buffer[ARGLEN];
660 register char *s, *d;
661
662 for (d = buffer, s = arg; *s; s++)
663 {
664 switch (*s)
665 {
666 case '*':
667 *d++ = '%';
668 *d++ = '%';
669 break;
670 case '?':
671 *d++ = '_';
672 break;
673 case '_':
674 *d++ = '*';
675 *d++ = *s;
676 break;
677 case '%':
678 *d++ = '*';
679 *d++ = '%';
680 *d++ = '%';
681 break;
682 default:
683 *d++ = toupper(*s); /* This is the only diff. */
684 break;
73cf66ba 685 }
686 }
5eaef520 687 *d = '\0';
73cf66ba 688
5eaef520 689 /* Copy back into argv */
690 strcpy(arg, buffer);
73cf66ba 691
5eaef520 692 return MR_EXISTS;
73cf66ba 693}
694
695
73cf66ba 696/* Adds a string to the string table. Returns the id number.
5eaef520 697 *
73cf66ba 698 */
5eaef520 699int add_string(char *nm)
73cf66ba 700{
5eaef520 701 EXEC SQL BEGIN DECLARE SECTION;
702 char buf[256], *name = nm;
703 int id;
704 EXEC SQL END DECLARE SECTION;
705
706 EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
707 id++;
708 EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
709
710 EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :nm);
711
712 return id;
73cf66ba 713}
This page took 0.158561 seconds and 5 git commands to generate.