]> jfr.im git - solanum.git/blobdiff - modules/m_services.c
MODRESTART/MODRELOAD: Defer reloading more quickly
[solanum.git] / modules / m_services.c
index b8a1f363ffc0d804a29b13be9e3ff036d19c942a..bf378600b7508258de0260a21c96e7f0132bd878 100644 (file)
@@ -59,9 +59,9 @@ static void me_login(struct MsgBuf *, struct Client *, struct Client *, int, con
 static void me_rsfnc(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
 static void me_nickdelay(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
 
-static void h_svc_server_introduced(hook_data_client *);
-static void h_svc_whois(hook_data_client *);
-static void h_svc_stats(hook_data_int *);
+static void h_svc_server_introduced(void *);
+static void h_svc_whois(void *);
+static void h_svc_stats(void *);
 static void h_svc_conf_read_start(void *);
 static void h_svc_conf_read_end(void *);
 
@@ -86,12 +86,12 @@ mapi_clist_av1 services_clist[] = {
        &su_msgtab, &login_msgtab, &rsfnc_msgtab, &nickdelay_msgtab, NULL
 };
 mapi_hfn_list_av1 services_hfnlist[] = {
-       { "doing_stats",        (hookfn) h_svc_stats },
-       { "doing_whois",        (hookfn) h_svc_whois },
-       { "doing_whois_global", (hookfn) h_svc_whois },
-       { "server_introduced",  (hookfn) h_svc_server_introduced },
-       { "conf_read_start", (hookfn) h_svc_conf_read_start },
-       { "conf_read_end", (hookfn) h_svc_conf_read_end },
+       { "doing_stats",        h_svc_stats },
+       { "doing_whois",        h_svc_whois },
+       { "doing_whois_global", h_svc_whois },
+       { "server_introduced",  h_svc_server_introduced },
+       { "conf_read_start", h_svc_conf_read_start },
+       { "conf_read_end", h_svc_conf_read_end },
        { NULL, NULL }
 };
 
@@ -136,10 +136,20 @@ me_su(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
        else
                rb_strlcpy(target_p->user->suser, parv[2], sizeof(target_p->user->suser));
 
-       sendto_common_channels_local_butone(target_p, CLICAP_ACCOUNT_NOTIFY, NOCAPS, ":%s!%s@%s ACCOUNT %s",
+       sendto_common_channels_local(target_p, CLICAP_ACCOUNT_NOTIFY, NOCAPS, ":%s!%s@%s ACCOUNT %s",
                                            target_p->name, target_p->username, target_p->host,
                                            EmptyString(target_p->user->suser) ? "*" : target_p->user->suser);
 
+       if (MyClient(target_p))
+       {
+               if (EmptyString(target_p->user->suser))
+                       sendto_one(target_p, form_str(RPL_LOGGEDOUT), me.name, target_p->name,
+                               target_p->name, target_p->username, target_p->host);
+               else
+                       sendto_one(target_p, form_str(RPL_LOGGEDIN), me.name, target_p->name,
+                               target_p->name, target_p->username, target_p->host, parv[2], parv[2]);
+       }
+
        invalidate_bancache_user(target_p);
 }
 
@@ -153,6 +163,13 @@ me_login(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
        rb_strlcpy(source_p->user->suser, parv[1], sizeof(source_p->user->suser));
 }
 
+/* me_rsfnc()
+ *     parv[1] = current user nickname
+ *     parv[2] = target nickname
+ *     parv[3] = new nickts
+ *     parv[4] = current nickts
+ *     parv[5] = optional; 0 (don't override RESVs) or 1 (override RESVs)
+ */
 static void
 me_rsfnc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
        int parc, const char *parv[])
@@ -160,7 +177,8 @@ me_rsfnc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
        struct Client *target_p;
        struct Client *exist_p;
        time_t newts, curts;
-       char note[NICKLEN + 10];
+       struct nd_entry *nd;
+       char note[NAMELEN + 10];
 
        if(!(source_p->flags & FLAGS_SERVICE))
        {
@@ -187,6 +205,12 @@ me_rsfnc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
        if(target_p->tsinfo != curts)
                return;
 
+       /* received a non-forced RSFNC for a nickname that is RESV.
+        * silently ignore it. ~jess
+        */
+       if(parc > 5 && atoi(parv[5]) == 0 && find_nick_resv(parv[2]))
+               return;
+
        if((exist_p = find_named_client(parv[2])))
        {
                char buf[BUFSIZE];
@@ -245,14 +269,23 @@ doit:
                        use_id(target_p), parv[2], (long) target_p->tsinfo);
 
        del_from_client_hash(target_p->name, target_p);
+
+       /* invalidate nick delay because we're forcing this nick to be used */
+       nd = rb_dictionary_retrieve(nd_dict, parv[2]);
+       if (nd != NULL)
+               free_nd_entry(nd);
+
        rb_strlcpy(target_p->name, parv[2], NICKLEN);
        add_to_client_hash(target_p->name, target_p);
 
        monitor_signon(target_p);
 
-       del_all_accepts(target_p);
+       /* Make sure everyone that has this client on its accept list
+        * loses that reference.
+        */
+       del_all_accepts(target_p, false);
 
-       snprintf(note, NICKLEN + 10, "Nick: %s", target_p->name);
+       snprintf(note, sizeof(note), "Nick: %s", target_p->name);
        rb_note(target_p->localClient->F, note);
 }
 
@@ -293,8 +326,9 @@ me_nickdelay(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *so
 }
 
 static void
-h_svc_server_introduced(hook_data_client *hdata)
+h_svc_server_introduced(void *data)
 {
+       hook_data_client *hdata = data;
        rb_dlink_node *ptr;
 
        RB_DLINK_FOREACH(ptr, service_list.head)
@@ -308,8 +342,9 @@ h_svc_server_introduced(hook_data_client *hdata)
 }
 
 static void
-h_svc_whois(hook_data_client *data)
+h_svc_whois(void *data_)
 {
+       hook_data_client *data = data_;
        char *p = data->target->user->suser;
        if(!EmptyString(p))
        {
@@ -329,12 +364,13 @@ h_svc_whois(hook_data_client *data)
 }
 
 static void
-h_svc_stats(hook_data_int *data)
+h_svc_stats(void *data_)
 {
+       hook_data_int *data = data_;
        char statchar = (char) data->arg2;
        rb_dlink_node *ptr;
 
-       if (statchar == 'U' && IsOper(data->client))
+       if (statchar == 'U' && IsOperGeneral(data->client))
        {
                RB_DLINK_FOREACH(ptr, service_list.head)
                {