+ struct SLink *lp;
+ struct Ban *bp;
+
+ if (cli_serv(bcptr) && cli_serv(bcptr)->client_list) /* Was SetServerYXX called ? */
+ ClearServerYXX(bcptr); /* Removes server from server_list[] */
+ if (IsUser(bcptr)) {
+ /*
+ * clear out uping requests
+ */
+ if (IsUPing(bcptr))
+ uping_cancel(bcptr, 0);
+ /*
+ * Stop a running /LIST clean
+ */
+ if (MyUser(bcptr) && cli_listing(bcptr)) {
+ MyFree(cli_listing(bcptr));
+ cli_listing(bcptr) = NULL;
+ }
+ /*
+ * If a person is on a channel, send a QUIT notice
+ * to every client (person) on the same channel (so
+ * that the client can show the "**signoff" message).
+ * (Note: The notice is to the local clients *only*)
+ */
+ sendcmdto_common_channels_butone(bcptr, CMD_QUIT, NULL, ":%s", comment);
+
+ remove_user_from_all_channels(bcptr);
+
+ /* Clean up invitefield */
+ while ((lp = cli_user(bcptr)->invited))
+ del_invite(bcptr, lp->value.chptr);
+
+ /* Clean up silencefield */
+ while ((bp = cli_user(bcptr)->silence)) {
+ cli_user(bcptr)->silence = bp->next;
+ free_ban(bp);
+ }
+
+ /* Clean up snotice lists */
+ if (MyUser(bcptr))
+ set_snomask(bcptr, ~0, SNO_DEL);
+
+ if (IsInvisible(bcptr)) {
+ assert(UserStats.inv_clients > 0);
+ --UserStats.inv_clients;
+ }
+ if (IsOper(bcptr)) {
+ assert(UserStats.opers > 0);
+ --UserStats.opers;
+ }
+ if (MyConnect(bcptr))
+ Count_clientdisconnects(bcptr, UserStats);
+ else
+ Count_remoteclientquits(UserStats, bcptr);
+ }
+ else if (IsServer(bcptr))
+ {
+ /* Remove downlink list node of uplink */
+ remove_dlink(&(cli_serv(cli_serv(bcptr)->up))->down, cli_serv(bcptr)->updown);
+ cli_serv(bcptr)->updown = 0;
+
+ if (MyConnect(bcptr))
+ Count_serverdisconnects(UserStats);
+ else
+ Count_remoteserverquits(UserStats);
+ }
+ else if (IsMe(bcptr))
+ {
+ sendto_opmask_butone(0, SNO_OLDSNO, "ERROR: tried to exit me! : %s",
+ comment);
+ return; /* ...must *never* exit self! */
+ }
+ else if (IsUnknown(bcptr) || IsConnecting(bcptr) || IsHandshake(bcptr))
+ Count_unknowndisconnects(UserStats);
+
+ /*
+ * Update IPregistry
+ */
+ if (IsIPChecked(bcptr))
+ IPcheck_disconnect(bcptr);
+
+ /*
+ * Remove from serv->client_list
+ * NOTE: user is *always* NULL if this is a server
+ */
+ if (cli_user(bcptr)) {
+ assert(!IsServer(bcptr));
+ /* bcptr->user->server->serv->client_list[IndexYXX(bcptr)] = NULL; */
+ RemoveYXXClient(cli_user(bcptr)->server, cli_yxx(bcptr));
+ }
+
+ /* Remove bcptr from the client list */
+#ifdef DEBUGMODE
+ if (hRemClient(bcptr) != 0)
+ Debug((DEBUG_ERROR, "%p !in tab %s[%s] %p %p %p %d %d %p",
+ bcptr, cli_name(bcptr), cli_from(bcptr) ? cli_sockhost(cli_from(bcptr)) : "??host",
+ cli_from(bcptr), cli_next(bcptr), cli_prev(bcptr), cli_fd(bcptr),
+ cli_status(bcptr), cli_user(bcptr)));
+#else
+ hRemClient(bcptr);
+#endif
+ remove_client_from_list(bcptr);