From 22bbb6f02323afff6774b295fc3965556b366e2f Mon Sep 17 00:00:00 2001 From: zacheiss Date: Fri, 22 Aug 2008 17:49:10 +0000 Subject: [PATCH] Support EXCHANGE poboxes. --- clients/lib/mail.c | 25 ++++- clients/lib/mrclient-internal.h | 2 +- clients/lib/pobox.c | 1 + db/dbopt.sql | 2 + db/schema.sql | 1 + dbck/phase1.pc | 13 ++- dbck/phase2.pc | 13 +++ gen/hesiod.pc | 10 +- gen/mailhub.pc | 159 +++++++++++++++++++------------- incremental/winad/winad.c | 1 + server/increment.pc | 14 +-- server/qaccess.pc | 16 ++-- server/qfollow.pc | 14 ++- server/qsetup.pc | 4 + server/qsupport.pc | 67 +++++++++++--- 15 files changed, 237 insertions(+), 105 deletions(-) diff --git a/clients/lib/mail.c b/clients/lib/mail.c index 2228120d..3749a6da 100644 --- a/clients/lib/mail.c +++ b/clients/lib/mail.c @@ -31,7 +31,7 @@ int mailtype(char *machine) int status, match = 0; static struct save_queue *pop = NULL, *local = NULL; static struct save_queue *mailhub = NULL, *mailhub_name = NULL; - static struct save_queue *imap = NULL; + static struct save_queue *imap = NULL, *exchange = NULL; mrcl_clear_message(); @@ -173,6 +173,29 @@ int mailtype(char *machine) if (match) return MAILTYPE_MAILHUB; + /* 6. Check for EXCHANGE service. */ + if (!exchange) + { + char *service = "EXCHANGE"; + exchange = sq_create(); + status = mr_query("get_server_locations", 1, &service, + save_sloc_machine, exchange); + if (status && (status != MR_NO_MATCH)) + { + mrcl_set_message("Could not read list of EXCHANGE servers: %s", + error_message(status)); + return MAILTYPE_ERROR; + } + } + + while (sq_get_data(exchange, &name)) + { + if (!match && !strcasecmp(name, machine)) + match = 1; + } + if (match) + return MAILTYPE_EXCHANGE; + return MAILTYPE_SMTP; } diff --git a/clients/lib/mrclient-internal.h b/clients/lib/mrclient-internal.h index b0afcec3..feaef6cf 100644 --- a/clients/lib/mrclient-internal.h +++ b/clients/lib/mrclient-internal.h @@ -10,7 +10,7 @@ void mrcl_set_message(char *, ...); void mrcl_clear_message(void); -enum { MAILTYPE_ERROR, MAILTYPE_IMAP, MAILTYPE_POP, +enum { MAILTYPE_ERROR, MAILTYPE_IMAP, MAILTYPE_EXCHANGE, MAILTYPE_POP, MAILTYPE_LOCAL, MAILTYPE_MAILHUB, MAILTYPE_SMTP }; int mailtype(char *machine); diff --git a/clients/lib/pobox.c b/clients/lib/pobox.c index bb4535b9..c3cee8c8 100644 --- a/clients/lib/pobox.c +++ b/clients/lib/pobox.c @@ -97,6 +97,7 @@ int mrcl_validate_pobox_smtp(char *user, char *address, char **ret) break; case MAILTYPE_MAILHUB: + case MAILTYPE_EXCHANGE: if (!strcmp(p, user)) { mrcl_set_message("The address \"%s@%s\" would create a mail " diff --git a/db/dbopt.sql b/db/dbopt.sql index 64a107f0..b6f4d72e 100644 --- a/db/dbopt.sql +++ b/db/dbopt.sql @@ -4,6 +4,8 @@ create index i_usr_name on users (first, last); create index i_usr_last on users (last, first); create index i_usr_uid on users (unix_uid); create index i_usr_pop on users (pop_id); +create index i_usr_imap on users (imap_id); +create index i_usr_exchange on users (exchange_id); create index i_usr_clearid on users (clearid); create index i_usr_resv on users (reservations); create index i_usr_sponsor on users (sponsor_id); diff --git a/db/schema.sql b/db/schema.sql index 6a0926e8..13262f06 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -30,6 +30,7 @@ create table users pop_id INTEGER DEFAULT 0 NOT NULL, imap_id INTEGER DEFAULT 0 NOT NULL, box_id INTEGER DEFAULT 0 NOT NULL, + exchange_id INTEGER DEFAULT 0 NOT NULL, pmodtime DATE DEFAULT SYSDATE NOT NULL, pmodby INTEGER DEFAULT 0 NOT NULL, pmodwith VARCHAR(8) DEFAULT CHR(0) NOT NULL, diff --git a/dbck/phase1.pc b/dbck/phase1.pc index f89a618d..d1c432b9 100644 --- a/dbck/phase1.pc +++ b/dbck/phase1.pc @@ -358,7 +358,8 @@ void phase1(void) EXEC SQL DECLARE csr102 CURSOR FOR SELECT users_id, login, last, first, status, potype, pop_id, box_id, - imap_id, modby, fmodby, pmodby, comments, sigwho, sponsor_type, sponsor_id + imap_id, exchange_id, modby, fmodby, pmodby, comments, sigwho, + sponsor_type, sponsor_id FROM users ORDER BY users_id; EXEC SQL OPEN csr102; while (1) @@ -367,13 +368,13 @@ void phase1(void) char login[USERS_LOGIN_SIZE], nbuf[USERS_FIRST_SIZE + USERS_LAST_SIZE]; char last[USERS_LAST_SIZE], first[USERS_FIRST_SIZE]; char potype[USERS_POTYPE_SIZE], sponsor_type[USERS_SPONSOR_TYPE_SIZE]; - int users_id, status, pop_id, box_id, imap_id, modby, fmodby, pmodby; - int comments, sigwho, sponsor_id; + int users_id, status, pop_id, box_id, imap_id, exchange_id, modby; + int fmodby, pmodby, comments, sigwho, sponsor_id; EXEC SQL END DECLARE SECTION; EXEC SQL FETCH csr102 INTO :users_id, :login, :last, :first, - :status, :potype, :pop_id, :box_id, :imap_id, :modby, :fmodby, - :pmodby, :comments, :sigwho, :sponsor_type, :sponsor_id; + :status, :potype, :pop_id, :box_id, :imap_id, :exchange_id, :modby, + :fmodby, :pmodby, :comments, :sigwho, :sponsor_type, :sponsor_id; if (sqlca.sqlcode) break; @@ -405,6 +406,8 @@ void phase1(void) case 'I': u->pobox_id = imap_id; break; + case 'E': + u->pobox_id = exchange_id; default: u->pobox_id = 0; } diff --git a/dbck/phase2.pc b/dbck/phase2.pc index 3c6d1a34..de786a3d 100644 --- a/dbck/phase2.pc +++ b/dbck/phase2.pc @@ -667,6 +667,19 @@ void pobox_check(int id, struct user *u) } break; + case 'E': + if (!hash_lookup(machines, u->pobox_id)) + { + printf("User %s(%s) has P.O.Box on non-existant machine %d\n", + u->login, u->fullname, u->pobox_id); + if (single_fix("Delete", 0)) + { + remove_pobox(u->users_id); + u->potype = 'N'; + } + } + break; + case 'S': if (hash_lookup(string_dups, u->pobox_id)) { diff --git a/gen/hesiod.pc b/gen/hesiod.pc index 2b490daf..3b995581 100644 --- a/gen/hesiod.pc +++ b/gen/hesiod.pc @@ -202,7 +202,7 @@ int do_passwd(void) char fullname[USERS_FULLNAME_SIZE], oa[USERS_OFFICE_ADDR_SIZE]; char op[USERS_OFFICE_PHONE_SIZE], hp[USERS_HOME_PHONE_SIZE]; char nn[USERS_NICKNAME_SIZE], potype[USERS_POTYPE_SIZE]; - int uid, id, pid, iid, mid, status; + int uid, id, pid, iid, eid, mid, status; EXEC SQL END DECLARE SECTION; sprintf(poutf, "%s/passwd.db", hesiod_dir); @@ -237,7 +237,8 @@ int do_passwd(void) users = create_hash(12001); EXEC SQL DECLARE u_cursor CURSOR FOR SELECT login, unix_uid, shell, fullname, nickname, office_addr, - office_phone, home_phone, users_id, potype, pop_id, imap_id, status + office_phone, home_phone, users_id, potype, pop_id, imap_id, exchange_id, + status FROM users WHERE status = 1 OR status = 2 OR status = 5 OR status = 6 ORDER BY users_id; @@ -245,7 +246,7 @@ int do_passwd(void) while (1) { EXEC SQL FETCH u_cursor INTO :login, :uid, :shell, :fullname, :nn, - :oa, :op, :hp, :id, :potype, :pid, :iid, :status; + :oa, :op, :hp, :id, :potype, :pid, :iid, :eid, :status; if (sqlca.sqlcode) break; strtrim(login); @@ -268,6 +269,9 @@ int do_passwd(void) fprintf(uout, "%d.uid\t%s CNAME %s.passwd\n", uid, HCLASS, login); } + if (eid != 0) + pid = eid; + if (iid != 0) { EXEC SQL SELECT mach_id INTO :mid FROM filesys diff --git a/gen/mailhub.pc b/gen/mailhub.pc index 6e531aa5..2d075aaa 100644 --- a/gen/mailhub.pc +++ b/gen/mailhub.pc @@ -34,6 +34,8 @@ char *divide = "##############################################################"; #define FALSE 0 #define TRUE (!FALSE) +FILE *out = stdout; + struct hash *users, *machines, *strings, *lists; struct user { char *login; @@ -56,10 +58,10 @@ struct list { }; void get_info(void); +void save_mlist(int id, void *list, void *force); int check_string(char *s); void output_login(int dummy, void *names, void *out); -void output_mlist(int id, void *list, void *out); -void output_membership(struct list *l, FILE *out); +void output_mlist(int id, struct list *l); void put_fill(FILE *aliases, char *string); void do_people(void); @@ -69,9 +71,7 @@ int main(int argc, char **argv) { time_t tm = time(NULL); char filename[MAXPATHLEN], *targetfile; - FILE *out = stdout; - srand(tm); EXEC SQL CONNECT :db; if (argc == 2) @@ -100,7 +100,7 @@ int main(int argc, char **argv) incount = 0; fprintf(out, "\n%s\n# Mailing lists\n%s\n\n", divide, divide); - hash_step(lists, output_mlist, out); + hash_step(lists, save_mlist, FALSE); fprintf(stderr, "Output %d lists\n", incount); incount = 0; @@ -124,7 +124,7 @@ int main(int argc, char **argv) void get_info(void) { EXEC SQL BEGIN DECLARE SECTION; - int id, pid, iid, bid, cnt, maillistp, acl, mid, mailman; + int id, pid, iid, bid, eid, cnt, maillistp, acl, mid, mailman; char mname[MACHINE_NAME_SIZE], str[STRINGS_STRING_SIZE]; char login[USERS_LOGIN_SIZE], potype[USERS_POTYPE_SIZE]; char lname[LIST_NAME_SIZE], desc[LIST_DESCRIPTION_SIZE]; @@ -150,7 +150,7 @@ void get_info(void) WHERE status = 1 AND ( mach_id IN ( SELECT UNIQUE pop_id FROM users ) OR mach_id IN ( SELECT UNIQUE mach_id FROM filesys - WHERE type = 'IMAP' ) ) + WHERE type = 'IMAP' ) ) ORDER BY mach_id; EXEC SQL OPEN m_cursor; while (1) @@ -174,6 +174,28 @@ void get_info(void) } EXEC SQL CLOSE m_cursor; + EXEC SQL DECLARE e_cursor CURSOR FOR + SELECT mach_id, name + FROM machine + WHERE status = 1 + AND mach_id in (SELECT UNIQUE exchange_id FROM users) + ORDER BY mach_id; + EXEC SQL OPEN e_cursor; + while (1) + { + EXEC SQL FETCH e_cursor INTO :id, :mname; + if (sqlca.sqlcode) + break; + strtrim(mname); + if (hash_store(machines, id, strdup(mname)) < 0) + { + fprintf(stderr, "Out of memory!\n"); + exit(MR_NO_MEM); + } + cnt++; + } + EXEC SQL CLOSE e_cursor; + fprintf(stderr, "Loaded %d machines\n", cnt); cnt = 0; @@ -204,7 +226,7 @@ void get_info(void) users = create_hash(13001); EXEC SQL DECLARE u_cursor CURSOR FOR - SELECT users_id, login, potype, pop_id, imap_id, box_id + SELECT users_id, login, potype, pop_id, imap_id, box_id, exchange_id FROM users WHERE status != 3 ORDER BY users_id; @@ -213,7 +235,8 @@ void get_info(void) { char *saddr = NULL, *paddr = NULL; - EXEC SQL FETCH u_cursor INTO :id, :login, :potype, :pid, :iid, :bid; + EXEC SQL FETCH u_cursor INTO :id, :login, :potype, :pid, :iid, :bid, + :eid; if (sqlca.sqlcode) break; u = malloc(sizeof(struct user)); @@ -230,7 +253,7 @@ void get_info(void) /* If SMTP, clear pid and iid. */ if (potype[1] == 'M') - pid = iid = 0; + pid = iid = eid = 0; } /* If IMAP, or SPLIT with IMAP, set pid to mach_id. */ @@ -240,6 +263,10 @@ void get_info(void) WHERE filsys_id = :iid; } + /* If EXCHANGE or SPLIT with EXCHANGE, set pid to eid. */ + if (potype[0] == 'E' || (potype[0] == 'S' && eid)) + pid = eid; + if (pid && (s = hash_lookup(machines, pid))) { paddr = malloc(strlen(u->login) + strlen(s) + 2); @@ -355,6 +382,34 @@ sqlerr: } +void save_mlist(int id, void *list, void *force) +{ + struct member *m; + struct list *l = list, *l1; + + if (l->maillist > 1 || (l->maillist == 0 && !force) || + !check_string(l->name)) + return; + + /* If user group appears on list, replace with user. */ + if (l->m && l->m->next == NULL && !strcasecmp(l->name, l->m->name)) + { + l->maillist = 3; + return; + } + l->maillist = 2; + output_mlist(id, l); + + if (l->acl_t == 'L' && (l1 = hash_lookup(lists, l->acl_id))) + save_mlist(0, l1, (void *)TRUE); + + for (m = l->m; m; m = m->next) + { + if (m->list_id && (l1 = hash_lookup(lists, m->list_id))) + save_mlist(0, l1, (void *)TRUE); + } +} + void output_login(int dummy, void *user, void *out) { struct user *u = user; @@ -364,24 +419,20 @@ void output_login(int dummy, void *user, void *out) fprintf(out, "%s: %s\n", u->login, u->pobox); } -int line_width, alias_width; static const char *mailman_suffixes[] = { "-admin", "-owner", "-request", - "-bounces", "-confirm", "-join", - "-leave", "-subscribe", - "-unsubscribe", NULL }; + "-bounces", "-confirm", "-join", + "-leave", "-subscribe", + "-unsubscribe", NULL }; -void output_mlist(int id, void *list, void *out) +void output_mlist(int id, struct list *l) { - struct list *l = list, *l1; + struct list *l1; + struct member *m; struct user *u; - int len = strlen(l->name), i; - - if (!l->maillist || !check_string(l->name)) - return; - - /* If standard user group appears on a list, substitute in the user. */ - if (l->m && l->m->next == NULL && !strcasecmp(l->name, l->m->name)) - return; + int line_width, alias_width, word_width, beginning; + static int cont = 1; + char str[8]; + int i; put_fill(out, l->description); @@ -390,44 +441,23 @@ void output_mlist(int id, void *list, void *out) for (i = 0; mailman_suffixes[i]; i++) fprintf(out, "%s%s: %s%s@%s\n", l->name, mailman_suffixes[i], l->name, mailman_suffixes[i], l->mailman_server); - fprintf(out, "owner-%s: %s-owner@%s\n", l->name, l->name, - l->mailman_server); + fprintf(out, "owner-%s: %s-owner@%s\n%s: ", l->name, l->name, + l->mailman_server, l->name); } else if (l->acl_t == 'L' && (l1 = hash_lookup(lists, l->acl_id))) - { - fprintf(out, "owner-%s: ", l->name); - if ((l1->maillist) && (strcmp(l->name, l1->name))) - fprintf(out, "%s\n", l1->name); - else - { - alias_width = line_width = len + 8; - output_membership(l1, out); - fprintf(out, "\n"); - } - } + fprintf(out, "owner-%s: %s\n%s: ", l->name, l1->name, l->name); else if (l->acl_t == 'U' && (u = hash_lookup(users, l->acl_id))) - fprintf(out, "owner-%s: %s\n", l->name, u->login); - - fprintf(out, "%s: ", l->name); - alias_width = line_width = len + 2; - output_membership(l, out); - fprintf(out, "\n\n"); - incount++; -} - -void output_membership(struct list *l, FILE *out) -{ - struct member *m; - struct list *l1; - int word_width, linestart = 1; - static int cont = 1; - char str[8]; + fprintf(out, "owner-%s: %s\n%s: ", l->name, u->login, l->name); + else + fprintf(out, "%s: ", l->name); + alias_width = line_width = strlen(l->name) + 2; + beginning = 1; for (m = l->m; m; m = m->next) { word_width = strlen(m->name); - if (!linestart && alias_width + word_width + 2 > MAX_ALIAS_WIDTH) + if (!beginning && alias_width + word_width + 2 > MAX_ALIAS_WIDTH) { /* Make a continuation. */ sprintf(str, "%c%c%c%c%c%c", rand() % 26 + 97, rand() % 26 + 97, @@ -436,18 +466,20 @@ void output_membership(struct list *l, FILE *out) fprintf(out, ",\n\tcont%d-%s\ncont%d-%s: ", cont, str, cont, str); cont++; alias_width = line_width = 17 + word_width; + fputs(m->name, out); } - else if (linestart) + else if (beginning) { - /* First word on line, so we can't wrap. */ + /* Beginning of alias, so don't wrap. */ line_width += word_width; alias_width = line_width; - linestart = 0; + fputs(m->name, out); + beginning = 0; } else if (line_width + word_width + 2 > MAX_LINE_WIDTH) { /* Wrap. */ - fputs(",\n\t", out); + fprintf(out, ",\n\t%s", m->name); alias_width += line_width + word_width + 2; line_width = word_width + 8; } @@ -455,16 +487,13 @@ void output_membership(struct list *l, FILE *out) { /* Continue line. */ line_width += word_width + 2; - fputs(", ", out); + fprintf(out, ", %s", m->name); } - - if (m->list_id && (l1 = hash_lookup(lists, m->list_id)) && !l1->maillist) - output_membership(l1, out); - else - fputs(m->name, out); } if (!l->m) fprintf(out, "/dev/null"); + fprintf(out, "\n\n"); + incount++; } /* Write a word-wrapped list description to the aliases file as a @@ -521,7 +550,7 @@ void put_fill(FILE *aliases, char *string) } -/* Illegal chars: this no longer corresponds to the array +/* Illegal chars: this no longer corresponds to the array * in setup_alis. '+' is a valid character in a string on * a list, but is not a valid character in a listname. */ diff --git a/incremental/winad/winad.c b/incremental/winad/winad.c index ffbf50af..c42a93a1 100755 --- a/incremental/winad/winad.c +++ b/incremental/winad/winad.c @@ -1312,6 +1312,7 @@ void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, #define U_USER_ID 10 #define U_HOMEDIR 11 #define U_PROFILEDIR 12 +#define U_POTYPE 13 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, char **before, int beforec, char **after, diff --git a/server/increment.pc b/server/increment.pc index 225648ec..2d2e5896 100644 --- a/server/increment.pc +++ b/server/increment.pc @@ -30,7 +30,7 @@ int inc_pid = 0; int inc_running = 0; time_t inc_started; -#define MAXARGC 15 +#define MAXARGC 16 EXEC SQL WHENEVER SQLERROR DO dbmserr(); @@ -96,10 +96,10 @@ void incremental_before(enum tables table, char *qual, char **argv) case USERS_TABLE: sprintf(stmt_buf, "SELECT u.login, u.unix_uid, u.shell, " "u.winconsoleshell, u.last, u.first, u.middle, u.status, " - "u.clearid, u.type, u.users_id, u.winhomedir, u.winprofiledir " - "FROM users u WHERE %s", qual); + "u.clearid, u.type, u.users_id, u.winhomedir, u.winprofiledir, " + "u.potype FROM users u WHERE %s", qual); dosql(before); - beforec = 13; + beforec = 14; break; case MACHINE_TABLE: sprintf(stmt_buf, "SELECT m.name, m.vendor, m.mach_id FROM machine m " @@ -280,10 +280,10 @@ void incremental_after(enum tables table, char *qual, char **argv) case USERS_TABLE: sprintf(stmt_buf, "SELECT u.login, u.unix_uid, u.shell, " "u.winconsoleshell, u.last, u.first, u.middle, u.status, " - "u.clearid, u.type, u.users_id, u.winhomedir, u.winprofiledir " - "FROM users u WHERE %s", qual); + "u.clearid, u.type, u.users_id, u.winhomedir, u.winprofiledir, " + "u.potype FROM users u WHERE %s", qual); dosql(after); - afterc = 13; + afterc = 14; break; case MACHINE_TABLE: sprintf(stmt_buf, "SELECT m.name, m.vendor, m.mach_id FROM machine m " diff --git a/server/qaccess.pc b/server/qaccess.pc index a0b13783..3f84fde8 100644 --- a/server/qaccess.pc +++ b/server/qaccess.pc @@ -147,13 +147,13 @@ int access_spob(struct query *q, char *argv[], client *cl) int status; if (!strcmp(argv[1], "IMAP")) - { - EXEC SQL SELECT owner INTO :id FROM filesys f - WHERE f.label = :argv[2] AND f.type = 'IMAP' AND - f.lockertype = 'USER'; - if (cl->users_id != id) - return MR_PERM; - } + { + EXEC SQL SELECT owner INTO :id FROM filesys f + WHERE f.label = :argv[2] AND f.type = 'IMAP' AND + f.lockertype = 'USER'; + if (cl->users_id != id) + return MR_PERM; + } /* Non-query owners can't forward mail to a POSTOFFICE or MAILHUB server, * nor to a nonresolving domain. @@ -164,7 +164,7 @@ int access_spob(struct query *q, char *argv[], client *cl) if (status) return status; } - + if (cl->users_id != *(int *)argv[0]) return MR_PERM; else diff --git a/server/qfollow.pc b/server/qfollow.pc index 5a84ba34..4bf66ea8 100644 --- a/server/qfollow.pc +++ b/server/qfollow.pc @@ -394,7 +394,7 @@ int followup_gpob(struct query *q, struct save_queue *sq, struct validate *v, char *ptype, *p; int mid, sid, status, i; EXEC SQL BEGIN DECLARE SECTION; - int users_id, pid, iid, bid; + int users_id, pid, iid, bid, eid; char mach[MACHINE_NAME_SIZE], fs[FILESYS_LABEL_SIZE]; char str[STRINGS_STRING_SIZE]; EXEC SQL END DECLARE SECTION; @@ -421,7 +421,7 @@ int followup_gpob(struct query *q, struct save_queue *sq, struct validate *v, /* If SMTP, don't bother fetching IMAP and POP boxes. */ if (ptype[1] == 'M') - pid = iid = 0; + pid = iid = eid = 0; } if (iid) { @@ -440,12 +440,20 @@ int followup_gpob(struct query *q, struct save_queue *sq, struct validate *v, if (sqlca.sqlcode) return MR_MACHINE; } + if (eid) + { + /* EXCHANGE, or SPLIT with EXCHANGE */ + EXEC SQL SELECT m.name INTO :mach FROM machine m, users u + WHERE u.users_id = :users_id AND u.exchange_id = m.mach_id; + if (sqlca.sqlcode) + return MR_MACHINE; + } free(argv[2]); free(argv[3]); /* Now assemble the right answer. */ - if (!strcmp(ptype, "POP")) + if (!strcmp(ptype, "POP") || !strcmp(ptype, "EXCHANGE")) { argv[2] = xstrdup(strtrim(mach)); argv[3] = xmalloc(strlen(argv[0]) + strlen(argv[2]) + 2); diff --git a/server/qsetup.pc b/server/qsetup.pc index afd73bbb..2b4befd3 100644 --- a/server/qsetup.pc +++ b/server/qsetup.pc @@ -221,6 +221,10 @@ int setup_dmac(struct query *q, char *argv[], client *cl) WHERE potype = 'POP' AND pop_id = :id; if (cnt > 0) return MR_IN_USE; + EXEC SQL SELECT COUNT(login) INTO :cnt FROM users + WHERE potype = 'EXCHANGE' and exchange_id = :id; + if (cnt > 0) + return MR_IN_USE; EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM serverhosts WHERE mach_id = :id; if (cnt > 0) diff --git a/server/qsupport.pc b/server/qsupport.pc index b7b4fdba..3ecbc28c 100644 --- a/server/qsupport.pc +++ b/server/qsupport.pc @@ -41,7 +41,9 @@ int qualified_get(struct query *q, char *argv[], * if type is POP, then box should be a machine, and its ID should be put in * pop_id. If type is IMAP, then box should be a filesys, 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. + * ID should be put in box_id. If type is EXCHANGE, then box should be a + * machine, and its ID should be put in exchange_id. If type is NONE, then + * box doesn't matter. */ int set_pobox(struct query *q, char **argv, client *cl) @@ -51,6 +53,7 @@ int set_pobox(struct query *q, char **argv, client *cl) char *box, potype[USERS_POTYPE_SIZE]; EXEC SQL END DECLARE SECTION; int status; + char buffer[256]; box = argv[2]; user = *(int *)argv[0]; @@ -63,6 +66,9 @@ int set_pobox(struct query *q, char **argv, client *cl) (!strcmp(strtrim(potype), "SPLIT") && id)) set_pop_usage(id, -1); + sprintf(buffer, "u.users_id = %d", user); + incremental_before(USERS_TABLE, buffer, 0); + if (!strcmp(argv[1], "POP")) { status = name_to_id(box, MACHINE_TABLE, &id); @@ -70,10 +76,20 @@ int set_pobox(struct query *q, char **argv, client *cl) return MR_MACHINE; else if (status) return status; - EXEC SQL UPDATE users SET potype = 'POP', pop_id = :id, imap_id = 0 - WHERE users_id = :user; + EXEC SQL UPDATE users SET potype = 'POP', pop_id = :id, imap_id = 0, + exchange_id = 0 WHERE users_id = :user; set_pop_usage(id, 1); } + else if (!strcmp(argv[1], "EXCHANGE")) + { + status = name_to_id(box, MACHINE_TABLE, &id); + if (status == MR_NO_MATCH) + return MR_MACHINE; + else if (status) + return status; + EXEC SQL UPDATE users SET POTYPE = 'EXCHANGE', exchange_id = :id, + pop_id = 0, imap_id = 0 WHERE users_id = :user; + } else if (!strcmp(argv[1], "SMTP") || !strcmp(argv[1], "SPLIT")) { if (strchr(box, '/') || strchr(box, '|')) @@ -104,8 +120,8 @@ int set_pobox(struct query *q, char **argv, client *cl) WHERE label = :box AND type = 'IMAP'; if (sqlca.sqlcode) return MR_FILESYS; - EXEC SQL UPDATE users SET potype = 'IMAP', imap_id = :id, pop_id = 0 - WHERE users_id = :user; + EXEC SQL UPDATE users SET potype = 'IMAP', imap_id = :id, pop_id = 0, + exchange_id = 0 WHERE users_id = :user; } else /* argv[1] == "NONE" */ { @@ -113,6 +129,8 @@ int set_pobox(struct query *q, char **argv, client *cl) WHERE users_id = :user; } + incremental_after(USERS_TABLE, buffer, 0); + set_pobox_modtime(q, argv, cl); EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE WHERE table_name = 'users'; @@ -121,22 +139,27 @@ int set_pobox(struct query *q, char **argv, client *cl) return MR_SUCCESS; } -/* set_pobox_pop: Revert to existing POP or IMAP pobox. +/* set_pobox_pop: Revert to existing POP, IMAP, or EXCHANGE pobox. * Also take care of keeping track of the post office usage. */ int set_pobox_pop(struct query *q, char **argv, client *cl) { EXEC SQL BEGIN DECLARE SECTION; - int id, pid, iid, mid; + int id, pid, iid, mid, eid; char type[USERS_POTYPE_SIZE]; EXEC SQL END DECLARE SECTION; + char buffer[256]; id = *(int *)argv[0]; - EXEC SQL SELECT potype, pop_id, imap_id INTO :type, :pid, :iid + EXEC SQL SELECT potype, pop_id, imap_id, exchange_id + INTO :type, :pid, :iid, :eid FROM users WHERE users_id = :id; - if (sqlca.sqlerrd[2] == 0 || (pid == 0 && iid == 0)) + if (sqlca.sqlerrd[2] == 0 || (pid == 0 && iid == 0 && eid == 0)) return MR_MACHINE; + sprintf(buffer, "u.users_id = %d", id); + incremental_before(USERS_TABLE, buffer, 0); + if (pid) { EXEC SQL SELECT mach_id INTO :mid FROM machine @@ -147,7 +170,7 @@ int set_pobox_pop(struct query *q, char **argv, client *cl) if (!strcmp(strtrim(type), "POP")) set_pop_usage(mid, 1); } - else + else if (iid) { EXEC SQL SELECT filsys_id INTO :mid FROM filesys WHERE filsys_id = :iid; @@ -155,6 +178,16 @@ int set_pobox_pop(struct query *q, char **argv, client *cl) return MR_MACHINE; EXEC SQL UPDATE users SET potype = 'IMAP' WHERE users_id = :id; } + else if (eid) + { + EXEC SQL SELECT mach_id INTO :mid FROM machine + WHERE mach_id = :eid; + if (sqlca.sqlerrd[2] == 0) + return MR_MACHINE; + EXEC SQL UPDATE users SET potype = 'EXCHANGE' WHERE users_id = :id; + } + + incremental_after(USERS_TABLE, buffer, 0); set_pobox_modtime(q, argv, cl); EXEC SQL UPDATE tblstats SET updates = updates + 1, modtime = SYSDATE @@ -1608,7 +1641,7 @@ int qualified_get_serverhost(struct query *q, char *argv[], client *cl, /* 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 - * pobox type ("POP" = POP, "IMAP" or numeric = IMAP) + * pobox type ("POP" = POP, "IMAP" or numeric = IMAP, "EXCHANGE" = EXCHANGE) */ int register_user(struct query *q, char **argv, client *cl) @@ -1621,7 +1654,7 @@ int register_user(struct query *q, char **argv, client *cl) int ostatus, nstatus, fsidval, popid; int npid, tmp; int po_exists = 0; - static int m_id, def_quota, def_imap_quota, list_id; + static int m_id, def_quota, def_imap_quota, list_id, exchange_id; EXEC SQL END DECLARE SECTION; char buffer[256], *aargv[3]; @@ -1632,6 +1665,9 @@ int register_user(struct query *q, char **argv, client *cl) EXEC SQL SELECT mach_id INTO :m_id FROM machine WHERE name = 'ATHENA.MIT.EDU'; + + EXEC SQL SELECT mach_id INTO :exchange_id FROM machine + WHERE name = 'EXCHANGE.MIT.EDU'; } EXEC SQL SELECT value INTO :def_quota FROM numvalues @@ -1756,6 +1792,13 @@ int register_user(struct query *q, char **argv, client *cl) WHERE users_id = :users_id; com_err(whoami, 0, "pobox set to POP:%s", strtrim(machname)); } + else if (!strcmp(potype, "EXCHANGE")) + { + EXEC SQL UPDATE users SET potype = 'EXCHANGE', + exchange_id = :exchange_id + WHERE users_id = :users_id; + com_err(whoami, 0, "pobox set to EXCHANGE:EXCHANGE.MIT.EDU"); + } else { /* Select all IMAP nfsphys entries in order of increasing -- 2.45.2