3 * Query followup routines
5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
11 #include <mit-copyright.h>
12 #include "mr_server.h"
21 EXEC SQL INCLUDE sqlca;
25 extern char *whoami, *table_name[];
26 extern int dbms_errno, mr_errcode;
28 EXEC SQL BEGIN DECLARE SECTION;
29 extern char stmt_buf[];
30 EXEC SQL END DECLARE SECTION;
32 EXEC SQL WHENEVER SQLERROR DO dbmserr();
35 /* FOLLOWUP ROUTINES */
37 /* generic set_modtime routine. This takes the table id from the query,
38 * and will update the modtime, modby, and modwho fields in the entry in
39 * the table whose name field matches argv[0].
42 int set_modtime(struct query *q, char *argv[], client *cl)
44 char *name, *entity, *table;
49 table = table_name[q->rtable];
51 if (q->type == MR_Q_UPDATE)
56 sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
57 "modwith = '%s' WHERE name = '%s'", table, who, entity, name);
58 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
63 /* generic set_modtime_by_id routine. This takes the table id from
64 * the query, and the id name from the validate record,
65 * and will update the modtime, modby, and modwho fields in the entry in
66 * the table whose id matches argv[0].
69 int set_modtime_by_id(struct query *q, char *argv[], client *cl)
71 char *entity, *table, *id_name;
76 table = table_name[q->rtable];
77 id_name = q->validate->object_id;
80 sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
81 "modwith = '%s' WHERE %s = %d", table, who, entity, id_name, id);
82 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
87 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
90 int set_finger_modtime(struct query *q, char *argv[], client *cl)
92 EXEC SQL BEGIN DECLARE SECTION;
95 EXEC SQL END DECLARE SECTION;
99 users_id = *(int *)argv[0];
101 EXEC SQL UPDATE users SET fmodtime = SYSDATE, fmodby = :who,
102 fmodwith = :entity WHERE users_id = :users_id;
108 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
111 int set_pobox_modtime(struct query *q, char *argv[], client *cl)
113 EXEC SQL BEGIN DECLARE SECTION;
116 EXEC SQL END DECLARE SECTION;
120 users_id = *(int *)argv[0];
122 EXEC SQL UPDATE users SET pmodtime = SYSDATE, pmodby = :who,
123 pmodwith = :entity WHERE users_id = :users_id;
129 /* Like set_modtime, but uppercases the name first.
132 int set_uppercase_modtime(struct query *q, char *argv[], client *cl)
134 char *name, *entity, *table;
139 table = table_name[q->rtable];
142 sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
143 "modwith = '%s' WHERE name = UPPER('%s')", table, who, entity, name);
144 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
150 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
151 * is necessary for add_machine_to_cluster becuase the table that query
152 * operates on is "mcm", not "machine".
155 int set_mach_modtime_by_id(struct query *q, char *argv[], client *cl)
157 EXEC SQL BEGIN DECLARE SECTION;
160 EXEC SQL END DECLARE SECTION;
164 id = *(int *)argv[0];
165 EXEC SQL UPDATE machine SET modtime = SYSDATE, modby = :who,
166 modwith = :entity WHERE mach_id = :id;
172 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
173 * is necessary for add_cluster_data and delete_cluster_data becuase the
174 * table that query operates on is "svc", not "cluster".
177 int set_cluster_modtime_by_id(struct query *q, char *argv[], client *cl)
179 EXEC SQL BEGIN DECLARE SECTION;
182 EXEC SQL END DECLARE SECTION;
187 id = *(int *)argv[0];
188 EXEC SQL UPDATE clusters SET modtime = SYSDATE, modby = :who,
189 modwith = :entity WHERE clu_id = :id;
194 /* sets the modtime on the serverhost where the service name is in argv[0]
195 * and the mach_id is in argv[1].
198 int set_serverhost_modtime(struct query *q, char *argv[], client *cl)
200 EXEC SQL BEGIN DECLARE SECTION;
203 EXEC SQL END DECLARE SECTION;
209 id = *(int *)argv[1];
210 EXEC SQL UPDATE serverhosts
211 SET modtime = SYSDATE, modby = :who, modwith = :entity
212 WHERE service = :serv AND mach_id = :id;
217 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
218 * directory name is in argv[1].
221 int set_nfsphys_modtime(struct query *q, char *argv[], client *cl)
223 EXEC SQL BEGIN DECLARE SECTION;
226 EXEC SQL END DECLARE SECTION;
231 id = *(int *)argv[0];
233 EXEC SQL UPDATE nfsphys SET modtime = SYSDATE, modby = :who,
234 modwith = :entity WHERE dir = :dir AND mach_id = :id;
239 /* sets the modtime on a filesystem, where argv[0] contains the filesys
243 int set_filesys_modtime(struct query *q, char *argv[], client *cl)
245 EXEC SQL BEGIN DECLARE SECTION;
246 char *label, *entity;
248 extern int _var_phys_id;
249 EXEC SQL END DECLARE SECTION;
255 if (!strcmp(q->shortname, "ufil"))
258 EXEC SQL UPDATE filesys SET modtime = SYSDATE, modby = :who,
259 modwith = :entity, phys_id = :_var_phys_id
260 WHERE label = :label;
265 /* sets the modtime on a zephyr class, where argv[0] contains the class
269 int set_zephyr_modtime(struct query *q, char *argv[], client *cl)
271 EXEC SQL BEGIN DECLARE SECTION;
272 char *class, *entity;
274 EXEC SQL END DECLARE SECTION;
281 EXEC SQL UPDATE zephyr SET modtime = SYSDATE, modby = :who,
282 modwith = :entity WHERE class = :class;
287 /* sets the modtime on an entry in services table, where argv[0] contains
291 int set_service_modtime(struct query *q, char *argv[], client *cl)
293 EXEC SQL BEGIN DECLARE SECTION;
294 char *service, *protocol, *entity;
296 EXEC SQL END DECLARE SECTION;
304 EXEC SQL UPDATE services SET modtime = SYSDATE, modby = :who,
305 modwith = :entity WHERE name = :service AND protocol = :protocol;
310 /* fixes the modby field. This will be the second to last thing in the
311 * argv, the argv length is determined from the query structure. It is
312 * passed as a pointer to an integer. This will either turn it into a
313 * username, or # + the users_id.
315 int followup_fix_modby(struct query *q, struct save_queue *sq,
316 struct validate *v, int (*action)(int, char *[], void *),
317 void *actarg, client *cl)
324 while (sq_get_data(sq, &argv))
328 status = id_to_name(id, USERS_TABLE, &argv[i]);
330 status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
331 if (status && status != MR_NO_MATCH)
333 (*action)(q->vcnt, argv, actarg);
334 for (j = 0; j < q->vcnt; j++)
343 ** followup_ausr - add finger and pobox entries, set_user_modtime
346 ** argv[0] - login (add_user)
347 ** argv[U_LAST] - last name
348 ** argv[U_FIRST] - first name
349 ** argv[U_MIDDLE] - middle name
353 int followup_ausr(struct query *q, char *argv[], client *cl)
355 EXEC SQL BEGIN DECLARE SECTION;
357 char *login, *entity, *name;
358 char fullname[USERS_FIRST_SIZE + USERS_MIDDLE_SIZE + USERS_LAST_SIZE];
359 EXEC SQL END DECLARE SECTION;
362 if (strlen(argv[U_FIRST]) && strlen(argv[U_MIDDLE]))
363 sprintf(fullname, "%s %s %s", argv[U_FIRST], argv[U_MIDDLE],
365 else if (strlen(argv[U_FIRST]))
366 sprintf(fullname, "%s %s", argv[U_FIRST], argv[U_LAST]);
368 sprintf(fullname, "%s", argv[U_LAST]);
374 /* create finger entry, pobox & set modtime on user */
375 EXEC SQL UPDATE users
376 SET modtime = SYSDATE, modby = :who, modwith = :entity,
377 fullname = NVL(:fullname, CHR(0)), affiliation = type,
378 fmodtime = SYSDATE, fmodby = :who, fmodwith = :entity,
379 potype = 'NONE', pmodtime = SYSDATE, pmodby = :who, pmodwith = :entity
380 WHERE login = :login;
385 /* followup_gpob: fixes argv[2] and argv[3] based on the pobox type.
386 * Then completes the upcall to the user.
388 * argv[2] is the users_id on input and should be converted to the
389 * pobox name on output. argv[3] is empty on input and should be
390 * converted to an email address on output.
393 int followup_gpob(struct query *q, struct save_queue *sq, struct validate *v,
394 int (*action)(int, char *[], void *), void *actarg,
399 int mid, sid, status, i;
400 EXEC SQL BEGIN DECLARE SECTION;
401 int users_id, pid, iid, bid, eid;
402 char mach[MACHINE_NAME_SIZE], fs[FILESYS_LABEL_SIZE];
403 char str[STRINGS_STRING_SIZE];
404 EXEC SQL END DECLARE SECTION;
407 while (sq_get_data(sq, &argv))
409 mr_trim_args(4, argv);
411 users_id = atoi(argv[2]);
413 EXEC SQL SELECT pop_id, imap_id, box_id, exchange_id INTO :pid, :iid, :bid, :eid
414 FROM users WHERE users_id = :users_id;
421 EXEC SQL SELECT string INTO :str FROM strings
422 WHERE string_id = :bid;
426 /* If SMTP, don't bother fetching IMAP and POP boxes. */
432 /* IMAP, or SPLIT with IMAP */
433 EXEC SQL SELECT f.label, m.name INTO :fs, :mach
434 FROM filesys f, machine m
435 WHERE f.filsys_id = :iid AND f.mach_id = m.mach_id;
441 /* POP, or SPLIT with POP */
442 EXEC SQL SELECT m.name INTO :mach FROM machine m, users u
443 WHERE u.users_id = :users_id AND u.pop_id = m.mach_id;
449 /* EXCHANGE, or SPLIT with EXCHANGE */
450 EXEC SQL SELECT m.name INTO :mach FROM machine m, users u
451 WHERE u.users_id = :users_id AND u.exchange_id = m.mach_id;
459 /* Now assemble the right answer. */
460 if (!strcmp(ptype, "POP") || !strcmp(ptype, "EXCHANGE"))
462 argv[2] = xstrdup(strtrim(mach));
463 argv[3] = xmalloc(strlen(argv[0]) + strlen(argv[2]) + 2);
464 sprintf(argv[3], "%s@%s", argv[0], argv[2]);
466 else if (!strcmp(ptype, "SMTP"))
468 argv[2] = xstrdup(strtrim(str));
469 argv[3] = xstrdup(str);
471 else if (!strcmp(ptype, "IMAP"))
473 argv[2] = xstrdup(strtrim(fs));
474 argv[3] = xmalloc(strlen(argv[0]) + strlen(strtrim(mach)) + 2);
475 sprintf(argv[3], "%s@%s", argv[0], mach);
477 else if (!strcmp(ptype, "SPLIT"))
479 argv[2] = xstrdup(strtrim(str));
480 argv[3] = xmalloc(strlen(argv[0]) + strlen(strtrim(mach)) +
482 sprintf(argv[3], "%s@%s, %s", argv[0], mach, str);
484 else /* ptype == "NONE" */
487 if (!strcmp(q->shortname, "gpob"))
491 status = id_to_name(sid, USERS_TABLE, &argv[5]);
493 status = id_to_name(-sid, STRINGS_TABLE, &argv[5]);
494 if (status && status != MR_NO_MATCH)
498 (*action)(q->vcnt, argv, actarg);
500 /* free saved data */
501 for (i = 0; i < q->vcnt; i++)
510 /* Fix an ace_name, based on its type. */
512 static int fix_ace(char *type, char **name)
514 int id = atoi(*name);
516 if (!strcmp(type, "LIST"))
517 return id_to_name(id, LIST_TABLE, name);
518 else if (!strcmp(type, "USER"))
519 return id_to_name(id, USERS_TABLE, name);
520 else if (!strcmp(type, "KERBEROS"))
521 return id_to_name(id, STRINGS_TABLE, name);
525 if (!strcmp(type, "NONE"))
526 *name = xstrdup("NONE");
528 *name = xstrdup("???");
534 /* followup_gsnt: fix the ace_name and modby */
536 int followup_gsnt(struct query *q, struct save_queue *sq, struct validate *v,
537 int (*action)(int, char *[], void *), void *actarg,
548 while (sq_get_data(sq, &argv))
550 mr_trim_args(q->vcnt, argv);
552 status = fix_ace(argv[7 + idx], &argv[8 + idx]);
553 if (status && status != MR_NO_MATCH)
557 return followup_fix_modby(q, sq, v, action, actarg, cl);
561 /* followup_ghst: fix the ace_name, strings and modby */
563 int followup_ghst(struct query *q, struct save_queue *sq, struct validate *v,
564 int (*action)(int, char *[], void *), void *actarg,
572 else if (q->version >= 6 && q->version < 8)
577 while (sq_get_data(sq, &argv))
579 mr_trim_args(q->vcnt, argv);
581 id = atoi(argv[13 + idx]);
582 status = id_to_name(id, STRINGS_TABLE, &argv[13 + idx]);
585 id = atoi(argv[14 + idx]);
586 status = id_to_name(id, STRINGS_TABLE, &argv[14 + idx]);
589 id = atoi(argv[16 + idx]);
591 status = id_to_name(-id, STRINGS_TABLE, &argv[16 + idx]);
593 status = id_to_name(id, USERS_TABLE, &argv[16 + idx]);
594 if (status && status != MR_NO_MATCH)
597 status = fix_ace(argv[11 + idx], &argv[12 + idx]);
598 if (status && status != MR_NO_MATCH)
602 return followup_fix_modby(q, sq, v, action, actarg, cl);
606 /* followup_glin: fix the ace_name, modace_name, expiration, and modby */
608 int followup_glin(struct query *q, struct save_queue *sq, struct validate *v,
609 int (*action)(int, char *[], void *), void *actarg,
615 while (sq_get_data(sq, &argv))
617 mr_trim_args(q->vcnt, argv);
620 status = fix_ace(argv[7], &argv[8]);
621 else if (q->version > 2 && q->version < 10)
622 status = fix_ace(argv[8], &argv[9]);
624 status = fix_ace(argv[10], &argv[11]);
626 if (status && status != MR_NO_MATCH)
632 status = fix_ace(argv[10], &argv[11]);
633 else if (q->version >= 10)
634 status = fix_ace(argv[12], &argv[13]);
636 if (status && status != MR_NO_MATCH)
640 if (atoi(argv[6]) == -1)
642 argv[6] = xrealloc(argv[6], strlen(UNIQUE_GID) + 1);
643 strcpy(argv[6], UNIQUE_GID);
647 return followup_fix_modby(q, sq, v, action, actarg, cl);
650 /* followup_gsin: fix the ace_name and modby. */
651 int followup_gsin(struct query *q, struct save_queue *sq, struct validate *v,
652 int (*action)(int, char *[], void *), void *actarg,
658 while (sq_get_data(sq, &argv))
660 mr_trim_args(q->vcnt, argv);
662 status = fix_ace(argv[11], &argv[12]);
663 if (status && status != MR_NO_MATCH)
667 return followup_fix_modby(q, sq, v, action, actarg, cl);
670 int followup_gpsv(struct query *q, struct save_queue *sq, struct validate *v,
671 int (*action)(int, char *[], void *), void *actarg,
677 while (sq_get_data(sq, &argv))
679 mr_trim_args(q->vcnt, argv);
681 status = fix_ace(argv[PRINTSERVER_OWNER_TYPE],
682 &argv[PRINTSERVER_OWNER_NAME]);
683 if (status && status != MR_NO_MATCH)
687 return followup_fix_modby(q, sq, v, action, actarg, cl);
691 /* followup_gqot: Fix the entity name, directory name & modby fields
692 * argv[0] = filsys_id
694 * argv[2] = entity_id
695 * argv[3] = ascii(quota)
698 int followup_gqot(struct query *q, struct save_queue *sq, struct validate *v,
699 int (*action)(int, char *[], void *), void *actarg,
704 EXEC SQL BEGIN DECLARE SECTION;
707 EXEC SQL END DECLARE SECTION;
710 if (!strcmp(q->name, "get_quota") ||
711 !strcmp(q->name, "get_quota_by_filesys"))
716 while (sq_get_data(sq, &argv))
723 status = id_to_name(atoi(argv[2]), USERS_TABLE, &argv[2]);
727 status = id_to_name(atoi(argv[2]), LIST_TABLE, &argv[2]);
731 argv[2] = xstrdup("system:anyuser");
735 argv[2] = xmalloc(8);
736 sprintf(argv[2], "%d", id);
739 id = atoi(argv[idx]);
741 argv[idx] = xmalloc(id ? NFSPHYS_DIR_SIZE : FILESYS_NAME_SIZE);
747 EXEC SQL SELECT name INTO :name FROM filesys
748 WHERE label = :label;
752 EXEC SQL SELECT dir INTO :name FROM nfsphys
753 WHERE nfsphys_id = :id;
755 if (sqlca.sqlerrd[2] != 1)
756 sprintf(argv[idx], "#%d", id);
758 id = atoi(argv[idx + 3]);
760 status = id_to_name(id, USERS_TABLE, &argv[idx + 3]);
762 status = id_to_name(-id, STRINGS_TABLE, &argv[idx + 3]);
763 if (status && status != MR_NO_MATCH)
765 (*action)(q->vcnt, argv, actarg);
766 for (j = 0; j < q->vcnt; j++)
775 /* followup_aqot: Add allocation to nfsphys after creating quota.
776 * argv[0] = filsys_id
777 * argv[1] = type if "add_quota" or "update_quota"
779 * argv[3 or 2] = ascii(quota)
782 int followup_aqot(struct query *q, char *argv[], client *cl)
784 EXEC SQL BEGIN DECLARE SECTION;
785 int quota, id, fs, who, physid, table;
786 char *entity, *qtype, *tname;
787 EXEC SQL END DECLARE SECTION;
793 tname = table_name[table];
794 fs = *(int *)argv[0];
795 EXEC SQL SELECT phys_id INTO :physid FROM filesys
796 WHERE filsys_id = :fs;
800 if (!strcmp(q->shortname, "aqot") || !strcmp(q->shortname, "uqot"))
803 id = *(int *)argv[2];
804 quota = atoi(argv[3]);
805 sprintf(incr_qual, "q.filsys_id = %d", fs);
810 id = *(int *)argv[1];
811 quota = atoi(argv[2]);
812 sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND "
813 "q.entity_id = %d", fs, qtype, id);
816 /* quota case of incremental_{before|after} only looks at slot 1 */
817 incr_argv[1] = qtype;
819 /* Follows one of many possible gross hacks to fix these particular
820 * conflicts between what is possible in the query table and what
821 * is possible in SQL.
823 if (q->type == MR_Q_APPEND)
825 incremental_clear_before();
826 EXEC SQL INSERT INTO quota
827 (filsys_id, type, entity_id, quota, phys_id)
828 VALUES (:fs, NVL(:qtype, CHR(0)), :id, :quota, :physid);
829 incremental_after(table, incr_qual, incr_argv);
833 incremental_before(table, incr_qual, incr_argv);
834 EXEC SQL UPDATE quota SET quota = :quota
835 WHERE filsys_id = :fs AND type = :qtype AND entity_id = :id;
837 incremental_after(table, incr_qual, incr_argv);
842 if (q->type == MR_Q_APPEND)
844 EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = SYSDATE
845 WHERE table_name = :tname;
849 EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE
850 WHERE table_name = :tname;
853 /* Proceed with original followup */
857 EXEC SQL UPDATE quota
858 SET modtime = SYSDATE, modby = :who, modwith = :entity
859 WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
860 EXEC SQL UPDATE nfsphys SET allocated = allocated + :quota
861 WHERE nfsphys_id = :physid;
868 /* Necessitated by the requirement of a correlation name by the incremental
869 * routines, since query table deletes don't provide one.
871 int followup_dqot(struct query *q, char **argv, client *cl)
876 EXEC SQL BEGIN DECLARE SECTION;
877 char incr_qual[80], *tname;
878 EXEC SQL END DECLARE SECTION;
881 tname = table_name[table];
882 fs = *(int *)argv[0];
883 if (!strcmp(q->shortname, "dqot"))
886 id = *(int *)argv[2];
891 id = *(int *)argv[1];
893 sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND q.entity_id = %d",
896 /* quota case of incremental_{before|after} only looks at slot 1 */
897 incr_argv[1] = qtype;
899 incremental_before(table, incr_qual, incr_argv);
900 EXEC SQL DELETE FROM quota q WHERE q.filsys_id = :fs AND q.type = :qtype
901 AND q.entity_id = :id;
902 incremental_clear_after();
907 EXEC SQL UPDATE tblstats SET deletes = deletes + 1, modtime = SYSDATE
908 WHERE table_name = :tname;
915 int followup_gzcl(struct query *q, struct save_queue *sq, struct validate *v,
916 int (*action)(int, char *[], void *), void *actarg,
927 while (sq_get_data(sq, &argv))
929 mr_trim_args(q->vcnt, argv);
931 for (i = 1; i < n; i += 2)
933 status = fix_ace(argv[i], &argv[i + 1]);
934 if (status && status != MR_NO_MATCH)
939 return followup_fix_modby(q, sq, v, action, actarg, cl);
946 int followup_gsha(struct query *q, struct save_queue *sq, struct validate *v,
947 int (*action)(int, char *[], void *), void *actarg,
953 while (sq_get_data(sq, &argv))
955 mr_trim_args(q->vcnt, argv);
957 status = fix_ace(argv[1], &argv[2]);
958 if (status && status != MR_NO_MATCH)
962 return followup_fix_modby(q, sq, v, action, actarg, cl);
966 int _sdl_followup(struct query *q, char *argv[], client *cl)
969 EXEC SQL ALTER SESSION SET SQL_TRACE TRUE;
971 EXEC SQL ALTER SESSION SET SQL_TRACE FALSE;
977 int trigger_dcm(struct query *q, char *argv[], client *cl)
980 char prog[MAXPATHLEN];
982 sprintf(prog, "%s/startdcm", BIN_DIR);
987 execl(prog, "startdcm", 0);
998 /* followup_gcon: fix the ace_name, memace_name, and modby */
1000 int followup_gcon(struct query *q, struct save_queue *sq, struct validate *v,
1001 int (*action)(int, char *[], void *), void *actarg,
1005 int status, idx = 0;
1007 if (q->version >= 9)
1010 while (sq_get_data(sq, &argv))
1012 mr_trim_args(q->vcnt, argv);
1014 status = fix_ace(argv[4 + idx], &argv[5 + idx]);
1015 if (status && status != MR_NO_MATCH)
1018 status = fix_ace(argv[6 + idx], &argv[7 + idx]);
1019 if (status && status != MR_NO_MATCH)
1023 return followup_fix_modby(q, sq, v, action, actarg, cl);
1026 /* followup_get_user: fix the modby and creator.
1027 * This assumes that the modby and creator fields are always
1028 * in the same relative position in the argv.
1031 int followup_get_user(struct query *q, struct save_queue *sq, struct
1032 validate *v, int (*action)(int, char *[], void *),
1033 void *actarg, client *cl)
1036 int i, j, k, status, id;
1040 while (sq_get_data(sq, &argv))
1042 mr_trim_args(q->vcnt, argv);
1046 status = id_to_name(id, USERS_TABLE, &argv[i]);
1048 status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
1049 if (status && status != MR_NO_MATCH)
1054 status = id_to_name(id, USERS_TABLE, &argv[j]);
1056 status = id_to_name(-id, STRINGS_TABLE, &argv[j]);
1057 if (status && status != MR_NO_MATCH)
1060 if (q->version > 11)
1062 status = fix_ace(argv[15], &argv[16]);
1063 if (status && status != MR_NO_MATCH)
1067 (*action)(q->vcnt, argv, actarg);
1068 for (k = 0; k < q->vcnt; k++)