fix possible crash on user deletion
[srvx.git] / src / proto-bahamut.c
index 790010ecfa6b2ec7f354defb12d589c70a0a7323..a0c1d98ef102d5f80004c0a05aa3cb8dc21a2f79 100644 (file)
@@ -38,10 +38,13 @@ static dict_t service_msginfo_dict; /* holds service_message_info structs */
 static int uplink_capab;
 static void privmsg_user_helper(struct userNode *un, void *data);
 
+/* These correspond to 1 << X:      012345678901234567 */
+const char irc_user_mode_chars[] = "o iw dkg      r   ";
+
 void irc_svsmode(struct userNode *target, char *modes, unsigned long stamp);
 
 struct server *
-AddServer(struct server *uplink, const char *name, int hops, unsigned long boot, unsigned long link, UNUSED_ARG(const char *numeric), const char *description) {
+AddServer(struct server *uplink, const char *name, int hops, unsigned long boot, unsigned long link_time, UNUSED_ARG(const char *numeric), const char *description) {
     struct server* sNode;
 
     sNode = calloc(1, sizeof(*sNode));
@@ -49,7 +52,7 @@ AddServer(struct server *uplink, const char *name, int hops, unsigned long boot,
     safestrncpy(sNode->name, name, sizeof(sNode->name));
     sNode->hops = hops;
     sNode->boot = boot;
-    sNode->link = link;
+    sNode->link_time = link_time;
     sNode->users = dict_new();
     safestrncpy(sNode->description, description, sizeof(sNode->description));
     serverList_init(&sNode->children);
@@ -168,9 +171,8 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char *
     if (dummy) uNode->modes |= FLAGS_DUMMY;
     if (stamp) call_account_func(uNode, NULL, 0, stamp);
     if (IsLocal(uNode)) irc_user(uNode);
-    for (nn=0; nn<nuf_used; nn++) {
-        if (nuf_list[nn](uNode)) break;
-    }
+    for (nn=0; (nn<nuf_used) && !uNode->dead; nn++)
+        nuf_list[nn](uNode);
     return uNode;
 }
 
@@ -242,16 +244,8 @@ irc_server(struct server *srv) {
 void
 irc_user(struct userNode *user) {
     char modes[32];
-    int modelen = 0;
     if (!user || user->nick[0] != ' ') return;
-    if (IsOper(user)) modes[modelen++] = 'o';
-    if (IsInvisible(user)) modes[modelen++] = 'i';
-    if (IsWallOp(user)) modes[modelen++] = 'w';
-    if (IsService(user)) modes[modelen++] = 'k';
-    if (IsDeaf(user)) modes[modelen++] = 'd';
-    if (IsReggedNick(user)) modes[modelen++] = 'r';
-    if (IsGlobal(user)) modes[modelen++] = 'g';
-    modes[modelen] = 0;
+    irc_user_modes(user, modes, sizeof(modes));
     putsock("NICK %s %d %lu +%s %s %s %s %d %u :%s",
             user->nick, user->uplink->hops+2, (unsigned long)user->timestamp,
             modes, user->ident, user->hostname, user->uplink->name, 0,
@@ -269,7 +263,7 @@ irc_account(struct userNode *user, UNUSED_ARG(const char *stamp), UNUSED_ARG(uns
 }
 
 void
-irc_fakehost(UNUSED_ARG(struct userNode *user), UNUSED_ARG(const char *host))
+irc_fakehost(UNUSED_ARG(struct userNode *user), UNUSED_ARG(const char *host), UNUSED_ARG(const char *ident), UNUSED_ARG(int force))
 {
     /* not supported in bahamut */
 }
@@ -1043,12 +1037,9 @@ static CMD_FUNC(cmd_svsnick)
     return 1;
 }
 
-static oper_func_t *of_list;
-static unsigned int of_size = 0, of_used = 0;
-
 void parse_cleanup(void) {
     unsigned int nn;
-    if (of_list) free(of_list);
+    free(of_list);
     dict_delete(irc_func_dict);
     dict_delete(service_msginfo_dict);
     free(mcf_list);
@@ -1114,6 +1105,7 @@ void init_parse(void) {
 
     userList_init(&dead_users);
     reg_exit_func(parse_cleanup);
+    (void)call_xquery_funcs;
 }
 
 int parse_line(char *line, int recursive) {
@@ -1206,32 +1198,6 @@ unreg_notice_func(struct userNode *user) {
     }
 }
 
-void
-reg_oper_func(oper_func_t handler)
-{
-    if (of_used == of_size) {
-        if (of_size) {
-            of_size <<= 1;
-            of_list = realloc(of_list, of_size*sizeof(oper_func_t));
-        } else {
-            of_size = 8;
-            of_list = malloc(of_size*sizeof(oper_func_t));
-        }
-    }
-    of_list[of_used++] = handler;
-}
-
-static void
-call_oper_funcs(struct userNode *user)
-{
-    unsigned int n;
-    if (IsLocal(user)) return;
-    for (n=0; n<of_used; n++)
-    {
-        of_list[n](user);
-    }
-}
-
 void mod_usermode(struct userNode *user, const char *mode_change) {
     int add = 1;
 
@@ -1265,7 +1231,7 @@ void mod_usermode(struct userNode *user, const char *mode_change) {
 }
 
 struct mod_chanmode *
-mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags, short base_oplevel)
+mod_chanmode_parse(struct chanNode *channel, struct userNode *user, char **modes, unsigned int argc, unsigned int flags, short base_oplevel)
 {
     struct mod_chanmode *change;
     unsigned int ii, in_arg, ch_arg, add;
@@ -1508,6 +1474,9 @@ char *
 mod_chanmode_format(struct mod_chanmode *change, char *outbuff)
 {
     unsigned int used = 0;
+    unsigned int args_used = 0;
+    char args[MAXLEN];
+
     assert(change->argc <= change->alloc_argc);
     if (change->modes_clear) {
         outbuff[used++] = '-';
@@ -1539,19 +1508,11 @@ mod_chanmode_format(struct mod_chanmode *change, char *outbuff)
         DO_MODE_CHAR(REGONLY, 'R');
         DO_MODE_CHAR(NOCOLORS, 'c');
         DO_MODE_CHAR(REGISTERED, 'r');
+        DO_MODE_CHAR(LIMIT, 'l'), args_used += sprintf(args + args_used, " %d", change->new_limit);
+        DO_MODE_CHAR(KEY, 'k'), args_used += sprintf(args + args_used, " %s", change->new_key);
 #undef DO_MODE_CHAR
-        switch (change->modes_set & (MODE_KEY|MODE_LIMIT)) {
-        case MODE_KEY|MODE_LIMIT:
-            used += sprintf(outbuff+used, "lk %d %s", change->new_limit, change->new_key);
-            break;
-        case MODE_KEY:
-            used += sprintf(outbuff+used, "k %s", change->new_key);
-            break;
-        case MODE_LIMIT:
-            used += sprintf(outbuff+used, "l %d", change->new_limit);
-            break;
-        }
     }
-    outbuff[used] = 0;
+    args[args_used] = '\0';
+    strcpy(outbuff + used, args);
     return outbuff;
 }