From 0659551fa6b562da96db724b0db5e094c498537b Mon Sep 17 00:00:00 2001 From: mar Date: Mon, 1 Nov 1993 12:04:46 +0000 Subject: [PATCH 1/1] split lots of stuff off into separate files --- server/qsupport.dc | 5284 ++++++++++---------------------------------- 1 file changed, 1188 insertions(+), 4096 deletions(-) diff --git a/server/qsupport.dc b/server/qsupport.dc index 21bdf88e..2b413c51 100644 --- a/server/qsupport.dc +++ b/server/qsupport.dc @@ -31,4341 +31,1433 @@ EXEC SQL BEGIN DECLARE SECTION; extern char stmt_buf[]; EXEC SQL END DECLARE SECTION; -/* Specialized Access Routines */ - -/* access_user - verify that client name equals specified login name - * - * - since field validation routines are called first, a users_id is - * now in argv[0] instead of the login name. - */ - EXEC SQL WHENEVER SQLERROR CALL ingerr; -access_user(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; -{ - if (cl->users_id != *(int *)argv[0]) - return(MR_PERM); - else - return(MR_SUCCESS); -} - - - -/* access_login - verify that client name equals specified login name - * - * argv[0...n] contain search info. q-> - */ - -access_login(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int id; - char qual[256]; - EXEC SQL END DECLARE SECTION; - - build_qual(q->qual, q->argc, argv, qual); - if (!strncmp(q->name,"get_user_account",strlen("get_user_account"))) { - EXEC SQL SELECT users_id INTO :id FROM users u, strings str WHERE :qual; - } else { - EXEC SQL SELECT users_id INTO :id FROM users u WHERE :qual; - } - - if (sqlca.sqlerrd[2] != 1 || id != cl->users_id) - return(MR_PERM); - else - return(MR_SUCCESS); -} - +/* Special query routines */ -/* access_list - check access for most list operations - * - * Inputs: argv[0] - list_id - * q - query name - * argv[2] - member ID (only for queries "amtl" and "dmfl") - * argv[7] - group IID (only for query "ulis") - * cl - client name - * - * - check that client is a member of the access control list - * - OR, if the query is add_member_to_list or delete_member_from_list - * and the list is public, allow access if client = member +/* set_pobox - this does all of the real work. + * argv = user_id, type, box + * if type is POP, then box should be a machine, and its ID should be put in + * pop_id. If type is SMTP, then box should be a string and its ID should + * be put in box_id. If type is NONE, then box doesn't matter. */ -access_list(q, argv, cl) +int set_pobox(q, argv, cl) struct query *q; - char *argv[]; + char **argv; client *cl; { EXEC SQL BEGIN DECLARE SECTION; - int list_id, acl_id, flags, gid; - char acl_type[9]; + int user, id; + char *box, potype[9]; EXEC SQL END DECLARE SECTION; - char *client_type; - int client_id, status; - - list_id = *(int *)argv[0]; - EXEC SQL SELECT acl_id, acl_type, gid, publicflg - INTO :acl_id, :acl_type, :gid, :flags - FROM list - WHERE list_id = :list_id; + int status; - if (sqlca.sqlerrd[2] != 1) - return(MR_INTERNAL); + box = argv[2]; + user = *(int *)argv[0]; - /* parse client structure */ - if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) - return(status); + EXEC SQL REPEATED SELECT pop_id, potype INTO :id, :potype FROM users + WHERE users_id = :user; + if (ingres_errno) return(mr_errcode); + if (!strcmp(strtrim(potype), "POP")) + set_pop_usage(id, -1); - /* if amtl or dmfl and list is public allow client to add or delete self */ - if (((!strcmp("amtl", q->shortname) && flags) || - (!strcmp("dmfl", q->shortname))) && - (!strcmp("USER", argv[1]))) { - if (*(int *)argv[2] == client_id) return(MR_SUCCESS); - /* if update_list, don't allow them to change the GID */ - } else if (!strcmp("ulis", q->shortname)) { - if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) || - (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7])))) - return(MR_PERM); + if (!strcmp(argv[1], "POP")) { + status = name_to_id(box, "MACHINE", &id); + if (status == MR_NO_MATCH) + return(MR_MACHINE); + else if (status) + return(status); + EXEC SQL REPEATED UPDATE users SET potype = 'POP', pop_id = :id + WHERE users_id = :user; + set_pop_usage(id, 1); + } else if (!strcmp(argv[1], "SMTP")) { + if (index(box, '/') || index(box, '|')) + return(MR_BAD_CHAR); + status = name_to_id(box, "STRING", &id); + if (status == MR_NO_MATCH) { + id=add_string(box); + } else if (status) + return(status); + EXEC SQL REPEATED UPDATE users SET potype='SMTP', box_id = :id + WHERE users_id = :user; + } else /* argv[1] == "NONE" */ { + EXEC SQL REPEATED UPDATE users SET potype='NONE' + WHERE users_id = :user; } - /* check for client in access control list */ - status = find_member(acl_type, acl_id, client_type, client_id, 0); - if (!status) return(MR_PERM); - + set_pobox_modtime(q, argv, cl); + EXEC SQL REPEATED UPDATE tblstats SET updates = updates+1, modtime='now' + WHERE table_name='users'; + if (ingres_errno) return(mr_errcode); return(MR_SUCCESS); } -/* access_visible_list - allow access to list only if it is not hidden, - * or if the client is on the ACL - * - * Inputs: argv[0] - list_id - * cl - client identifier +/* get_list_info: passed a wildcard list name, returns lots of stuff about + * each list. This is tricky: first build a queue of all requested + * data. Rest of processing consists of fixing gid, ace_name, and modby. */ -access_visible_list(q, argv, cl) - struct query *q; - char *argv[]; +get_list_info(q, aargv, cl, action, actarg) + register struct query *q; + char **aargv; client *cl; + register int (*action)(); + int actarg; { + char *argv[13], *malloc(), *realloc(); EXEC SQL BEGIN DECLARE SECTION; - int list_id, acl_id, flags ; - char acl_type[9]; + char *name, acl_type[9], listname[33], active[5], public[5], hidden[5]; + char maillist[5], grouplist[5], gid_str[6], acl_name[256], desc[256]; + char modtime[27], modby[256], modwith[9]; + int id, rowcount, acl_id, hid, modby_id; + char qual[80]; EXEC SQL END DECLARE SECTION; - char *client_type; - int client_id, status; - - list_id = *(int *)argv[0]; - EXEC SQL SELECT hidden, acl_id, acl_type - INTO :flags, :acl_id, :acl_type - FROM list - WHERE list_id = :list_id; - if (sqlca.sqlerrd[2] != 1) - return(MR_INTERNAL); - if (!flags) - return(MR_SUCCESS); - - /* parse client structure */ - if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) - return(status); - - /* check for client in access control list */ - status = find_member(acl_type, acl_id, client_type, client_id, 0); - if (!status) - return(MR_PERM); - - return(MR_SUCCESS); -} - - -/* access_vis_list_by_name - allow access to list only if it is not hidden, - * or if the client is on the ACL - * - * Inputs: argv[0] - list name - * cl - client identifier - */ + int returned, status; + struct save_queue *sq, *sq_create(); -access_vis_list_by_name(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int acl_id, flags, rowcount; - char acl_type[9], *listname; - EXEC SQL END DECLARE SECTION; - char *client_type; - int client_id, status; + returned = rowcount = 0; + name = aargv[0]; + convert_wildcards(name); - listname = argv[0]; - EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type - FROM list WHERE name = :listname; + sq = sq_create(); + sprintf(qual,"name LIKE '%s' ESCAPE '*'",name); + optimize_sql_stmt(qual); + EXEC SQL DECLARE csr102 CURSOR FOR SELECT list_id FROM list + WHERE :qual; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr102; + if (ingres_errno) + return(mr_errcode); + while(1) + { + EXEC SQL FETCH csr102 INTO :id; + if(sqlca.sqlcode!=0) break; + sq_save_data(sq, id); + rowcount++; + } + EXEC SQL CLOSE csr102; - rowcount=sqlca.sqlerrd[2]; - if (rowcount > 1) - return(MR_WILDCARD); + if (ingres_errno) return(mr_errcode); if (rowcount == 0) return(MR_NO_MATCH); - if (!flags) - return(MR_SUCCESS); - - /* parse client structure */ - if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) - return(status); - /* check for client in access control list */ - status = find_member(acl_type, acl_id, client_type, client_id, 0); - if (!status) - return(MR_PERM); + argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden; + argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str; + argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith; - return(MR_SUCCESS); -} + while (sq_get_data(sq, &id)) { + if (id == 0) + continue; + argv[6] = gid_str; + EXEC SQL REPEATED SELECT name, CHAR(active), CHAR(publicflg), + CHAR(hidden), hidden, CHAR(maillist), CHAR(grouplist), CHAR(gid), + TRIM(acl_type), acl_id, description, CHAR(modtime), modby, modwith + INTO :listname, :active, :public, :hidden, :hid, :maillist, + :grouplist, :gid_str, :acl_type, :acl_id, :desc, + :modtime, :modby_id, :modwith + FROM list WHERE list_id = :id; + if (ingres_errno) return(mr_errcode); -/* access_member - allow user to access member of type "USER" and name matches - * username, or to access member of type "LIST" and list is one that user is - * on the acl of, or the list is visible. - */ + if (atoi(gid_str) == -1) + argv[6] = UNIQUE_GID; -access_member(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; -{ - if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST")) - return(access_visible_list(q, &argv[1], cl)); + argv[8] = malloc(0); + if (!strcmp(acl_type, "LIST")) { + status = id_to_name(acl_id, "LIST", &argv[8]); + } else if (!strcmp(acl_type, "USER")) { + status = id_to_name(acl_id, "USER", &argv[8]); + } else if (!strcmp(acl_type, "KERBEROS")) { + status = id_to_name(acl_id, "STRING", &argv[8]); + } else if (!strcmp(acl_type, "NONE")) { + status = 0; + free(argv[8]); + argv[8] = strsave("NONE"); + } else { + status = 0; + free(argv[8]); + argv[8] = strsave("???"); + } + if (status && status != MR_NO_MATCH) return(status); - if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) { - if (cl->users_id == *(int *)argv[1]) - return(MR_SUCCESS); - } + argv[11] = malloc(0); + if (modby_id > 0) + status = id_to_name(modby_id, "USER", &argv[11]); + else + status = id_to_name(-modby_id, "STRING", &argv[11]); + if (status && status != MR_NO_MATCH) return(status); - if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBERO")) { - if (cl->client_id == *(int *)argv[1]) - return(MR_SUCCESS); + mr_trim_args(q->vcnt, argv); + returned++; + (*action)(q->vcnt, argv, actarg); + free(argv[8]); + free(argv[11]); } - return(MR_PERM); + sq_destroy(sq); + if (ingres_errno) return(mr_errcode); + return (MR_SUCCESS); } -/* access_qgli - special access routine for Qualified_get_lists. Allows - * access iff argv[0] == "TRUE" and argv[2] == "FALSE". +/* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is + * how many different ancestors a member is allowed to have. */ -access_qgli(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; -{ - if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE")) - return(MR_SUCCESS); - return(MR_PERM); -} - - -/* access_service - allow access if user is on ACL of service. Don't - * allow access if a wildcard is used. - */ +#define MAXLISTDEPTH 1024 -access_service(q, argv, cl) +int add_member_to_list(q, argv, cl) struct query *q; - char *argv[]; + char **argv; client *cl; { EXEC SQL BEGIN DECLARE SECTION; - int acl_id; - char *name, acl_type[9]; + int id, lid, mid, error, who, ref, rowcnt; + char *mtype, dtype[9], *entity; EXEC SQL END DECLARE SECTION; - int client_id, status; - char *client_type, *c; - - name = argv[0]; - for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* uppercasify */ - EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers - WHERE name = :name; - if (sqlca.sqlerrd[2] > 1) - return(MR_PERM); - - /* parse client structure */ - if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) - return(status); - - /* check for client in access control list */ - status = find_member(acl_type, acl_id, client_type, client_id, 0); - if (!status) return(MR_PERM); - - return(MR_SUCCESS); -} - + int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a; + int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d; + int status; + char *dtypes[MAXLISTDEPTH]; + char *iargv[3], *buf; -/* access_filesys - verify that client is owner or on owners list of filesystem - * named by argv[0] - */ + lid = *(int *)argv[0]; + mtype = argv[1]; + mid = *(int *)argv[2]; + /* if the member is already a direct member of the list, punt */ + EXEC SQL REPEATED SELECT COUNT(list_id) INTO :rowcnt FROM imembers + WHERE list_id = :lid AND member_id = :mid + AND member_type = :mtype AND direct = 1; + if (rowcnt > 0) + return(MR_EXISTS); + if (!strcasecmp(mtype, "STRING")) { + buf = malloc(0); + status = id_to_name(mid, "STRING", &buf); + if (status) return(status); + if (index(buf, '/') || index(buf, '|')) { + free(buf); + return(MR_BAD_CHAR); + } + free(buf); + } -access_filesys(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int users_id, list_id; - char *name; - EXEC SQL END DECLARE SECTION; - int status, client_id; - char *client_type; - - name = argv[0]; - EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys - WHERE label = :name; - - if (sqlca.sqlerrd[2] != 1) - return(MR_PERM); - if (users_id == cl->users_id) - return(MR_SUCCESS); - if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) - return(status); - status = find_member("LIST", list_id, client_type, client_id, 0); - if (status) - return(MR_SUCCESS); - else - return(MR_PERM); -} - - - -/* Setup Routines */ - -/* Setup routine for add_user - * - * Inputs: argv[0] - login - * argv[1] - uid - * - * Description: - * - * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid) - * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#" - */ - -setup_ausr(q, argv, cl) - struct query *q; - register char *argv[]; - client *cl; -{ - int row; - EXEC SQL BEGIN DECLARE SECTION; - int nuid; - EXEC SQL END DECLARE SECTION; - - if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac")) - row = 2; - else - row = 1; - if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1) { - if (set_next_object_id("uid", "users", 1)) - return(MR_INGRES_ERR); - EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'uid'; - if (sqlca.sqlerrd[2] != 1) + ancestors[0] = lid; + aref[0] = 1; + acount = 1; + EXEC SQL DECLARE csr103 CURSOR FOR + SELECT list_id, ref_count FROM imembers + WHERE member_id = :lid AND member_type='LIST'; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr103; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr103 INTO :id, :ref; + if(sqlca.sqlcode != 0) break; + aref[acount] = ref; + ancestors[acount++] = id; + if (acount >= MAXLISTDEPTH) break; + } + EXEC SQL CLOSE csr103; + if (ingres_errno) return(mr_errcode); + if (acount >= MAXLISTDEPTH) { + return(MR_INTERNAL); + } + descendants[0] = mid; + dtypes[0] = mtype; + dref[0] = 1; + dcount = 1; + error = 0; + if (!strcmp(mtype, "LIST")) { + EXEC SQL DECLARE csr104 CURSOR FOR + SELECT member_id, member_type, ref_count + FROM imembers + WHERE list_id = :mid; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr104; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr104 INTO :id, :dtype, :ref; + if(sqlca.sqlcode != 0) break; + switch (dtype[0]) { + case 'L': + dtypes[dcount] = "LIST"; + break; + case 'U': + dtypes[dcount] = "USER"; + break; + case 'S': + dtypes[dcount] = "STRING"; + break; + case 'K': + dtypes[dcount] = "KERBEROS"; + break; + default: + error++; + break; + } + dref[dcount] = ref; + descendants[dcount++] = id; + if (dcount >= MAXLISTDEPTH) { + error++; + break; + } + } + EXEC SQL CLOSE csr104; + if (ingres_errno) return(mr_errcode); + if (error) return(MR_INTERNAL); - sprintf(argv[row], "%d", nuid); } - - if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1) { - sprintf(argv[0], "#%s", argv[row]); + for (a = 0; a < acount; a++) { + lid = ancestors[a]; + for (d = 0; d < dcount; d++) { + mid = descendants[d]; + mtype = dtypes[d]; + if (mid == lid && !strcmp(mtype, "LIST")) { + return(MR_LISTLOOP); + } + EXEC SQL REPEATED SELECT COUNT(ref_count) INTO :rowcnt + FROM imembers + WHERE list_id = :lid AND member_id = :mid + AND member_type = :mtype; + ref = aref[a] * dref[d]; + if (rowcnt > 0) { + if (a == 0 && d == 0) { + EXEC SQL UPDATE imembers + SET ref_count = ref_count+:ref, direct=1 + WHERE list_id = :lid AND member_id = :mid + AND member_type = :mtype; + } else { + EXEC SQL UPDATE imembers + SET ref_count = ref_count+:ref + WHERE list_id = :lid AND member_id = :mid + AND member_type = :mtype; + } + } else { + incremental_clear_before(); + if (a == 0 && d == 0) { + EXEC SQL INSERT INTO imembers + (list_id, member_id, direct, member_type, ref_count) + VALUES (:lid, :mid, 1, :mtype, 1); + } else { + EXEC SQL INSERT INTO imembers + (list_id, member_id, member_type, ref_count) + VALUES (:lid, :mid, :mtype, 1); + } + iargv[0] = (char *)lid; + iargv[1] = mtype; + iargv[2] = (char *)mid; + incremental_after("members", 0, iargv); + } + } } - - if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS) - return(mr_errcode); - - return(MR_SUCCESS); -} - - -/* setup_dusr - verify that the user is no longer being referenced - * and may safely be deleted. - */ - -int setup_dusr(q, argv) - struct query *q; - char **argv; -{ - EXEC SQL BEGIN DECLARE SECTION; - int flag, id, cnt; - EXEC SQL END DECLARE SECTION; - - id = *(int *)argv[0]; - - /* For now, only allow users to be deleted if their status is 0 */ - EXEC SQL REPEATED SELECT status INTO :flag FROM users - WHERE users_id = :id; - if (flag != 0 && flag != 4) - return(MR_IN_USE); - - EXEC SQL REPEATED DELETE FROM quota WHERE entity_id = :id AND type='USER'; - EXEC SQL REPEATED DELETE FROM krbmap WHERE users_id = :id; - EXEC SQL REPEATED SELECT COUNT(member_id) INTO :cnt FROM imembers - WHERE member_id = :id AND member_type = 'USER'; - if (cnt > 0) - return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(label) INTO :cnt FROM filesys - WHERE owner = :id; - if (cnt > 0) - return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(name) INTO :cnt FROM list - WHERE acl_id = :id AND acl_type = 'USER'; - if (cnt > 0) - return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(name) INTO :cnt FROM servers - WHERE acl_id = :id AND acl_type = 'USER'; - if (cnt > 0) - return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(acl_id) INTO :cnt FROM hostaccess - WHERE acl_id = :id AND acl_type = 'USER'; - if (cnt > 0) - return(MR_IN_USE); - if (ingres_errno) - return(mr_errcode); - return(MR_SUCCESS); -} - - -/* setup_spop: verify that there is already a valid POP machine_id in the - * pop_id field. Also take care of keeping track of the post office usage. - */ -int setup_spop(q, argv) -struct query *q; -char **argv; -{ - EXEC SQL BEGIN DECLARE SECTION; - int id, mid, flag; - char type[9]; - EXEC SQL END DECLARE SECTION; - - id = *(int *)argv[0]; - EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :mid FROM users - WHERE users_id = :id; - if(sqlca.sqlerrd[2] = 0) - return(MR_MACHINE); - EXEC SQL REPEATED SELECT mach_id INTO :mid FROM machine - WHERE mach_id = :mid; - if (sqlca.sqlerrd[2] = 0) - return(MR_MACHINE); - if (strcmp(strtrim(type), "POP")) - set_pop_usage(mid, 1); - return(MR_SUCCESS); -} - - -/* setup_dpob: Take care of keeping track of the post office usage. - */ -int setup_dpob(q, argv) - struct query *q; - char **argv; -{ - EXEC SQL BEGIN DECLARE SECTION; - int id, user; - char type[9]; - EXEC SQL END DECLARE SECTION; - - user = *(int *)argv[0]; - EXEC SQL REPEATED SELECT potype, pop_id INTO :type, :id FROM users - WHERE users_id = :user; + lid = *(int *)argv[0]; + entity = cl->entity; + who = cl->client_id; + EXEC SQL REPEATED UPDATE list + SET modtime='now', modby = :who, modwith = :entity + WHERE list_id = :lid; if (ingres_errno) return(mr_errcode); - - if (!strcmp(strtrim(type), "POP")) - set_pop_usage(id, -1); return(MR_SUCCESS); } -/* setup_dmac - verify that the machine is no longer being referenced - * and may safely be deleted. +/* Delete_member_from_list: do list flattening as we go! */ -int setup_dmac(q, argv) +int delete_member_from_list(q, argv, cl) struct query *q; char **argv; + client *cl; { EXEC SQL BEGIN DECLARE SECTION; - int flag, id, cnt; + int id, lid, mid, cnt, error, who, ref; + char *mtype, dtype[9], *entity; EXEC SQL END DECLARE SECTION; + int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a; + int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d; + char *dtypes[MAXLISTDEPTH]; + char *iargv[3]; - id = *(int *)argv[0]; - EXEC SQL REPEATED SELECT COUNT(login) INTO :cnt FROM users - WHERE potype='POP' AND pop_id = :id; - if (cnt > 0) - return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM serverhosts - WHERE mach_id = :id; - if (cnt > 0) - return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM nfsphys - WHERE mach_id = :id; - if (cnt > 0) - return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM hostaccess - WHERE mach_id = :id; - if (cnt > 0) - return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM printcap - WHERE mach_id = :id; - if (cnt > 0) - return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(quotaserver) INTO :cnt FROM printcap - WHERE quotaserver = :id; - if (cnt > 0) - return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM palladium - WHERE mach_id = :id; - if (cnt > 0) - return(MR_IN_USE); - - EXEC SQL REPEATED DELETE FROM mcmap WHERE mach_id = :id; + lid = *(int *)argv[0]; + mtype = argv[1]; + mid = *(int *)argv[2]; + /* if the member is not a direct member of the list, punt */ + EXEC SQL REPEATED SELECT COUNT(list_id) INTO :cnt FROM imembers + WHERE list_id = :lid AND member_id = :mid + AND member_type = :mtype AND direct = 1; if (ingres_errno) return(mr_errcode); - return(MR_SUCCESS); -} - - -/* setup_dclu - verify that the cluster is no longer being referenced - * and may safely be deleted. - */ - -int setup_dclu(q, argv) - struct query *q; - char **argv; -{ - EXEC SQL BEGIN DECLARE SECTION; - int id, cnt; - EXEC SQL END DECLARE SECTION; - - id = *(int *)argv[0]; - EXEC SQL REPEATED SELECT COUNT(mach_id) INTO :cnt FROM mcmap - WHERE clu_id = :id; - if (cnt > 0) - return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(clu_id) INTO :cnt FROM svc - WHERE clu_id = :id; - if (cnt > 0) - return(MR_IN_USE); + if (cnt == 0) + return(MR_NO_MATCH); + ancestors[0] = lid; + aref[0] = 1; + acount = 1; + EXEC SQL DECLARE csr105 CURSOR FOR + SELECT list_id, ref_count FROM imembers + WHERE member_id = :lid AND member_type = 'LIST'; if (ingres_errno) return(mr_errcode); - return(MR_SUCCESS); -} - - -/* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate - * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but - * argv[5] is not, then remember that UNIQUE_ID is being stored by putting - * a -1 there. Remember that this is also used for ulis, with the indexes - * at 6 & 7. Also check that the list name does not contain uppercase - * characters, control characters, @, or :. - */ - -static int badlistchars[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */ - 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -}; - -int setup_alis(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int ngid; - EXEC SQL END DECLARE SECTION; - char *malloc(); - unsigned char *p; - int idx; - - if (!strcmp(q->shortname, "alis")) - idx = 0; - else if (!strcmp(q->shortname, "ulis")) - idx = 1; - - for (p = (unsigned char *) argv[idx]; *p; p++) - if (badlistchars[*p]) - return(MR_BAD_CHAR); - - if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1) { - if (atoi(argv[5 + idx])) { - if (set_next_object_id("gid", "list", 1)) - return(MR_INGRES_ERR); - EXEC SQL REPEATED SELECT value INTO :ngid FROM numvalues - WHERE name = 'gid'; - if (ingres_errno) return(mr_errcode); - sprintf(argv[6 + idx], "%d", ngid); - } else { - strcpy(argv[6 + idx], "-1"); - } + EXEC SQL OPEN csr105; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr105 INTO :id, :ref; + if(sqlca.sqlcode!=0) break; + aref[acount] = ref; + ancestors[acount++] = id; + if (acount >= MAXLISTDEPTH) break; } - - if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS) + EXEC SQL CLOSE csr105; + if (ingres_errno) return(mr_errcode); - - return(MR_SUCCESS); -} - - -/* setup_dlis - verify that the list is no longer being referenced - * and may safely be deleted. - */ - -int setup_dlis(q, argv) - struct query *q; - char *argv[]; -{ - int flag, id, ec; - - id = *(int *)argv[0]; - sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE member_id = %d AND member_type='LIST'",id); - if(ec=mr_select_any(stmt_buf)) { - if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec); - } - - sprintf(stmt_buf,"SELECT member_id FROM imembers WHERE list_id = %d",id); - if(ec=mr_select_any(stmt_buf)) { - if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec); - } - - sprintf(stmt_buf,"SELECT label FROM filesys WHERE owners = %d",id); - if(ec=mr_select_any(stmt_buf)) { - if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec); - } - - sprintf(stmt_buf,"SELECT tag FROM capacls WHERE list_id = %d",id); - if(ec=mr_select_any(stmt_buf)) { - if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec); - } - - sprintf(stmt_buf,"SELECT name FROM list WHERE acl_id = %d AND acl_type='LIST' AND list_id != %d",id,id); - if(ec=mr_select_any(stmt_buf)) { - if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec); - } - - sprintf(stmt_buf,"SELECT name FROM servers WHERE acl_id = %d AND acl_type='LIST'",id); - if(ec=mr_select_any(stmt_buf)) { - if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec); - } - - sprintf(stmt_buf,"SELECT entity_id FROM quota WHERE entity_id = %d AND type='GROUP'",id); - if(ec=mr_select_any(stmt_buf)) { - if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec); - } - - sprintf(stmt_buf,"SELECT acl_id FROM hostaccess WHERE acl_id = %d AND acl_type='LIST'",id); - if(ec=mr_select_any(stmt_buf)) { - if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec); - } - - sprintf(stmt_buf,"SELECT class FROM zephyr z \ -WHERE z.xmt_type = 'LIST' AND z.xmt_id = %d \ -OR z.sub_type = 'LIST' AND z.sub_id = %d \ -OR z.iws_type = 'LIST' AND z.iws_id = %d \ -OR z.iui_type = 'LIST' AND z.iui_id = %d",id,id,id,id); - if(ec=mr_select_any(stmt_buf)) { - if(ec==MR_EXISTS) return(MR_IN_USE); else return(ec); + if (acount >= MAXLISTDEPTH) + return(MR_INTERNAL); + descendants[0] = mid; + dtypes[0] = mtype; + dref[0] = 1; + dcount = 1; + error = 0; + if (!strcmp(mtype, "LIST")) { + EXEC SQL DECLARE csr106 CURSOR FOR + SELECT member_id, member_type, ref_count FROM imembers + WHERE list_id = :mid; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr106; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr106 INTO :id, :dtype, :ref; + if(sqlca.sqlcode!=0) break; + switch (dtype[0]) { + case 'L': + dtypes[dcount] = "LIST"; + break; + case 'U': + dtypes[dcount] = "USER"; + break; + case 'S': + dtypes[dcount] = "STRING"; + break; + case 'K': + dtypes[dcount] = "KERBEROS"; + break; + default: + error++; + break; + } + dref[dcount] = ref; + descendants[dcount++] = id; + if (dcount >= MAXLISTDEPTH) break; + } + EXEC SQL CLOSE csr106; + if (ingres_errno) + return(mr_errcode); + if (error) + return(MR_INTERNAL); } - - return(MR_SUCCESS); -} - - -/* setup_dsin - verify that the service is no longer being referenced - * and may safely be deleted. - */ - -int setup_dsin(q, argv) - struct query *q; - char **argv; -{ - EXEC SQL BEGIN DECLARE SECTION; - int ec; - char *svrname; - EXEC SQL END DECLARE SECTION; - - sprintf(stmt_buf,"SELECT service FROM serverhosts WHERE service = UPPERCASE('%s')",argv[0]); - if(ec=mr_select_any(stmt_buf)) { - if(ec==MR_EXISTS) - return(MR_IN_USE); - else - return(ec); + for (a = 0; a < acount; a++) { + lid = ancestors[a]; + for (d = 0; d < dcount; d++) { + mid = descendants[d]; + mtype = dtypes[d]; + if (mid == lid && !strcmp(mtype, "LIST")) { + return(MR_LISTLOOP); + } + EXEC SQL REPEATED SELECT ref_count INTO :cnt FROM imembers + WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype; + ref = aref[a] * dref[d]; + if (cnt <= ref) { + iargv[0] = (char *)lid; + iargv[1] = mtype; + iargv[2] = (char *)mid; + incremental_before("members", 0, iargv); + EXEC SQL DELETE FROM imembers + WHERE list_id = :lid AND member_id = :mid + AND member_type= :mtype; + incremental_clear_after(); + } else if (a == 0 && d == 0) { + EXEC SQL UPDATE imembers + SET ref_count = ref_count - :ref, direct = 0 + WHERE list_id = :lid AND member_id = :mid + AND member_type = :mtype; + } else { + EXEC SQL UPDATE imembers + SET ref_count = ref_count - :ref + WHERE list_id = :lid AND member_id = :mid + AND member_type = :mtype; + } + } } - - svrname=argv[0]; - EXEC SQL SELECT inprogress INTO :ec FROM servers - WHERE name=UPPERCASE(:svrname); - if(ingres_errno) - return(mr_errcode); - if(ec) - return(MR_IN_USE); - + lid = *(int *)argv[0]; + entity = cl->entity; + who = cl->client_id; + EXEC SQL UPDATE list SET modtime = 'now', modby = :who, modwith = :entity + WHERE list_id = :lid; + if (ingres_errno) return(mr_errcode); return(MR_SUCCESS); } -/* setup_dshi - verify that the service-host is no longer being referenced - * and may safely be deleted. +/* get_ace_use - given a type and a name, return a type and a name. + * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0], + * and argv[1] will contain the ID of the entity in question. The R* + * types mean to recursively look at every containing list, not just + * when the object in question is a direct member. On return, the + * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR. */ -int setup_dshi(q, argv) - struct query *q; - char **argv; -{ - EXEC SQL BEGIN DECLARE SECTION; - int id, ec; - char *svrname; - EXEC SQL END DECLARE SECTION; - - svrname=argv[0]; - id = *(int *)argv[1]; - - EXEC SQL SELECT inprogress INTO :ec FROM serverhosts - WHERE service=UPPERCASE(:svrname) AND mach_id = :id; - if(ingres_errno) - return(mr_errcode); - if(ec) - return(MR_IN_USE); - - - return(MR_SUCCESS); -} - - -/** - ** setup_add_filesys - verify existance of referenced file systems - ** - ** Inputs: Add - ** argv[1] - type - ** argv[2] - mach_id - ** argv[3] - name - ** argv[5] - access - ** - ** Description: - ** - for type = RVD: - ** * allow anything - ** - for type = NFS: - ** * extract directory prefix from name - ** * verify mach_id/dir in nfsphys - ** * verify access in {r, w, R, W} - ** - ** Side effect: sets variable var_phys_id to the ID of the physical - ** filesystem (nfsphys_id for NFS, 0 for RVD) - ** - ** Errors: - ** MR_NFS - specified directory not exported - ** MR_FILESYS_ACCESS - invalid filesys access - ** - **/ - -EXEC SQL BEGIN DECLARE SECTION; -static int var_phys_id; -EXEC SQL END DECLARE SECTION; - -setup_afil(q, argv, cl) +int get_ace_use(q, argv, cl, action, actarg) struct query *q; char *argv[]; client *cl; + int (*action)(); + int actarg; { - char *type, *name; - int mach_id; + int found = 0; EXEC SQL BEGIN DECLARE SECTION; - int ok; - char ftype[32], *access; + char *atype; + int aid, listid, id; EXEC SQL END DECLARE SECTION; + struct save_queue *sq, *sq_create(); - type = argv[1]; - mach_id = *(int *)argv[2]; - name = argv[3]; - access = argv[5]; - var_phys_id = 0; + atype = argv[0]; + aid = *(int *)argv[1]; + if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") || + !strcmp(atype, "KERBEROS")) { + return(get_ace_internal(atype, aid, action, actarg)); + } - sprintf(ftype, "fs_access_%s", type); - EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias - WHERE name = :ftype AND type = 'TYPE' and trans = :access; - if (ingres_errno) return(mr_errcode); - if (ok == 0) return(MR_FILESYS_ACCESS); + sq = sq_create(); + if (!strcmp(atype, "RLIST")) { + sq_save_data(sq, aid); + /* get all the list_id's of containing lists */ + EXEC SQL DECLARE csr107 CURSOR FOR + SELECT list_id FROM imembers + WHERE member_type='LIST' AND member_id = :aid; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr107; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr107 INTO :listid; + if(sqlca.sqlcode != 0) break; + sq_save_unique_data(sq, listid); + } + EXEC SQL CLOSE csr107; + /* now process each one */ + while (sq_get_data(sq, &id)) { + if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS) + found++; + } + } - if((mr_errcode=prefetch_value(q,argv,cl))!=MR_SUCCESS) - return(mr_errcode); + if (!strcmp(atype, "RUSER")) { + EXEC SQL DECLARE csr108 CURSOR FOR + SELECT list_id FROM imembers + WHERE member_type='USER' AND member_id = :aid; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr108; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr108 INTO :listid; + if(sqlca.sqlcode != 0) break; + sq_save_data(sq, listid); + } + EXEC SQL CLOSE csr108; + /* now process each one */ + while (sq_get_data(sq, &id)) { + if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS) + found++; + } + if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS) + found++; + } - if (!strcmp(type, "NFS")) - return (check_nfs(mach_id, name, access)); + if (!strcmp(atype, "RKERBERO")) { + EXEC SQL DECLARE csr109 CURSOR FOR + SELECT list_id FROM imembers + WHERE member_type='KERBEROS' AND member_id = :aid; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr109; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr109 INTO :listid; + if(sqlca.sqlcode != 0) break; + sq_save_data(sq, listid); + } + EXEC SQL CLOSE csr109; + /* now process each one */ + while (sq_get_data(sq, &id)) { + if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS) + found++; + } + if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS) + found++; + } + sq_destroy(sq); + if (ingres_errno) return(mr_errcode); + if (!found) return(MR_NO_MATCH); return(MR_SUCCESS); } -/* Verify the arguments, depending on the FStype. Also, if this is an - * NFS filesystem, then update any quotas for that filesystem to reflect - * the new phys_id. +/* This looks up a single list or user for ace use. atype must be "USER" + * or "LIST", and aid is the ID of the corresponding object. This is used + * by get_ace_use above. */ -setup_ufil(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; +get_ace_internal(atype, aid, action, actarg) + EXEC SQL BEGIN DECLARE SECTION; + char *atype; + int aid; + EXEC SQL END DECLARE SECTION; + int (*action)(); + int actarg; { - int mach_id, status; - char *type, *name; + char *rargv[2]; + int found = 0; EXEC SQL BEGIN DECLARE SECTION; - int fid, total, who, ok; - char *entity, ftype[32], *access; - int var_phys_id = 0; - short int total_null; + char name[33]; EXEC SQL END DECLARE SECTION; - type = argv[2]; - mach_id = *(int *)argv[3]; - name = argv[4]; - access = argv[6]; - fid = *(int *)argv[0]; - who = cl->client_id; - entity = cl->entity; - - sprintf(ftype, "fs_access_%s", type); - EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias - WHERE name = :ftype AND type='TYPE' AND trans = :access; - if (ingres_errno) return(mr_errcode); - if (ok == 0) return(MR_FILESYS_ACCESS); - - EXEC SQL SELECT type INTO :ftype FROM filesys - WHERE filsys_id = :fid; - strtrim(ftype); - if (ingres_errno) return(mr_errcode); - - if (!strcmp(type, "NFS")) { - status = check_nfs(mach_id, name, access); - EXEC SQL UPDATE quota SET phys_id = :var_phys_id - WHERE filsys_id = :fid; - if (ingres_errno) return(mr_errcode); - return(status); - } else if (!strcmp(type, "AFS") && strcmp(ftype, "AFS")) { - total = 0; - EXEC SQL REPEATED DELETE FROM quota - WHERE type = 'ANY' AND filsys_id = :fid; - EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota - WHERE filsys_id = :fid AND phys_id != 0; - if (ingres_errno) return(mr_errcode); - if (!total_null && (total != 0)) { -/* - * append quota (quota = total, filsys_id = fid, - * phys_id = 0, entity_id = 0, type = "ANY", - * modtime = "now", modby = who, modwith = entity) - */ - EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id, - type, modtime, modby, modwith) - VALUES (:total, :fid, 0, 0, - 'ANY', 'now', :who, :entity) ; - if (ingres_errno) return(mr_errcode); - } - } else { - EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid; - if (ingres_errno) return(mr_errcode); - } - return(MR_SUCCESS); -} - - -/* Find the NFS physical partition that the named directory is on. - * This is done by comparing the dir against the mount point of the - * partition. To make sure we get the correct match when there is - * more than one, we sort the query in reverse order by dir name. - */ - -check_nfs(mach_id, name, access) - EXEC SQL BEGIN DECLARE SECTION; - int mach_id; - EXEC SQL END DECLARE SECTION; - char *name; - char *access; -{ - EXEC SQL BEGIN DECLARE SECTION; - char dir[81]; - EXEC SQL END DECLARE SECTION; - char caccess; - register int status; - register char *cp1; - register char *cp2; - - status = MR_NFS; - EXEC SQL DECLARE csr101 CURSOR FOR - SELECT nfsphys_id, TRIM (dir) FROM nfsphys - WHERE mach_id = :mach_id - ORDER BY 2 DESC; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr101; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr101 INTO :var_phys_id, :dir; - if(sqlca.sqlcode != 0) break; - cp1 = name; - cp2 = dir; - while (*cp2) { - if (*cp1++ != *cp2) break; - cp2++; - } - if (*cp2 == 0) { - status = MR_SUCCESS; - break; - } - } - EXEC SQL CLOSE csr101; - if (ingres_errno) - return(mr_errcode); - return(status); -} - - -/* setup_dfil: free any quota records and fsgroup info associated with - * a filesystem when it is deleted. Also adjust the allocation numbers. - */ - -setup_dfil(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int id, total, phys_id; - short int none; - EXEC SQL END DECLARE SECTION; - - id = *(int *)argv[0]; - EXEC SQL REPEATED SELECT SUM (quota) INTO :total:none FROM quota - WHERE filsys_id = :id; - - if(none) total=0; - - /** What if there are multiple phys_id's per f/s? (bad data) **/ - EXEC SQL REPEATED SELECT phys_id INTO :phys_id FROM filesys - WHERE filsys_id = :id; - EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :total - WHERE nfsphys_id = :phys_id; - - if(!none) { - EXEC SQL REPEATED DELETE FROM quota WHERE filsys_id = :id; - } - EXEC SQL REPEATED DELETE FROM fsgroup WHERE filsys_id = :id; - EXEC SQL REPEATED DELETE FROM fsgroup WHERE group_id = :id; - if (ingres_errno) return(mr_errcode); - return(MR_SUCCESS); -} - - -/* setup_dnfp: check to see that the nfs physical partition does not have - * any filesystems assigned to it before allowing it to be deleted. - */ - -setup_dnfp(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int id, cnt; - char *dir; - EXEC SQL END DECLARE SECTION; - - id = *(int *)argv[0]; - dir = argv[1]; - EXEC SQL REPEATED SELECT fs.tid INTO :cnt FROM filesys fs, nfsphys np - WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id - AND np.mach_id = :id AND np.dir = :dir; - if (cnt > 0) - return(MR_IN_USE); - if (ingres_errno) - return(mr_errcode); - return(MR_SUCCESS); -} - - -/* setup_dqot: Remove allocation from nfsphys before deleting quota. - * argv[0] = filsys_id - * argv[1] = type if "update_quota" or "delete_quota" - * argv[2 or 1] = users_id or list_id - */ - -setup_dqot(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int quota, fs, id, physid; - char *qtype; - EXEC SQL END DECLARE SECTION; - - fs = *(int *)argv[0]; - if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota")) { - qtype = argv[1]; - id = *(int *)argv[2]; - } else { - qtype = "USER"; - id = *(int *)argv[1]; - } - - EXEC SQL REPEATED SELECT quota INTO :quota FROM quota - WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs; - EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys - WHERE filsys_id = :fs; - EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated - :quota - WHERE nfsphys_id = :physid; - - if (ingres_errno) return(mr_errcode); - return(MR_SUCCESS); -} - - -/* setup_sshi: don't exclusive lock the machine table during - * set_server_host_internal. - */ -/** Not allowed under (INGRES) SQL **/ -setup_sshi(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ -#if 0 -#ifsql INGRES - EXEC SQL set lockmode session where readlock = system; -#endsql -#endif - return(MR_SUCCESS); -} - - -/* setup add_kerberos_user_mapping: add the string to the string - * table if necessary. - */ - -setup_akum(q, argv, cl) -struct query *q; -char **argv; -client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int id, rowcount; - char *name; - EXEC SQL END DECLARE SECTION; - - name = argv[1]; - if (name_to_id(name, "STRING", &id) != MR_SUCCESS) { - if (q->type != APPEND) return(MR_STRING); - id=add_string(name); - cache_entry(name, "STRING", id); - } - if (ingres_errno) return(mr_errcode); - *(int *)argv[1] = id; - return(MR_SUCCESS); -} - - - -/* FOLLOWUP ROUTINES */ - -/* generic set_modtime routine. This takes the table name from the query, - * and will update the modtime, modby, and modwho fields in the entry in - * the table whose name field matches argv[0]. - */ - -set_modtime(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; -{ - char *name, *entity, *table; - int who; - - entity = cl->entity; - who = cl->client_id; - table = q->rtable; - name = argv[0]; - - sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, modwith = '%s' WHERE %s.name = LEFT('%s',SIZE(%s.name))",table,who,entity,table,name,table); - EXEC SQL EXECUTE IMMEDIATE :stmt_buf; - - return(MR_SUCCESS); -} - -/* generic set_modtime_by_id routine. This takes the table name 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]. - */ - -set_modtime_by_id(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ - char *entity, *table, *id_name; - int who, id; - - entity = cl->entity; - who = cl->client_id; - table = q->rtable; - id_name = q->validate->object_id; - - id = *(int *)argv[0]; - sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, \ -modwith = '%s' WHERE %s.%s = %d",table,who,entity,table,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]. - */ - -set_finger_modtime(q, argv, cl) - 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='now', fmodby = :who, fmodwith = :entity - WHERE users.users_id = :users_id; - - return(MR_SUCCESS); -} - - -/* Sets the pobox modtime on a user record. The users_id will be in argv[0]. - */ - -set_pobox_modtime(q, argv, cl) - 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='now', pmodby = :who, pmodwith = :entity - WHERE users.users_id = :users_id; - - return(MR_SUCCESS); -} - - -/* Like set_modtime, but uppercases the name first. - */ - -set_uppercase_modtime(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ - char *name, *entity, *table; - int who; - - entity = cl->entity; - who = cl->client_id; - table = q->rtable; - name = argv[0]; - - sprintf(stmt_buf,"UPDATE %s SET modtime = 'now', modby = %d, modwith = '%s' WHERE %s.name = UPPERCASE(LEFT('%s',SIZE(%s.name)))",table,who,entity,table,name,table); - 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". - */ - -set_mach_modtime_by_id(q, argv, cl) - 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='now', modby = :who, modwith = :entity - WHERE machine.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". - */ - -set_cluster_modtime_by_id(q, argv, cl) - 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 cluster SET modtime='now', modby = :who, modwith = :entity - WHERE cluster.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]. - */ - -set_serverhost_modtime(q, argv, cl) - 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 = 'now', 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]. - */ - -set_nfsphys_modtime(q, argv, cl) - 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 = 'now', 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. - */ - -set_filesys_modtime(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - char *label, *entity; - int who; - 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 = 'now', modby = :who, - modwith = :entity, phys_id = :var_phys_id - WHERE label = LEFT(:label,SIZE(label)); - return(MR_SUCCESS); -} - - -/* sets the modtime on a zephyr class, where argv[0] contains the class - * name. - */ - -set_zephyr_modtime(q, argv, cl) - 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 = 'now', modby = :who, modwith = :entity - WHERE class = LEFT(:class,SIZE(class)); - - 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. - */ -followup_fix_modby(q, sq, v, action, actarg, cl) - struct query *q; - register struct save_queue *sq; - struct validate *v; - register int (*action)(); - register int actarg; - client *cl; -{ - register int i, j; - char **argv, *malloc(); - 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, "USER", &argv[i]); - else - status = id_to_name(-id, "STRING", &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); -} - - -/* After retrieving a user account, fix the modby field and signature. - * The modby field is 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. Only "gua*" queries have a signature, - * these are ones with U_END return values. "gub*" queries also use this - * routine but don't have a signature. - */ -followup_guax(q, sq, v, action, actarg, cl) - struct query *q; - register struct save_queue *sq; - struct validate *v; - register int (*action)(); - register int actarg; - client *cl; -{ - register int i, j; - char **argv, *malloc(); -#ifdef GDSS - unsigned char sigbuf[256]; - char *kname; - SigInfo si; - EXEC SQL BEGIN DECLARE SECTION; - int timestamp, who; - char *login; - varchar struct { short data_size; char data_buf[257];} rsig; - EXEC SQL END DECLARE SECTION; -#endif /* GDSS */ - int id, status; - - i = q->vcnt - 2; - while (sq_get_data(sq, &argv)) { -#ifdef DEBUG - com_err(whoami, 0, "argv[SIGNATURE] = \"%s\"", argv[U_SIGNATURE]); -#endif /* DEBUG */ - id = atoi(argv[i]); - if (id > 0) - status = id_to_name(id, "USER", &argv[i]); - else - status = id_to_name(-id, "STRING", &argv[i]); - if (status && status != MR_NO_MATCH) - return(status); -#ifdef GDSS - if (q->vcnt == U_END && strlen(argv[U_SIGNATURE])) { - login = argv[U_NAME]; - EXEC SQL REPEATED SELECT signature, sigdate, sigwho - INTO :rsig, :timestamp, :who FROM users - WHERE login = :login; - /** What about (INGRES) error handling? **/ - kname = malloc(1); - status = id_to_name(who, "STRING", &kname); - si.timestamp = timestamp; - si.SigInfoVersion = 0; /* XXXXX this isn't used */ - kname_parse(si.pname, si.pinst, si.prealm, kname); - free(kname); - rsig.data_buf[rsig.data_size] = 0; - si.rawsig = (unsigned char *)strsave(rsig.data_buf); - if (log_flags & LOG_GDSS) - com_err(whoami, 0, "rawsig length = %d, sig=\"%s\"", strlen(si.rawsig), si.rawsig); - GDSS_Recompose(&si, sigbuf); - free(si.rawsig); - free(argv[U_SIGNATURE]); - argv[U_SIGNATURE] = strsave(sigbuf); - if (log_flags & LOG_GDSS) - com_err(whoami, 0, "generated signature length %d", strlen(sigbuf)); - } -#endif /* GDSS */ - (*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[3] - last name - ** argv[4] - first name - ** argv[5] - middle name - ** - **/ - -followup_ausr(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int who, status, id; - char *login, *entity, *src, *dst, *name; - char fullname[129]; - EXEC SQL END DECLARE SECTION; -#ifdef GDSS - char databuf[32], *kname_unparse(); - EXEC SQL BEGIN DECLARE SECTION; - char rawsig[128]; - int sigwho, timestamp; - EXEC SQL END DECLARE SECTION; - SigInfo si; -#endif /* GDSS */ - - /* build fullname */ - if (strlen(argv[4]) && strlen(argv[5])) - sprintf(fullname, "%s %s %s", argv[4], argv[5], argv[3]); - else if (strlen(argv[4])) - sprintf(fullname, "%s %s", argv[4], argv[3]); - else - sprintf(fullname, "%s", argv[3]); - -#ifdef GDSS - if (q->vcnt == U_END && *argv[U_SIGNATURE]) { - /* unquote ' chars in signature */ - for (dst = src = argv[U_SIGNATURE]; *src; ) { - if (*src == '\'') - src++; - *dst++ = *src++; - } - *dst = 0; - sprintf(databuf, "%s:%s", argv[U_NAME], argv[U_MITID]); - /* skip bytes for timestamp & kname */ - si.rawsig = (unsigned char *) rawsig; - status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE], &si); - if (strlen(rawsig) > mr_sig_length) { - com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/ - return(MR_INTERNAL); - } - if (status == 0) { - name = kname_unparse(si.pname, si.pinst, si.prealm); - status = name_to_id(name, "STRING", &sigwho); - if (status == MR_NO_MATCH) { - sigwho=add_string(name); - } else if (status) - return(status); - timestamp = si.timestamp; - } else { - if (log_flags & LOG_GDSS) - hex_dump(argv[U_SIGNATURE]); - return(gdss2et(status)); - } - } else { - rawsig[0] = 0; - sigwho = 0; - timestamp = 0; - } -#endif /* GDSS */ - - login = argv[0]; - who = cl->client_id; - entity = cl->entity; - - /* create finger entry, pobox & set modtime on user */ -#ifdef GDSS - EXEC SQL REPEATED UPDATE users - SET modtime='now', modby=:who, modwith = :entity, - fullname = :fullname, affiliation = type, - signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho, - fmodtime='now', fmodby = :who, fmodwith = :entity, - potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity - WHERE login = :login; -#else /* GDSS */ - EXEC SQL REPEATED UPDATE users - SET modtime='now', modby=:who, modwith = :entity, - fullname = :fullname, affiliation = type, - fmodtime='now', fmodby = :who, fmodwith = :entity, - potype='NONE', pmodtime='now', pmodby = :who, pmodwith = :entity - WHERE login = :login; -#endif /* GDSS */ - - return(MR_SUCCESS); -} - - -/** - ** followup_uusr - do signature, set_user_modtime - ** - ** Inputs: - ** argv[0] - login (add_user) - ** argv[U_SIGNATURE] - sig - ** - **/ - -followup_uuac(q, argv, cl) - struct query *q; - char *argv[]; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int who, status, id; - char *entity, *name, *src, *dst; - EXEC SQL END DECLARE SECTION; -#ifdef GDSS - char databuf[32], *kname_unparse(); - EXEC SQL BEGIN DECLARE SECTION; - char rawsig[128]; - char *login; - int sigwho, timestamp; - EXEC SQL END DECLARE SECTION; - SigInfo si; -#endif /* GDSS */ - - id = *(int *)argv[0]; - who = cl->client_id; - entity = cl->entity; - -#ifdef GDSS - if (q->vcnt == U_MODTIME && *argv[U_SIGNATURE + 1]) { - /* unquote ' chars in signature */ - for (dst = src = argv[U_SIGNATURE+1]; *src; ) { - if (*src == '\'') - src++; - *dst++ = *src++; - } - *dst = 0; - login = malloc(1); - status = id_to_name(id, "USER", &login); - sprintf(databuf, "%s:%s", login, argv[U_MITID+1]); - free(login); - /* skip bytes for timestamp & kname */ - si.rawsig = (unsigned char *) rawsig; -#ifdef DEBUG - com_err(whoami, 0, "verifying sig"); -#endif /* DEBUG */ - status = GDSS_Verify(databuf, strlen(databuf), argv[U_SIGNATURE+1], &si); -#ifdef DEBUG - com_err(whoami, 0, "verified"); -#endif /* DEBUG */ - if (strlen(rawsig) > mr_sig_length) { - com_err(whoami, 0, "GDSS signature would be truncated."); /** untested **/ - return(MR_INTERNAL); - } - if (status == 0) { - name = kname_unparse(si.pname, si.pinst, si.prealm); - status = name_to_id(name, "STRING", &sigwho); - if (status == MR_NO_MATCH) { - sigwho=add_string(name); - } else if (status) - return(status); - timestamp = si.timestamp; - } else { - if (log_flags & LOG_GDSS) - hex_dump(argv[U_SIGNATURE+1]); - return(gdss2et(status)); - } - } else { - rawsig[0] = 0; - sigwho = 0; - timestamp = 0; - } -#endif /* GDSS */ - - /* create finger entry, pobox & set modtime on user */ - -#ifdef GDSS - EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity, - signature = :rawsig, sigdate = :timestamp, sigwho = :sigwho - WHERE users_id = :id; -#else /* GDSS */ - EXEC SQL REPEATED UPDATE users SET modtime='now', modby = :who, modwith = :entity - WHERE users_id = :id; -#endif /* GDSS */ - return(MR_SUCCESS); -} - - -/* followup_gpob: fixes argv[2] based on the IDs currently there and the - * type in argv[1]. Then completes the upcall to the user. - * - * argv[2] is of the form "123:234" where the first integer is the machine - * ID if it is a pop box, and the second is the string ID if it is an SMTP - * box. argv[1] should be "POP", "SMTP", or "NONE". Boxes of type NONE - * are skipped. - */ - -followup_gpob(q, sq, v, action, actarg, cl) - register struct query *q; - register struct save_queue *sq; - register struct validate *v; - register int (*action)(); - int actarg; - client *cl; -{ - char **argv, *index(); - char *ptype, *p; - int mid, sid, status, i; - - /* for each row */ - while (sq_get_data(sq, &argv)) { - mr_trim_args(2, argv); - ptype = argv[1]; - p = index(argv[2], ':'); - *p++ = 0; - mid = atoi(argv[2]); - sid = atoi(p); - - if (!strcmp(ptype, "POP")) { - status = id_to_name(mid, "MACHINE", &argv[2]); - if (status == MR_NO_MATCH) - return(MR_MACHINE); - } else if (!strcmp(ptype, "SMTP")) { - status = id_to_name(sid, "STRING", &argv[2]); - if (status == MR_NO_MATCH) - return(MR_STRING); - } else /* ptype == "NONE" */ { - goto skip; - } - if (status) return(status); - - if (!strcmp(q->shortname, "gpob")) { - sid = atoi(argv[4]); - if (sid > 0) - status = id_to_name(sid, "USER", &argv[4]); - else - status = id_to_name(-sid, "STRING", &argv[4]); - } - 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); -} - - -/* followup_glin: fix the ace_name in argv[8]. argv[7] will contain the - * ace_type: "LIST", "USER", or "NONE". Decode the id in argv[8] into the - * proper name based on the type, and repace that string in the argv. - * Also fixes the modby field by called followup_fix_modby. - */ - -followup_glin(q, sq, v, action, actarg, cl) - register struct query *q; - register struct save_queue *sq; - register struct validate *v; - register int (*action)(); - int actarg; - client *cl; -{ - char **argv, *malloc(), *realloc(), *type; - int id, i, idx, status; - - idx = 8; - if (!strcmp(q->shortname, "gsin")) - idx = 12; - - while (sq_get_data(sq, &argv)) { - mr_trim_args(q->vcnt, argv); - - id = atoi(argv[i = q->vcnt - 2]); - if (id > 0) - status = id_to_name(id, "USER", &argv[i]); - else - status = id_to_name(-id, "STRING", &argv[i]); - if (status && status != MR_NO_MATCH) - return(status); - - id = atoi(argv[idx]); - type = argv[idx - 1]; - - if (!strcmp(type, "LIST")) { - status = id_to_name(id, "LIST", &argv[idx]); - } else if (!strcmp(type, "USER")) { - status = id_to_name(id, "USER", &argv[idx]); - } else if (!strcmp(type, "KERBEROS")) { - status = id_to_name(id, "STRING", &argv[idx]); - } else if (!strcmp(type, "NONE")) { - status = 0; - free(argv[idx]); - argv[idx] = strsave("NONE"); - } else { - status = 0; - free(argv[idx]); - argv[idx] = strsave("???"); - } - if (status && status != MR_NO_MATCH) - return(status); - - if (!strcmp(q->shortname, "glin") && atoi(argv[6]) == -1) { - argv[6] = realloc(argv[6], strlen(UNIQUE_GID) + 1); - strcpy(argv[6], UNIQUE_GID); - } - - /* send the data */ - (*action)(q->vcnt, argv, actarg); - - /* free saved data */ - for (i = 0; i < q->vcnt; i++) - free(argv[i]); - free(argv); - } - - sq_destroy(sq); - return (MR_SUCCESS); -} - - -/* 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) - */ - -followup_gqot(q, sq, v, action, actarg, cl) - struct query *q; - register struct save_queue *sq; - struct validate *v; - register int (*action)(); - register int actarg; - client *cl; -{ - register int j; - char **argv, *malloc(); - 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]), "USER", &argv[2]); - break; - case 'G': - case 'L': - status = id_to_name(atoi(argv[2]), "LIST", &argv[2]); - break; - case 'A': - free(argv[2]); - argv[2] = strsave("system:anyuser"); - break; - default: - id = atoi(argv[2]); - argv[2] = malloc(8); - sprintf(argv[2], "%d", id); - } - } - id = atoi(argv[idx]); - free(argv[idx]); - argv[idx] = malloc(256); - name = argv[idx]; - if (id == 0) { - label = argv[0]; - EXEC SQL REPEATED SELECT name INTO :name FROM filesys - WHERE label = :label; - } else { - EXEC SQL REPEATED 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, "USER", &argv[idx+3]); - else - status = id_to_name(-id, "STRING", &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) - */ - -followup_aqot(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int quota, id, fs, who, physid; - char *entity, *qtype, *table_name; - EXEC SQL END DECLARE SECTION; - char incr_qual[60]; - char *incr_argv[2]; - int status; - - table_name=q->rtable; - fs = *(int *)argv[0]; - EXEC SQL REPEATED SELECT phys_id INTO :physid FROM filesys - WHERE filsys_id = :fs; - if(ingres_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==APPEND) { - incremental_clear_before(); - EXEC SQL INSERT INTO quota - (filsys_id, type, entity_id, quota, phys_id) - VALUES (:fs, :qtype, :id, :quota, :physid); - incremental_after(table_name, incr_qual, incr_argv); - } else { - incremental_before(table_name, 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_name, incr_qual, incr_argv); - } - - if (ingres_errno) - return(mr_errcode); - flush_name(argv[0], q->rtable); - if(q->type==APPEND) { - EXEC SQL UPDATE tblstats SET appends = appends + 1, modtime = 'now' - WHERE table_name = :table_name; - } else { - EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = 'now' - WHERE table_name = :table_name; - } - - /* Proceed with original followup */ - who = cl->client_id; - entity = cl->entity; - - EXEC SQL REPEATED UPDATE quota - SET modtime = 'now', modby = :who, modwith = :entity - WHERE filsys_id = :fs and type = :qtype and entity_id = :id; - EXEC SQL REPEATED UPDATE nfsphys SET allocated = allocated + :quota - WHERE nfsphys_id = :physid; - if (ingres_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. - */ -followup_dqot(q,argv,cl) - struct query *q; - char **argv; - struct client *cl; -{ - char *qtype; - int id, fs; - char *incr_argv[2]; - EXEC SQL BEGIN DECLARE SECTION; - char incr_qual[80]; - char *tblname; - EXEC SQL END DECLARE SECTION; - - 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(q->rtable, incr_qual, incr_argv); - EXEC SQL DELETE FROM quota q WHERE :incr_qual; - incremental_clear_after(); - - if (ingres_errno) - return(mr_errcode); - flush_name(argv[0], q->rtable); - - tblname = q->rtable; - EXEC SQL UPDATE tblstats SET deletes = deletes + 1, modtime = 'now' - WHERE table_name = :tblname; - return(MR_SUCCESS); -} - - -followup_gpce(q, sq, v, action, actarg, cl) - struct query *q; - register struct save_queue *sq; - struct validate *v; - register int (*action)(); - register int actarg; - client *cl; -{ - register int i, j; - char **argv, *malloc(); - int id, status; - - i = q->vcnt - 2; - while (sq_get_data(sq, &argv)) { - id = atoi(argv[PCAP_QSERVER]); - status = id_to_name(id, "MACHINE", &argv[PCAP_QSERVER]); - if (status) return (status); - id = atoi(argv[i]); - if (id > 0) - status = id_to_name(id, "USER", &argv[i]); - else - status = id_to_name(-id, "STRING", &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_gzcl: - */ - -followup_gzcl(q, sq, v, action, actarg, cl) - register struct query *q; - register struct save_queue *sq; - register struct validate *v; - register int (*action)(); - int actarg; - client *cl; -{ - int id, i, status; - char **argv; - - while (sq_get_data(sq, &argv)) { - mr_trim_args(q->vcnt, argv); - - id = atoi(argv[i = q->vcnt - 2]); - if (id > 0) - status = id_to_name(id, "USER", &argv[i]); - else - status = id_to_name(-id, "STRING", &argv[i]); - if (status && status != MR_NO_MATCH) - return(status); - - for (i = 1; i < 8; i+=2) { - id = atoi(argv[i+1]); - if (!strcmp(argv[i], "LIST")) { - status = id_to_name(id, "LIST", &argv[i+1]); - } else if (!strcmp(argv[i], "USER")) { - status = id_to_name(id, "USER", &argv[i+1]); - } else if (!strcmp(argv[i], "KERBEROS")) { - status = id_to_name(id, "STRING", &argv[i+1]); - } else if (!strcmp(argv[i], "NONE")) { - status = 0; - free(argv[i+1]); - argv[i+1] = strsave("NONE"); - } else { - status = 0; - free(argv[i+1]); - argv[i+1] = strsave("???"); - } - if (status && status != MR_NO_MATCH) - return(status); - } - - /* send the data */ - (*action)(q->vcnt, argv, actarg); - - /* free saved data */ - for (i = 0; i < q->vcnt; i++) - free(argv[i]); - free(argv); - } - sq_destroy(sq); - return(MR_SUCCESS); -} - - -/* followup_gsha: - */ - -followup_gsha(q, sq, v, action, actarg, cl) - register struct query *q; - register struct save_queue *sq; - register struct validate *v; - register int (*action)(); - int actarg; - client *cl; -{ - char **argv; - int i, id, status; - - while (sq_get_data(sq, &argv)) { - mr_trim_args(q->vcnt, argv); - - id = atoi(argv[4]); - if (id > 0) - status = id_to_name(id, "USER", &argv[4]); - else - status = id_to_name(-id, "STRING", &argv[4]); - if (status && status != MR_NO_MATCH) - return(status); - - id = atoi(argv[2]); - if (!strcmp(argv[1], "LIST")) { - status = id_to_name(id, "LIST", &argv[2]); - } else if (!strcmp(argv[1], "USER")) { - status = id_to_name(id, "USER", &argv[2]); - } else if (!strcmp(argv[1], "KERBEROS")) { - status = id_to_name(id, "STRING", &argv[2]); - } else if (!strcmp(argv[1], "NONE")) { - status = 0; - free(argv[2]); - argv[2] = strsave("NONE"); - } else { - status = 0; - free(argv[2]); - argv[2] = strsave("???"); - } - if (status && status != MR_NO_MATCH) - return(status); - - /* send the data */ - (*action)(q->vcnt, argv, actarg); - - /* free saved data */ - for (i = 0; i < q->vcnt; i++) - free(argv[i]); - free(argv); - } - sq_destroy(sq); - return(MR_SUCCESS); -} - - - -/* Special query routines */ - -/* set_pobox - this does all of the real work. - * argv = user_id, type, box - * if type is POP, then box should be a machine, and its ID should be put in - * pop_id. If type is SMTP, then box should be a string and its ID should - * be put in box_id. If type is NONE, then box doesn't matter. - */ - -int set_pobox(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int user, id; - char *box, potype[9]; - EXEC SQL END DECLARE SECTION; - int status; - - box = argv[2]; - user = *(int *)argv[0]; - - EXEC SQL REPEATED SELECT pop_id, potype INTO :id, :potype FROM users - WHERE users_id = :user; - if (ingres_errno) return(mr_errcode); - if (!strcmp(strtrim(potype), "POP")) - set_pop_usage(id, -1); - - if (!strcmp(argv[1], "POP")) { - status = name_to_id(box, "MACHINE", &id); - if (status == MR_NO_MATCH) - return(MR_MACHINE); - else if (status) - return(status); - EXEC SQL REPEATED UPDATE users SET potype = 'POP', pop_id = :id - WHERE users_id = :user; - set_pop_usage(id, 1); - } else if (!strcmp(argv[1], "SMTP")) { - if (index(box, '/') || index(box, '|')) - return(MR_BAD_CHAR); - status = name_to_id(box, "STRING", &id); - if (status == MR_NO_MATCH) { - id=add_string(box); - } else if (status) - return(status); - EXEC SQL REPEATED UPDATE users SET potype='SMTP', box_id = :id - WHERE users_id = :user; - } else /* argv[1] == "NONE" */ { - EXEC SQL REPEATED UPDATE users SET potype='NONE' - WHERE users_id = :user; - } - - set_pobox_modtime(q, argv, cl); - EXEC SQL REPEATED UPDATE tblstats SET updates = updates+1, modtime='now' - WHERE table_name='users'; - if (ingres_errno) return(mr_errcode); - return(MR_SUCCESS); -} - - -/* get_list_info: passed a wildcard list name, returns lots of stuff about - * each list. This is tricky: first build a queue of all requested - * data. Rest of processing consists of fixing gid, ace_name, and modby. - */ - -get_list_info(q, aargv, cl, action, actarg) - register struct query *q; - char **aargv; - client *cl; - register int (*action)(); - int actarg; -{ - char *argv[13], *malloc(), *realloc(); - EXEC SQL BEGIN DECLARE SECTION; - char *name, acl_type[9], listname[33], active[5], public[5], hidden[5]; - char maillist[5], grouplist[5], gid_str[6], acl_name[256], desc[256]; - char modtime[27], modby[256], modwith[9]; - int id, rowcount, acl_id, hid, modby_id; - char qual[80]; - EXEC SQL END DECLARE SECTION; - int returned, status; - struct save_queue *sq, *sq_create(); - - returned = rowcount = 0; - name = aargv[0]; - convert_wildcards(name); - - sq = sq_create(); - sprintf(qual,"name LIKE '%s' ESCAPE '*'",name); - optimize_sql_stmt(qual); - EXEC SQL DECLARE csr102 CURSOR FOR SELECT list_id FROM list - WHERE :qual; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr102; - if (ingres_errno) - return(mr_errcode); - while(1) - { - EXEC SQL FETCH csr102 INTO :id; - if(sqlca.sqlcode!=0) break; - sq_save_data(sq, id); - rowcount++; - } - EXEC SQL CLOSE csr102; - - if (ingres_errno) return(mr_errcode); - if (rowcount == 0) - return(MR_NO_MATCH); - - argv[0] = listname; argv[1] = active; argv[2] = public; argv[3] = hidden; - argv[4] = maillist; argv[5] = grouplist; argv[6] = gid_str; - argv[7] = acl_type; argv[9] = desc; argv[10] = modtime; argv[12] = modwith; - - while (sq_get_data(sq, &id)) { - if (id == 0) - continue; - argv[6] = gid_str; - EXEC SQL REPEATED SELECT name, CHAR(active), CHAR(publicflg), - CHAR(hidden), hidden, CHAR(maillist), CHAR(grouplist), CHAR(gid), - TRIM(acl_type), acl_id, description, CHAR(modtime), modby, modwith - INTO :listname, :active, :public, :hidden, :hid, :maillist, - :grouplist, :gid_str, :acl_type, :acl_id, :desc, - :modtime, :modby_id, :modwith - FROM list WHERE list_id = :id; - - if (ingres_errno) return(mr_errcode); - - if (atoi(gid_str) == -1) - argv[6] = UNIQUE_GID; - - argv[8] = malloc(0); - if (!strcmp(acl_type, "LIST")) { - status = id_to_name(acl_id, "LIST", &argv[8]); - } else if (!strcmp(acl_type, "USER")) { - status = id_to_name(acl_id, "USER", &argv[8]); - } else if (!strcmp(acl_type, "KERBEROS")) { - status = id_to_name(acl_id, "STRING", &argv[8]); - } else if (!strcmp(acl_type, "NONE")) { - status = 0; - free(argv[8]); - argv[8] = strsave("NONE"); - } else { - status = 0; - free(argv[8]); - argv[8] = strsave("???"); - } - if (status && status != MR_NO_MATCH) return(status); - - argv[11] = malloc(0); - if (modby_id > 0) - status = id_to_name(modby_id, "USER", &argv[11]); - else - status = id_to_name(-modby_id, "STRING", &argv[11]); - if (status && status != MR_NO_MATCH) return(status); - - mr_trim_args(q->vcnt, argv); - returned++; - (*action)(q->vcnt, argv, actarg); - free(argv[8]); - free(argv[11]); - } - - sq_destroy(sq); - if (ingres_errno) return(mr_errcode); - return (MR_SUCCESS); -} - - -/* Add_member_to_list: do list flattening as we go! MAXLISTDEPTH is - * how many different ancestors a member is allowed to have. - */ - -#define MAXLISTDEPTH 1024 - -int add_member_to_list(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int id, lid, mid, error, who, ref, rowcnt; - char *mtype, dtype[9], *entity; - EXEC SQL END DECLARE SECTION; - int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a; - int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d; - int status; - char *dtypes[MAXLISTDEPTH]; - char *iargv[3], *buf; - - lid = *(int *)argv[0]; - mtype = argv[1]; - mid = *(int *)argv[2]; - /* if the member is already a direct member of the list, punt */ - EXEC SQL REPEATED SELECT COUNT(list_id) INTO :rowcnt FROM imembers - WHERE list_id = :lid AND member_id = :mid - AND member_type = :mtype AND direct = 1; - if (rowcnt > 0) - return(MR_EXISTS); - if (!strcasecmp(mtype, "STRING")) { - buf = malloc(0); - status = id_to_name(mid, "STRING", &buf); - if (status) return(status); - if (index(buf, '/') || index(buf, '|')) { - free(buf); - return(MR_BAD_CHAR); - } - free(buf); - } - - ancestors[0] = lid; - aref[0] = 1; - acount = 1; - EXEC SQL DECLARE csr103 CURSOR FOR - SELECT list_id, ref_count FROM imembers - WHERE member_id = :lid AND member_type='LIST'; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr103; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr103 INTO :id, :ref; - if(sqlca.sqlcode != 0) break; - aref[acount] = ref; - ancestors[acount++] = id; - if (acount >= MAXLISTDEPTH) break; - } - EXEC SQL CLOSE csr103; - if (ingres_errno) return(mr_errcode); - if (acount >= MAXLISTDEPTH) { - return(MR_INTERNAL); - } - descendants[0] = mid; - dtypes[0] = mtype; - dref[0] = 1; - dcount = 1; - error = 0; - if (!strcmp(mtype, "LIST")) { - EXEC SQL DECLARE csr104 CURSOR FOR - SELECT member_id, member_type, ref_count - FROM imembers - WHERE list_id = :mid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr104; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr104 INTO :id, :dtype, :ref; - if(sqlca.sqlcode != 0) break; - switch (dtype[0]) { - case 'L': - dtypes[dcount] = "LIST"; - break; - case 'U': - dtypes[dcount] = "USER"; - break; - case 'S': - dtypes[dcount] = "STRING"; - break; - case 'K': - dtypes[dcount] = "KERBEROS"; - break; - default: - error++; - break; - } - dref[dcount] = ref; - descendants[dcount++] = id; - if (dcount >= MAXLISTDEPTH) { - error++; - break; - } - } - EXEC SQL CLOSE csr104; - if (ingres_errno) return(mr_errcode); - if (error) - return(MR_INTERNAL); - } - for (a = 0; a < acount; a++) { - lid = ancestors[a]; - for (d = 0; d < dcount; d++) { - mid = descendants[d]; - mtype = dtypes[d]; - if (mid == lid && !strcmp(mtype, "LIST")) { - return(MR_LISTLOOP); - } - EXEC SQL REPEATED SELECT COUNT(ref_count) INTO :rowcnt - FROM imembers - WHERE list_id = :lid AND member_id = :mid - AND member_type = :mtype; - ref = aref[a] * dref[d]; - if (rowcnt > 0) { - if (a == 0 && d == 0) { - EXEC SQL UPDATE imembers - SET ref_count = ref_count+:ref, direct=1 - WHERE list_id = :lid AND member_id = :mid - AND member_type = :mtype; - } else { - EXEC SQL UPDATE imembers - SET ref_count = ref_count+:ref - WHERE list_id = :lid AND member_id = :mid - AND member_type = :mtype; - } - } else { - incremental_clear_before(); - if (a == 0 && d == 0) { - EXEC SQL INSERT INTO imembers - (list_id, member_id, direct, member_type, ref_count) - VALUES (:lid, :mid, 1, :mtype, 1); - } else { - EXEC SQL INSERT INTO imembers - (list_id, member_id, member_type, ref_count) - VALUES (:lid, :mid, :mtype, 1); - } - iargv[0] = (char *)lid; - iargv[1] = mtype; - iargv[2] = (char *)mid; - incremental_after("members", 0, iargv); - } - } - } - lid = *(int *)argv[0]; - entity = cl->entity; - who = cl->client_id; - EXEC SQL REPEATED UPDATE list - SET modtime='now', modby = :who, modwith = :entity - WHERE list_id = :lid; - if (ingres_errno) return(mr_errcode); - return(MR_SUCCESS); -} - - -/* Delete_member_from_list: do list flattening as we go! - */ - -int delete_member_from_list(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - int id, lid, mid, cnt, error, who, ref; - char *mtype, dtype[9], *entity; - EXEC SQL END DECLARE SECTION; - int ancestors[MAXLISTDEPTH], aref[MAXLISTDEPTH], acount, a; - int descendants[MAXLISTDEPTH], dref[MAXLISTDEPTH], dcount, d; - char *dtypes[MAXLISTDEPTH]; - char *iargv[3]; - - lid = *(int *)argv[0]; - mtype = argv[1]; - mid = *(int *)argv[2]; - /* if the member is not a direct member of the list, punt */ - EXEC SQL REPEATED SELECT COUNT(list_id) INTO :cnt FROM imembers - WHERE list_id = :lid AND member_id = :mid - AND member_type = :mtype AND direct = 1; - if (ingres_errno) return(mr_errcode); - if (cnt == 0) - return(MR_NO_MATCH); - ancestors[0] = lid; - aref[0] = 1; - acount = 1; - EXEC SQL DECLARE csr105 CURSOR FOR - SELECT list_id, ref_count FROM imembers - WHERE member_id = :lid AND member_type = 'LIST'; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr105; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr105 INTO :id, :ref; - if(sqlca.sqlcode!=0) break; - aref[acount] = ref; - ancestors[acount++] = id; - if (acount >= MAXLISTDEPTH) break; - } - EXEC SQL CLOSE csr105; - if (ingres_errno) - return(mr_errcode); - if (acount >= MAXLISTDEPTH) - return(MR_INTERNAL); - descendants[0] = mid; - dtypes[0] = mtype; - dref[0] = 1; - dcount = 1; - error = 0; - if (!strcmp(mtype, "LIST")) { - EXEC SQL DECLARE csr106 CURSOR FOR - SELECT member_id, member_type, ref_count FROM imembers - WHERE list_id = :mid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr106; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr106 INTO :id, :dtype, :ref; - if(sqlca.sqlcode!=0) break; - switch (dtype[0]) { - case 'L': - dtypes[dcount] = "LIST"; - break; - case 'U': - dtypes[dcount] = "USER"; - break; - case 'S': - dtypes[dcount] = "STRING"; - break; - case 'K': - dtypes[dcount] = "KERBEROS"; - break; - default: - error++; - break; - } - dref[dcount] = ref; - descendants[dcount++] = id; - if (dcount >= MAXLISTDEPTH) break; - } - EXEC SQL CLOSE csr106; - if (ingres_errno) - return(mr_errcode); - if (error) - return(MR_INTERNAL); - } - for (a = 0; a < acount; a++) { - lid = ancestors[a]; - for (d = 0; d < dcount; d++) { - mid = descendants[d]; - mtype = dtypes[d]; - if (mid == lid && !strcmp(mtype, "LIST")) { - return(MR_LISTLOOP); - } - EXEC SQL REPEATED SELECT ref_count INTO :cnt FROM imembers - WHERE list_id = :lid AND member_id = :mid AND member_type = :mtype; - ref = aref[a] * dref[d]; - if (cnt <= ref) { - iargv[0] = (char *)lid; - iargv[1] = mtype; - iargv[2] = (char *)mid; - incremental_before("members", 0, iargv); - EXEC SQL DELETE FROM imembers - WHERE list_id = :lid AND member_id = :mid - AND member_type= :mtype; - incremental_clear_after(); - } else if (a == 0 && d == 0) { - EXEC SQL UPDATE imembers - SET ref_count = ref_count - :ref, direct = 0 - WHERE list_id = :lid AND member_id = :mid - AND member_type = :mtype; - } else { - EXEC SQL UPDATE imembers - SET ref_count = ref_count - :ref - WHERE list_id = :lid AND member_id = :mid - AND member_type = :mtype; - } - } - } - lid = *(int *)argv[0]; - entity = cl->entity; - who = cl->client_id; - EXEC SQL UPDATE list SET modtime = 'now', modby = :who, modwith = :entity - WHERE list_id = :lid; - if (ingres_errno) return(mr_errcode); - return(MR_SUCCESS); -} - - -/* get_ace_use - given a type and a name, return a type and a name. - * The ace_type is one of "LIST", "USER", "RLIST", or "RUSER" in argv[0], - * and argv[1] will contain the ID of the entity in question. The R* - * types mean to recursively look at every containing list, not just - * when the object in question is a direct member. On return, the - * usage type will be one of LIST, SERVICE, FILESYS, QUOTA, QUERY, or ZEPHYR. - */ - -int get_ace_use(q, argv, cl, action, actarg) - struct query *q; - char *argv[]; - client *cl; - int (*action)(); - int actarg; -{ - int found = 0; - EXEC SQL BEGIN DECLARE SECTION; - char *atype; - int aid, listid, id; - EXEC SQL END DECLARE SECTION; - struct save_queue *sq, *sq_create(); - - atype = argv[0]; - aid = *(int *)argv[1]; - if (!strcmp(atype, "LIST") || !strcmp(atype, "USER") || - !strcmp(atype, "KERBEROS")) { - return(get_ace_internal(atype, aid, action, actarg)); - } - - sq = sq_create(); - if (!strcmp(atype, "RLIST")) { - sq_save_data(sq, aid); - /* get all the list_id's of containing lists */ - EXEC SQL DECLARE csr107 CURSOR FOR - SELECT list_id FROM imembers - WHERE member_type='LIST' AND member_id = :aid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr107; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr107 INTO :listid; - if(sqlca.sqlcode != 0) break; - sq_save_unique_data(sq, listid); - } - EXEC SQL CLOSE csr107; - /* now process each one */ - while (sq_get_data(sq, &id)) { - if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS) - found++; - } - } - - if (!strcmp(atype, "RUSER")) { - EXEC SQL DECLARE csr108 CURSOR FOR - SELECT list_id FROM imembers - WHERE member_type='USER' AND member_id = :aid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr108; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr108 INTO :listid; - if(sqlca.sqlcode != 0) break; - sq_save_data(sq, listid); - } - EXEC SQL CLOSE csr108; - /* now process each one */ - while (sq_get_data(sq, &id)) { - if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS) - found++; - } - if (get_ace_internal("USER", aid, action, actarg) == MR_SUCCESS) - found++; - } - - if (!strcmp(atype, "RKERBERO")) { - EXEC SQL DECLARE csr109 CURSOR FOR - SELECT list_id FROM imembers - WHERE member_type='KERBEROS' AND member_id = :aid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr109; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr109 INTO :listid; - if(sqlca.sqlcode != 0) break; - sq_save_data(sq, listid); - } - EXEC SQL CLOSE csr109; - /* now process each one */ - while (sq_get_data(sq, &id)) { - if (get_ace_internal("LIST", id, action, actarg) == MR_SUCCESS) - found++; - } - if (get_ace_internal("KERBEROS", aid, action, actarg) == MR_SUCCESS) - found++; - } - - sq_destroy(sq); - if (ingres_errno) return(mr_errcode); - if (!found) return(MR_NO_MATCH); - return(MR_SUCCESS); -} - - -/* This looks up a single list or user for ace use. atype must be "USER" - * or "LIST", and aid is the ID of the corresponding object. This is used - * by get_ace_use above. - */ - -get_ace_internal(atype, aid, action, actarg) - EXEC SQL BEGIN DECLARE SECTION; - char *atype; - int aid; - EXEC SQL END DECLARE SECTION; - int (*action)(); - int actarg; -{ - char *rargv[2]; - int found = 0; - EXEC SQL BEGIN DECLARE SECTION; - char name[33]; - EXEC SQL END DECLARE SECTION; - - rargv[1] = name; - if (!strcmp(atype, "LIST")) { - rargv[0] = "FILESYS"; - EXEC SQL DECLARE csr110 CURSOR FOR - SELECT label FROM filesys - WHERE owners = :aid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr110; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr110 INTO :name; - if(sqlca.sqlcode != 0) break; - (*action)(2, rargv, actarg); - found++; - } - EXEC SQL CLOSE csr110; - - rargv[0] = "QUERY"; - EXEC SQL DECLARE csr111 CURSOR FOR - SELECT capability FROM capacls - WHERE list_id = :aid ; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr111; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr111 INTO :name ; - if(sqlca.sqlcode != 0) break; - (*action)(2, rargv, actarg); - found++; - } - EXEC SQL CLOSE csr111; - } else if (!strcmp(atype, "USER")) { - rargv[0] = "FILESYS"; - EXEC SQL DECLARE csr112 CURSOR FOR - SELECT label FROM filesys - WHERE owner = :aid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr112; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr112 INTO :name ; - if(sqlca.sqlcode != 0) break; - (*action)(2, rargv, actarg); - found++; - } - EXEC SQL CLOSE csr112; - } - - rargv[0] = "LIST"; - EXEC SQL DECLARE csr113 CURSOR FOR - SELECT name FROM list - WHERE acl_type = :atype AND acl_id = :aid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr113; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr113 INTO :name; - if(sqlca.sqlcode != 0) break; - (*action)(2, rargv, actarg); - found++; - } - EXEC SQL CLOSE csr113; - - rargv[0] = "SERVICE"; - EXEC SQL DECLARE csr114 CURSOR FOR - SELECT name FROM servers - WHERE acl_type = :atype AND acl_id = :aid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr114; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr114 INTO :name; - if(sqlca.sqlcode != 0) break; - (*action)(2, rargv, actarg); - found++; - } - EXEC SQL CLOSE csr114; - - rargv[0] = "HOSTACCESS"; - EXEC SQL DECLARE csr115 CURSOR FOR - SELECT name FROM machine m, hostaccess ha - WHERE m.mach_id = ha.mach_id AND ha.acl_type = :atype - AND ha.acl_id = :aid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr115; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr115 INTO :name; - if(sqlca.sqlcode != 0) break; - (*action)(2, rargv, actarg); - found++; - } - EXEC SQL CLOSE csr115; - - rargv[0] = "ZEPHYR"; - EXEC SQL DECLARE csr116 CURSOR FOR - SELECT class FROM zephyr z - WHERE z.xmt_type = :atype AND z.xmt_id = :aid - OR z.sub_type = :atype AND z.sub_id = :aid - OR z.iws_type = :atype AND z.iws_id = :aid - OR z.iui_type = :atype AND z.iui_id = :aid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr116; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr116 INTO :name; - if(sqlca.sqlcode != 0) break; - (*action)(2, rargv, actarg); - found++; - } - EXEC SQL CLOSE csr116; - - if (!found) return(MR_NO_MATCH); - return(MR_SUCCESS); -} - - -/* get_lists_of_member - given a type and a name, return the name and flags - * of all of the lists of the given member. The member_type is one of - * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0], - * and argv[1] will contain the ID of the entity in question. The R* - * types mean to recursively look at every containing list, not just - * when the object in question is a direct member. - */ - -int get_lists_of_member(q, argv, cl, action, actarg) - struct query *q; - char *argv[]; - client *cl; - int (*action)(); - int actarg; -{ - int found = 0, direct = 1; - char *rargv[6]; - EXEC SQL BEGIN DECLARE SECTION; - char *atype; - int aid, listid, id; - char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5]; - EXEC SQL END DECLARE SECTION; - - atype = argv[0]; - aid = *(int *)argv[1]; - if (!strcmp(atype, "RLIST")) { - atype = "LIST"; - direct = 0; - } - if (!strcmp(atype, "RUSER")) { - atype = "USER"; - direct = 0; - } - if (!strcmp(atype, "RSTRING")) { - atype = "STRING"; - direct = 0; - } - if (!strcmp(atype, "RKERBEROS")) { - atype = "KERBEROS"; - direct = 0; - } - - rargv[0] = name; - rargv[1] = active; - rargv[2] = public; - rargv[3] = hidden; - rargv[4] = maillist; - rargv[5] = grouplist; - if (direct) { - EXEC SQL DECLARE csr117a CURSOR FOR - SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden), - CHAR(l.maillist), CHAR(l.grouplist) - FROM list l, imembers im - WHERE l.list_id = im.list_id AND im.direct = 1 - AND im.member_type = :atype AND im.member_id = :aid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr117a; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr117a - INTO :name, :active, :public, :hidden, :maillist, :grouplist; - if(sqlca.sqlcode != 0) break; - (*action)(6, rargv, actarg); - found++; - } - EXEC SQL CLOSE csr117a; - } else { - EXEC SQL DECLARE csr117b CURSOR FOR - SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden), - CHAR(l.maillist), CHAR(l.grouplist) - FROM list l, imembers im - WHERE l.list_id = im.list_id - AND im.member_type = :atype AND im.member_id = :aid; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr117b; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr117b - INTO :name, :active, :public, :hidden, :maillist, :grouplist; - if(sqlca.sqlcode != 0) break; - (*action)(6, rargv, actarg); - found++; - } - EXEC SQL CLOSE csr117b; - } - - if (ingres_errno) return(mr_errcode); - if (!found) return(MR_NO_MATCH); - return(MR_SUCCESS); -} - - -/* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of - * the five flags associated with each list. It will return the name of - * each list that meets the quailifications. It does this by building a - * where clause based on the arguments, then doing a retrieve. - */ - -static char *lflags[5] = { "active", "publicflg", "hidden", "maillist", "grouplist" }; - -int qualified_get_lists(q, argv, cl, action, actarg) - struct query *q; - char *argv[]; - client *cl; - int (*action)(); - int actarg; -{ - return(qualified_get(q, argv, action, actarg, "l.list_id != 0", - "l", "name", lflags)); -} - - -/* get_members_of_list - this gets only direct members */ - -get_members_of_list(q, argv, cl, action, actarg) - struct query *q; - char *argv[]; - client *cl; - int (*action)(); - int actarg; -{ - return(gmol_internal(q, argv, cl, action, actarg, 1)); -} - -/* get_end_members_of_list - this gets direct or indirect members */ - -get_end_members_of_list(q, argv, cl, action, actarg) - struct query *q; - char *argv[]; - client *cl; - int (*action)(); - int actarg; -{ - return(gmol_internal(q, argv, cl, action, actarg, 0)); -} - -/** gmol_internal - optimized query for retrieval of list members - ** used by both get_members_of_list and get_end_members_of_list - ** - ** Inputs: - ** argv[0] - list_id - ** - ** Description: - ** - retrieve USER members, then LIST members, then STRING members - **/ - -gmol_internal(q, argv, cl, action, actarg, flag) - struct query *q; - char *argv[]; - client *cl; - int (*action)(); - int actarg; - int flag; -{ - EXEC SQL BEGIN DECLARE SECTION; - int list_id, member_id, direct; - char member_name[129], member_type[9]; - EXEC SQL END DECLARE SECTION; - char *targv[2]; - int members; - struct save_queue *sq; - - /* true/false flag indicates whether to display only direct members. */ - if (flag) - direct = 0; - else - direct = -1; - - list_id = *(int *)argv[0]; - members = 0; - sq = sq_create(); - - EXEC SQL DECLARE csr118 CURSOR FOR - SELECT member_type, member_id FROM imembers - WHERE list_id = :list_id AND direct > :direct; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr118; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr118 INTO :member_type, :member_id; - if (sqlca.sqlcode != 0) break; - if (members++ > 49) - break; - sq_save_data(sq, ((int)member_type[0] << 24) | (member_id & 0xffffff)); - } - EXEC SQL CLOSE csr118; - - if (members <= 49) { - targv[1] = malloc(0); - while (sq_remove_data(sq, &member_id)) { - switch (member_id >> 24) { - case 'U': - targv[0] = "USER"; - id_to_name(member_id & 0xffffff, "USER", &targv[1]); - (*action)(2, targv, actarg); - break; - case 'L': - targv[0] = "LIST"; - id_to_name(member_id & 0xffffff, "LIST", &targv[1]); - (*action)(2, targv, actarg); - break; - case 'S': - targv[0] = "STRING"; - id_to_name(member_id & 0xffffff, "STRING", &targv[1]); - (*action)(2, targv, actarg); - break; - case 'K': - targv[0] = "KERBEROS"; - id_to_name(member_id & 0xffffff, "STRING", &targv[1]); - (*action)(2, targv, actarg); - break; - default: - sq_destroy(sq); - return(MR_INTERNAL); - } + rargv[1] = name; + if (!strcmp(atype, "LIST")) { + rargv[0] = "FILESYS"; + EXEC SQL DECLARE csr110 CURSOR FOR + SELECT label FROM filesys + WHERE owners = :aid; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr110; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr110 INTO :name; + if(sqlca.sqlcode != 0) break; + (*action)(2, rargv, actarg); + found++; } - free(targv[1]); - sq_destroy(sq); - return(MR_SUCCESS); - } - sq_destroy(sq); - - targv[1] = member_name; - targv[0] = "USER"; - EXEC SQL DECLARE csr119 CURSOR FOR - SELECT u.login FROM users u, imembers im - WHERE im.list_id = :list_id AND im.member_type = 'USER' - AND im.member_id = u.users_id AND im.direct > :direct - ORDER BY 1; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr119; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr119 INTO :member_name; - if(sqlca.sqlcode != 0) break; - (*action)(2, targv, actarg); - } - EXEC SQL CLOSE csr119; - if (ingres_errno) return(mr_errcode); - - targv[0] = "LIST"; - EXEC SQL DECLARE csr120 CURSOR FOR - SELECT l.name FROM list l, imembers im - WHERE im.list_id = :list_id AND im.member_type='LIST' - AND im.member_id = l.list_id AND im.direct > :direct - ORDER BY 1; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr120; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr120 INTO :member_name; - if(sqlca.sqlcode != 0) break; - (*action)(2, targv, actarg); - } - EXEC SQL CLOSE csr120; - if (ingres_errno) return(mr_errcode); - - targv[0] = "STRING"; - EXEC SQL DECLARE csr121 CURSOR FOR - SELECT CHAR(str.string) FROM strings str, imembers im - WHERE im.list_id = :list_id AND im.member_type='STRING' - AND im.member_id = str.string_id AND im.direct > :direct - ORDER BY 1; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr121; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr121 INTO :member_name; - if(sqlca.sqlcode != 0) break; - (*action)(2, targv, actarg); - } - EXEC SQL CLOSE csr121; - if (ingres_errno) return(mr_errcode); - - targv[0] = "KERBEROS"; - EXEC SQL DECLARE csr122 CURSOR FOR - SELECT CHAR(str.string) FROM strings str, imembers im - WHERE im.list_id = :list_id AND im.member_type='KERBEROS' - AND im.member_id = str.string_id - AND im.direct > :direct - ORDER BY 1; - if (ingres_errno) - return(mr_errcode); - EXEC SQL OPEN csr122; - if (ingres_errno) - return(mr_errcode); - while(1) { - EXEC SQL FETCH csr122 INTO :member_name; - if(sqlca.sqlcode != 0) break; - (*action)(2, targv, actarg); - } - EXEC SQL CLOSE csr122; - if (ingres_errno) return(mr_errcode); - - return(MR_SUCCESS); -} - - -/* count_members_of_list: this is a simple query, but it cannot be done - * through the dispatch table. - */ - -int count_members_of_list(q, argv, cl, action, actarg) - struct query *q; - char *argv[]; - client *cl; - int (*action)(); - int actarg; -{ - EXEC SQL BEGIN DECLARE SECTION; - int list, ct = 0; - EXEC SQL END DECLARE SECTION; - char *rargv[1], countbuf[5]; - - list = *(int *)argv[0]; - rargv[0] = countbuf; - EXEC SQL REPEATED SELECT count (*) INTO :ct FROM imembers - WHERE list_id = :list AND direct=1; - if (ingres_errno) return(mr_errcode); - sprintf(countbuf, "%d", ct); - (*action)(1, rargv, actarg); - return(MR_SUCCESS); -} - - -/* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of - * the three flags associated with each service. It will return the name of - * each service that meets the quailifications. It does this by building a - * where clause based on the arguments, then doing a retrieve. - */ - -static char *sflags[3] = { "enable", "inprogress", "harderror" }; - -int qualified_get_server(q, argv, cl, action, actarg) - struct query *q; - char *argv[]; - client *cl; - int (*action)(); - int actarg; -{ - return(qualified_get(q, argv, action, actarg, "s.name != ''", - "s", "name", sflags)); -} - - -/* generic qualified get routine, used by qualified_get_lists, - * qualified_get_server, and qualified_get_serverhost. - * Args: - * start - a simple where clause, must not be empty - * range - the name of the range variable - * field - the field to return - * flags - an array of strings, names of the flag variables - */ - -int qualified_get(q, argv, action, actarg, start, range, field, flags) - struct query *q; - char *argv[]; - int (*action)(); - int actarg; - char *start; - char *range; - char *field; - char *flags[]; -{ - char name[33], qual[256]; - int rowcount=0, i; - char *rargv[1], buf[32]; + EXEC SQL CLOSE csr110; - strcpy(qual, start); - for (i = 0; i < q->argc; i++) { - if (!strcmp(argv[i], "TRUE")) { - sprintf(buf, " AND %s.%s != 0", range, flags[i]); - (void) strcat(qual, buf); - } else if (!strcmp(argv[i], "FALSE")) { - sprintf(buf, " AND %s.%s = 0", range, flags[i]); - (void) strcat(qual, buf); + rargv[0] = "QUERY"; + EXEC SQL DECLARE csr111 CURSOR FOR + SELECT capability FROM capacls + WHERE list_id = :aid ; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr111; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr111 INTO :name ; + if(sqlca.sqlcode != 0) break; + (*action)(2, rargv, actarg); + found++; } - } - - rargv[0] = SQLDA->sqlvar[0].sqldata; - sprintf(stmt_buf,"SELECT CHAR(%s.%s) FROM %s %s WHERE %s",range,field,q->rtable,range,qual); - EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf; - if(sqlca.sqlcode) - return(MR_INTERNAL); - EXEC SQL DECLARE csr123 CURSOR FOR stmt; - EXEC SQL OPEN csr123; - while(1) { - EXEC SQL FETCH csr123 USING DESCRIPTOR :SQLDA; - if(sqlca.sqlcode != 0) break; - rowcount++; - (*action)(1, rargv, actarg); - } - EXEC SQL CLOSE csr123; - if (ingres_errno) return(mr_errcode); - if (rowcount == 0) - return(MR_NO_MATCH); - return(MR_SUCCESS); -} - - -/* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of - * the five flags associated with each serverhost. It will return the name of - * each service and host that meets the quailifications. It does this by - * building a where clause based on the arguments, then doing a retrieve. - */ - -static char *shflags[6] = { "service", "enable", "override", "success", - "inprogress", "hosterror" }; - -int qualified_get_serverhost(q, argv, cl, action, actarg) - struct query *q; - char *argv[]; - client *cl; - int (*action)(); - int actarg; -{ - EXEC SQL BEGIN DECLARE SECTION; - char sname[33], mname[33], qual[256]; - EXEC SQL END DECLARE SECTION; - char *rargv[2], buf[32]; - int i, rowcount; - - sprintf(qual, "m.mach_id = sh.mach_id AND sh.service = uppercase('%s')", - argv[0]); - for (i = 1; i < q->argc; i++) { - if (!strcmp(argv[i], "TRUE")) { - sprintf(buf, " AND sh.%s != 0", shflags[i]); - strcat(qual, buf); - } else if (!strcmp(argv[i], "FALSE")) { - sprintf(buf, " AND sh.%s = 0", shflags[i]); - strcat(qual, buf); + EXEC SQL CLOSE csr111; + } else if (!strcmp(atype, "USER")) { + rargv[0] = "FILESYS"; + EXEC SQL DECLARE csr112 CURSOR FOR + SELECT label FROM filesys + WHERE owner = :aid; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr112; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr112 INTO :name ; + if(sqlca.sqlcode != 0) break; + (*action)(2, rargv, actarg); + found++; } + EXEC SQL CLOSE csr112; } - rargv[0] = sname; - rargv[1] = mname; - EXEC SQL DECLARE csr124 CURSOR FOR - SELECT sh.service, m.name FROM serverhosts sh, machine m - WHERE :qual; + rargv[0] = "LIST"; + EXEC SQL DECLARE csr113 CURSOR FOR + SELECT name FROM list + WHERE acl_type = :atype AND acl_id = :aid; if (ingres_errno) return(mr_errcode); - EXEC SQL OPEN csr124; + EXEC SQL OPEN csr113; if (ingres_errno) return(mr_errcode); while(1) { - EXEC SQL FETCH csr124 INTO :sname, :mname; + EXEC SQL FETCH csr113 INTO :name; if(sqlca.sqlcode != 0) break; - rowcount++; (*action)(2, rargv, actarg); + found++; } - EXEC SQL CLOSE csr124; - - if (ingres_errno) return(mr_errcode); - if (rowcount == 0) - return(MR_NO_MATCH); - return(MR_SUCCESS); -} - - -/* register_user - change user's login name and allocate a pobox, group, - * filesystem, and quota for them. The user's status must start out as 0, - * and is left as 2. Arguments are: user's UID, new login name, and user's - * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY, - * MR_FS_STAFF, MR_FS_MISC). - */ - -register_user(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ - EXEC SQL BEGIN DECLARE SECTION; - char *login, dir[65], *entity, directory[129], machname[33]; - int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota; - int size, alloc, pid, ostatus, nstatus, gidval, fsidval, npidval; - static int m_id = 0, def_quota = 0; - EXEC SQL END DECLARE SECTION; - char buffer[256], *aargv[3]; - - entity = cl->entity; - who = cl->client_id; - - uid = atoi(argv[0]); - login = argv[1]; - utype = atoi(argv[2]); - - /* find user */ - EXEC SQL REPEATED SELECT users_id, status INTO :users_id, :ostatus - FROM users - WHERE uid = :uid AND (status=0 OR status=5 OR status=6); - - if (sqlca.sqlerrd[2] == 0) - return(MR_NO_MATCH); - if (sqlca.sqlerrd[2] > 1) - return(MR_NOT_UNIQUE); - - /* check new login name */ - EXEC SQL REPEATED SELECT COUNT(login) INTO :rowcount FROM users - WHERE login = :login AND users_id != :users_id; - if (ingres_errno) return(mr_errcode); - if (rowcount > 0) return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(name) INTO :rowcount FROM list - WHERE name = :login; - if (ingres_errno) return(mr_errcode); - if (rowcount > 0) return(MR_IN_USE); - EXEC SQL REPEATED SELECT COUNT(label) INTO :rowcount FROM filesys - WHERE label = :login; - if (ingres_errno) return(mr_errcode); - if (rowcount > 0) return(MR_IN_USE); - com_err(whoami, 0, "login name OK"); + EXEC SQL CLOSE csr113; - /* choose place for pobox, put in mid */ - EXEC SQL DECLARE csr130 CURSOR FOR - SELECT sh.mach_id, m.name FROM serverhosts sh, machine m - WHERE sh.service='POP' AND sh.mach_id=m.mach_id - AND sh.value2 - sh.value1 = - (SELECT MAX(value2 - value1) FROM serverhosts - WHERE service = 'POP'); + rargv[0] = "SERVICE"; + EXEC SQL DECLARE csr114 CURSOR FOR + SELECT name FROM servers + WHERE acl_type = :atype AND acl_id = :aid; if (ingres_errno) return(mr_errcode); - EXEC SQL OPEN csr130; + EXEC SQL OPEN csr114; if (ingres_errno) return(mr_errcode); - EXEC SQL FETCH csr130 INTO :mid, :machname; - if (sqlca.sqlerrd[2] == 0) { - EXEC SQL CLOSE csr130; - if (ingres_errno) return(mr_errcode); - return(MR_NO_POBOX); - } else { - EXEC SQL CLOSE csr130; - if (ingres_errno) return(mr_errcode); - } - - /* change login name, set pobox */ - sprintf(buffer, "u.users_id = %d", users_id); - incremental_before("users", buffer, 0); - nstatus = 2; - if (ostatus == 5 || ostatus == 6) - nstatus = 1; - EXEC SQL REPEATED UPDATE users SET login = :login, status = :nstatus, - modtime='now', modby = :who, modwith = :entity, potype='POP', - pop_id = :mid, pmodtime='now', pmodby = :who, pmodwith = :entity - WHERE users_id = :users_id; - - if (ingres_errno) return(mr_errcode); - if (sqlca.sqlerrd[2] != 1) - return(MR_INTERNAL); - set_pop_usage(mid, 1); - com_err(whoami, 0, "set login name to %s and pobox to %s", login, - strtrim(machname)); - incremental_after("users", buffer, 0); - - /* create group list */ - if (set_next_object_id("gid", "list", 1)) - return(MR_NO_ID); - if (set_next_object_id("list_id", "list", 0)) - return(MR_NO_ID); - EXEC SQL REPEATED SELECT value INTO :list_id FROM numvalues - WHERE name='list_id'; - if (ingres_errno) return(mr_errcode); - if (sqlca.sqlerrd[2] != 1) - return(MR_INTERNAL); - incremental_clear_before(); - EXEC SQL SELECT value INTO :gidval FROM numvalues WHERE name = 'gid'; - EXEC SQL REPEATED INSERT INTO list - (name, list_id, active, publicflg, hidden, maillist, grouplist, - gid, description, acl_type, acl_id, - modtime, modby, modwith) - VALUES (:login, :list_id, 1, 0, 0, 0, 1, - :gidval, 'User Group', 'USER', :users_id, - 'now', :who, :entity); - if (ingres_errno) return(mr_errcode); - if (sqlca.sqlerrd[2] != 1) - return(MR_INTERNAL); - sprintf(buffer, "l.list_id = %d", list_id); - incremental_after("list", buffer, 0); - aargv[0] = (char *) list_id; - aargv[1] = "USER"; - aargv[2] = (char *) users_id; - incremental_clear_before(); - EXEC SQL REPEATED INSERT INTO imembers - (list_id, member_type, member_id, ref_count, direct) - VALUES (:list_id, 'USER', :users_id, 1, 1); - if (ingres_errno) return(mr_errcode); - if (sqlca.sqlerrd[2] != 1) - return(MR_INTERNAL); - incremental_after("members", 0, aargv); - - if (m_id == 0) { - /* Cell Name (I know, it shouldn't be hard coded...) */ - strcpy(machname, "ATHENA.MIT.EDU"); - EXEC SQL SELECT mach_id INTO :m_id FROM machine - WHERE name = :machname; - } - - /* create filesystem */ - if (set_next_object_id("filsys_id", "filesys", 0)) - return(MR_NO_ID); - incremental_clear_before(); - if (islower(login[0]) && islower(login[1])) { - sprintf(directory, "/afs/athena.mit.edu/user/%c/%c/%s", - login[0], login[1], login); - } else { - sprintf(directory, "/afs/athena.mit.edu/user/other/%s", login); + while(1) { + EXEC SQL FETCH csr114 INTO :name; + if(sqlca.sqlcode != 0) break; + (*action)(2, rargv, actarg); + found++; } - - EXEC SQL SELECT value INTO :fsidval FROM numvalues - WHERE numvalues.name='filsys_id'; - EXEC SQL REPEATED INSERT INTO filesys - (filsys_id, phys_id, label, type, mach_id, name, - mount, access, comments, owner, owners, createflg, - lockertype, modtime, modby, modwith) - VALUES - (:fsidval, 0, :login, 'AFS', :m_id, :directory, - '/mit/'+:login, 'w', 'User Locker', :users_id, :list_id, 1, - 'HOMEDIR', 'now', :who, :entity); - - if (ingres_errno) return(mr_errcode); - if (sqlca.sqlerrd[2] != 1) - return(MR_INTERNAL); - sprintf(buffer,"fs.filsys_id = %d",fsidval); - incremental_after("filesys", buffer, 0); + EXEC SQL CLOSE csr114; - /* set quota */ - if (def_quota == 0) { - EXEC SQL REPEATED SELECT value INTO :def_quota FROM numvalues - WHERE name='def_quota'; - if (ingres_errno) return(mr_errcode); - if (sqlca.sqlerrd[2] != 1) - return(MR_NO_QUOTA); - + rargv[0] = "HOSTACCESS"; + EXEC SQL DECLARE csr115 CURSOR FOR + SELECT name FROM machine m, hostaccess ha + WHERE m.mach_id = ha.mach_id AND ha.acl_type = :atype + AND ha.acl_id = :aid; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr115; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr115 INTO :name; + if(sqlca.sqlcode != 0) break; + (*action)(2, rargv, actarg); + found++; } - incremental_clear_before(); - EXEC SQL REPEATED INSERT INTO quota - (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith) - VALUES - (0, :fsidval, 'ANY', :def_quota, 0, 'now', :who, :entity); - if (ingres_errno) return(mr_errcode); - if (sqlca.sqlerrd[2] != 1) - return(MR_INTERNAL); - aargv[0] = login; - aargv[1] = "ANY"; - aargv[2] = login; - sprintf(buffer, "q.entity_id = 0 and q.filsys_id = %d and q.type = 'ANY'", fsidval); - incremental_after("quota", buffer, aargv); - com_err(whoami, 0, "quota of %d assigned", def_quota); - if (ingres_errno) return(mr_errcode); + EXEC SQL CLOSE csr115; - cache_entry(login, "USER", users_id); + rargv[0] = "ZEPHYR"; + EXEC SQL DECLARE csr116 CURSOR FOR + SELECT class FROM zephyr z + WHERE z.xmt_type = :atype AND z.xmt_id = :aid + OR z.sub_type = :atype AND z.sub_id = :aid + OR z.iws_type = :atype AND z.iws_id = :aid + OR z.iui_type = :atype AND z.iui_id = :aid; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr116; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr116 INTO :name; + if(sqlca.sqlcode != 0) break; + (*action)(2, rargv, actarg); + found++; + } + EXEC SQL CLOSE csr116; - EXEC SQL REPEATED UPDATE tblstats SET updates=updates+1, modtime='now' - WHERE table_name='users'; - EXEC SQL REPEATED UPDATE tblstats SET appends=appends+1, modtime='now' - WHERE table_name='list' OR table_name='filesys' OR table_name='quota'; - if (ingres_errno) return(mr_errcode); + if (!found) return(MR_NO_MATCH); return(MR_SUCCESS); } +/* get_lists_of_member - given a type and a name, return the name and flags + * of all of the lists of the given member. The member_type is one of + * "LIST", "USER", "STRING", "RLIST", "RUSER", or "RSTRING" in argv[0], + * and argv[1] will contain the ID of the entity in question. The R* + * types mean to recursively look at every containing list, not just + * when the object in question is a direct member. + */ -/** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe - ** - ** Inputs: - ** id of machine - ** delta (will be +/- 1) - ** - ** Description: - ** - incr/decr value field in serverhosts table for pop/mach_id - ** - **/ - -static int set_pop_usage(id, cnt) +int get_lists_of_member(q, argv, cl, action, actarg) + struct query *q; + char *argv[]; + client *cl; + int (*action)(); + int actarg; +{ + int found = 0, direct = 1; + char *rargv[6]; EXEC SQL BEGIN DECLARE SECTION; - int id; - int cnt; + char *atype; + int aid, listid, id; + char name[33], active[5], public[5], hidden[5], maillist[5], grouplist[5]; EXEC SQL END DECLARE SECTION; -{ - EXEC SQL REPEATED UPDATE serverhosts SET value1 = value1 + :cnt - WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :id; - if (ingres_errno) return(mr_errcode); - return(MR_SUCCESS); -} + atype = argv[0]; + aid = *(int *)argv[1]; + if (!strcmp(atype, "RLIST")) { + atype = "LIST"; + direct = 0; + } + if (!strcmp(atype, "RUSER")) { + atype = "USER"; + direct = 0; + } + if (!strcmp(atype, "RSTRING")) { + atype = "STRING"; + direct = 0; + } + if (!strcmp(atype, "RKERBEROS")) { + atype = "KERBEROS"; + direct = 0; + } -int _sdl_followup(q, argv, cl) - struct query *q; - char **argv; - client *cl; -{ - int i; - i = atoi(argv[0]); - log_flags = i; - if (i & LOG_SQL) { - EXEC SQL set printqry; + rargv[0] = name; + rargv[1] = active; + rargv[2] = public; + rargv[3] = hidden; + rargv[4] = maillist; + rargv[5] = grouplist; + if (direct) { + EXEC SQL DECLARE csr117a CURSOR FOR + SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden), + CHAR(l.maillist), CHAR(l.grouplist) + FROM list l, imembers im + WHERE l.list_id = im.list_id AND im.direct = 1 + AND im.member_type = :atype AND im.member_id = :aid; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr117a; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr117a + INTO :name, :active, :public, :hidden, :maillist, :grouplist; + if(sqlca.sqlcode != 0) break; + (*action)(6, rargv, actarg); + found++; + } + EXEC SQL CLOSE csr117a; } else { - EXEC SQL set noprintqry; + EXEC SQL DECLARE csr117b CURSOR FOR + SELECT l.name, CHAR(l.active), CHAR(l.publicflg), CHAR(l.hidden), + CHAR(l.maillist), CHAR(l.grouplist) + FROM list l, imembers im + WHERE l.list_id = im.list_id + AND im.member_type = :atype AND im.member_id = :aid; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr117b; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr117b + INTO :name, :active, :public, :hidden, :maillist, :grouplist; + if(sqlca.sqlcode != 0) break; + (*action)(6, rargv, actarg); + found++; + } + EXEC SQL CLOSE csr117b; } + + if (ingres_errno) return(mr_errcode); + if (!found) return(MR_NO_MATCH); return(MR_SUCCESS); } - -/* Validation Routines */ +/* qualified_get_lists: passed "TRUE", "FALSE", or "DONTCARE" for each of + * the five flags associated with each list. It will return the name of + * each list that meets the quailifications. It does this by building a + * where clause based on the arguments, then doing a retrieve. + */ + +static char *lflags[5] = { "active", "publicflg", "hidden", "maillist", "grouplist" }; -validate_row(q, argv, v) - register struct query *q; +int qualified_get_lists(q, argv, cl, action, actarg) + struct query *q; char *argv[]; - register struct validate *v; + client *cl; + int (*action)(); + int actarg; { - EXEC SQL BEGIN DECLARE SECTION; - char *name; - char qual[128]; - int rowcount; - EXEC SQL END DECLARE SECTION; - - /* build where clause */ - build_qual(v->qual, v->argc, argv, qual); - - if (log_flags & LOG_VALID) - /* tell the logfile what we're doing */ - com_err(whoami, 0, "validating row: %s", qual); + return(qualified_get(q, argv, action, actarg, "l.list_id != 0", + "l", "name", lflags)); +} - /* look for the record */ - sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s",q->rtable,qual); - EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf; - if(sqlca.sqlcode) - return(MR_INTERNAL); - EXEC SQL DECLARE csr126 CURSOR FOR stmt; - EXEC SQL OPEN csr126; - EXEC SQL FETCH csr126 USING DESCRIPTOR :SQLDA; - EXEC SQL CLOSE csr126; - rowcount = *(int *)SQLDA->sqlvar[0].sqldata; - if (ingres_errno) return(mr_errcode); - if (rowcount == 0) return(MR_NO_MATCH); - if (rowcount > 1) return(MR_NOT_UNIQUE); - return(MR_EXISTS); +/* get_members_of_list - this gets only direct members */ + +get_members_of_list(q, argv, cl, action, actarg) + struct query *q; + char *argv[]; + client *cl; + int (*action)(); + int actarg; +{ + return(gmol_internal(q, argv, cl, action, actarg, 1)); } - -validate_fields(q, argv, vo, n) + +/* get_end_members_of_list - this gets direct or indirect members */ + +get_end_members_of_list(q, argv, cl, action, actarg) struct query *q; - register char *argv[]; - register struct valobj *vo; - register int n; + char *argv[]; + client *cl; + int (*action)(); + int actarg; { - register int status; - - while (--n >= 0) { - switch (vo->type) { - case V_NAME: - if (log_flags & LOG_VALID) - com_err(whoami, 0, "validating %s in %s: %s", - vo->namefield, vo->table, argv[vo->index]); - status = validate_name(argv, vo); - break; - - case V_ID: - if (log_flags & LOG_VALID) - com_err(whoami, 0, "validating %s in %s: %s", - vo->idfield, vo->table, argv[vo->index]); - status = validate_id(q, argv, vo); - break; - - case V_DATE: - if (log_flags & LOG_VALID) - com_err(whoami, 0, "validating date: %s", argv[vo->index]); - status = validate_date(argv, vo); - break; - - case V_TYPE: - if (log_flags & LOG_VALID) - com_err(whoami, 0, "validating %s type: %s", - vo->table, argv[vo->index]); - status = validate_type(argv, vo); - break; - - case V_TYPEDATA: - if (log_flags & LOG_VALID) - com_err(whoami, 0, "validating typed data (%s): %s", - argv[vo->index - 1], argv[vo->index]); - status = validate_typedata(q, argv, vo); - break; - - case V_RENAME: - if (log_flags & LOG_VALID) - com_err(whoami, 0, "validating rename %s in %s", - argv[vo->index], vo->table); - status = validate_rename(argv, vo); - break; - - case V_CHAR: - if (log_flags & LOG_VALID) - com_err(whoami, 0, "validating chars: %s", argv[vo->index]); - status = validate_chars(argv[vo->index]); - break; + return(gmol_internal(q, argv, cl, action, actarg, 0)); +} + +/** gmol_internal - optimized query for retrieval of list members + ** used by both get_members_of_list and get_end_members_of_list + ** + ** Inputs: + ** argv[0] - list_id + ** + ** Description: + ** - retrieve USER members, then LIST members, then STRING members + **/ - case V_SORT: - status = MR_EXISTS; - break; +gmol_internal(q, argv, cl, action, actarg, flag) + struct query *q; + char *argv[]; + client *cl; + int (*action)(); + int actarg; + int flag; +{ + EXEC SQL BEGIN DECLARE SECTION; + int list_id, member_id, direct; + char member_name[129], member_type[9]; + EXEC SQL END DECLARE SECTION; + char *targv[2]; + int members; + struct save_queue *sq; - case V_LOCK: - status = lock_table(vo); - break; + /* true/false flag indicates whether to display only direct members. */ + if (flag) + direct = 0; + else + direct = -1; - case V_WILD: - status = convert_wildcards(argv[vo->index]); - break; + list_id = *(int *)argv[0]; + members = 0; + sq = sq_create(); - case V_UPWILD: - status = convert_wildcards_uppercase(argv[vo->index]); - break; + EXEC SQL DECLARE csr118 CURSOR FOR + SELECT member_type, member_id FROM imembers + WHERE list_id = :list_id AND direct > :direct; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr118; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr118 INTO :member_type, :member_id; + if (sqlca.sqlcode != 0) break; + if (members++ > 49) + break; + sq_save_data(sq, ((int)member_type[0] << 24) | (member_id & 0xffffff)); + } + EXEC SQL CLOSE csr118; + if (members <= 49) { + targv[1] = malloc(0); + while (sq_remove_data(sq, &member_id)) { + switch (member_id >> 24) { + case 'U': + targv[0] = "USER"; + id_to_name(member_id & 0xffffff, "USER", &targv[1]); + (*action)(2, targv, actarg); + break; + case 'L': + targv[0] = "LIST"; + id_to_name(member_id & 0xffffff, "LIST", &targv[1]); + (*action)(2, targv, actarg); + break; + case 'S': + targv[0] = "STRING"; + id_to_name(member_id & 0xffffff, "STRING", &targv[1]); + (*action)(2, targv, actarg); + break; + case 'K': + targv[0] = "KERBEROS"; + id_to_name(member_id & 0xffffff, "STRING", &targv[1]); + (*action)(2, targv, actarg); + break; + default: + sq_destroy(sq); + return(MR_INTERNAL); + } } + free(targv[1]); + sq_destroy(sq); + return(MR_SUCCESS); + } + sq_destroy(sq); - if (status != MR_EXISTS) return(status); - vo++; + targv[1] = member_name; + targv[0] = "USER"; + EXEC SQL DECLARE csr119 CURSOR FOR + SELECT u.login FROM users u, imembers im + WHERE im.list_id = :list_id AND im.member_type = 'USER' + AND im.member_id = u.users_id AND im.direct > :direct + ORDER BY 1; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr119; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr119 INTO :member_name; + if(sqlca.sqlcode != 0) break; + (*action)(2, targv, actarg); } - + EXEC SQL CLOSE csr119; if (ingres_errno) return(mr_errcode); - return(MR_SUCCESS); -} - - -/* validate_chars: verify that there are no illegal characters in - * the string. Legal characters are printing chars other than - * ", *, ?, \, [ and ]. - */ -static int illegalchars[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */ - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -}; - -validate_chars(s) -register char *s; -{ - while (*s) - if (illegalchars[*s++]) - return(MR_BAD_CHAR); - return(MR_EXISTS); -} - - -validate_id(q, argv, vo) - struct query *q; - char *argv[]; - register struct valobj *vo; -{ - EXEC SQL BEGIN DECLARE SECTION; - char *name, *tbl, *namefield, *idfield; - int id, rowcount; - EXEC SQL END DECLARE SECTION; - int status; - register char *c; - name = argv[vo->index]; - tbl = vo->table; - namefield = vo->namefield; - idfield = vo->idfield; - - if ((!strcmp(tbl, "users") && !strcmp(namefield, "login")) || - !strcmp(tbl, "machine") || - !strcmp(tbl, "filesys") || - !strcmp(tbl, "list") || - !strcmp(tbl, "cluster") || - !strcmp(tbl, "strings")) { - if (!strcmp(tbl, "machine")) - for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c); - status = name_to_id(name, tbl, &id); - if (status == 0) { - *(int *)argv[vo->index] = id; - return(MR_EXISTS); - } else if (status == MR_NO_MATCH && !strcmp(tbl, "strings") && - (q->type == APPEND || q->type == UPDATE)) { - id=add_string(name); - cache_entry(name, "STRING", id); - *(int *)argv[vo->index] = id; - return(MR_EXISTS); - } else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE) - return(vo->error); - else - return(status); + targv[0] = "LIST"; + EXEC SQL DECLARE csr120 CURSOR FOR + SELECT l.name FROM list l, imembers im + WHERE im.list_id = :list_id AND im.member_type='LIST' + AND im.member_id = l.list_id AND im.direct > :direct + ORDER BY 1; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr120; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr120 INTO :member_name; + if(sqlca.sqlcode != 0) break; + (*action)(2, targv, actarg); } + EXEC SQL CLOSE csr120; + if (ingres_errno) return(mr_errcode); - if (!strcmp(namefield, "uid")) { - sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = %s",idfield,tbl,namefield,name); - } else { - sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = '%s'",idfield,tbl,namefield,name); - } - EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf; - if(sqlca.sqlcode) - return(MR_INTERNAL); - EXEC SQL DECLARE csr127 CURSOR FOR stmt; - EXEC SQL OPEN csr127; - rowcount=0; - EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA; - if(sqlca.sqlcode == 0) { - rowcount++; - EXEC SQL FETCH csr127 USING DESCRIPTOR :SQLDA; - if(sqlca.sqlcode == 0) rowcount++; - } - EXEC SQL CLOSE csr127; + targv[0] = "STRING"; + EXEC SQL DECLARE csr121 CURSOR FOR + SELECT CHAR(str.string) FROM strings str, imembers im + WHERE im.list_id = :list_id AND im.member_type='STRING' + AND im.member_id = str.string_id AND im.direct > :direct + ORDER BY 1; if (ingres_errno) - return(mr_errcode); - - if (rowcount != 1) return(vo->error); - bcopy(SQLDA->sqlvar[0].sqldata,argv[vo->index],sizeof(int)); - return(MR_EXISTS); -} - -validate_name(argv, vo) - char *argv[]; - register struct valobj *vo; -{ - EXEC SQL BEGIN DECLARE SECTION; - char *name, *tbl, *namefield; - int rowcount; - EXEC SQL END DECLARE SECTION; - register char *c; - - name = argv[vo->index]; - tbl = vo->table; - namefield = vo->namefield; - if (!strcmp(tbl, "servers") && !strcmp(namefield, "name")) { - for (c = name; *c; c++) - if (islower(*c)) - *c = toupper(*c); + return(mr_errcode); + EXEC SQL OPEN csr121; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr121 INTO :member_name; + if(sqlca.sqlcode != 0) break; + (*action)(2, targv, actarg); } - sprintf(stmt_buf,"SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'", - tbl,tbl,namefield,name); - EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf; - if(sqlca.sqlcode) - return(MR_INTERNAL); - EXEC SQL DECLARE csr128 CURSOR FOR stmt; - EXEC SQL OPEN csr128; - EXEC SQL FETCH csr128 USING DESCRIPTOR :SQLDA; - rowcount = *(int *)SQLDA->sqlvar[0].sqldata; - EXEC SQL CLOSE csr128; - + EXEC SQL CLOSE csr121; if (ingres_errno) return(mr_errcode); - return ((rowcount == 1) ? MR_EXISTS : vo->error); -} - -validate_date(argv, vo) - char *argv[]; - struct valobj *vo; -{ - EXEC SQL BEGIN DECLARE SECTION; - char *idate; - double dd; - int errorno; - EXEC SQL END DECLARE SECTION; - idate = argv[vo->index]; - EXEC SQL SELECT interval('years',date(:idate)-date('today')) INTO :dd; + targv[0] = "KERBEROS"; + EXEC SQL DECLARE csr122 CURSOR FOR + SELECT CHAR(str.string) FROM strings str, imembers im + WHERE im.list_id = :list_id AND im.member_type='KERBEROS' + AND im.member_id = str.string_id + AND im.direct > :direct + ORDER BY 1; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr122; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr122 INTO :member_name; + if(sqlca.sqlcode != 0) break; + (*action)(2, targv, actarg); + } + EXEC SQL CLOSE csr122; + if (ingres_errno) return(mr_errcode); - if (sqlca.sqlcode != 0 || dd > 5.0) return(MR_DATE); - return(MR_EXISTS); + return(MR_SUCCESS); } -validate_rename(argv, vo) -char *argv[]; -struct valobj *vo; -{ - EXEC SQL BEGIN DECLARE SECTION; - char *name, *tbl, *namefield, *idfield; - int id; - EXEC SQL END DECLARE SECTION; - int status; - register char *c; - - c = name = argv[vo->index]; - while (*c) - if (illegalchars[*c++]) - return(MR_BAD_CHAR); - tbl = vo->table; - /* minor kludge to upcasify machine names */ - if (!strcmp(tbl, "machine")) - for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c); - namefield = vo->namefield; - idfield = vo->idfield; - id = -1; - if (idfield == 0) { - if (!strcmp(argv[vo->index], argv[vo->index - 1])) - return(MR_EXISTS); - sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s = LEFT('%s',SIZE(%s))", - namefield,tbl,namefield,name,namefield); - EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf; - if(sqlca.sqlcode) - return(MR_INTERNAL); - EXEC SQL DECLARE csr129 CURSOR FOR stmt; - EXEC SQL OPEN csr129; - EXEC SQL FETCH csr129 USING DESCRIPTOR :SQLDA; - if(sqlca.sqlcode == 0) id=1; else id=0; - EXEC SQL CLOSE csr129; - - if (ingres_errno) return(mr_errcode); - if (id) - return(vo->error); - else - return(MR_EXISTS); - } - status = name_to_id(name, tbl, &id); - if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1]) - return(MR_EXISTS); - else - return(vo->error); -} - +/* count_members_of_list: this is a simple query, but it cannot be done + * through the dispatch table. + */ -validate_type(argv, vo) +int count_members_of_list(q, argv, cl, action, actarg) + struct query *q; char *argv[]; - register struct valobj *vo; + client *cl; + int (*action)(); + int actarg; { EXEC SQL BEGIN DECLARE SECTION; - char *typename; - char *val; - int cnt; + int list, ct = 0; EXEC SQL END DECLARE SECTION; - register char *c; - - typename = vo->table; - c = val = argv[vo->index]; - while (*c) { - if (illegalchars[*c++]) - return(MR_BAD_CHAR); - } - - /* uppercase type fields */ - for (c = val; *c; c++) if (islower(*c)) *c = toupper(*c); + char *rargv[1], countbuf[5]; - EXEC SQL SELECT COUNT(trans) INTO :cnt FROM alias - WHERE name = :typename AND type='TYPE' AND trans = :val; + list = *(int *)argv[0]; + rargv[0] = countbuf; + EXEC SQL REPEATED SELECT count (*) INTO :ct FROM imembers + WHERE list_id = :list AND direct=1; if (ingres_errno) return(mr_errcode); - return (cnt ? MR_EXISTS : vo->error); + sprintf(countbuf, "%d", ct); + (*action)(1, rargv, actarg); + return(MR_SUCCESS); } -/* validate member or type-specific data field */ - -validate_typedata(q, argv, vo) - register struct query *q; - register char *argv[]; - register struct valobj *vo; -{ - EXEC SQL BEGIN DECLARE SECTION; - char *name; - char *field_type; - char data_type[129]; - int id; - EXEC SQL END DECLARE SECTION; - int status; - char *index(); - register char *c; - - /* get named object */ - name = argv[vo->index]; - - /* get field type string (known to be at index-1) */ - field_type = argv[vo->index-1]; - - /* get corresponding data type associated with field type name */ - EXEC SQL SELECT trans INTO :data_type FROM alias - WHERE name = :field_type AND type='TYPEDATA'; - if (ingres_errno) return(mr_errcode); - if (sqlca.sqlerrd[2] != 1) return(MR_TYPE); - - /* now retrieve the record id corresponding to the named object */ - if (index(data_type, ' ')) - *index(data_type, ' ') = 0; - if (!strcmp(data_type, "user")) { - /* USER */ - if (index(name, '@')) - return(MR_USER); - status = name_to_id(name, data_type, &id); - if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)) - return(MR_USER); - if (status) return(status); - } else if (!strcmp(data_type, "list")) { - /* LIST */ - status = name_to_id(name, data_type, &id); - if (status && status == MR_NOT_UNIQUE) - return(MR_LIST); - if (status == MR_NO_MATCH) { - /* if idfield is non-zero, then if argv[0] matches the string - * that we're trying to resolve, we should get the value of - * numvalues.[idfield] for the id. - */ - if (vo->idfield && !strcmp(argv[0], argv[vo->index])) { - set_next_object_id(q->validate->object_id, q->rtable, 0); - name = vo->idfield; - EXEC SQL REPEATED SELECT value INTO :id FROM numvalues - WHERE name = :name; - if (sqlca.sqlerrd[2] != 1) return(MR_LIST); - } else - return(MR_LIST); - } else if (status) return(status); - } else if (!strcmp(data_type, "machine")) { - /* MACHINE */ - for (c = name; *c; c++) if (islower(*c)) *c = toupper(*c); - status = name_to_id(name, data_type, &id); - if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)) - return(MR_MACHINE); - if (status) return(status); - } else if (!strcmp(data_type, "string")) { - /* STRING */ - status = name_to_id(name, data_type, &id); - if (status && status == MR_NOT_UNIQUE) - return(MR_STRING); - if (status == MR_NO_MATCH) { - if (q->type != APPEND && q->type != UPDATE) return(MR_STRING); - id=add_string(name); - cache_entry(name, "STRING", id); - } else if (status) return(status); - } else if (!strcmp(data_type, "none")) { - id = 0; - } else { - return(MR_TYPE); - } - - /* now set value in argv */ - *(int *)argv[vo->index] = id; - - return (MR_EXISTS); -} +/* qualified_get_server: passed "TRUE", "FALSE", or "DONTCARE" for each of + * the three flags associated with each service. It will return the name of + * each service that meets the quailifications. It does this by building a + * where clause based on the arguments, then doing a retrieve. + */ -/* Lock the table named by the validation object */ +static char *sflags[3] = { "enable", "inprogress", "harderror" }; -lock_table(vo) -struct valobj *vo; +int qualified_get_server(q, argv, cl, action, actarg) + struct query *q; + char *argv[]; + client *cl; + int (*action)(); + int actarg; { - sprintf(stmt_buf,"UPDATE %s SET modtime='now' WHERE %s.%s = 0", - vo->table,vo->table,vo->idfield); - EXEC SQL EXECUTE IMMEDIATE :stmt_buf; - if (ingres_errno) return(mr_errcode); - if (sqlca.sqlerrd[2] != 1) - return(vo->error); - else - return(MR_EXISTS); + return(qualified_get(q, argv, action, actarg, "s.name != ''", + "s", "name", sflags)); } -/* Check the database at startup time. For now this just resets the - * inprogress flags that the DCM uses. +/* generic qualified get routine, used by qualified_get_lists, + * qualified_get_server, and qualified_get_serverhost. + * Args: + * start - a simple where clause, must not be empty + * range - the name of the range variable + * field - the field to return + * flags - an array of strings, names of the flag variables */ -sanity_check_database() -{ -} - - -/* Dynamic SQL support routines */ -MR_SQLDA_T *mr_alloc_SQLDA() +int qualified_get(q, argv, action, actarg, start, range, field, flags) + struct query *q; + char *argv[]; + int (*action)(); + int actarg; + char *start; + char *range; + char *field; + char *flags[]; { - MR_SQLDA_T *it; - short *null_indicators; - register int j; - - if((it=(MR_SQLDA_T *)malloc(sizeof(MR_SQLDA_T)))==NULL) { - com_err(whoami, MR_NO_MEM, "setting up SQLDA"); - exit(1); - } + char name[33], qual[256]; + int rowcount=0, i; + char *rargv[1], buf[32]; - if((null_indicators=(short *)calloc(QMAXARGS,sizeof(short)))==NULL) { - com_err(whoami, MR_NO_MEM, "setting up SQLDA null indicators"); - exit(1); + strcpy(qual, start); + for (i = 0; i < q->argc; i++) { + if (!strcmp(argv[i], "TRUE")) { + sprintf(buf, " AND %s.%s != 0", range, flags[i]); + (void) strcat(qual, buf); + } else if (!strcmp(argv[i], "FALSE")) { + sprintf(buf, " AND %s.%s = 0", range, flags[i]); + (void) strcat(qual, buf); + } } - for(j=0; jsqlvar[j].sqldata=malloc(sizeof(short)+ARGLEN))==NULL) { - com_err(whoami, MR_NO_MEM, "setting up SQLDA variables"); - exit(1); - } - it->sqlvar[j].sqllen=ARGLEN; - it->sqlvar[j].sqlind=null_indicators+j; - null_indicators[j]=0; + rargv[0] = SQLDA->sqlvar[0].sqldata; + sprintf(stmt_buf,"SELECT CHAR(%s.%s) FROM %s %s WHERE %s",range,field,q->rtable,range,qual); + EXEC SQL PREPARE stmt INTO :SQLDA USING NAMES FROM :stmt_buf; + if(sqlca.sqlcode) + return(MR_INTERNAL); + EXEC SQL DECLARE csr123 CURSOR FOR stmt; + EXEC SQL OPEN csr123; + while(1) { + EXEC SQL FETCH csr123 USING DESCRIPTOR :SQLDA; + if(sqlca.sqlcode != 0) break; + rowcount++; + (*action)(1, rargv, actarg); } - it->sqln=QMAXARGS; - return it; + EXEC SQL CLOSE csr123; + if (ingres_errno) return(mr_errcode); + if (rowcount == 0) + return(MR_NO_MATCH); + return(MR_SUCCESS); } -/* Use this after FETCH USING DESCRIPTOR one or more - * result columns may contain NULLs. This routine is - * not currently needed, since db/schema creates all - * columns with a NOT NULL WITH DEFAULT clause. - * - * This is currently dead flesh, since no Moira columns - * allow null values; all use default values. +/* qualified_get_serverhost: passed "TRUE", "FALSE", or "DONTCARE" for each of + * the five flags associated with each serverhost. It will return the name of + * each service and host that meets the quailifications. It does this by + * building a where clause based on the arguments, then doing a retrieve. */ -mr_fix_nulls_in_SQLDA(da) - MR_SQLDA_T *da; -{ - register IISQLVAR *var; - register int j; - int *intp; - - for(j=0, var=da->sqlvar; jsqld; j++, var++) { - switch(var->sqltype) { - case -IISQ_CHA_TYPE: - if(*var->sqlind) - *var->sqldata='\0'; - break; - case -IISQ_INT_TYPE: - if(*var->sqlind) { - intp=(int *)var->sqldata; - *intp=0; - } - break; - } - } -} -/* prefetch_value(): - * This routine fetches an appropriate value from the numvalues table. - * It is a little hack to get around the fact that SQL doesn't let you - * do something like INSERT INTO table (foo) VALUES (other_table.bar). - * - * It is called from the query table as (*v->pre_rtn)(q,Argv,cl) or - * from within a setup_...() routine with the appropriate arguments. - * - * Correct functioning of this routine may depend on the assumption - * that this query is an APPEND. - */ +static char *shflags[6] = { "service", "enable", "override", "success", + "inprogress", "hosterror" }; -prefetch_value(q,argv,cl) +int qualified_get_serverhost(q, argv, cl, action, actarg) struct query *q; - char **argv; + char *argv[]; client *cl; + int (*action)(); + int actarg; { EXEC SQL BEGIN DECLARE SECTION; - char *name = q->validate->object_id; - int value; + char sname[33], mname[33], qual[256]; EXEC SQL END DECLARE SECTION; - int status, limit, argc; - - /* set next object id, limiting it if necessary */ - if(!strcmp(name, "uid") || !strcmp(name, "gid")) - limit = 1; /* So far as I know, this isn't needed. Just CMA. */ - else - limit = 0; - if((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS) - return(status); + char *rargv[2], buf[32]; + int i, rowcount; - /* fetch object id */ - EXEC SQL SELECT value INTO :value FROM numvalues WHERE name=:name; - if(ingres_errno) return(mr_errcode); - if(sqlca.sqlerrd[2] != 1) return(MR_INTERNAL); + sprintf(qual, "m.mach_id = sh.mach_id AND sh.service = uppercase('%s')", + argv[0]); + for (i = 1; i < q->argc; i++) { + if (!strcmp(argv[i], "TRUE")) { + sprintf(buf, " AND sh.%s != 0", shflags[i]); + strcat(qual, buf); + } else if (!strcmp(argv[i], "FALSE")) { + sprintf(buf, " AND sh.%s = 0", shflags[i]); + strcat(qual, buf); + } + } - argc = q->argc + q->vcnt; /* end of Argv for APPENDs */ - sprintf(argv[argc],"%d",value); /** Could save this step by changing tlist from %s to %d **/ + rargv[0] = sname; + rargv[1] = mname; + EXEC SQL DECLARE csr124 CURSOR FOR + SELECT sh.service, m.name FROM serverhosts sh, machine m + WHERE :qual; + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr124; + if (ingres_errno) + return(mr_errcode); + while(1) { + EXEC SQL FETCH csr124 INTO :sname, :mname; + if(sqlca.sqlcode != 0) break; + rowcount++; + (*action)(2, rargv, actarg); + } + EXEC SQL CLOSE csr124; + if (ingres_errno) return(mr_errcode); + if (rowcount == 0) + return(MR_NO_MATCH); return(MR_SUCCESS); } -/* prefetch_filesys(): - * Fetches the phys_id from filesys based on the filsys_id in argv[0]. - * Appends the filsys_id and the phys_id to the argv so they can be - * referenced in an INSERT into a table other than filesys. Also - * see comments at prefetch_value(). - * - * Assumes the existence of a row where filsys_id = argv[0], since a - * filesys label has already been resolved to a filsys_id. + +/* register_user - change user's login name and allocate a pobox, group, + * filesystem, and quota for them. The user's status must start out as 0, + * and is left as 2. Arguments are: user's UID, new login name, and user's + * type for filesystem allocation (MR_FS_STUDENT, MR_FS_FACULTY, + * MR_FS_STAFF, MR_FS_MISC). */ -prefetch_filesys(q,argv,cl) + +register_user(q, argv, cl) struct query *q; char **argv; client *cl; { EXEC SQL BEGIN DECLARE SECTION; - int fid,phid; + char *login, dir[65], *entity, directory[129], machname[33]; + int who, rowcount, mid, uid, users_id, flag, utype, nid, list_id, quota; + int size, alloc, pid, ostatus, nstatus, gidval, fsidval, npidval; + static int m_id = 0, def_quota = 0; EXEC SQL END DECLARE SECTION; - int argc; - - fid = *(int *)argv[0]; - EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid; - if(ingres_errno) return(mr_errcode); - - argc=q->argc+q->vcnt; - sprintf(argv[argc++],"%d",phid); - sprintf(argv[argc],"%d",fid); - - return(MR_SUCCESS); -} + char buffer[256], *aargv[3]; -/* Convert normal Unix-style wildcards to SQL voodoo */ -convert_wildcards(arg) - char *arg; -{ - static char buffer[ARGLEN]; - register char *s, *d; + entity = cl->entity; + who = cl->client_id; - for(d=buffer,s=arg;*s;s++) { - switch(*s) { - case '*': *d++='%'; *d++='%'; break; - case '?': *d++='_'; break; - case '_': - case '[': - case ']': *d++='*'; *d++ = *s; break; - case '%': *d++='*'; *d++='%'; *d++='%'; break; - default: *d++ = *s; break; - } - } - *d='\0'; + uid = atoi(argv[0]); + login = argv[1]; + utype = atoi(argv[2]); - /* Copy back into argv */ - strcpy(arg,buffer); + /* find user */ + EXEC SQL REPEATED SELECT users_id, status INTO :users_id, :ostatus + FROM users + WHERE uid = :uid AND (status=0 OR status=5 OR status=6); - return(MR_EXISTS); -} + if (sqlca.sqlerrd[2] == 0) + return(MR_NO_MATCH); + if (sqlca.sqlerrd[2] > 1) + return(MR_NOT_UNIQUE); -/* This version includes uppercase conversion, for things like gmac. - * This is necessary because "LIKE" doesn't work with "uppercase()". - * Including it in a wildcard routine saves making two passes over - * the argument string. - */ -convert_wildcards_uppercase(arg) - char *arg; -{ - static char buffer[ARGLEN]; - register char *s, *d; + /* check new login name */ + EXEC SQL REPEATED SELECT COUNT(login) INTO :rowcount FROM users + WHERE login = :login AND users_id != :users_id; + if (ingres_errno) return(mr_errcode); + if (rowcount > 0) return(MR_IN_USE); + EXEC SQL REPEATED SELECT COUNT(name) INTO :rowcount FROM list + WHERE name = :login; + if (ingres_errno) return(mr_errcode); + if (rowcount > 0) return(MR_IN_USE); + EXEC SQL REPEATED SELECT COUNT(label) INTO :rowcount FROM filesys + WHERE label = :login; + if (ingres_errno) return(mr_errcode); + if (rowcount > 0) return(MR_IN_USE); + com_err(whoami, 0, "login name OK"); - for(d=buffer,s=arg;*s;s++) { - switch(*s) { - case '*': *d++='%'; *d++='%'; break; - case '?': *d++='_'; break; - case '_': - case '[': - case ']': *d++='*'; *d++ = *s; break; - case '%': *d++='*'; *d++='%'; *d++='%'; break; - default: *d++=toupper(*s); break; /* This is the only diff. */ - } + /* choose place for pobox, put in mid */ + EXEC SQL DECLARE csr130 CURSOR FOR + SELECT sh.mach_id, m.name FROM serverhosts sh, machine m + WHERE sh.service='POP' AND sh.mach_id=m.mach_id + AND sh.value2 - sh.value1 = + (SELECT MAX(value2 - value1) FROM serverhosts + WHERE service = 'POP'); + if (ingres_errno) + return(mr_errcode); + EXEC SQL OPEN csr130; + if (ingres_errno) + return(mr_errcode); + EXEC SQL FETCH csr130 INTO :mid, :machname; + if (sqlca.sqlerrd[2] == 0) { + EXEC SQL CLOSE csr130; + if (ingres_errno) return(mr_errcode); + return(MR_NO_POBOX); + } else { + EXEC SQL CLOSE csr130; + if (ingres_errno) return(mr_errcode); } - *d='\0'; - /* Copy back into argv */ - strcpy(arg,buffer); + /* change login name, set pobox */ + sprintf(buffer, "u.users_id = %d", users_id); + incremental_before("users", buffer, 0); + nstatus = 2; + if (ostatus == 5 || ostatus == 6) + nstatus = 1; + EXEC SQL REPEATED UPDATE users SET login = :login, status = :nstatus, + modtime='now', modby = :who, modwith = :entity, potype='POP', + pop_id = :mid, pmodtime='now', pmodby = :who, pmodwith = :entity + WHERE users_id = :users_id; - return(MR_EXISTS); -} + if (ingres_errno) return(mr_errcode); + if (sqlca.sqlerrd[2] != 1) + return(MR_INTERNAL); + set_pop_usage(mid, 1); + com_err(whoami, 0, "set login name to %s and pobox to %s", login, + strtrim(machname)); + incremental_after("users", buffer, 0); + /* create group list */ + if (set_next_object_id("gid", "list", 1)) + return(MR_NO_ID); + if (set_next_object_id("list_id", "list", 0)) + return(MR_NO_ID); + EXEC SQL REPEATED SELECT value INTO :list_id FROM numvalues + WHERE name='list_id'; + if (ingres_errno) return(mr_errcode); + if (sqlca.sqlerrd[2] != 1) + return(MR_INTERNAL); + incremental_clear_before(); + EXEC SQL SELECT value INTO :gidval FROM numvalues WHERE name = 'gid'; + EXEC SQL REPEATED INSERT INTO list + (name, list_id, active, publicflg, hidden, maillist, grouplist, + gid, description, acl_type, acl_id, + modtime, modby, modwith) + VALUES (:login, :list_id, 1, 0, 0, 0, 1, + :gidval, 'User Group', 'USER', :users_id, + 'now', :who, :entity); + if (ingres_errno) return(mr_errcode); + if (sqlca.sqlerrd[2] != 1) + return(MR_INTERNAL); + sprintf(buffer, "l.list_id = %d", list_id); + incremental_after("list", buffer, 0); + aargv[0] = (char *) list_id; + aargv[1] = "USER"; + aargv[2] = (char *) users_id; + incremental_clear_before(); + EXEC SQL REPEATED INSERT INTO imembers + (list_id, member_type, member_id, ref_count, direct) + VALUES (:list_id, 'USER', :users_id, 1, 1); + if (ingres_errno) return(mr_errcode); + if (sqlca.sqlerrd[2] != 1) + return(MR_INTERNAL); + incremental_after("members", 0, aargv); -/* Looks like it's time to build an abstraction barrier, Yogi */ -mr_select_any(stmt) - EXEC SQL BEGIN DECLARE SECTION; - char *stmt; - EXEC SQL END DECLARE SECTION; -{ - int result=0; + if (m_id == 0) { + /* Cell Name (I know, it shouldn't be hard coded...) */ + strcpy(machname, "ATHENA.MIT.EDU"); + EXEC SQL SELECT mach_id INTO :m_id FROM machine + WHERE name = :machname; + } - EXEC SQL PREPARE stmt FROM :stmt; - EXEC SQL DESCRIBE stmt INTO :SQLDA; - if(SQLDA->sqld==0) /* Not a SELECT */ - return(MR_INTERNAL); - EXEC SQL DECLARE csr CURSOR FOR stmt; - EXEC SQL OPEN csr; - EXEC SQL FETCH csr USING DESCRIPTOR :SQLDA; - if(sqlca.sqlcode==0) - result=MR_EXISTS; - else if((sqlca.sqlcode<0) && mr_errcode) - result=mr_errcode; - else - result=0; - EXEC SQL CLOSE csr; - return(result); -} + /* create filesystem */ + if (set_next_object_id("filsys_id", "filesys", 0)) + return(MR_NO_ID); + incremental_clear_before(); + if (islower(login[0]) && islower(login[1])) { + sprintf(directory, "/afs/athena.mit.edu/user/%c/%c/%s", + login[0], login[1], login); + } else { + sprintf(directory, "/afs/athena.mit.edu/user/other/%s", login); + } + + EXEC SQL SELECT value INTO :fsidval FROM numvalues + WHERE numvalues.name='filsys_id'; + EXEC SQL REPEATED INSERT INTO filesys + (filsys_id, phys_id, label, type, mach_id, name, + mount, access, comments, owner, owners, createflg, + lockertype, modtime, modby, modwith) + VALUES + (:fsidval, 0, :login, 'AFS', :m_id, :directory, + '/mit/'+:login, 'w', 'User Locker', :users_id, :list_id, 1, + 'HOMEDIR', 'now', :who, :entity); + if (ingres_errno) return(mr_errcode); + if (sqlca.sqlerrd[2] != 1) + return(MR_INTERNAL); + sprintf(buffer,"fs.filsys_id = %d",fsidval); + incremental_after("filesys", buffer, 0); + /* set quota */ + if (def_quota == 0) { + EXEC SQL REPEATED SELECT value INTO :def_quota FROM numvalues + WHERE name='def_quota'; + if (ingres_errno) return(mr_errcode); + if (sqlca.sqlerrd[2] != 1) + return(MR_NO_QUOTA); + + } + incremental_clear_before(); + EXEC SQL REPEATED INSERT INTO quota + (entity_id, filsys_id, type, quota, phys_id, modtime, modby, modwith) + VALUES + (0, :fsidval, 'ANY', :def_quota, 0, 'now', :who, :entity); + if (ingres_errno) return(mr_errcode); + if (sqlca.sqlerrd[2] != 1) + return(MR_INTERNAL); + aargv[0] = login; + aargv[1] = "ANY"; + aargv[2] = login; + sprintf(buffer, "q.entity_id = 0 and q.filsys_id = %d and q.type = 'ANY'", fsidval); + incremental_after("quota", buffer, aargv); + com_err(whoami, 0, "quota of %d assigned", def_quota); + if (ingres_errno) return(mr_errcode); -static hex_dump(p) -unsigned char *p; -{ - char buf[BUFSIZ]; - int i; + cache_entry(login, "USER", users_id); - fprintf(stderr, "Size: %d\n", strlen(p)); - while (strlen(p) >= 8) { - fprintf(stderr, "%02x %02x %02x %02x %02x %02x %02x %02x\n", - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); - p += 8; - } - switch (strlen(p)) { - case 7: - fprintf(stderr, "%02x %02x %02x %02x %02x %02x %02x\n", - p[0], p[1], p[2], p[3], p[4], p[5], p[6]); - break; - case 6: - fprintf(stderr, "%02x %02x %02x %02x %02x %02x\n", - p[0], p[1], p[2], p[3], p[4], p[5]); - break; - case 5: - fprintf(stderr, "%02x %02x %02x %02x %02x\n", - p[0], p[1], p[2], p[3], p[4]); - break; - case 4: - fprintf(stderr, "%02x %02x %02x %02x\n", - p[0], p[1], p[2], p[3]); - break; - case 3: - fprintf(stderr, "%02x %02x %02x\n", - p[0], p[1], p[2]); - break; - case 2: - fprintf(stderr, "%02x %02x\n", - p[0], p[1]); - break; - case 1: - fprintf(stderr, "%02x\n", - p[0]); - break; - default: - return; - } + EXEC SQL REPEATED UPDATE tblstats SET updates=updates+1, modtime='now' + WHERE table_name='users'; + EXEC SQL REPEATED UPDATE tblstats SET appends=appends+1, modtime='now' + WHERE table_name='list' OR table_name='filesys' OR table_name='quota'; + if (ingres_errno) return(mr_errcode); + return(MR_SUCCESS); } -/* Adds a string to the string table. Returns the id number. - * - */ -int add_string(name) - EXEC SQL BEGIN DECLARE SECTION; - char *name; - EXEC SQL END DECLARE SECTION; -{ +/** set_pop_usage - incr/decr usage count for pop server in serverhosts talbe + ** + ** Inputs: + ** id of machine + ** delta (will be +/- 1) + ** + ** Description: + ** - incr/decr value field in serverhosts table for pop/mach_id + ** + **/ + +int set_pop_usage(id, cnt) EXEC SQL BEGIN DECLARE SECTION; - char buf[256]; int id; - EXEC SQL END DECLARE SECTION; + int cnt; + EXEC SQL END DECLARE SECTION; +{ + EXEC SQL REPEATED UPDATE serverhosts SET value1 = value1 + :cnt + WHERE serverhosts.service = 'POP' AND serverhosts.mach_id = :id; - EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id'; - id++; - EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id'; - - /* Use sprintf to get around problem with doubled single quotes */ - sprintf(buf,"INSERT INTO strings (string_id, string) VALUES (%d, '%s')",id,name); - EXEC SQL EXECUTE IMMEDIATE :buf; - - return(id); + if (ingres_errno) return(mr_errcode); + return(MR_SUCCESS); } - -/* eof:qsupport.dc */ -- 2.45.2