+
+
+run_cmd(cmd)
+char *cmd;
+{
+ int success=0, tries=0;
+
+ check_afs();
+
+ while (success == 0 && tries < 2) {
+ if (tries++)
+ sleep(90);
+ com_err(whoami, 0, "Executing command: %s", cmd);
+ if (system(cmd) == 0)
+ success++;
+ }
+ if (!success)
+ critical_alert("incremental", "failed command: %s", cmd);
+}
+
+
+add_user_lists(ac, av, user)
+ int ac;
+ char *av[];
+ char *user;
+{
+ if (atoi(av[L_ACTIVE]) && atoi(av[L_GROUP])) /* active group ? */
+ edit_group(1, av[L_NAME], "USER", user);
+ return 0;
+}
+
+
+add_list_members(ac, av, group)
+ int ac;
+ char *av[];
+ char *group;
+{
+ edit_group(1, group, av[0], av[1]);
+ return 0;
+}
+
+
+check_user(ac, av, ustate)
+ int ac;
+ char *av[];
+ int *ustate;
+{
+ *ustate = atoi(av[U_STATE]);
+ return 0;
+}
+
+
+edit_group(op, group, type, member)
+ int op;
+ char *group;
+ char *type;
+ char *member;
+{
+ char *p = 0;
+ char buf[PR_MAXNAMELEN];
+ int code, ustate;
+ static char local_realm[REALM_SZ+1] = "";
+ struct member *m;
+
+ /* The following KERBEROS code allows for the use of entities
+ * user@foreign_cell.
+ */
+ if (!local_realm[0])
+ krb_get_lrealm(local_realm, 1);
+ if (!strcmp(type, "KERBEROS")) {
+ p = strchr(member, '@');
+ if (p && !strcasecmp(p+1, local_realm))
+ *p = 0;
+ } else if (strcmp(type, "USER"))
+ return; /* invalid type */
+
+ /* Cannot risk doing another query during a callback */
+ /* We could do this simply for type USER, but eventually this may also
+ * dynamically add KERBEROS types to the prdb, and we will need to do
+ * a query to look up the uid of the null-instance user */
+ if (mr_connections) {
+ m = (struct member *)malloc(sizeof(struct member));
+ if (!m) {
+ critical_alert("incremental", "Out of memory");
+ exit(1);
+ }
+ m->op = op;
+ strcpy(m->list, group);
+ strcpy(m->type, type);
+ strcpy(m->member, member);
+ m->next = member_head;
+ member_head = m;
+ return;
+ }
+
+ strcpy(buf, "system:");
+ strcat(buf, group);
+ com_err(whoami, 0, "%s %s %s group %s",
+ (op ? "Adding" : "Removing"), member,
+ (op ? "to" : "from"), group);
+ code = 0;
+ code=pr_try(op ? pr_AddToGroup : pr_RemoveUserFromGroup, member, buf);
+ if (code) {
+ if (op==1 && code == PRIDEXIST) return; /* Already added */
+
+ if (code == PRNOENT) { /* Something is missing */
+ if (op==0) return; /* Already deleted */
+ if (!strcmp(type, "KERBEROS")) /* Special instances; ok */
+ return;
+
+ /* Check whether the member being added is an active user */
+ code = moira_connect();
+ if (!code) code = mr_query("get_user_by_login", 1, &member,
+ check_user, &ustate);
+ if (code) {
+ critical_alert("incremental",
+ "Error contacting Moira server to lookup user %s: %s",
+ member, error_message(code));
+ }
+
+ /* We don't use moira_disconnect()
+ * because we may already be in the routine.
+ */
+ mr_disconnect();
+ mr_connections--;
+
+ if (!code && ustate!=1 && ustate!=2) return; /* inactive user */
+ code = PRNOENT;
+ }
+
+ critical_alert("incremental",
+ "Couldn't %s %s %s %s: %s",
+ op ? "add" : "remove", member,
+ op ? "to" : "from", buf,
+ error_message(code));
+ }
+}
+
+
+long pr_try(fn, a1, a2, a3, a4, a5, a6, a7, a8)
+ long (*fn)();
+ char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
+{
+ static int initd=0;
+ register long code;
+ register int tries = 0;
+#ifdef DEBUG
+ char fname[64];
+#endif
+
+ check_afs();
+
+ if (initd) {
+ code=pr_Initialize(0, AFSCONF_CLIENTNAME, 0);
+ } else {
+ code = 0;
+ initd = 1;
+ }
+ if (!code) code=pr_Initialize(1, AFSCONF_CLIENTNAME, 0);
+ if (code) {
+ critical_alert("incremental", "Couldn't initialize libprot: %s",
+ error_message(code));
+ return;
+ }
+
+ sleep(1); /* give ptserver room */
+
+ while (code = (*fn)(a1, a2, a3, a4, a5, a6, a7, a8)) {
+#ifdef DEBUG
+ long t;
+ t = time(0);
+ if (fn == pr_AddToGroup) strcpy(fname, "pr_AddToGroup");
+ else if (fn == pr_RemoveUserFromGroup)
+ strcpy(fname, "pr_RemoveUserFromGroup");
+ else if (fn == pr_CreateUser) strcpy(fname, "pr_CreateUser");
+ else if (fn == pr_CreateGroup) strcpy(fname, "pr_CreateGroup");
+ else if (fn == pr_DeleteByID) strcpy(fname, "pr_DeleteByID");
+ else if (fn == pr_ChangeEntry) strcpy(fname, "pr_ChangeEntry");
+ else if (fn == pr_SetFieldsEntry) strcpy(fname, "pr_SetFieldsEntry");
+ else if (fn == pr_AddToGroup) strcpy(fname, "pr_AddToGroup");
+ else
+ sprintf(fname, "pr_??? (0x%08x)", (long)fn);
+
+ com_err(whoami, code, "- %s failed (try %d @%u)", fname, tries+1, t);
+#endif
+ if (++tries > 2) break; /* 3 tries */
+
+ if (code == UNOQUORUM) sleep(90);
+ else sleep(15);
+
+ /* Re-initialize the prdb connection */
+ code=pr_Initialize(0, AFSCONF_CLIENTNAME, 0);
+ if (!code) code=pr_Initialize(1, AFSCONF_CLIENTNAME, 0);
+ if (code) {
+ critical_alert("incremental", "Couldn't re-initialize libprot: %s",
+ error_message(code));
+ initd = 0; /* we lost */
+ break;
+ }
+ }
+ return code;
+}
+
+
+check_afs()
+{
+ int i;
+
+ for (i=0; file_exists(STOP_FILE); i++) {
+ if (i > 30) {
+ critical_alert("incremental",
+ "AFS incremental failed (%s exists): %s",
+ STOP_FILE, tbl_buf);
+ exit(1);
+ }
+ sleep(60);
+ }
+}
+
+
+moira_connect()
+{
+ static char hostname[64];
+ long code;
+
+ if (!mr_connections++) {
+ gethostname(hostname, sizeof(hostname));
+ code = mr_connect(hostname);
+ if (!code) code = mr_auth("afs.incr");
+ return code;
+ }
+ return 0;
+}
+
+moira_disconnect()
+{
+ struct member *m;
+
+ if (!--mr_connections) {
+ mr_disconnect();
+ while(m = member_head) {
+ edit_group(m->op, m->list, m->type, m->member);
+ member_head = m->next;
+ free(m);
+ }
+ }
+ return 0;
+}