+/**
+ * Send WHO reply for a "channel target" ("WHO #channel").
+ *
+ * @param Client Client requesting the information.
+ * @param Chan Channel being requested.
+ * @param OnlyOps Only display IRC operators.
+ * @return CONNECTED or DISCONNECTED.
+ */
+static bool
+IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
+{
+ bool is_visible, is_member, is_ircop;
+ CL2CHAN *cl2chan;
+ const char *client_modes;
+ const char *chan_user_modes;
+ char flags[10];
+ CLIENT *c;
+ int count = 0;
+
+ assert( Client != NULL );
+ assert( Chan != NULL );
+
+ is_member = Channel_IsMemberOf(Chan, Client);
+
+ /* Secret channel? */
+ if (!is_member && strchr(Channel_Modes(Chan), 's'))
+ return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG,
+ Client_ID(Client), Channel_Name(Chan));
+
+ cl2chan = Channel_FirstMember(Chan);
+ for (; cl2chan ; cl2chan = Channel_NextMember(Chan, cl2chan)) {
+ c = Channel_GetClient(cl2chan);
+
+ client_modes = Client_Modes(c);
+ is_ircop = strchr(client_modes, 'o') != NULL;
+ if (OnlyOps && !is_ircop)
+ continue;
+
+ is_visible = strchr(client_modes, 'i') == NULL;
+ if (is_member || is_visible) {
+ if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO"))
+ break;
+
+ strcpy(flags, who_flags_status(client_modes));
+ if (is_ircop)
+ strlcat(flags, "*", sizeof(flags));
+
+ chan_user_modes = Channel_UserModes(Chan, c);
+ who_flags_qualifier(c, chan_user_modes, flags, sizeof(flags));
+
+ if (!write_whoreply(Client, c, Channel_Name(Chan),
+ flags))
+ return DISCONNECTED;
+ count++;
+ }