+ { RPL_FEATURE, 0, "284" },
+/* 285 */
+ { 0 },
+/* 286 */
+ { 0 },
+/* 287 */
+ { 0 },
+/* 288 */
+ { 0 },
+/* 289 */
+ { 0 },
+/* 290 */
+ { 0 },
+/* 291 */
+ { 0 },
+/* 292 */
+ { 0 },
+/* 293 */
+ { 0 },
+/* 294 */
+ { 0 },
+/* 295 */
+ { 0 },
+/* 296 */
+ { 0 },
+/* 297 */
+ { 0 },
+/* 298 */
+ { 0 },
+/* 299 */
+ { 0 },
+/* 300 */
+ { 0 },
+/* 301 */
+ { RPL_AWAY, "%s :%s", "301" },
+/* 302 */
+ { RPL_USERHOST, ":", "302" },
+/* 303 */
+ { RPL_ISON, ":", "303" },
+/* 304 */
+ { 0 },
+/* 305 */
+ { RPL_UNAWAY, ":You are no longer marked as being away", "305" },
+/* 306 */
+ { RPL_NOWAWAY, ":You have been marked as being away", "306" },
+/* 307 */
+ { 0 },
+/* 308 */
+ { 0 },
+/* 309 */
+ { 0 },
+/* 310 */
+ { 0 },
+/* 311 */
+ { RPL_WHOISUSER, "%s %s %s * :%s", "311" },
+/* 312 */
+ { RPL_WHOISSERVER, "%s %s :%s", "312" },
+/* 313 */
+ { RPL_WHOISOPERATOR, "%s :is an IRC Operator", "313" },
+/* 314 */
+ { RPL_WHOWASUSER, "%s %s %s * :%s", "314" },
+/* 315 */
+ { RPL_ENDOFWHO, "%s :End of /WHO list.", "315" },
+/* 316 */
+ { 0 },
+/* 317 */
+ { RPL_WHOISIDLE, "%s %ld %ld :seconds idle, signon time", "317" },
+/* 318 */
+ { RPL_ENDOFWHOIS, "%s :End of /WHOIS list.", "318" },
+/* 319 */
+ { RPL_WHOISCHANNELS, "%s :%s", "319" },
+/* 320 */
+ { 0 },
+/* 321 */
+ { RPL_LISTSTART, "Channel :Users Name", "321" },
+/* 322 */
+ { RPL_LIST, "%s %u :%s", "322" },
+/* 323 */
+ { RPL_LISTEND, ":End of /LIST", "323" },
+/* 324 */
+ { RPL_CHANNELMODEIS, "%s %s %s", "324" },
+/* 325 */
+ { 0 },
+/* 326 */
+ { 0 },
+/* 327 */
+ { 0 },
+/* 328 */
+ { 0 },
+/* 329 */
+ { RPL_CREATIONTIME, "%s %Tu", "329" },
+/* 330 */
+ { RPL_WHOISACCOUNT, "%s %s :is logged in as", "330" },
+/* 331 */
+ { RPL_NOTOPIC, "%s :No topic is set.", "331" },
+/* 332 */
+ { RPL_TOPIC, "%s :%s", "332" },
+/* 333 */
+ { RPL_TOPICWHOTIME, "%s %s %Tu", "333" },
+/* 334 */
+ { RPL_LISTUSAGE, ":%s", "334" },
+/* 335 */
+ { 0 },
+/* 336 */
+ { 0 },
+/* 337 */
+ { 0 },
+/* 338 */
+ { RPL_WHOISACTUALLY, "%s %s@%s %s :Actual user@host, Actual IP", "338" },
+/* 339 */
+ { 0 },
+/* 340 */
+ { RPL_USERIP, ":", "340" },
+/* 341 */
+ { RPL_INVITING, "%s %s", "341" },
+/* 342 */
+ { 0 },
+/* 343 */
+ { 0 },
+/* 344 */
+ { 0 },
+/* 345 */
+ { RPL_ISSUEDINVITE, "%s %s %s :%s has been invited by %s", "345" },
+/* 346 */
+ { RPL_INVITELIST, ":%s", "346" },
+/* 347 */
+ { RPL_ENDOFINVITELIST, ":End of Invite List", "347" },
+/* 348 */
+ { 0 },
+/* 349 */
+ { 0 },
+/* 350 */
+ { 0 },
+/* 351 */
+ { RPL_VERSION, "%s.%s %s :%s", "351" },
+/* 352 */
+ { RPL_WHOREPLY, "%s", "352" },
+/* 353 */
+ { RPL_NAMREPLY, "%s", "353" },
+/* 354 */
+ { RPL_WHOSPCRPL, "%s", "354" },
+/* 355 */
+ { RPL_DELNAMREPLY, "%s", "355" },
+/* 356 */
+ { 0 },
+/* 357 */
+ { 0 },
+/* 358 */
+ { 0 },
+/* 359 */
+ { 0 },
+/* 360 */
+ { 0 },
+/* 361 */
+ { 0 },
+/* 362 */
+ { RPL_CLOSING, "%s :Operator enforced Close", "362" },
+/* 363 */
+ { RPL_CLOSEEND, "%d :Connections Closed", "363" },
+/* 364 */
+ { RPL_LINKS, "%s %s :%u P%u %s", "364" },
+/* 365 */
+ { RPL_ENDOFLINKS, "%s :End of /LINKS list.", "365" },
+/* 366 */
+ { RPL_ENDOFNAMES, "%s :End of /NAMES list.", "366" },
+/* 367 */
+ { RPL_BANLIST, "%s %s %s %Tu", "367" },
+/* 368 */
+ { RPL_ENDOFBANLIST, "%s :End of Channel Ban List", "368" },
+/* 369 */
+ { RPL_ENDOFWHOWAS, "%s :End of WHOWAS", "369" },
+/* 370 */
+ { 0 },
+/* 371 */
+ { RPL_INFO, ":%s", "371" },
+/* 372 */
+ { RPL_MOTD, ":- %s", "372" },
+/* 373 */
+ { 0 },
+/* 374 */
+ { RPL_ENDOFINFO, ":End of /INFO list.", "374" },
+/* 375 */
+ { RPL_MOTDSTART, ":- %s Message of the Day - ", "375" },
+/* 376 */
+ { RPL_ENDOFMOTD, ":End of /MOTD command.", "376" },
+/* 377 */
+ { 0 },
+/* 378 */
+ { 0 },
+/* 379 */
+ { 0 },
+/* 380 */
+ { 0 },
+/* 381 */
+ { RPL_YOUREOPER, ":You are now an IRC Operator", "381" },
+/* 382 */
+ { RPL_REHASHING, "%s :Rehashing", "382" },
+/* 383 */
+ { 0 },
+/* 384 */
+ { 0 },
+/* 385 */
+ { 0 },
+/* 386 */
+ { 0 },
+/* 387 */
+ { 0 },
+/* 388 */
+ { 0 },
+/* 389 */
+ { 0 },
+/* 390 */
+ { 0 },
+/* 391 */
+ { RPL_TIME, "%s %Tu %ld :%s", "391" },
+/* 392 */
+ { 0 },
+/* 393 */
+ { 0 },
+/* 394 */
+ { 0 },
+/* 395 */
+ { 0 },
+/* 396 */
+ { RPL_HOSTHIDDEN, "%s :is now your hidden host", "396" },
+/* 397 */
+ { 0 },
+/* 398 */
+ { 0 },
+/* 399 */
+ { 0 },
+/* 400 */
+ { 0 },
+/* 401 */
+ { ERR_NOSUCHNICK, "%s :No such nick", "401" },
+/* 402 */
+ { ERR_NOSUCHSERVER, "%s :No such server", "402" },
+/* 403 */
+ { ERR_NOSUCHCHANNEL, "%s :No such channel", "403" },
+/* 404 */
+ { ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel", "404" },
+/* 405 */
+ { ERR_TOOMANYCHANNELS, "%s :You have joined too many channels", "405" },
+/* 406 */
+ { ERR_WASNOSUCHNICK, "%s :There was no such nickname", "406" },
+/* 407 */
+ { ERR_TOOMANYTARGETS, "%s :Duplicate recipients. No message delivered", "407" },
+/* 408 */
+ { 0 },
+/* 409 */
+ { ERR_NOORIGIN, ":No origin specified", "409" },
+/* 410 */
+ { ERR_UNKNOWNCAPCMD, "%s :Unknown CAP subcommand", "410" },
+/* 411 */
+ { ERR_NORECIPIENT, ":No recipient given (%s)", "411" },
+/* 412 */
+ { ERR_NOTEXTTOSEND, ":No text to send", "412" },
+/* 413 */
+ { ERR_NOTOPLEVEL, "%s :No toplevel domain specified", "413" },
+/* 414 */
+ { ERR_WILDTOPLEVEL, "%s :Wildcard in toplevel Domain", "414" },
+/* 415 */
+ { 0 },
+/* 416 */
+ { ERR_QUERYTOOLONG, "%s :Too many lines in the output, restrict your query", "416" },
+/* 417 */
+ { ERR_INPUTTOOLONG, ":Input line was too long", "417" },
+/* 418 */
+ { 0 },
+/* 419 */
+ { 0 },
+/* 420 */
+ { 0 },
+/* 421 */
+ { ERR_UNKNOWNCOMMAND, "%s :Unknown command", "421" },
+/* 422 */
+ { ERR_NOMOTD, ":MOTD File is missing", "422" },
+/* 423 */
+ { ERR_NOADMININFO, "%s :No administrative info available", "423" },
+/* 424 */
+ { 0 },
+/* 425 */
+ { 0 },
+/* 426 */
+ { 0 },
+/* 427 */
+ { 0 },
+/* 428 */
+ { 0 },
+/* 429 */
+ { 0 },
+/* 430 */
+ { 0 },
+/* 431 */
+ { ERR_NONICKNAMEGIVEN, ":No nickname given", "431" },
+/* 432 */
+ { ERR_ERRONEUSNICKNAME, "%s :Erroneous Nickname", "432" },
+/* 433 */
+ { ERR_NICKNAMEINUSE, "%s :Nickname is already in use.", "433" },
+/* 434 */
+ { 0 },
+/* 435 */
+ { 0 },
+/* 436 */
+ { ERR_NICKCOLLISION, "%s :Nickname collision KILL", "436" },
+/* 437 */
+ { ERR_BANNICKCHANGE, "%s :Cannot change nickname while banned on channel or channel is moderated", "437" },
+/* 438 */
+ { ERR_NICKTOOFAST, "%s :Nick change too fast. Please wait %d seconds.", "438" },
+/* 439 */
+ { ERR_TARGETTOOFAST, "%s :Target change too fast. Please wait %d seconds.", "439" },
+/* 440 */
+ { ERR_SERVICESDOWN, "%s :Services are currently unavailable.", "440" },
+/* 441 */
+ { ERR_USERNOTINCHANNEL, "%s %s :They aren't on that channel", "441" },
+/* 442 */
+ { ERR_NOTONCHANNEL, "%s :You're not on that channel", "442" },
+/* 443 */
+ { ERR_USERONCHANNEL, "%s %s :is already on channel", "443" },
+/* 444 */
+ { 0 },
+/* 445 */
+ { 0 },
+/* 446 */
+ { 0 },
+/* 447 */
+ { 0 },
+/* 448 */
+ { 0 },
+/* 449 */
+ { 0 },
+/* 450 */
+ { 0 },
+/* 451 */
+ { ERR_NOTREGISTERED, ":You have not registered", "451" },
+/* 452 */
+ { 0 },
+/* 453 */
+ { 0 },
+/* 454 */
+ { 0 },
+/* 455 */
+ { 0 },
+/* 456 */
+ { 0 },
+/* 457 */
+ { 0 },
+/* 458 */
+ { 0 },
+/* 459 */
+ { 0 },
+/* 460 */
+ { 0 },
+/* 461 */
+ { ERR_NEEDMOREPARAMS, "%s :Not enough parameters", "461" },
+/* 462 */
+ { ERR_ALREADYREGISTRED, ":You may not reregister", "462" },
+/* 463 */
+ { ERR_NOPERMFORHOST, ":Your host isn't among the privileged", "463" },
+/* 464 */
+ { ERR_PASSWDMISMATCH, ":Password Incorrect", "464" },
+/* 465 */
+ { ERR_YOUREBANNEDCREEP, ":You are banned from this server", "465" },
+/* 466 */
+ { ERR_YOUWILLBEBANNED, "", "466" },
+/* 467 */
+ { ERR_KEYSET, "%s :Channel key already set", "467" },
+/* 468 */
+ { ERR_INVALIDUSERNAME, 0, "468" },
+/* 469 */
+ { 0 },
+/* 470 */
+ { 0 },
+/* 471 */
+ { ERR_CHANNELISFULL, "%s :Cannot join channel (+l)", "471" },
+/* 472 */
+ { ERR_UNKNOWNMODE, "%c :is unknown mode char to me", "472" },
+/* 473 */
+ { ERR_INVITEONLYCHAN, "%s :Cannot join channel (+i)", "473" },
+/* 474 */
+ { ERR_BANNEDFROMCHAN, "%s :Cannot join channel (+b)", "474" },
+/* 475 */
+ { ERR_BADCHANNELKEY, "%s :Cannot join channel (+k)", "475" },
+/* 476 */
+ { ERR_BADCHANMASK, "%s :Bad Channel Mask", "476" },
+/* 477 */
+ { ERR_NEEDREGGEDNICK, "%s :Cannot join channel (+r): this channel requires authentication -- you can obtain an account from %s", "477" },
+/* 478 */
+ { ERR_BANLISTFULL, "%s %s :Channel ban/ignore list is full", "478" },
+/* 479 */
+ { ERR_BADCHANNAME, "%s :Cannot join channel (access denied on this server)", "479" },
+/* 480 */
+ { 0 },
+/* 481 */
+ { ERR_NOPRIVILEGES, ":Permission Denied: Insufficient privileges", "481" },
+/* 482 */
+ { ERR_CHANOPRIVSNEEDED, "%s :You're not channel operator", "482" },
+/* 483 */
+ { ERR_CANTKILLSERVER, ":You cant kill a server!", "483" },
+/* 484 */
+ { ERR_ISCHANSERVICE, "%s %s :Cannot kill, kick or deop a network service", "484" },
+/* 485 */
+ { 0 },
+/* 486 */
+ { 0 },
+/* 487 */
+ { 0 },
+/* 488 */
+ { 0 },
+/* 489 */
+ { ERR_VOICENEEDED, "%s :You're neither voiced nor channel operator", "489" },
+/* 490 */
+ { 0 },
+/* 491 */
+ { ERR_NOOPERHOST, ":No Operator block for your host", "491" },
+/* 492 */
+ { 0 },
+/* 493 */
+ { ERR_NOFEATURE, "%s :No such feature", "493" },
+/* 494 */
+ { ERR_BADFEATVALUE, "%s :Bad value for feature %s", "494" },
+/* 495 */
+ { ERR_BADLOGTYPE, "%s :No such log type", "495" },
+/* 496 */
+ { ERR_BADLOGSYS, "%s :No such log subsystem", "496" },
+/* 497 */
+ { ERR_BADLOGVALUE, "%s :Bad value for log type", "497" },
+/* 498 */
+ { ERR_ISOPERLCHAN, "%s %s :Cannot kick or deop an IRC Operator on a local channel", "498" },
+/* 499 */
+ { 0 },
+/* 500 */
+ { 0 },
+/* 501 */
+ { ERR_UMODEUNKNOWNFLAG, "%c :Unknown user MODE flag", "501" },
+/* 502 */
+ { ERR_USERSDONTMATCH, ":Cant change mode for other users", "502" },
+/* 503 */
+ { 0 },
+/* 504 */
+ { 0 },
+/* 505 */
+ { 0 },
+/* 506 */
+ { 0 },
+/* 507 */
+ { 0 },
+/* 508 */
+ { 0 },
+/* 509 */
+ { 0 },
+/* 510 */
+ { 0 },
+/* 511 */
+ { ERR_SILELISTFULL, "%s :Your silence list is full", "511" },
+/* 512 */
+ { ERR_NOSUCHGLINE, "%s :No such gline", "512" },
+/* 513 */
+ { ERR_BADPING, 0, "513" },
+/* 514 */
+ { ERR_NOSUCHJUPE, "%s :No such jupe", "514" },
+/* 515 */
+ { ERR_BADEXPIRE, "%Tu :Bad expire time", "515" },
+/* 516 */
+ { ERR_DONTCHEAT, "%s :Don't Cheat.", "516" },
+/* 517 */
+ { ERR_DISABLED, "%s :Command disabled.", "517" },
+/* 518 */
+ { ERR_LONGMASK, ":Mask is too long", "518" },
+/* 519 */
+ { ERR_TOOMANYUSERS, "%d :Too many users affected by mask", "519" },
+/* 520 */
+ { ERR_MASKTOOWIDE, "%s :Mask is too wide", "520" },
+/* 521 */
+ { 0 },
+/* 522 */
+ { 0 },
+/* 523 */
+ { 0 },
+/* 524 */
+ { ERR_QUARANTINED, "%s :Channel is quarantined : %s", "524" },
+/* 525 */
+ { ERR_INVALIDKEY, "%s :Key is not well-formed", "525" },
+/* 526 */
+ { 0 },
+/* 527 */
+ { 0 },
+/* 528 */
+ { 0 },
+/* 529 */
+ { 0 },
+/* 530 */
+ { 0 },
+/* 531 */
+ { 0 },
+/* 532 */
+ { 0 },
+/* 533 */
+ { 0 },
+/* 534 */
+ { 0 },
+/* 535 */
+ { 0 },
+/* 536 */
+ { 0 },
+/* 537 */
+ { 0 },
+/* 538 */
+ { 0 },
+/* 539 */
+ { 0 },
+/* 540 */
+ { 0 },
+/* 541 */
+ { 0 },
+/* 542 */
+ { 0 },
+/* 543 */
+ { 0 },
+/* 544 */
+ { 0 },
+/* 545 */
+ { 0 },
+/* 546 */
+ { 0 },
+/* 547 */
+ { 0 },
+/* 548 */
+ { 0 },
+/* 549 */
+ { 0 },
+/* 550 */
+ { 0 },
+/* 551 */
+ { 0 },
+/* 552 */
+ { 0 },
+/* 553 */
+ { 0 },
+/* 554 */
+ { 0 },
+/* 555 */
+ { 0 },
+/* 556 */
+ { 0 },
+/* 557 */
+ { 0 },
+/* 558 */
+ { 0 },
+/* 559 */
+ { 0 },
+/* 560 */
+ { ERR_NOTLOWEROPLEVEL, "%s %s %hu %hu :Cannot %s someone with %s op-level", "560" },
+/* 561 */
+ { ERR_NOTMANAGER, "%s :You must be channel Admin to add or remove a password. Use /JOIN %s <AdminPass>.", "561" },
+/* 562 */
+ { ERR_CHANSECURED, "%s :Channel is older than 48 hours and secured. Cannot change Admin pass anymore", "562" },
+/* 563 */
+ { ERR_UPASSSET, "%s :Cannot remove Admin pass (+A) while User pass (+U) is still set. First use /MODE %s -U <userpass>", "563" },
+/* 564 */
+ { ERR_UPASSNOTSET, "%s :Cannot set user pass (+U) until Admin pass (+A) is set. First use /MODE %s +A <adminpass>", "564" },
+/* 565 */
+ { 0 },
+/* 566 */
+ { ERR_NOMANAGER, "%s :Re-create the channel. The channel must be completely empty for a period of %s before it can be recreated.", "566" },
+/* 567 */
+ { ERR_UPASS_SAME_APASS, "%s :Cannot use the same pass for both admin (+A) and user (+U) pass.", "567" },
+/* 568 */
+ { 0 },
+/* 569 */
+ { 0 },
+/* 570 */
+ { 0 },
+/* 571 */
+ { 0 },
+/* 572 */
+ { 0 },
+/* 573 */
+ { 0 },
+/* 574 */
+ { 0 },
+/* 575 */
+ { 0 },
+/* 576 */
+ { 0 },
+/* 577 */
+ { 0 },
+/* 578 */
+ { 0 },
+/* 579 */
+ { 0 },
+/* 580 */
+ { 0 },
+/* 581 */
+ { 0 },
+/* 582 */
+ { 0 },
+/* 583 */
+ { 0 },
+/* 584 */
+ { 0 },
+/* 585 */
+ { 0 },
+/* 586 */
+ { 0 },
+/* 587 */
+ { 0 },
+/* 588 */
+ { 0 },
+/* 589 */
+ { 0 },
+/* 590 */
+ { 0 },
+/* 591 */
+ { 0 },
+/* 592 */
+ { 0 },
+/* 593 */
+ { 0 },
+/* 594 */
+ { 0 },
+/* 595 */
+ { 0 },
+/* 596 */
+ { 0 },
+/* 597 */
+ { 0 },
+/* 598 */
+ { 0 },
+/* 599 */
+ { 0 }
+};
+
+/** Return a pointer to the Numeric for a particular code.
+ * @param n %Numeric to look up.
+ * @return Numeric structure.
+ */
+const struct Numeric* get_error_numeric(int n)
+{
+ assert(0 < n);
+ assert(n < ERR_LASTERROR);
+ assert(0 != replyTable[n].value);
+
+ return &replyTable[n];
+}
+
+/** Return a format string for a numeric response.
+ * @param n %Numeric to look up.
+ * @return Pointer to a static buffer containing the format string.
+ */
+char* rpl_str(int n)
+{
+ static char numbuff[512];
+ Numeric* p;
+
+ assert(0 < n);
+ assert(n < ERR_LASTERROR);
+ assert(0 != replyTable[n].value);
+
+ p = &replyTable[n];
+ strcpy(numbuff, ":%s 000 %s ");
+ if (p->str) {
+ numbuff[4] = p->str[0];
+ numbuff[5] = p->str[1];
+ numbuff[6] = p->str[2];
+ strcpy(numbuff + 11, p->format);
+ }
+
+ return numbuff;
+}
+