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];
52 sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
53 "modwith = '%s' WHERE name = '%s'", table, who, entity, name);
54 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
59 /* generic set_modtime_by_id routine. This takes the table id from
60 * the query, and the id name from the validate record,
61 * and will update the modtime, modby, and modwho fields in the entry in
62 * the table whose id matches argv[0].
65 int set_modtime_by_id(struct query *q, char *argv[], client *cl)
67 char *entity, *table, *id_name;
72 table = table_name[q->rtable];
73 id_name = q->validate->object_id;
76 sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
77 "modwith = '%s' WHERE %s = %d", table, who, entity, id_name, id);
78 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
83 /* Sets the finger modtime on a user record. The users_id will be in argv[0].
86 int set_finger_modtime(struct query *q, char *argv[], client *cl)
88 EXEC SQL BEGIN DECLARE SECTION;
91 EXEC SQL END DECLARE SECTION;
95 users_id = *(int *)argv[0];
97 EXEC SQL UPDATE users SET fmodtime = SYSDATE, fmodby = :who,
98 fmodwith = :entity WHERE users_id = :users_id;
104 /* Sets the pobox modtime on a user record. The users_id will be in argv[0].
107 int set_pobox_modtime(struct query *q, char *argv[], client *cl)
109 EXEC SQL BEGIN DECLARE SECTION;
112 EXEC SQL END DECLARE SECTION;
116 users_id = *(int *)argv[0];
118 EXEC SQL UPDATE users SET pmodtime = SYSDATE, pmodby = :who,
119 pmodwith = :entity WHERE users_id = :users_id;
125 /* Like set_modtime, but uppercases the name first.
128 int set_uppercase_modtime(struct query *q, char *argv[], client *cl)
130 char *name, *entity, *table;
135 table = table_name[q->rtable];
138 sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, "
139 "modwith = '%s' WHERE name = UPPER('%s')", table, who, entity, name);
140 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
146 /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine
147 * is necessary for add_machine_to_cluster becuase the table that query
148 * operates on is "mcm", not "machine".
151 int set_mach_modtime_by_id(struct query *q, char *argv[], client *cl)
153 EXEC SQL BEGIN DECLARE SECTION;
156 EXEC SQL END DECLARE SECTION;
160 id = *(int *)argv[0];
161 EXEC SQL UPDATE machine SET modtime = SYSDATE, modby = :who,
162 modwith = :entity WHERE mach_id = :id;
168 /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine
169 * is necessary for add_cluster_data and delete_cluster_data becuase the
170 * table that query operates on is "svc", not "cluster".
173 int set_cluster_modtime_by_id(struct query *q, char *argv[], client *cl)
175 EXEC SQL BEGIN DECLARE SECTION;
178 EXEC SQL END DECLARE SECTION;
183 id = *(int *)argv[0];
184 EXEC SQL UPDATE clusters SET modtime = SYSDATE, modby = :who,
185 modwith = :entity WHERE clu_id = :id;
190 /* sets the modtime on the serverhost where the service name is in argv[0]
191 * and the mach_id is in argv[1].
194 int set_serverhost_modtime(struct query *q, char *argv[], client *cl)
196 EXEC SQL BEGIN DECLARE SECTION;
199 EXEC SQL END DECLARE SECTION;
205 id = *(int *)argv[1];
206 EXEC SQL UPDATE serverhosts
207 SET modtime = SYSDATE, modby = :who, modwith = :entity
208 WHERE service = :serv AND mach_id = :id;
213 /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the
214 * directory name is in argv[1].
217 int set_nfsphys_modtime(struct query *q, char *argv[], client *cl)
219 EXEC SQL BEGIN DECLARE SECTION;
222 EXEC SQL END DECLARE SECTION;
227 id = *(int *)argv[0];
229 EXEC SQL UPDATE nfsphys SET modtime = SYSDATE, modby = :who,
230 modwith = :entity WHERE dir = :dir AND mach_id = :id;
235 /* sets the modtime on a filesystem, where argv[0] contains the filesys
239 int set_filesys_modtime(struct query *q, char *argv[], client *cl)
241 EXEC SQL BEGIN DECLARE SECTION;
242 char *label, *entity;
244 extern int _var_phys_id;
245 EXEC SQL END DECLARE SECTION;
251 if (!strcmp(q->shortname, "ufil"))
254 EXEC SQL UPDATE filesys SET modtime = SYSDATE, modby = :who,
255 modwith = :entity, phys_id = :_var_phys_id
256 WHERE label = :label;
261 /* sets the modtime on a zephyr class, where argv[0] contains the class
265 int set_zephyr_modtime(struct query *q, char *argv[], client *cl)
267 EXEC SQL BEGIN DECLARE SECTION;
268 char *class, *entity;
270 EXEC SQL END DECLARE SECTION;
277 EXEC SQL UPDATE zephyr SET modtime = SYSDATE, modby = :who,
278 modwith = :entity WHERE class = :class;
283 /* sets the modtime on an entry in services table, where argv[0] contains
287 int set_service_modtime(struct query *q, char *argv[], client *cl)
289 EXEC SQL BEGIN DECLARE SECTION;
290 char *service, *protocol, *entity;
292 EXEC SQL END DECLARE SECTION;
300 EXEC SQL UPDATE services SET modtime = SYSDATE, modby = :who,
301 modwith = :entity WHERE name = :service AND protocol = :protocol;
306 /* fixes the modby field. This will be the second to last thing in the
307 * argv, the argv length is determined from the query structure. It is
308 * passed as a pointer to an integer. This will either turn it into a
309 * username, or # + the users_id.
311 int followup_fix_modby(struct query *q, struct save_queue *sq,
312 struct validate *v, int (*action)(int, char *[], void *),
313 void *actarg, client *cl)
320 while (sq_get_data(sq, &argv))
324 status = id_to_name(id, USERS_TABLE, &argv[i]);
326 status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
327 if (status && status != MR_NO_MATCH)
329 (*action)(q->vcnt, argv, actarg);
330 for (j = 0; j < q->vcnt; j++)
339 ** followup_ausr - add finger and pobox entries, set_user_modtime
342 ** argv[0] - login (add_user)
343 ** argv[U_LAST] - last name
344 ** argv[U_FIRST] - first name
345 ** argv[U_MIDDLE] - middle name
349 int followup_ausr(struct query *q, char *argv[], client *cl)
351 EXEC SQL BEGIN DECLARE SECTION;
353 char *login, *entity, *name;
354 char fullname[USERS_FIRST_SIZE + USERS_MIDDLE_SIZE + USERS_LAST_SIZE];
355 EXEC SQL END DECLARE SECTION;
358 if (strlen(argv[U_FIRST]) && strlen(argv[U_MIDDLE]))
359 sprintf(fullname, "%s %s %s", argv[U_FIRST], argv[U_MIDDLE],
361 else if (strlen(argv[U_FIRST]))
362 sprintf(fullname, "%s %s", argv[U_FIRST], argv[U_LAST]);
364 sprintf(fullname, "%s", argv[U_LAST]);
370 /* create finger entry, pobox & set modtime on user */
371 EXEC SQL UPDATE users
372 SET modtime = SYSDATE, modby = :who, modwith = :entity,
373 fullname = NVL(:fullname, CHR(0)), affiliation = type,
374 fmodtime = SYSDATE, fmodby = :who, fmodwith = :entity,
375 potype = 'NONE', pmodtime = SYSDATE, pmodby = :who, pmodwith = :entity
376 WHERE login = :login;
381 /* followup_gpob: fixes argv[2] and argv[3] based on the pobox type.
382 * Then completes the upcall to the user.
384 * argv[2] is the users_id on input and should be converted to the
385 * pobox name on output. argv[3] is empty on input and should be
386 * converted to an email address on output.
389 int followup_gpob(struct query *q, struct save_queue *sq, struct validate *v,
390 int (*action)(int, char *[], void *), void *actarg,
395 int mid, sid, status, i;
396 EXEC SQL BEGIN DECLARE SECTION;
397 int users_id, pid, iid, bid, eid;
398 char mach[MACHINE_NAME_SIZE], fs[FILESYS_LABEL_SIZE];
399 char str[STRINGS_STRING_SIZE];
400 EXEC SQL END DECLARE SECTION;
403 while (sq_get_data(sq, &argv))
405 mr_trim_args(4, argv);
407 users_id = atoi(argv[2]);
409 EXEC SQL SELECT pop_id, imap_id, box_id, exchange_id INTO :pid, :iid, :bid, :eid
410 FROM users WHERE users_id = :users_id;
417 EXEC SQL SELECT string INTO :str FROM strings
418 WHERE string_id = :bid;
422 /* If SMTP, don't bother fetching IMAP and POP boxes. */
428 /* IMAP, or SPLIT with IMAP */
429 EXEC SQL SELECT f.label, m.name INTO :fs, :mach
430 FROM filesys f, machine m
431 WHERE f.filsys_id = :iid AND f.mach_id = m.mach_id;
437 /* POP, or SPLIT with POP */
438 EXEC SQL SELECT m.name INTO :mach FROM machine m, users u
439 WHERE u.users_id = :users_id AND u.pop_id = m.mach_id;
445 /* EXCHANGE, or SPLIT with EXCHANGE */
446 EXEC SQL SELECT m.name INTO :mach FROM machine m, users u
447 WHERE u.users_id = :users_id AND u.exchange_id = m.mach_id;
455 /* Now assemble the right answer. */
456 if (!strcmp(ptype, "POP") || !strcmp(ptype, "EXCHANGE"))
458 argv[2] = xstrdup(strtrim(mach));
459 argv[3] = xmalloc(strlen(argv[0]) + strlen(argv[2]) + 2);
460 sprintf(argv[3], "%s@%s", argv[0], argv[2]);
462 else if (!strcmp(ptype, "SMTP"))
464 argv[2] = xstrdup(strtrim(str));
465 argv[3] = xstrdup(str);
467 else if (!strcmp(ptype, "IMAP"))
469 argv[2] = xstrdup(strtrim(fs));
470 argv[3] = xmalloc(strlen(argv[0]) + strlen(strtrim(mach)) + 2);
471 sprintf(argv[3], "%s@%s", argv[0], mach);
473 else if (!strcmp(ptype, "SPLIT"))
475 argv[2] = xstrdup(strtrim(str));
476 argv[3] = xmalloc(strlen(argv[0]) + strlen(strtrim(mach)) +
478 sprintf(argv[3], "%s@%s, %s", argv[0], mach, str);
480 else /* ptype == "NONE" */
483 if (!strcmp(q->shortname, "gpob"))
487 status = id_to_name(sid, USERS_TABLE, &argv[5]);
489 status = id_to_name(-sid, STRINGS_TABLE, &argv[5]);
490 if (status && status != MR_NO_MATCH)
494 (*action)(q->vcnt, argv, actarg);
496 /* free saved data */
497 for (i = 0; i < q->vcnt; i++)
506 /* Fix an ace_name, based on its type. */
508 static int fix_ace(char *type, char **name)
510 int id = atoi(*name);
512 if (!strcmp(type, "LIST"))
513 return id_to_name(id, LIST_TABLE, name);
514 else if (!strcmp(type, "USER"))
515 return id_to_name(id, USERS_TABLE, name);
516 else if (!strcmp(type, "KERBEROS"))
517 return id_to_name(id, STRINGS_TABLE, name);
521 if (!strcmp(type, "NONE"))
522 *name = xstrdup("NONE");
524 *name = xstrdup("???");
530 /* followup_gsnt: fix the ace_name and modby */
532 int followup_gsnt(struct query *q, struct save_queue *sq, struct validate *v,
533 int (*action)(int, char *[], void *), void *actarg,
544 while (sq_get_data(sq, &argv))
546 mr_trim_args(q->vcnt, argv);
548 status = fix_ace(argv[7 + idx], &argv[8 + idx]);
549 if (status && status != MR_NO_MATCH)
553 return followup_fix_modby(q, sq, v, action, actarg, cl);
557 /* followup_ghst: fix the ace_name, strings and modby */
559 int followup_ghst(struct query *q, struct save_queue *sq, struct validate *v,
560 int (*action)(int, char *[], void *), void *actarg,
568 else if (q->version >= 6 && q->version < 8)
573 while (sq_get_data(sq, &argv))
575 mr_trim_args(q->vcnt, argv);
577 id = atoi(argv[13 + idx]);
578 status = id_to_name(id, STRINGS_TABLE, &argv[13 + idx]);
581 id = atoi(argv[14 + idx]);
582 status = id_to_name(id, STRINGS_TABLE, &argv[14 + idx]);
585 id = atoi(argv[16 + idx]);
587 status = id_to_name(-id, STRINGS_TABLE, &argv[16 + idx]);
589 status = id_to_name(id, USERS_TABLE, &argv[16 + idx]);
590 if (status && status != MR_NO_MATCH)
593 status = fix_ace(argv[11 + idx], &argv[12 + idx]);
594 if (status && status != MR_NO_MATCH)
598 return followup_fix_modby(q, sq, v, action, actarg, cl);
602 /* followup_glin: fix the ace_name, modace_name, expiration, and modby */
604 int followup_glin(struct query *q, struct save_queue *sq, struct validate *v,
605 int (*action)(int, char *[], void *), void *actarg,
611 while (sq_get_data(sq, &argv))
613 mr_trim_args(q->vcnt, argv);
616 status = fix_ace(argv[7], &argv[8]);
617 else if (q->version > 2 && q->version < 10)
618 status = fix_ace(argv[8], &argv[9]);
620 status = fix_ace(argv[10], &argv[11]);
622 if (status && status != MR_NO_MATCH)
628 status = fix_ace(argv[10], &argv[11]);
629 else if (q->version >= 10)
630 status = fix_ace(argv[12], &argv[13]);
632 if (status && status != MR_NO_MATCH)
636 if (atoi(argv[6]) == -1)
638 argv[6] = xrealloc(argv[6], strlen(UNIQUE_GID) + 1);
639 strcpy(argv[6], UNIQUE_GID);
643 return followup_fix_modby(q, sq, v, action, actarg, cl);
646 /* followup_gsin: fix the ace_name and modby. */
647 int followup_gsin(struct query *q, struct save_queue *sq, struct validate *v,
648 int (*action)(int, char *[], void *), void *actarg,
654 while (sq_get_data(sq, &argv))
656 mr_trim_args(q->vcnt, argv);
658 status = fix_ace(argv[11], &argv[12]);
659 if (status && status != MR_NO_MATCH)
663 return followup_fix_modby(q, sq, v, action, actarg, cl);
666 int followup_gpsv(struct query *q, struct save_queue *sq, struct validate *v,
667 int (*action)(int, char *[], void *), void *actarg,
673 while (sq_get_data(sq, &argv))
675 mr_trim_args(q->vcnt, argv);
677 status = fix_ace(argv[PRINTSERVER_OWNER_TYPE],
678 &argv[PRINTSERVER_OWNER_NAME]);
679 if (status && status != MR_NO_MATCH)
683 return followup_fix_modby(q, sq, v, action, actarg, cl);
687 /* followup_gqot: Fix the entity name, directory name & modby fields
688 * argv[0] = filsys_id
690 * argv[2] = entity_id
691 * argv[3] = ascii(quota)
694 int followup_gqot(struct query *q, struct save_queue *sq, struct validate *v,
695 int (*action)(int, char *[], void *), void *actarg,
700 EXEC SQL BEGIN DECLARE SECTION;
703 EXEC SQL END DECLARE SECTION;
706 if (!strcmp(q->name, "get_quota") ||
707 !strcmp(q->name, "get_quota_by_filesys"))
712 while (sq_get_data(sq, &argv))
719 status = id_to_name(atoi(argv[2]), USERS_TABLE, &argv[2]);
723 status = id_to_name(atoi(argv[2]), LIST_TABLE, &argv[2]);
727 argv[2] = xstrdup("system:anyuser");
731 argv[2] = xmalloc(8);
732 sprintf(argv[2], "%d", id);
735 id = atoi(argv[idx]);
737 argv[idx] = xmalloc(id ? NFSPHYS_DIR_SIZE : FILESYS_NAME_SIZE);
743 EXEC SQL SELECT name INTO :name FROM filesys
744 WHERE label = :label;
748 EXEC SQL SELECT dir INTO :name FROM nfsphys
749 WHERE nfsphys_id = :id;
751 if (sqlca.sqlerrd[2] != 1)
752 sprintf(argv[idx], "#%d", id);
754 id = atoi(argv[idx + 3]);
756 status = id_to_name(id, USERS_TABLE, &argv[idx + 3]);
758 status = id_to_name(-id, STRINGS_TABLE, &argv[idx + 3]);
759 if (status && status != MR_NO_MATCH)
761 (*action)(q->vcnt, argv, actarg);
762 for (j = 0; j < q->vcnt; j++)
771 /* followup_aqot: Add allocation to nfsphys after creating quota.
772 * argv[0] = filsys_id
773 * argv[1] = type if "add_quota" or "update_quota"
775 * argv[3 or 2] = ascii(quota)
778 int followup_aqot(struct query *q, char *argv[], client *cl)
780 EXEC SQL BEGIN DECLARE SECTION;
781 int quota, id, fs, who, physid, table;
782 char *entity, *qtype, *tname;
783 EXEC SQL END DECLARE SECTION;
789 tname = table_name[table];
790 fs = *(int *)argv[0];
791 EXEC SQL SELECT phys_id INTO :physid FROM filesys
792 WHERE filsys_id = :fs;
796 if (!strcmp(q->shortname, "aqot") || !strcmp(q->shortname, "uqot"))
799 id = *(int *)argv[2];
800 quota = atoi(argv[3]);
801 sprintf(incr_qual, "q.filsys_id = %d", fs);
806 id = *(int *)argv[1];
807 quota = atoi(argv[2]);
808 sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND "
809 "q.entity_id = %d", fs, qtype, id);
812 /* quota case of incremental_{before|after} only looks at slot 1 */
813 incr_argv[1] = qtype;
815 /* Follows one of many possible gross hacks to fix these particular
816 * conflicts between what is possible in the query table and what
817 * is possible in SQL.
819 if (q->type == APPEND)
821 incremental_clear_before();
822 EXEC SQL INSERT INTO quota
823 (filsys_id, type, entity_id, quota, phys_id)
824 VALUES (:fs, NVL(:qtype, CHR(0)), :id, :quota, :physid);
825 incremental_after(table, incr_qual, incr_argv);
829 incremental_before(table, incr_qual, incr_argv);
830 EXEC SQL UPDATE quota SET quota = :quota
831 WHERE filsys_id = :fs AND type = :qtype AND entity_id = :id;
833 incremental_after(table, incr_qual, incr_argv);
838 if (q->type == APPEND)
840 EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = SYSDATE
841 WHERE table_name = :tname;
845 EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE
846 WHERE table_name = :tname;
849 /* Proceed with original followup */
853 EXEC SQL UPDATE quota
854 SET modtime = SYSDATE, modby = :who, modwith = :entity
855 WHERE filsys_id = :fs and type = :qtype and entity_id = :id;
856 EXEC SQL UPDATE nfsphys SET allocated = allocated + :quota
857 WHERE nfsphys_id = :physid;
864 /* Necessitated by the requirement of a correlation name by the incremental
865 * routines, since query table deletes don't provide one.
867 int followup_dqot(struct query *q, char **argv, client *cl)
872 EXEC SQL BEGIN DECLARE SECTION;
873 char incr_qual[80], *tname;
874 EXEC SQL END DECLARE SECTION;
877 tname = table_name[table];
878 fs = *(int *)argv[0];
879 if (!strcmp(q->shortname, "dqot"))
882 id = *(int *)argv[2];
887 id = *(int *)argv[1];
889 sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND q.entity_id = %d",
892 /* quota case of incremental_{before|after} only looks at slot 1 */
893 incr_argv[1] = qtype;
895 incremental_before(table, incr_qual, incr_argv);
896 EXEC SQL DELETE FROM quota q WHERE q.filsys_id = :fs AND q.type = :qtype
897 AND q.entity_id = :id;
898 incremental_clear_after();
903 EXEC SQL UPDATE tblstats SET deletes = deletes + 1, modtime = SYSDATE
904 WHERE table_name = :tname;
911 int followup_gzcl(struct query *q, struct save_queue *sq, struct validate *v,
912 int (*action)(int, char *[], void *), void *actarg,
923 while (sq_get_data(sq, &argv))
925 mr_trim_args(q->vcnt, argv);
927 for (i = 1; i < n; i += 2)
929 status = fix_ace(argv[i], &argv[i + 1]);
930 if (status && status != MR_NO_MATCH)
935 return followup_fix_modby(q, sq, v, action, actarg, cl);
942 int followup_gsha(struct query *q, struct save_queue *sq, struct validate *v,
943 int (*action)(int, char *[], void *), void *actarg,
949 while (sq_get_data(sq, &argv))
951 mr_trim_args(q->vcnt, argv);
953 status = fix_ace(argv[1], &argv[2]);
954 if (status && status != MR_NO_MATCH)
958 return followup_fix_modby(q, sq, v, action, actarg, cl);
962 int _sdl_followup(struct query *q, char *argv[], client *cl)
965 EXEC SQL ALTER SESSION SET SQL_TRACE TRUE;
967 EXEC SQL ALTER SESSION SET SQL_TRACE FALSE;
973 int trigger_dcm(struct query *q, char *argv[], client *cl)
976 char prog[MAXPATHLEN];
978 sprintf(prog, "%s/startdcm", BIN_DIR);
983 execl(prog, "startdcm", 0);
994 /* followup_gcon: fix the ace_name, memace_name, and modby */
996 int followup_gcon(struct query *q, struct save_queue *sq, struct validate *v,
997 int (*action)(int, char *[], void *), void *actarg,
1001 int status, idx = 0;
1003 if (q->version >= 9)
1006 while (sq_get_data(sq, &argv))
1008 mr_trim_args(q->vcnt, argv);
1010 status = fix_ace(argv[4 + idx], &argv[5 + idx]);
1011 if (status && status != MR_NO_MATCH)
1014 status = fix_ace(argv[6 + idx], &argv[7 + idx]);
1015 if (status && status != MR_NO_MATCH)
1019 return followup_fix_modby(q, sq, v, action, actarg, cl);
1022 /* followup_get_user: fix the modby and creator.
1023 * This assumes that the modby and creator fields are always
1024 * in the same relative position in the argv.
1027 int followup_get_user(struct query *q, struct save_queue *sq, struct
1028 validate *v, int (*action)(int, char *[], void *),
1029 void *actarg, client *cl)
1032 int i, j, k, status, id;
1036 while (sq_get_data(sq, &argv))
1038 mr_trim_args(q->vcnt, argv);
1042 status = id_to_name(id, USERS_TABLE, &argv[i]);
1044 status = id_to_name(-id, STRINGS_TABLE, &argv[i]);
1045 if (status && status != MR_NO_MATCH)
1050 status = id_to_name(id, USERS_TABLE, &argv[j]);
1052 status = id_to_name(-id, STRINGS_TABLE, &argv[j]);
1053 if (status && status != MR_NO_MATCH)
1056 if (q->version > 11)
1058 status = fix_ace(argv[15], &argv[16]);
1059 if (status && status != MR_NO_MATCH)
1063 (*action)(q->vcnt, argv, actarg);
1064 for (k = 0; k < q->vcnt; k++)