-static int
-add_target(struct Client *source_p, struct Client *target_p)
-{
- int i, j;
- uint32_t hashv;
- uint32_t *targets;
-
- /* can msg themselves or services without using any target slots */
- if(source_p == target_p || IsService(target_p))
- return 1;
-
- /* special condition for those who have had PRIVMSG crippled to allow them
- * to talk to IRCops still.
- *
- * XXX: is this controversial?
- */
- if(source_p->localClient->target_last > rb_current_time() && IsOper(target_p))
- return 1;
-
- hashv = fnv_hash_upper((const unsigned char *)use_id(target_p), 32);
- targets = source_p->localClient->targets;
-
- /* check for existing target, and move it to the head */
- for(i = 0; i < TGCHANGE_NUM; i++)
- {
- if(targets[i] == hashv)
- {
- for(j = i; j > 0; j--)
- targets[j] = targets[j - 1];
- targets[0] = hashv;
- return 1;
- }
- }
-
- if(source_p->localClient->targets_free < TGCHANGE_NUM)
- {
- /* first message after connect, we may only start clearing
- * slots after this message --anfl
- */
- if(!IsTGChange(source_p))
- {
- SetTGChange(source_p);
- source_p->localClient->target_last = rb_current_time();
- }
- /* clear as many targets as we can */
- else if((i = (rb_current_time() - source_p->localClient->target_last) / 60))
- {
- if(i + source_p->localClient->targets_free > TGCHANGE_NUM)
- source_p->localClient->targets_free = TGCHANGE_NUM;
- else
- source_p->localClient->targets_free += i;
-
- source_p->localClient->target_last = rb_current_time();
- }
- /* cant clear any, full target list */
- else if(source_p->localClient->targets_free == 0)
- {
- ServerStats.is_tgch++;
- add_tgchange(source_p->sockhost);
- return 0;
- }
- }
- /* no targets in use, reset their target_last so that they cant
- * abuse a long idle to get targets back more quickly
- */
- else
- {
- source_p->localClient->target_last = rb_current_time();
- SetTGChange(source_p);
- }
-
- for(i = TGCHANGE_NUM - 1; i > 0; i--)
- targets[i] = targets[i - 1];
- targets[0] = hashv;
- source_p->localClient->targets_free--;
- return 1;
-}
-