+static struct adduserPending*
+add_adduser_pending(struct chanNode *channel, struct userNode *user, int level)
+{
+ struct adduserPending *ap;
+ ap = calloc(1,sizeof(struct adduserPending));
+ ap->channel = channel;
+ ap->user = user;
+ ap->level = level;
+ ap->created = time(NULL);
+
+ /* ap->prev defaults to NULL already.. */
+ ap->next = adduser_pendings;
+ if(adduser_pendings)
+ adduser_pendings->prev = ap;
+ adduser_pendings = ap;
+ adduser_pendings_count++;
+ return(ap);
+}
+
+static void
+del_adduser_pending(struct adduserPending *ap)
+{
+ if(ap->prev)
+ ap->prev->next = ap->next;
+ else
+ adduser_pendings = ap->next;
+
+ if(ap->next)
+ ap->next->prev = ap->prev;
+ free(ap);
+}
+
+static void expire_adduser_pending();
+
+/* find_adduser_pending(channel, user) will find an arbitrary record
+ * from user, channel, or user and channel.
+ * if user or channel are NULL, they will match any records.
+ */
+static struct adduserPending*
+find_adduser_pending(struct chanNode *channel, struct userNode *user)
+{
+ struct adduserPending *ap;
+
+ expire_adduser_pending(); /* why not here.. */
+
+ if(!channel && !user) /* 2 nulls matches all */
+ return(adduser_pendings);
+ for(ap = adduser_pendings;ap;ap = ap->next)
+ {
+ if((channel == ap->channel && (user == NULL || user == ap->user)) || (user==ap->user && channel==NULL))
+ return ap;
+ }
+ return NULL;
+}
+
+
+/* Remove all pendings for a user or channel
+ *
+ * called in nickserv.c DelUser() and proto-* unregister_channel()
+ */
+void
+wipe_adduser_pending(struct chanNode *channel, struct userNode *user)
+{
+ struct adduserPending *ap;
+
+ /* So this is a bit wastefull, i hate dealing with linked lists.
+ * if its a problem we'll rewrite it right */
+ while((ap = find_adduser_pending(channel, user))) {
+ del_adduser_pending(ap);
+ }
+}
+
+/* Called from nickserv.c cmd_auth after someone auths */
+void
+process_adduser_pending(struct userNode *user)
+{
+ struct adduserPending *ap;
+ if(!user->handle_info)
+ return; /* not associated with an account */
+ while((ap = find_adduser_pending(NULL, user)))
+ {
+ struct userData *actee;
+ if(GetTrueChannelAccess(ap->channel->channel_info, ap->user->handle_info))
+ {
+ /* Already on the userlist. do nothing*/
+ }
+ else
+ {
+ actee = add_channel_user(ap->channel->channel_info, ap->user->handle_info, ap->level, 0, NULL);
+ scan_user_presence(actee, NULL);
+ }
+ del_adduser_pending(ap);
+ }
+}
+
+static void
+expire_adduser_pending()
+{
+ struct adduserPending *ap, *ap_next;
+ ap = adduser_pendings;
+ while(ap)
+ {
+ if((ap->created + ADDUSER_PENDING_EXPIRE) < time(NULL))
+ { /* expire it */
+ ap_next = ap->next; /* save next */
+ del_adduser_pending(ap); /* free and relink */
+ ap = ap_next; /* advance */
+ }
+ else
+ ap = ap->next;
+ }
+}
+