00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 static int msg_hello(char *nick, char *h, struct userrec *u, char *p)
00027 {
00028 char host[UHOSTLEN], s[UHOSTLEN], s1[UHOSTLEN], handle[HANDLEN + 1];
00029 char *p1;
00030 int common = 0;
00031 int atr = 0;
00032 struct chanset_t *chan;
00033
00034 if (!learn_users && !make_userfile)
00035 return 0;
00036
00037 if (match_my_nick(nick))
00038 return 1;
00039
00040 if (u) {
00041 atr = u->flags;
00042 if (!(atr & USER_COMMON)) {
00043 dprintf(DP_HELP, "NOTICE %s :%s, %s.\n", nick, IRC_HI, u->handle);
00044 return 1;
00045 }
00046 }
00047 strncpyz(handle, nick, sizeof(handle));
00048 if (get_user_by_handle(userlist, handle)) {
00049 dprintf(DP_HELP, IRC_BADHOST1, nick);
00050 dprintf(DP_HELP, IRC_BADHOST2, nick, botname);
00051 return 1;
00052 }
00053 egg_snprintf(s, sizeof s, "%s!%s", nick, h);
00054 if (u_match_mask(global_bans, s)) {
00055 dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, IRC_BANNED2);
00056 return 1;
00057 }
00058 if (atr & USER_COMMON) {
00059 maskhost(s, host);
00060 strcpy(s, host);
00061 egg_snprintf(host, sizeof host, "%s!%s", nick, s + 2);
00062 userlist = adduser(userlist, handle, host, "-", USER_DEFAULT);
00063 putlog(LOG_MISC, "*", "%s %s (%s) -- %s",
00064 IRC_INTRODUCED, nick, host, IRC_COMMONSITE);
00065 common = 1;
00066 } else {
00067 maskhost(s, host);
00068 if (make_userfile) {
00069 userlist = adduser(userlist, handle, host, "-",
00070 sanity_check(default_flags | USER_MASTER | USER_OWNER));
00071 set_user(&USERENTRY_HOSTS, get_user_by_handle(userlist, handle),
00072 "-telnet!*@*");
00073 } else
00074 userlist = adduser(userlist, handle, host, "-",
00075 sanity_check(default_flags));
00076 putlog(LOG_MISC, "*", "%s %s (%s)", IRC_INTRODUCED, nick, host);
00077 }
00078 for (chan = chanset; chan; chan = chan->next)
00079 if (ismember(chan, handle))
00080 add_chanrec_by_handle(userlist, handle, chan->dname);
00081 dprintf(DP_HELP, IRC_SALUT1, nick, nick, botname);
00082 dprintf(DP_HELP, IRC_SALUT2, nick, host);
00083 if (common) {
00084 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_SALUT2A);
00085 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_SALUT2B);
00086 }
00087 if (make_userfile) {
00088 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_INITOWNER1);
00089 dprintf(DP_HELP, IRC_NEWBOT1, nick, botname);
00090 dprintf(DP_HELP, IRC_NEWBOT2, nick);
00091 putlog(LOG_MISC, "*", IRC_INIT1, handle);
00092 make_userfile = 0;
00093 write_userfile(-1);
00094 add_note(handle, botnetnick, IRC_INITNOTE, -1, 0);
00095 } else {
00096 dprintf(DP_HELP, IRC_INTRO1, nick, botname);
00097 }
00098 if (strlen(nick) > HANDLEN)
00099
00100 dprintf(DP_HELP, IRC_NICKTOOLONG, nick, handle);
00101 if (notify_new[0]) {
00102 egg_snprintf(s, sizeof s, IRC_INITINTRO, nick, host);
00103 strcpy(s1, notify_new);
00104 while (s1[0]) {
00105 p1 = strchr(s1, ',');
00106 if (p1 != NULL) {
00107 *p1 = 0;
00108 p1++;
00109 rmspace(p1);
00110 }
00111 rmspace(s1);
00112 add_note(s1, botnetnick, s, -1, 0);
00113 if (p1 == NULL)
00114 s1[0] = 0;
00115 else
00116 strcpy(s1, p1);
00117 }
00118 }
00119 return 1;
00120 }
00121
00122 static int msg_pass(char *nick, char *host, struct userrec *u, char *par)
00123 {
00124 char *old, *new;
00125
00126 if (!u || match_my_nick(nick) || (u->flags & (USER_BOT | USER_COMMON)))
00127 return 1;
00128
00129 if (!par[0]) {
00130 dprintf(DP_HELP, "NOTICE %s :%s\n", nick,
00131 u_pass_match(u, "-") ? IRC_NOPASS : IRC_PASS);
00132 putlog(LOG_CMDS, "*", "(%s!%s) !%s! PASS?", nick, host, u->handle);
00133 return 1;
00134 }
00135 old = newsplit(&par);
00136 if (!u_pass_match(u, "-") && !par[0]) {
00137 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_EXISTPASS);
00138 return 1;
00139 }
00140 if (par[0]) {
00141 if (!u_pass_match(u, old)) {
00142 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_FAILPASS);
00143 return 1;
00144 }
00145 new = newsplit(&par);
00146 } else
00147 new = old;
00148 putlog(LOG_CMDS, "*", "(%s!%s) !%s! PASS...", nick, host, u->handle);
00149 if (strlen(new) > 15)
00150 new[15] = 0;
00151 if (strlen(new) < 6) {
00152 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_PASSFORMAT);
00153 return 0;
00154 }
00155 set_user(&USERENTRY_PASS, u, new);
00156 dprintf(DP_HELP, "NOTICE %s :%s '%s'.\n", nick,
00157 new == old ? IRC_SETPASS : IRC_CHANGEPASS, new);
00158 return 1;
00159 }
00160
00161 static int msg_ident(char *nick, char *host, struct userrec *u, char *par)
00162 {
00163 char s[UHOSTLEN], s1[UHOSTLEN], *pass, who[NICKLEN];
00164 struct userrec *u2;
00165
00166 if (match_my_nick(nick) || (u && (u->flags & USER_BOT)))
00167 return 1;
00168
00169 if (u && (u->flags & USER_COMMON)) {
00170 if (!quiet_reject)
00171 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_FAILCOMMON);
00172 return 1;
00173 }
00174 pass = newsplit(&par);
00175 if (!par[0])
00176 strcpy(who, nick);
00177 else {
00178 strncpy(who, par, NICKMAX);
00179 who[NICKMAX] = 0;
00180 }
00181 u2 = get_user_by_handle(userlist, who);
00182 if (!u2) {
00183 if (u && !quiet_reject)
00184 dprintf(DP_HELP, IRC_MISIDENT, nick, nick, u->handle);
00185 } else if (rfc_casecmp(who, origbotname) && !(u2->flags & USER_BOT)) {
00186
00187 if (u_pass_match(u2, "-")) {
00188 putlog(LOG_CMDS, "*", "(%s!%s) !*! IDENT %s", nick, host, who);
00189 if (!quiet_reject)
00190 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOPASS);
00191 } else if (!u_pass_match(u2, pass)) {
00192 if (!quiet_reject)
00193 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_DENYACCESS);
00194 } else if (u == u2) {
00195
00196
00197
00198
00199
00200
00201 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_RECOGNIZED);
00202 return 1;
00203 } else if (u) {
00204 dprintf(DP_HELP, IRC_MISIDENT, nick, who, u->handle);
00205 return 1;
00206 } else {
00207 putlog(LOG_CMDS, "*", "(%s!%s) !*! IDENT %s", nick, host, who);
00208 egg_snprintf(s, sizeof s, "%s!%s", nick, host);
00209 maskhost(s, s1);
00210 dprintf(DP_HELP, "NOTICE %s :%s: %s\n", nick, IRC_ADDHOSTMASK, s1);
00211 addhost_by_handle(who, s1);
00212 check_this_user(who, 0, NULL);
00213 return 1;
00214 }
00215 }
00216 putlog(LOG_CMDS, "*", "(%s!%s) !*! failed IDENT %s", nick, host, who);
00217 return 1;
00218 }
00219
00220 static int msg_addhost(char *nick, char *host, struct userrec *u, char *par)
00221 {
00222 char *pass;
00223
00224 if (match_my_nick(nick) || !u || (u->flags & USER_BOT))
00225 return 1;
00226
00227 if (u->flags & USER_COMMON) {
00228 if (!quiet_reject)
00229 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_FAILCOMMON);
00230 return 1;
00231 }
00232 pass = newsplit(&par);
00233 if (!par[0]) {
00234 if (!quiet_reject)
00235 dprintf(DP_HELP, "NOTICE %s :You must supply a hostmask\n", nick);
00236 } else if (rfc_casecmp(u->handle, origbotname)) {
00237
00238 if (u_pass_match(u, "-")) {
00239 if (!quiet_reject)
00240 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOPASS);
00241 } else if (!u_pass_match(u, pass)) {
00242 if (!quiet_reject)
00243 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_DENYACCESS);
00244 } else if (get_user_by_host(par)) {
00245 if (!quiet_reject)
00246 dprintf(DP_HELP, "NOTICE %s :That hostmask clashes with another "
00247 "already in use.\n", nick);
00248 } else {
00249 putlog(LOG_CMDS, "*", "(%s!%s) !*! ADDHOST %s", nick, host, par);
00250 dprintf(DP_HELP, "NOTICE %s :%s: %s\n", nick, IRC_ADDHOSTMASK, par);
00251 addhost_by_handle(u->handle, par);
00252 check_this_user(u->handle, 0, NULL);
00253 return 1;
00254 }
00255 }
00256 putlog(LOG_CMDS, "*", "(%s!%s) !*! failed ADDHOST %s", nick, host, par);
00257 return 1;
00258 }
00259
00260 static int msg_info(char *nick, char *host, struct userrec *u, char *par)
00261 {
00262 char s[121], *pass, *chname, *p;
00263 int locked = 0;
00264
00265 if (!use_info || match_my_nick(nick))
00266 return 1;
00267
00268 if (!u)
00269 return 0;
00270
00271 if (u->flags & (USER_COMMON | USER_BOT))
00272 return 1;
00273
00274 if (!u_pass_match(u, "-")) {
00275 pass = newsplit(&par);
00276 if (!u_pass_match(u, pass)) {
00277 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed INFO", nick, host, u->handle);
00278 return 1;
00279 }
00280 } else {
00281 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed INFO", nick, host, u->handle);
00282 if (!quiet_reject)
00283 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOPASS);
00284 return 1;
00285 }
00286 if (par[0] && (strchr(CHANMETA, par[0]) != NULL)) {
00287 if (!findchan_by_dname(chname = newsplit(&par))) {
00288 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOMONITOR);
00289 return 1;
00290 }
00291 } else
00292 chname = 0;
00293 if (par[0]) {
00294 p = get_user(&USERENTRY_INFO, u);
00295 if (p && (p[0] == '@'))
00296 locked = 1;
00297 if (chname) {
00298 get_handle_chaninfo(u->handle, chname, s);
00299 if (s[0] == '@')
00300 locked = 1;
00301 }
00302 if (locked) {
00303 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_INFOLOCKED);
00304 return 1;
00305 }
00306 if (!egg_strcasecmp(par, "none")) {
00307 par[0] = 0;
00308 if (chname) {
00309 set_handle_chaninfo(userlist, u->handle, chname, NULL);
00310 dprintf(DP_HELP, "NOTICE %s :%s %s.\n", nick, IRC_REMINFOON, chname);
00311 putlog(LOG_CMDS, "*", "(%s!%s) !%s! INFO %s NONE", nick, host,
00312 u->handle, chname);
00313 } else {
00314 set_user(&USERENTRY_INFO, u, NULL);
00315 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_REMINFO);
00316 putlog(LOG_CMDS, "*", "(%s!%s) !%s! INFO NONE", nick, host, u->handle);
00317 }
00318 return 1;
00319 }
00320 if (par[0] == '@')
00321 par++;
00322 dprintf(DP_HELP, "NOTICE %s :%s %s\n", nick, IRC_FIELDCHANGED, par);
00323 if (chname) {
00324 set_handle_chaninfo(userlist, u->handle, chname, par);
00325 putlog(LOG_CMDS, "*", "(%s!%s) !%s! INFO %s ...", nick, host, u->handle,
00326 chname);
00327 } else {
00328 set_user(&USERENTRY_INFO, u, par);
00329 putlog(LOG_CMDS, "*", "(%s!%s) !%s! INFO ...", nick, host, u->handle);
00330 }
00331 return 1;
00332 }
00333 if (chname) {
00334 get_handle_chaninfo(u->handle, chname, s);
00335 p = s;
00336 putlog(LOG_CMDS, "*", "(%s!%s) !%s! INFO? %s", nick, host, u->handle,
00337 chname);
00338 } else {
00339 p = get_user(&USERENTRY_INFO, u);
00340 putlog(LOG_CMDS, "*", "(%s!%s) !%s! INFO?", nick, host, u->handle);
00341 }
00342 if (p && p[0]) {
00343 dprintf(DP_HELP, "NOTICE %s :%s %s\n", nick, IRC_FIELDCURRENT, p);
00344 dprintf(DP_HELP, "NOTICE %s :%s /msg %s info <pass>%s%s none\n",
00345 nick, IRC_FIELDTOREMOVE, botname, chname ? " " : "", chname
00346 ? chname : "");
00347 } else {
00348 if (chname)
00349 dprintf(DP_HELP, "NOTICE %s :%s %s.\n", nick, IRC_NOINFOON, chname);
00350 else
00351 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOINFO);
00352 }
00353 return 1;
00354 }
00355
00356 static int msg_who(char *nick, char *host, struct userrec *u, char *par)
00357 {
00358 struct chanset_t *chan;
00359 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00360 memberlist *m;
00361 char s[UHOSTLEN], also[512], *info;
00362 int i;
00363
00364 if (!use_info || match_my_nick(nick))
00365 return 1;
00366
00367 if (!u)
00368 return 0;
00369
00370 if (!par[0]) {
00371 dprintf(DP_HELP, "NOTICE %s :%s: /msg %s who <channel>\n", nick,
00372 MISC_USAGE, botname);
00373 return 0;
00374 }
00375 chan = findchan_by_dname(par);
00376 if (!chan) {
00377 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOMONITOR);
00378 return 0;
00379 }
00380 get_user_flagrec(u, &fr, par);
00381 if (channel_hidden(chan) && !hand_on_chan(chan, u) &&
00382 !glob_op(fr) && !glob_friend(fr) && !chan_op(fr) && !chan_friend(fr)) {
00383 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_CHANHIDDEN);
00384 return 1;
00385 }
00386 putlog(LOG_CMDS, "*", "(%s!%s) !%s! WHO", nick, host, u->handle);
00387 also[0] = 0;
00388 i = 0;
00389 for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
00390 struct userrec *u;
00391
00392 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
00393 u = get_user_by_host(s);
00394 info = get_user(&USERENTRY_INFO, u);
00395 if (u && (u->flags & USER_BOT))
00396 info = 0;
00397 if (info && (info[0] == '@'))
00398 info++;
00399 else if (u) {
00400 get_handle_chaninfo(u->handle, chan->dname, s);
00401 if (s[0]) {
00402 info = s;
00403 if (info[0] == '@')
00404 info++;
00405 }
00406 }
00407 if (info && info[0])
00408 dprintf(DP_HELP, "NOTICE %s :[%9s] %s\n", nick, m->nick, info);
00409 else {
00410 if (match_my_nick(m->nick))
00411 dprintf(DP_HELP, "NOTICE %s :[%9s] <-- I'm the bot, of course.\n",
00412 nick, m->nick);
00413 else if (u && (u->flags & USER_BOT)) {
00414 if (bot_flags(u) & BOT_SHARE)
00415 dprintf(DP_HELP, "NOTICE %s :[%9s] <-- a twin of me\n",
00416 nick, m->nick);
00417 else
00418 dprintf(DP_HELP, "NOTICE %s :[%9s] <-- another bot\n", nick, m->nick);
00419 } else {
00420 if (i) {
00421 also[i++] = ',';
00422 also[i++] = ' ';
00423 }
00424 i += my_strcpy(also + i, m->nick);
00425 if (i > 400) {
00426 dprintf(DP_HELP, "NOTICE %s :No info: %s\n", nick, also);
00427 i = 0;
00428 also[0] = 0;
00429 }
00430 }
00431 }
00432 }
00433 if (i) {
00434 dprintf(DP_HELP, "NOTICE %s :No info: %s\n", nick, also);
00435 }
00436 return 1;
00437 }
00438
00439 static int msg_whois(char *nick, char *host, struct userrec *u, char *par)
00440 {
00441 char s[UHOSTLEN], s1[81], *s2;
00442 int ok;
00443 struct chanset_t *chan;
00444 memberlist *m;
00445 struct chanuserrec *cr;
00446 struct userrec *u2;
00447 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00448 struct xtra_key *xk;
00449 time_t tt = 0;
00450
00451 if (match_my_nick(nick))
00452 return 1;
00453
00454 if (!u)
00455 return 0;
00456
00457 if (!par[0]) {
00458 dprintf(DP_HELP, "NOTICE %s :%s: /msg %s whois <handle>\n", nick,
00459 MISC_USAGE, botname);
00460 return 0;
00461 }
00462 if (strlen(par) > NICKMAX)
00463 par[NICKMAX] = 0;
00464 putlog(LOG_CMDS, "*", "(%s!%s) !%s! WHOIS %s", nick, host, u->handle, par);
00465 u2 = get_user_by_handle(userlist, par);
00466 if (!u2) {
00467
00468 ok = 0;
00469 for (chan = chanset; chan && !ok; chan = chan->next) {
00470 m = ismember(chan, par);
00471 if (m) {
00472 egg_snprintf(s, sizeof s, "%s!%s", par, m->userhost);
00473 u2 = get_user_by_host(s);
00474 if (u2) {
00475 ok = 1;
00476 dprintf(DP_HELP, "NOTICE %s :[%s] AKA '%s':\n", nick,
00477 par, u2->handle);
00478 }
00479 }
00480 }
00481 if (!ok) {
00482 dprintf(DP_HELP, "NOTICE %s :[%s] %s\n", nick, par, USERF_NOUSERREC);
00483 return 1;
00484 }
00485 }
00486 s2 = get_user(&USERENTRY_INFO, u2);
00487 if (s2 && (s2[0] == '@'))
00488 s2++;
00489 if (s2 && s2[0] && !(u2->flags & USER_BOT))
00490 dprintf(DP_HELP, "NOTICE %s :[%s] %s\n", nick, u2->handle, s2);
00491 for (xk = get_user(&USERENTRY_XTRA, u2); xk; xk = xk->next)
00492 if (!egg_strcasecmp(xk->key, "EMAIL"))
00493 dprintf(DP_HELP, "NOTICE %s :[%s] E-mail: %s\n", nick, u2->handle,
00494 xk->data);
00495 ok = 0;
00496 for (chan = chanset; chan; chan = chan->next) {
00497 if (hand_on_chan(chan, u2)) {
00498 egg_snprintf(s1, sizeof s1, "NOTICE %s :[%s] %s: %s.", nick, u2->handle,
00499 IRC_ONCHANNOW, chan->dname);
00500 ok = 1;
00501 } else {
00502 get_user_flagrec(u, &fr, chan->dname);
00503 cr = get_chanrec(u2, chan->dname);
00504 if (cr && (cr->laston > tt) && (!channel_hidden(chan) ||
00505 hand_on_chan(chan, u) || (glob_op(fr) && !chan_deop(fr)) ||
00506 glob_friend(fr) || chan_op(fr) || chan_friend(fr))) {
00507 tt = cr->laston;
00508 egg_strftime(s, 14, "%b %d %H:%M", localtime(&tt));
00509 ok = 1;
00510 egg_snprintf(s1, sizeof s1, "NOTICE %s :[%s] %s %s on %s", nick,
00511 u2->handle, IRC_LASTSEENAT, s, chan->dname);
00512 }
00513 }
00514 }
00515 if (!ok)
00516 egg_snprintf(s1, sizeof s1, "NOTICE %s :[%s] %s", nick, u2->handle,
00517 IRC_NEVERJOINED);
00518 dprintf(DP_HELP, "%s\n", s1);
00519 if (u2->flags & USER_BOT)
00520 dprintf(DP_HELP, "NOTICE %s :[%s] Status: bot\n", nick, u2->handle);
00521 else if (u2->flags & USER_OWNER)
00522 dprintf(DP_HELP, "NOTICE %s :[%s] Status: global owner\n", nick, u2->handle);
00523 else if (u2->flags & USER_MASTER)
00524 dprintf(DP_HELP, "NOTICE %s :[%s] Status: global master\n", nick, u2->handle);
00525 else if (u2->flags & USER_BOTMAST)
00526 dprintf(DP_HELP, "NOTICE %s :[%s] Status: botnet master\n", nick, u2->handle);
00527 else if (u2->flags & USER_OP)
00528 dprintf(DP_HELP, "NOTICE %s :[%s] Status: global op\n", nick, u2->handle);
00529 else if (u2->flags & USER_VOICE)
00530 dprintf(DP_HELP, "NOTICE %s :[%s] Status: global voice\n", nick, u2->handle);
00531 return 1;
00532 }
00533
00534 static int msg_help(char *nick, char *host, struct userrec *u, char *par)
00535 {
00536 char *p;
00537
00538 if (match_my_nick(nick))
00539 return 1;
00540
00541 if (!u) {
00542 if (!quiet_reject) {
00543 if (!learn_users)
00544 dprintf(DP_HELP, "NOTICE %s :No access\n", nick);
00545 else {
00546 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_DONTKNOWYOU);
00547 dprintf(DP_HELP, "NOTICE %s :/MSG %s hello\n", nick, botname);
00548 }
00549 }
00550 return 0;
00551 }
00552
00553 if (helpdir[0]) {
00554 struct flag_record fr = { FR_ANYWH | FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00555
00556 get_user_flagrec(u, &fr, 0);
00557 if (!par[0])
00558 showhelp(nick, "help", &fr, 0);
00559 else {
00560 for (p = par; *p != 0; p++)
00561 if ((*p >= 'A') && (*p <= 'Z'))
00562 *p += ('a' - 'A');
00563 showhelp(nick, par, &fr, 0);
00564 }
00565 } else
00566 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOHELP);
00567
00568 return 1;
00569 }
00570
00571 static int msg_op(char *nick, char *host, struct userrec *u, char *par)
00572 {
00573 struct chanset_t *chan;
00574 char *pass;
00575 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00576
00577 if (match_my_nick(nick))
00578 return 1;
00579
00580 pass = newsplit(&par);
00581 if (u_pass_match(u, pass)) {
00582 if (!u_pass_match(u, "-")) {
00583 if (par[0]) {
00584 chan = findchan_by_dname(par);
00585 if (chan && channel_active(chan)) {
00586 get_user_flagrec(u, &fr, par);
00587 if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr)))
00588 add_mode(chan, '+', 'o', nick);
00589 putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP %s", nick, host, u->handle,
00590 par);
00591 return 1;
00592 }
00593 } else {
00594 for (chan = chanset; chan; chan = chan->next) {
00595 get_user_flagrec(u, &fr, chan->dname);
00596 if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr)))
00597 add_mode(chan, '+', 'o', nick);
00598 }
00599 putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP", nick, host, u->handle);
00600 return 1;
00601 }
00602 }
00603 }
00604 putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP", nick, host);
00605 return 1;
00606 }
00607
00608 static int msg_halfop(char *nick, char *host, struct userrec *u, char *par)
00609 {
00610 struct chanset_t *chan;
00611 char *pass;
00612 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00613
00614 if (match_my_nick(nick))
00615 return 1;
00616
00617 pass = newsplit(&par);
00618 if (u_pass_match(u, pass)) {
00619 if (!u_pass_match(u, "-")) {
00620 if (par[0]) {
00621 chan = findchan_by_dname(par);
00622 if (chan && channel_active(chan)) {
00623 get_user_flagrec(u, &fr, par);
00624 if (chan_op(fr) || chan_halfop(fr) || (glob_op(fr) &&
00625 !chan_deop(fr)) || (glob_halfop(fr) && !chan_dehalfop(fr)))
00626 add_mode(chan, '+', 'h', nick);
00627 putlog(LOG_CMDS, "*", "(%s!%s) !%s! HALFOP %s",
00628 nick, host, u->handle, par);
00629 return 1;
00630 }
00631 } else {
00632 for (chan = chanset; chan; chan = chan->next) {
00633 get_user_flagrec(u, &fr, chan->dname);
00634 if (chan_op(fr) || chan_halfop(fr) || (glob_op(fr) &&
00635 !chan_deop(fr)) || (glob_halfop(fr) && !chan_dehalfop(fr)))
00636 add_mode(chan, '+', 'h', nick);
00637 }
00638 putlog(LOG_CMDS, "*", "(%s!%s) !%s! HALFOP", nick, host, u->handle);
00639 return 1;
00640 }
00641 }
00642 }
00643 putlog(LOG_CMDS, "*", "(%s!%s) !*! failed HALFOP", nick, host);
00644 return 1;
00645 }
00646
00647 static int msg_key(char *nick, char *host, struct userrec *u, char *par)
00648 {
00649 struct chanset_t *chan;
00650 char *pass;
00651 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00652
00653 if (match_my_nick(nick))
00654 return 1;
00655
00656 pass = newsplit(&par);
00657 if (u_pass_match(u, pass)) {
00658
00659 if (!u_pass_match(u, "-")) {
00660 if (!(chan = findchan_by_dname(par))) {
00661 dprintf(DP_HELP, "NOTICE %s :%s: /MSG %s key <pass> <channel>\n",
00662 nick, MISC_USAGE, botname);
00663 return 1;
00664 }
00665 if (!channel_active(chan)) {
00666 dprintf(DP_HELP, "NOTICE %s :%s: %s\n", nick, par, IRC_NOTONCHAN);
00667 return 1;
00668 }
00669 chan = findchan_by_dname(par);
00670 if (chan && channel_active(chan)) {
00671 get_user_flagrec(u, &fr, par);
00672 if (chan_op(fr) || chan_halfop(fr) || (glob_op(fr) && !chan_deop(fr)) ||
00673 (glob_halfop(fr) && !chan_dehalfop(fr))) {
00674 if (chan->channel.key[0]) {
00675 dprintf(DP_SERVER, "NOTICE %s :%s: key is %s\n", nick, par,
00676 chan->channel.key);
00677 putlog(LOG_CMDS, "*", "(%s!%s) !%s! KEY %s", nick, host, u->handle,
00678 par);
00679 if (invite_key && (chan->channel.mode & CHANINV)) {
00680 dprintf(DP_SERVER, "INVITE %s %s\n", nick, chan->name);
00681 }
00682 } else {
00683 dprintf(DP_HELP, "NOTICE %s :%s: no key set for this channel\n",
00684 nick, par);
00685 putlog(LOG_CMDS, "*", "(%s!%s) !%s! KEY %s", nick, host, u->handle,
00686 par);
00687 }
00688 }
00689 return 1;
00690 }
00691 }
00692 }
00693 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed KEY %s", nick, host,
00694 (u ? u->handle : "*"), par);
00695 return 1;
00696 }
00697
00698
00699
00700
00701 static int msg_voice(char *nick, char *host, struct userrec *u, char *par)
00702 {
00703 struct chanset_t *chan;
00704 char *pass;
00705 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00706
00707 if (match_my_nick(nick))
00708 return 1;
00709
00710 pass = newsplit(&par);
00711 if (u_pass_match(u, pass)) {
00712 if (!u_pass_match(u, "-")) {
00713 if (par[0]) {
00714 chan = findchan_by_dname(par);
00715 if (chan && channel_active(chan)) {
00716 get_user_flagrec(u, &fr, par);
00717 if (chan_voice(fr) || glob_voice(fr) || chan_op(fr) || glob_op(fr)) {
00718 add_mode(chan, '+', 'v', nick);
00719 putlog(LOG_CMDS, "*", "(%s!%s) !%s! VOICE %s", nick, host,
00720 u->handle, par);
00721 } else
00722 putlog(LOG_CMDS, "*", "(%s!%s) !*! failed VOICE %s",
00723 nick, host, par);
00724 return 1;
00725 }
00726 } else {
00727 for (chan = chanset; chan; chan = chan->next) {
00728 get_user_flagrec(u, &fr, chan->dname);
00729 if (chan_voice(fr) || glob_voice(fr) ||
00730 chan_op(fr) || glob_op(fr) || chan_halfop(fr) || glob_halfop(fr))
00731 add_mode(chan, '+', 'v', nick);
00732 }
00733 putlog(LOG_CMDS, "*", "(%s!%s) !%s! VOICE", nick, host, u->handle);
00734 return 1;
00735 }
00736 }
00737 }
00738 putlog(LOG_CMDS, "*", "(%s!%s) !*! failed VOICE", nick, host);
00739 return 1;
00740 }
00741
00742 static int msg_invite(char *nick, char *host, struct userrec *u, char *par)
00743 {
00744 char *pass;
00745 struct chanset_t *chan;
00746 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00747
00748 if (match_my_nick(nick))
00749 return 1;
00750
00751 pass = newsplit(&par);
00752 if (u_pass_match(u, pass) && !u_pass_match(u, "-")) {
00753 if (par[0] == '*') {
00754 for (chan = chanset; chan; chan = chan->next) {
00755 get_user_flagrec(u, &fr, chan->dname);
00756 if ((chan_op(fr) || chan_halfop(fr) || (glob_op(fr) &&
00757 !chan_deop(fr)) || (glob_halfop(fr) && !chan_dehalfop(fr))) &&
00758 (chan->channel.mode & CHANINV))
00759 dprintf(DP_SERVER, "INVITE %s %s\n", nick, chan->name);
00760 }
00761 putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE ALL", nick, host, u->handle);
00762 return 1;
00763 }
00764 if (!(chan = findchan_by_dname(par))) {
00765 dprintf(DP_HELP, "NOTICE %s :%s: /MSG %s invite <pass> <channel>\n",
00766 nick, MISC_USAGE, botname);
00767 return 1;
00768 }
00769 if (!channel_active(chan)) {
00770 dprintf(DP_HELP, "NOTICE %s :%s: %s\n", nick, par, IRC_NOTONCHAN);
00771 return 1;
00772 }
00773
00774 get_user_flagrec(u, &fr, par);
00775 if (chan_op(fr) || chan_halfop(fr) || (glob_op(fr) && !chan_deop(fr)) ||
00776 (glob_halfop(fr) && !chan_dehalfop(fr))) {
00777 dprintf(DP_SERVER, "INVITE %s %s\n", nick, chan->name);
00778 putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE %s", nick, host,
00779 u->handle, par);
00780 return 1;
00781 }
00782 }
00783 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed INVITE %s", nick, host,
00784 (u ? u->handle : "*"), par);
00785 return 1;
00786 }
00787
00788 static int msg_status(char *nick, char *host, struct userrec *u, char *par)
00789 {
00790 char s[256], *vers_t, *uni_t, *pass;
00791 int i;
00792 struct chanset_t *chan;
00793 time_t now2 = now - online_since, hr, min;
00794
00795 #ifdef HAVE_UNAME
00796 struct utsname un;
00797
00798 if (!uname(&un) < 0) {
00799 #endif
00800 vers_t = " ";
00801 uni_t = "*unknown*";
00802 #ifdef HAVE_UNAME
00803 } else {
00804 vers_t = un.release;
00805 uni_t = un.sysname;
00806 }
00807 #endif
00808
00809 if (match_my_nick(nick))
00810 return 1;
00811
00812 if (!u_pass_match(u, "-")) {
00813 pass = newsplit(&par);
00814 if (!u_pass_match(u, pass)) {
00815 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed STATUS", nick, host,
00816 u->handle);
00817 return 1;
00818 }
00819 } else {
00820 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed STATUS", nick, host, u->handle);
00821 if (!quiet_reject)
00822 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOPASS);
00823 return 1;
00824 }
00825 putlog(LOG_CMDS, "*", "(%s!%s) !%s! STATUS", nick, host, u->handle);
00826
00827 i = count_users(userlist);
00828 dprintf(DP_HELP, "NOTICE %s :I am %s, running %s: %d user%s (mem: %uk).\n",
00829 nick, botnetnick, ver, i, i == 1 ? "" : "s",
00830 (int) (expected_memory() / 1024));
00831
00832 s[0] = 0;
00833 if (now2 > 86400) {
00834
00835 sprintf(s, "%d day", (int) (now2 / 86400));
00836 if ((int) (now2 / 86400) >= 2)
00837 strcat(s, "s");
00838 strcat(s, ", ");
00839 now2 -= (((int) (now2 / 86400)) * 86400);
00840 }
00841 hr = (time_t) ((int) now2 / 3600);
00842 now2 -= (hr * 3600);
00843 min = (time_t) ((int) now2 / 60);
00844 sprintf(&s[strlen(s)], "%02d:%02d", (int) hr, (int) min);
00845 dprintf(DP_HELP, "NOTICE %s :%s %s.\n", nick, MISC_ONLINEFOR, s);
00846
00847 if (admin[0])
00848 dprintf(DP_HELP, "NOTICE %s :Admin: %s.\n", nick, admin);
00849 dprintf(DP_HELP, "NOTICE %s :OS: %s %s.\n", nick, uni_t, vers_t);
00850 dprintf(DP_HELP, "NOTICE %s :Online as: %s!%s.\n", nick, botname, botuserhost);
00851
00852
00853 s[0] = 0;
00854 strncpyz(s, "Channels: ", sizeof s);
00855 for (chan = chanset; chan; chan = chan->next) {
00856 strncat(s, chan->dname, sizeof(s) - 1 - strlen(s));
00857 if (!channel_active(chan))
00858 strncat(s, " (trying)", sizeof(s) - 1 - strlen(s));
00859 else if (channel_pending(chan))
00860 strncat(s, " (pending)", sizeof(s) - 1 - strlen(s));
00861 else if (!me_op(chan))
00862 strncat(s, " (need ops)", sizeof(s) - 1 - strlen(s));
00863 strncat(s, ", ", sizeof(s) - 1 - strlen(s));
00864 if (strlen(s) > 140) {
00865 s[strlen(s) - 2] = 0;
00866 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, s);
00867 s[0] = 0;
00868 }
00869 }
00870 if (strlen(s) > 10) {
00871 s[strlen(s) - 2] = 0;
00872 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, s);
00873 }
00874 return 1;
00875 }
00876
00877 static int msg_memory(char *nick, char *host, struct userrec *u, char *par)
00878 {
00879 char *pass;
00880
00881 if (match_my_nick(nick))
00882 return 1;
00883
00884 if (!u_pass_match(u, "-")) {
00885 pass = newsplit(&par);
00886 if (!u_pass_match(u, pass)) {
00887 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed MEMORY", nick, host,
00888 u->handle);
00889 return 1;
00890 }
00891 } else {
00892 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed MEMORY", nick, host, u->handle);
00893 if (!quiet_reject)
00894 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOPASS);
00895 return 1;
00896 }
00897 putlog(LOG_CMDS, "*", "(%s!%s) !%s! MEMORY", nick, host, u->handle);
00898 tell_mem_status(nick);
00899 return 1;
00900 }
00901
00902 static int msg_die(char *nick, char *host, struct userrec *u, char *par)
00903 {
00904 char s[1024];
00905 char *pass;
00906
00907 if (match_my_nick(nick))
00908 return 1;
00909
00910 if (!u_pass_match(u, "-")) {
00911 pass = newsplit(&par);
00912 if (!u_pass_match(u, pass)) {
00913 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed DIE", nick, host, u->handle);
00914 return 1;
00915 }
00916 } else {
00917 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed DIE", nick, host, u->handle);
00918 if (!quiet_reject)
00919 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOPASS);
00920 return 1;
00921 }
00922 putlog(LOG_CMDS, "*", "(%s!%s) !%s! DIE", nick, host, u->handle);
00923 dprintf(-serv, "NOTICE %s :%s\n", nick, BOT_MSGDIE);
00924 if (!par[0])
00925 egg_snprintf(s, sizeof s, "BOT SHUTDOWN (authorized by %s)", u->handle);
00926 else
00927 egg_snprintf(s, sizeof s, "BOT SHUTDOWN (%s: %s)", u->handle, par);
00928 chatout("*** %s\n", s);
00929 botnet_send_chat(-1, botnetnick, s);
00930 botnet_send_bye();
00931 if (!par[0])
00932 nuke_server(nick);
00933 else
00934 nuke_server(par);
00935 write_userfile(-1);
00936 sleep(1);
00937 egg_snprintf(s, sizeof s, "DEAD BY REQUEST OF %s!%s", nick, host);
00938 fatal(s, 0);
00939 return 1;
00940 }
00941
00942 static int msg_rehash(char *nick, char *host, struct userrec *u, char *par)
00943 {
00944 if (match_my_nick(nick))
00945 return 1;
00946
00947 if (u_pass_match(u, par)) {
00948 putlog(LOG_CMDS, "*", "(%s!%s) !%s! REHASH", nick, host, u->handle);
00949 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, USERF_REHASHING);
00950 if (make_userfile)
00951 make_userfile = 0;
00952 write_userfile(-1);
00953 do_restart = -2;
00954 return 1;
00955 }
00956 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed REHASH", nick, host, u->handle);
00957 return 1;
00958 }
00959
00960 static int msg_save(char *nick, char *host, struct userrec *u, char *par)
00961 {
00962 if (match_my_nick(nick))
00963 return 1;
00964
00965 if (u_pass_match(u, par)) {
00966 putlog(LOG_CMDS, "*", "(%s!%s) !%s! SAVE", nick, host, u->handle);
00967 dprintf(DP_HELP, "NOTICE %s :Saving user file...\n", nick);
00968 write_userfile(-1);
00969 return 1;
00970 }
00971 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed SAVE", nick, host, u->handle);
00972 return 1;
00973 }
00974
00975 static int msg_reset(char *nick, char *host, struct userrec *u, char *par)
00976 {
00977 struct chanset_t *chan;
00978 char *pass;
00979
00980 if (match_my_nick(nick))
00981 return 1;
00982
00983 if (!u_pass_match(u, "-")) {
00984 pass = newsplit(&par);
00985 if (!u_pass_match(u, pass)) {
00986 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed RESET", nick, host,
00987 u->handle);
00988 return 1;
00989 }
00990 } else {
00991 putlog(LOG_CMDS, "*", "(%s!%s) !*! failed RESET", nick, host);
00992 if (!quiet_reject)
00993 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOPASS);
00994 return 1;
00995 }
00996 if (par[0]) {
00997 chan = findchan_by_dname(par);
00998 if (!chan) {
00999 dprintf(DP_HELP, "NOTICE %s :%s: %s\n", nick, par, IRC_NOMONITOR);
01000 return 0;
01001 }
01002 putlog(LOG_CMDS, "*", "(%s!%s) !%s! RESET %s", nick, host, u->handle, par);
01003 dprintf(DP_HELP, "NOTICE %s :%s: %s\n", nick, par, IRC_RESETCHAN);
01004 reset_chan_info(chan, CHAN_RESETALL);
01005 return 1;
01006 }
01007 putlog(LOG_CMDS, "*", "(%s!%s) !%s! RESET ALL", nick, host, u->handle);
01008 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_RESETCHAN);
01009 for (chan = chanset; chan; chan = chan->next)
01010 reset_chan_info(chan, CHAN_RESETALL);
01011 return 1;
01012 }
01013
01014 static int msg_go(char *nick, char *host, struct userrec *u, char *par)
01015 {
01016 struct chanset_t *chan;
01017 int ok = 0, ok2 = 0;
01018 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
01019
01020 if (match_my_nick(nick))
01021 return 1;
01022
01023 if (!u)
01024 return 0;
01025
01026 if (par[0]) {
01027 chan = findchan_by_dname(par);
01028 if (!chan)
01029 return 0;
01030 if (!(chan->status & CHAN_ACTIVE)) {
01031 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed GO %s (i'm blind)", nick,
01032 host, u->handle, par);
01033 return 1;
01034 }
01035 get_user_flagrec(u, &fr, par);
01036 if (!chan_op(fr) && !(glob_op(fr) && !chan_deop(fr))) {
01037 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed GO %s (not op)", nick, host,
01038 u->handle, par);
01039 return 1;
01040 }
01041 if (!me_op(chan)) {
01042 dprintf(DP_SERVER, "PART %s\n", chan->name);
01043 putlog(LOG_CMDS, chan->dname, "(%s!%s) !%s! GO %s", nick, host,
01044 u->handle, par);
01045 return 1;
01046 }
01047 putlog(LOG_CMDS, chan->dname, "(%s!%s) !%s! failed GO %s (i'm chop)",
01048 nick, host, u->handle, par);
01049 return 1;
01050 }
01051 for (chan = chanset; chan; chan = chan->next) {
01052 if (ismember(chan, nick)) {
01053 get_user_flagrec(u, &fr, par);
01054 if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr))) {
01055 ok2 = 1;
01056 if (!me_op(chan)) {
01057 dprintf(DP_SERVER, "PART %s\n", chan->name);
01058 ok = 1;
01059 }
01060 }
01061 }
01062 }
01063 if (ok) {
01064 putlog(LOG_CMDS, "*", "(%s!%s) !%s! GO %s", nick, host, u->handle, par);
01065 } else if (ok2) {
01066 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed GO %s (i'm chop)", nick, host,
01067 u->handle, par);
01068 } else {
01069 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed GO %s (not op)", nick, host,
01070 u->handle, par);
01071 }
01072 return 1;
01073 }
01074
01075 static int msg_jump(char *nick, char *host, struct userrec *u, char *par)
01076 {
01077 char *s;
01078 int port;
01079
01080 if (match_my_nick(nick))
01081 return 1;
01082
01083 if (u_pass_match(u, "-")) {
01084 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed JUMP", nick, host, u->handle);
01085 if (!quiet_reject)
01086 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_NOPASS);
01087 return 1;
01088 }
01089 s = newsplit(&par);
01090 if (u_pass_match(u, s)) {
01091 if (par[0]) {
01092 s = newsplit(&par);
01093 port = atoi(newsplit(&par));
01094 if (!port)
01095 port = default_port;
01096 putlog(LOG_CMDS, "*", "(%s!%s) !%s! JUMP %s %d %s", nick, host,
01097 u->handle, s, port, par);
01098 strcpy(newserver, s);
01099 newserverport = port;
01100 strcpy(newserverpass, par);
01101 } else
01102 putlog(LOG_CMDS, "*", "(%s!%s) !%s! JUMP", nick, host, u->handle);
01103 dprintf(-serv, "NOTICE %s :%s\n", nick, IRC_JUMP);
01104 cycle_time = 0;
01105 nuke_server("changing servers");
01106 } else
01107 putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed JUMP", nick, host, u->handle);
01108 return 1;
01109 }
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119 static cmd_t C_msg[] = {
01120 {"addhost", "", (IntFunc) msg_addhost, NULL},
01121 {"die", "n", (IntFunc) msg_die, NULL},
01122 {"go", "", (IntFunc) msg_go, NULL},
01123 {"hello", "", (IntFunc) msg_hello, NULL},
01124 {"help", "", (IntFunc) msg_help, NULL},
01125 {"ident", "", (IntFunc) msg_ident, NULL},
01126 {"info", "", (IntFunc) msg_info, NULL},
01127 {"invite", "o|o", (IntFunc) msg_invite, NULL},
01128 {"jump", "m", (IntFunc) msg_jump, NULL},
01129 {"key", "o|o", (IntFunc) msg_key, NULL},
01130 {"memory", "m", (IntFunc) msg_memory, NULL},
01131 {"op", "", (IntFunc) msg_op, NULL},
01132 {"halfop", "", (IntFunc) msg_halfop, NULL},
01133 {"pass", "", (IntFunc) msg_pass, NULL},
01134 {"rehash", "m", (IntFunc) msg_rehash, NULL},
01135 {"reset", "m", (IntFunc) msg_reset, NULL},
01136 {"save", "m", (IntFunc) msg_save, NULL},
01137 {"status", "m|m", (IntFunc) msg_status, NULL},
01138 {"voice", "", (IntFunc) msg_voice, NULL},
01139 {"who", "", (IntFunc) msg_who, NULL},
01140 {"whois", "", (IntFunc) msg_whois, NULL},
01141 {NULL, NULL, NULL, NULL}
01142 };