2 * - fix STOP error when we can't find control's nick
3 * - deal with Q/fishbot/O/T clones
4 * - deal with our own localusers
8 #include "../lib/version.h"
9 #include "../lib/ccassert.h"
10 #include "../lib/strlfunc.h"
11 #include "../core/error.h"
12 #include "../core/hooks.h"
13 #include "../core/schedule.h"
14 #include "../irc/irc.h"
15 #include "../nick/nick.h"
16 #include "../control/control.h"
17 #include "signontracker.h"
19 #define MAXWHOISLINES 50 /* from the ircd */
23 static void hook_newnick(int hook
, void *arg
);
24 static void hook_rename(int hook
, void *arg
);
25 static void queue_scan_nick(nick
*np
);
26 static void flush_queue_sched(void *arg
);
27 static int whois_reply_handler(void *source
, int cargc
, char **cargv
);
29 static int nickext
= -1;
31 #define QUEUEBUFLEN (MAXWHOISLINES*(NICKLEN+1)+1)
34 char buf
[QUEUEBUFLEN
];
43 CCASSERT(sizeof(time_t) <= sizeof(long));
45 nickext
= registernickext("signontracker");
49 registerhook(HOOK_NICK_NEWNICK
, &hook_newnick
);
50 registerhook(HOOK_NICK_RENAME
, &hook_rename
);
51 registernumerichandler(317, whois_reply_handler
, 7);
53 for(i
=0;i
<NICKHASHSIZE
;i
++)
54 for(np
=nicktable
[i
];np
;np
=np
->next
)
64 deregisterhook(HOOK_NICK_NEWNICK
, &hook_newnick
);
65 deregisterhook(HOOK_NICK_RENAME
, &hook_rename
);
66 deregisternumerichandler(317, whois_reply_handler
);
68 for(i
=0;i
<MAXSERVERS
;i
++)
69 deleteschedule(queue
[i
].sched
, flush_queue_sched
, (void *)(long)i
);
71 releasenickext(nickext
);
74 static int whois_reply_handler(void *source
, int cargc
, char **cargv
) {
81 np
= getnickbynick(cargv
[3]);
85 connected
= strtoul(cargv
[5], NULL
, 10);
86 np
->exts
[nickext
] = (void *)connected
;
88 triggerhook(HOOK_SIGNONTRACKER_HAVETIME
, np
);
93 static void flush_queue(int server
) {
94 char control_numeric
[6];
96 if(!queue
[server
].len
)
101 Error("signontracker", ERR_STOP
, "Unable to get control nick.");
104 longtonumeric2(mynick
->numeric
, 5, control_numeric
);
106 irc_send("%s W %s %s", control_numeric
, longtonumeric(server
, 2), queue
[server
].buf
);
107 queue
[server
].len
= 0;
108 queue
[server
].buf
[0] = '\0';
111 static void queue_scan_nick(nick
*np
) {
114 if(NickOnServiceServer(np
)) /* TODO: fix */
117 server
= homeserver(np
->numeric
);
119 if(queue
[server
].len
)
120 strlcat(queue
[server
].buf
, ",", QUEUEBUFLEN
);
124 strlcat(queue
[server
].buf
, np
->nick
, QUEUEBUFLEN
);
126 if(queue
[server
].len
== MAXWHOISLINES
) {
128 } else if(queue
[server
].sched
== NULL
) {
129 queue
[server
].sched
= scheduleoneshot(time(NULL
), flush_queue_sched
, (void *)(long)server
);
133 static void flush_queue_sched(void *arg
) {
134 int server
= (long)arg
;
137 queue
[server
].sched
= NULL
;
140 static void hook_newnick(int hook
, void *arg
) {
141 nick
*np
= (nick
*)arg
;
146 static void hook_rename(int hook
, void *arg
) {
147 nick
*np
= (nick
*)arg
;
149 if(getnicksignon(np
))
155 time_t getnicksignon(nick
*np
) {
159 return (time_t)np
->exts
[nickext
];