/* $Id$ * * Query followup routines * * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology * For copying and distribution information, please see the file * . * */ #include #include "mr_server.h" #include "query.h" #include "qrtn.h" #include #include #include #include EXEC SQL INCLUDE sqlca; RCSID("$Header$"); extern char *whoami, *table_name[]; extern int dbms_errno, mr_errcode; EXEC SQL BEGIN DECLARE SECTION; extern char stmt_buf[]; EXEC SQL END DECLARE SECTION; EXEC SQL WHENEVER SQLERROR DO dbmserr(); /* FOLLOWUP ROUTINES */ /* generic set_modtime routine. This takes the table id from the query, * and will update the modtime, modby, and modwho fields in the entry in * the table whose name field matches argv[0]. */ int set_modtime(struct query *q, char *argv[], client *cl) { char *name, *entity, *table; int who, row = 0; entity = cl->entity; who = cl->client_id; table = table_name[q->rtable]; if (q->type == MR_Q_UPDATE) row = 1; name = argv[0 + row]; sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, " "modwith = '%s' WHERE name = '%s'", table, who, entity, name); EXEC SQL EXECUTE IMMEDIATE :stmt_buf; return MR_SUCCESS; } /* generic set_modtime_by_id routine. This takes the table id from * the query, and the id name from the validate record, * and will update the modtime, modby, and modwho fields in the entry in * the table whose id matches argv[0]. */ int set_modtime_by_id(struct query *q, char *argv[], client *cl) { char *entity, *table, *id_name; int who, id; entity = cl->entity; who = cl->client_id; table = table_name[q->rtable]; id_name = q->validate->object_id; id = *(int *)argv[0]; sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, " "modwith = '%s' WHERE %s = %d", table, who, entity, id_name, id); EXEC SQL EXECUTE IMMEDIATE :stmt_buf; return MR_SUCCESS; } /* Sets the finger modtime on a user record. The users_id will be in argv[0]. */ int set_finger_modtime(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; int users_id, who; char *entity; EXEC SQL END DECLARE SECTION; entity = cl->entity; who = cl->client_id; users_id = *(int *)argv[0]; EXEC SQL UPDATE users SET fmodtime = SYSDATE, fmodby = :who, fmodwith = :entity WHERE users_id = :users_id; return MR_SUCCESS; } /* Sets the pobox modtime on a user record. The users_id will be in argv[0]. */ int set_pobox_modtime(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; int users_id, who; char *entity; EXEC SQL END DECLARE SECTION; entity = cl->entity; who = cl->client_id; users_id = *(int *)argv[0]; EXEC SQL UPDATE users SET pmodtime = SYSDATE, pmodby = :who, pmodwith = :entity WHERE users_id = :users_id; return MR_SUCCESS; } /* Like set_modtime, but uppercases the name first. */ int set_uppercase_modtime(struct query *q, char *argv[], client *cl) { char *name, *entity, *table; int who; entity = cl->entity; who = cl->client_id; table = table_name[q->rtable]; name = argv[0]; sprintf(stmt_buf, "UPDATE %s SET modtime = SYSDATE, modby = %d, " "modwith = '%s' WHERE name = UPPER('%s')", table, who, entity, name); EXEC SQL EXECUTE IMMEDIATE :stmt_buf; return MR_SUCCESS; } /* Sets the modtime on the machine whose mach_id is in argv[0]. This routine * is necessary for add_machine_to_cluster becuase the table that query * operates on is "mcm", not "machine". */ int set_mach_modtime_by_id(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; char *entity; int who, id; EXEC SQL END DECLARE SECTION; entity = cl->entity; who = cl->client_id; id = *(int *)argv[0]; EXEC SQL UPDATE machine SET modtime = SYSDATE, modby = :who, modwith = :entity WHERE mach_id = :id; return MR_SUCCESS; } /* Sets the modtime on the cluster whose mach_id is in argv[0]. This routine * is necessary for add_cluster_data and delete_cluster_data becuase the * table that query operates on is "svc", not "cluster". */ int set_cluster_modtime_by_id(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; char *entity; int who, id; EXEC SQL END DECLARE SECTION; entity = cl->entity; who = cl->client_id; id = *(int *)argv[0]; EXEC SQL UPDATE clusters SET modtime = SYSDATE, modby = :who, modwith = :entity WHERE clu_id = :id; return MR_SUCCESS; } /* sets the modtime on the serverhost where the service name is in argv[0] * and the mach_id is in argv[1]. */ int set_serverhost_modtime(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; char *entity, *serv; int who, id; EXEC SQL END DECLARE SECTION; entity = cl->entity; who = cl->client_id; serv = argv[0]; id = *(int *)argv[1]; EXEC SQL UPDATE serverhosts SET modtime = SYSDATE, modby = :who, modwith = :entity WHERE service = :serv AND mach_id = :id; return MR_SUCCESS; } /* sets the modtime on the nfsphys where the mach_id is in argv[0] and the * directory name is in argv[1]. */ int set_nfsphys_modtime(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; char *entity, *dir; int who, id; EXEC SQL END DECLARE SECTION; entity = cl->entity; who = cl->client_id; id = *(int *)argv[0]; dir = argv[1]; EXEC SQL UPDATE nfsphys SET modtime = SYSDATE, modby = :who, modwith = :entity WHERE dir = :dir AND mach_id = :id; return MR_SUCCESS; } /* sets the modtime on a filesystem, where argv[0] contains the filesys * label. */ int set_filesys_modtime(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; char *label, *entity; int who; extern int _var_phys_id; EXEC SQL END DECLARE SECTION; entity = cl->entity; who = cl->client_id; label = argv[0]; if (!strcmp(q->shortname, "ufil")) label = argv[1]; EXEC SQL UPDATE filesys SET modtime = SYSDATE, modby = :who, modwith = :entity, phys_id = :_var_phys_id WHERE label = :label; return MR_SUCCESS; } /* sets the modtime on a zephyr class, where argv[0] contains the class * name. */ int set_zephyr_modtime(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; char *class, *entity; int who; EXEC SQL END DECLARE SECTION; entity = cl->entity; who = cl->client_id; class = argv[0]; EXEC SQL UPDATE zephyr SET modtime = SYSDATE, modby = :who, modwith = :entity WHERE class = :class; return MR_SUCCESS; } /* sets the modtime on an entry in services table, where argv[0] contains * the service name. */ int set_service_modtime(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; char *service, *protocol, *entity; int who; EXEC SQL END DECLARE SECTION; entity = cl->entity; who = cl->client_id; service = argv[0]; protocol = argv[1]; EXEC SQL UPDATE services SET modtime = SYSDATE, modby = :who, modwith = :entity WHERE name = :service AND protocol = :protocol; return MR_SUCCESS; } /* fixes the modby field. This will be the second to last thing in the * argv, the argv length is determined from the query structure. It is * passed as a pointer to an integer. This will either turn it into a * username, or # + the users_id. */ int followup_fix_modby(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { int i, j; char **argv; int id, status; i = q->vcnt - 2; while (sq_get_data(sq, &argv)) { id = atoi(argv[i]); if (id > 0) status = id_to_name(id, USERS_TABLE, &argv[i]); else status = id_to_name(-id, STRINGS_TABLE, &argv[i]); if (status && status != MR_NO_MATCH) return status; (*action)(q->vcnt, argv, actarg); for (j = 0; j < q->vcnt; j++) free(argv[j]); free(argv); } sq_destroy(sq); return MR_SUCCESS; } /** ** followup_ausr - add finger and pobox entries, set_user_modtime ** ** Inputs: ** argv[0] - login (add_user) ** argv[U_LAST] - last name ** argv[U_FIRST] - first name ** argv[U_MIDDLE] - middle name ** **/ int followup_ausr(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; int who, status; char *login, *entity, *name; char fullname[USERS_FIRST_SIZE + USERS_MIDDLE_SIZE + USERS_LAST_SIZE]; EXEC SQL END DECLARE SECTION; /* build fullname */ if (strlen(argv[U_FIRST]) && strlen(argv[U_MIDDLE])) sprintf(fullname, "%s %s %s", argv[U_FIRST], argv[U_MIDDLE], argv[U_LAST]); else if (strlen(argv[U_FIRST])) sprintf(fullname, "%s %s", argv[U_FIRST], argv[U_LAST]); else sprintf(fullname, "%s", argv[U_LAST]); login = argv[0]; who = cl->client_id; entity = cl->entity; /* create finger entry, pobox & set modtime on user */ EXEC SQL UPDATE users SET modtime = SYSDATE, modby = :who, modwith = :entity, fullname = NVL(:fullname, CHR(0)), affiliation = type, fmodtime = SYSDATE, fmodby = :who, fmodwith = :entity, potype = 'NONE', pmodtime = SYSDATE, pmodby = :who, pmodwith = :entity WHERE login = :login; return MR_SUCCESS; } /* followup_gpob: fixes argv[2] and argv[3] based on the pobox type. * Then completes the upcall to the user. * * argv[2] is the users_id on input and should be converted to the * pobox name on output. argv[3] is empty on input and should be * converted to an email address on output. */ int followup_gpob(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { char **argv; char *ptype, *p; int mid, sid, status, i; EXEC SQL BEGIN DECLARE SECTION; int users_id, pid, iid, bid, eid; char mach[MACHINE_NAME_SIZE], fs[FILESYS_LABEL_SIZE]; char str[STRINGS_STRING_SIZE]; EXEC SQL END DECLARE SECTION; /* for each row */ while (sq_get_data(sq, &argv)) { mr_trim_args(4, argv); ptype = argv[1]; users_id = atoi(argv[2]); EXEC SQL SELECT pop_id, imap_id, box_id, exchange_id INTO :pid, :iid, :bid, :eid FROM users WHERE users_id = :users_id; if (sqlca.sqlcode) return MR_USER; if (ptype[0] == 'S') { /* SMTP or SPLIT */ EXEC SQL SELECT string INTO :str FROM strings WHERE string_id = :bid; if (sqlca.sqlcode) return MR_STRING; /* If SMTP, don't bother fetching IMAP and POP boxes. */ if (ptype[1] == 'M') pid = iid = eid = 0; } if (iid) { /* IMAP, or SPLIT with IMAP */ EXEC SQL SELECT f.label, m.name INTO :fs, :mach FROM filesys f, machine m WHERE f.filsys_id = :iid AND f.mach_id = m.mach_id; if (sqlca.sqlcode) return MR_FILESYS; } if (pid) { /* POP, or SPLIT with POP */ EXEC SQL SELECT m.name INTO :mach FROM machine m, users u WHERE u.users_id = :users_id AND u.pop_id = m.mach_id; if (sqlca.sqlcode) return MR_MACHINE; } if (eid) { /* EXCHANGE, or SPLIT with EXCHANGE */ EXEC SQL SELECT m.name INTO :mach FROM machine m, users u WHERE u.users_id = :users_id AND u.exchange_id = m.mach_id; if (sqlca.sqlcode) return MR_MACHINE; } free(argv[2]); free(argv[3]); /* Now assemble the right answer. */ if (!strcmp(ptype, "POP") || !strcmp(ptype, "EXCHANGE")) { argv[2] = xstrdup(strtrim(mach)); argv[3] = xmalloc(strlen(argv[0]) + strlen(argv[2]) + 2); sprintf(argv[3], "%s@%s", argv[0], argv[2]); } else if (!strcmp(ptype, "SMTP")) { argv[2] = xstrdup(strtrim(str)); argv[3] = xstrdup(str); } else if (!strcmp(ptype, "IMAP")) { argv[2] = xstrdup(strtrim(fs)); argv[3] = xmalloc(strlen(argv[0]) + strlen(strtrim(mach)) + 2); sprintf(argv[3], "%s@%s", argv[0], mach); } else if (!strcmp(ptype, "SPLIT")) { argv[2] = xstrdup(strtrim(str)); argv[3] = xmalloc(strlen(argv[0]) + strlen(strtrim(mach)) + strlen(str) + 4); sprintf(argv[3], "%s@%s, %s", argv[0], mach, str); } else /* ptype == "NONE" */ goto skip; if (!strcmp(q->shortname, "gpob")) { sid = atoi(argv[5]); if (sid > 0) status = id_to_name(sid, USERS_TABLE, &argv[5]); else status = id_to_name(-sid, STRINGS_TABLE, &argv[5]); if (status && status != MR_NO_MATCH) return status; } (*action)(q->vcnt, argv, actarg); skip: /* free saved data */ for (i = 0; i < q->vcnt; i++) free(argv[i]); free(argv); } sq_destroy(sq); return MR_SUCCESS; } /* Fix an ace_name, based on its type. */ static int fix_ace(char *type, char **name) { int id = atoi(*name); if (!strcmp(type, "LIST")) return id_to_name(id, LIST_TABLE, name); else if (!strcmp(type, "USER")) return id_to_name(id, USERS_TABLE, name); else if (!strcmp(type, "KERBEROS")) return id_to_name(id, STRINGS_TABLE, name); else { free(*name); if (!strcmp(type, "NONE")) *name = xstrdup("NONE"); else *name = xstrdup("???"); return MR_SUCCESS; } } /* followup_gsnt: fix the ace_name and modby */ int followup_gsnt(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { char **argv; int status, idx; if (q->version < 8) idx = 0; else idx = 3; while (sq_get_data(sq, &argv)) { mr_trim_args(q->vcnt, argv); status = fix_ace(argv[7 + idx], &argv[8 + idx]); if (status && status != MR_NO_MATCH) return status; } return followup_fix_modby(q, sq, v, action, actarg, cl); } /* followup_ghst: fix the ace_name, strings and modby */ int followup_ghst(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { char **argv; int id, status, idx; if (q->version < 6) idx = 0; else if (q->version >= 6 && q->version < 8) idx = 1; else idx = 2; while (sq_get_data(sq, &argv)) { mr_trim_args(q->vcnt, argv); id = atoi(argv[13 + idx]); status = id_to_name(id, STRINGS_TABLE, &argv[13 + idx]); if (status) return status; id = atoi(argv[14 + idx]); status = id_to_name(id, STRINGS_TABLE, &argv[14 + idx]); if (status) return status; id = atoi(argv[16 + idx]); if (id < 0) status = id_to_name(-id, STRINGS_TABLE, &argv[16 + idx]); else status = id_to_name(id, USERS_TABLE, &argv[16 + idx]); if (status && status != MR_NO_MATCH) return status; status = fix_ace(argv[11 + idx], &argv[12 + idx]); if (status && status != MR_NO_MATCH) return status; } return followup_fix_modby(q, sq, v, action, actarg, cl); } /* followup_glin: fix the ace_name, modace_name, expiration, and modby */ int followup_glin(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { char **argv; int status; while (sq_get_data(sq, &argv)) { mr_trim_args(q->vcnt, argv); if (q->version == 2) status = fix_ace(argv[7], &argv[8]); else if (q->version > 2 && q->version < 10) status = fix_ace(argv[8], &argv[9]); else status = fix_ace(argv[10], &argv[11]); if (status && status != MR_NO_MATCH) return status; if (q->version > 3) { if (q->version < 10) status = fix_ace(argv[10], &argv[11]); else if (q->version >= 10) status = fix_ace(argv[12], &argv[13]); if (status && status != MR_NO_MATCH) return status; } if (atoi(argv[6]) == -1) { argv[6] = xrealloc(argv[6], strlen(UNIQUE_GID) + 1); strcpy(argv[6], UNIQUE_GID); } } return followup_fix_modby(q, sq, v, action, actarg, cl); } /* followup_gsin: fix the ace_name and modby. */ int followup_gsin(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { char **argv; int status; while (sq_get_data(sq, &argv)) { mr_trim_args(q->vcnt, argv); status = fix_ace(argv[11], &argv[12]); if (status && status != MR_NO_MATCH) return status; } return followup_fix_modby(q, sq, v, action, actarg, cl); } int followup_gpsv(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { char **argv; int status; while (sq_get_data(sq, &argv)) { mr_trim_args(q->vcnt, argv); status = fix_ace(argv[PRINTSERVER_OWNER_TYPE], &argv[PRINTSERVER_OWNER_NAME]); if (status && status != MR_NO_MATCH) return status; } return followup_fix_modby(q, sq, v, action, actarg, cl); } /* followup_gqot: Fix the entity name, directory name & modby fields * argv[0] = filsys_id * argv[1] = type * argv[2] = entity_id * argv[3] = ascii(quota) */ int followup_gqot(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { int j; char **argv; EXEC SQL BEGIN DECLARE SECTION; int id; char *name, *label; EXEC SQL END DECLARE SECTION; int status, idx; if (!strcmp(q->name, "get_quota") || !strcmp(q->name, "get_quota_by_filesys")) idx = 4; else idx = 3; while (sq_get_data(sq, &argv)) { if (idx == 4) { switch (argv[1][0]) { case 'U': status = id_to_name(atoi(argv[2]), USERS_TABLE, &argv[2]); break; case 'G': case 'L': status = id_to_name(atoi(argv[2]), LIST_TABLE, &argv[2]); break; case 'A': free(argv[2]); argv[2] = xstrdup("system:anyuser"); break; default: id = atoi(argv[2]); argv[2] = xmalloc(8); sprintf(argv[2], "%d", id); } } id = atoi(argv[idx]); free(argv[idx]); argv[idx] = xmalloc(id ? NFSPHYS_DIR_SIZE : FILESYS_NAME_SIZE); name = argv[idx]; name[0] = '\0'; if (id == 0) { label = argv[0]; EXEC SQL SELECT name INTO :name FROM filesys WHERE label = :label; } else { EXEC SQL SELECT dir INTO :name FROM nfsphys WHERE nfsphys_id = :id; } if (sqlca.sqlerrd[2] != 1) sprintf(argv[idx], "#%d", id); id = atoi(argv[idx + 3]); if (id > 0) status = id_to_name(id, USERS_TABLE, &argv[idx + 3]); else status = id_to_name(-id, STRINGS_TABLE, &argv[idx + 3]); if (status && status != MR_NO_MATCH) return status; (*action)(q->vcnt, argv, actarg); for (j = 0; j < q->vcnt; j++) free(argv[j]); free(argv); } sq_destroy(sq); return MR_SUCCESS; } /* followup_aqot: Add allocation to nfsphys after creating quota. * argv[0] = filsys_id * argv[1] = type if "add_quota" or "update_quota" * argv[2 or 1] = id * argv[3 or 2] = ascii(quota) */ int followup_aqot(struct query *q, char *argv[], client *cl) { EXEC SQL BEGIN DECLARE SECTION; int quota, id, fs, who, physid, table; char *entity, *qtype, *tname; EXEC SQL END DECLARE SECTION; char incr_qual[60]; char *incr_argv[2]; int status; table = q->rtable; tname = table_name[table]; fs = *(int *)argv[0]; EXEC SQL SELECT phys_id INTO :physid FROM filesys WHERE filsys_id = :fs; if (dbms_errno) return mr_errcode; if (!strcmp(q->shortname, "aqot") || !strcmp(q->shortname, "uqot")) { qtype = argv[1]; id = *(int *)argv[2]; quota = atoi(argv[3]); sprintf(incr_qual, "q.filsys_id = %d", fs); } else { qtype = "USER"; id = *(int *)argv[1]; quota = atoi(argv[2]); sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND " "q.entity_id = %d", fs, qtype, id); } /* quota case of incremental_{before|after} only looks at slot 1 */ incr_argv[1] = qtype; /* Follows one of many possible gross hacks to fix these particular * conflicts between what is possible in the query table and what * is possible in SQL. */ if (q->type == MR_Q_APPEND) { incremental_clear_before(); EXEC SQL INSERT INTO quota (filsys_id, type, entity_id, quota, phys_id) VALUES (:fs, NVL(:qtype, CHR(0)), :id, :quota, :physid); incremental_after(table, incr_qual, incr_argv); } else { incremental_before(table, incr_qual, incr_argv); EXEC SQL UPDATE quota SET quota = :quota WHERE filsys_id = :fs AND type = :qtype AND entity_id = :id; status = mr_errcode; incremental_after(table, incr_qual, incr_argv); } if (dbms_errno) return mr_errcode; if (q->type == MR_Q_APPEND) { EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = SYSDATE WHERE table_name = :tname; } else { EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE WHERE table_name = :tname; } /* Proceed with original followup */ who = cl->client_id; entity = cl->entity; EXEC SQL UPDATE quota SET modtime = SYSDATE, modby = :who, modwith = :entity WHERE filsys_id = :fs and type = :qtype and entity_id = :id; EXEC SQL UPDATE nfsphys SET allocated = allocated + :quota WHERE nfsphys_id = :physid; if (dbms_errno) return mr_errcode; return MR_SUCCESS; } /* Necessitated by the requirement of a correlation name by the incremental * routines, since query table deletes don't provide one. */ int followup_dqot(struct query *q, char **argv, client *cl) { char *qtype; int id, fs, table; char *incr_argv[2]; EXEC SQL BEGIN DECLARE SECTION; char incr_qual[80], *tname; EXEC SQL END DECLARE SECTION; table = q->rtable; tname = table_name[table]; fs = *(int *)argv[0]; if (!strcmp(q->shortname, "dqot")) { qtype = argv[1]; id = *(int *)argv[2]; } else { qtype = "USER"; id = *(int *)argv[1]; } sprintf(incr_qual, "q.filsys_id = %d AND q.type = '%s' AND q.entity_id = %d", fs, qtype, id); /* quota case of incremental_{before|after} only looks at slot 1 */ incr_argv[1] = qtype; incremental_before(table, incr_qual, incr_argv); EXEC SQL DELETE FROM quota q WHERE q.filsys_id = :fs AND q.type = :qtype AND q.entity_id = :id; incremental_clear_after(); if (dbms_errno) return mr_errcode; EXEC SQL UPDATE tblstats SET deletes = deletes + 1, modtime = SYSDATE WHERE table_name = :tname; return MR_SUCCESS; } /* followup_gzcl: */ int followup_gzcl(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { int i, n, status; char **argv; if (q->version < 5) n = 8; else n = 10; while (sq_get_data(sq, &argv)) { mr_trim_args(q->vcnt, argv); for (i = 1; i < n; i += 2) { status = fix_ace(argv[i], &argv[i + 1]); if (status && status != MR_NO_MATCH) return status; } } return followup_fix_modby(q, sq, v, action, actarg, cl); } /* followup_gsha: */ int followup_gsha(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { char **argv; int status; while (sq_get_data(sq, &argv)) { mr_trim_args(q->vcnt, argv); status = fix_ace(argv[1], &argv[2]); if (status && status != MR_NO_MATCH) return status; } return followup_fix_modby(q, sq, v, action, actarg, cl); } int _sdl_followup(struct query *q, char *argv[], client *cl) { if (atoi(argv[0])) EXEC SQL ALTER SESSION SET SQL_TRACE TRUE; else EXEC SQL ALTER SESSION SET SQL_TRACE FALSE; return MR_SUCCESS; } int trigger_dcm(struct query *q, char *argv[], client *cl) { pid_t pid; char prog[MAXPATHLEN]; sprintf(prog, "%s/startdcm", BIN_DIR); pid = vfork(); switch (pid) { case 0: execl(prog, "startdcm", 0); exit(1); case -1: return errno; default: return MR_SUCCESS; } } /* followup_gcon: fix the ace_name, memace_name, and modby */ int followup_gcon(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { char **argv; int status, idx = 0; if (q->version >= 9) idx = 1; while (sq_get_data(sq, &argv)) { mr_trim_args(q->vcnt, argv); status = fix_ace(argv[4 + idx], &argv[5 + idx]); if (status && status != MR_NO_MATCH) return status; status = fix_ace(argv[6 + idx], &argv[7 + idx]); if (status && status != MR_NO_MATCH) return status; } return followup_fix_modby(q, sq, v, action, actarg, cl); } /* followup_get_user: fix the modby and creator. * This assumes that the modby and creator fields are always * in the same relative position in the argv. */ int followup_get_user(struct query *q, struct save_queue *sq, struct validate *v, int (*action)(int, char *[], void *), void *actarg, client *cl) { char **argv; int i, j, k, status, id; i = q->vcnt - 4; j = q->vcnt - 1; while (sq_get_data(sq, &argv)) { mr_trim_args(q->vcnt, argv); id = atoi(argv[i]); if (id > 0) status = id_to_name(id, USERS_TABLE, &argv[i]); else status = id_to_name(-id, STRINGS_TABLE, &argv[i]); if (status && status != MR_NO_MATCH) return status; id = atoi(argv[j]); if (id > 0) status = id_to_name(id, USERS_TABLE, &argv[j]); else status = id_to_name(-id, STRINGS_TABLE, &argv[j]); if (status && status != MR_NO_MATCH) return status; if (q->version > 11) { status = fix_ace(argv[15], &argv[16]); if (status && status != MR_NO_MATCH) return status; } (*action)(q->vcnt, argv, actarg); for (k = 0; k < q->vcnt; k++) free(argv[k]); free(argv); } sq_destroy(sq); return MR_SUCCESS; }