Author: Bleep <tomh@inxpress.net>
[ircu2.10.12-pk.git] / ircd / s_err.c
1 /*
2  * IRC - Internet Relay Chat, ircd/s_err.c
3  * Copyright (C) 1992 Darren Reed
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 1, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  * $Id$
20  */
21 #include "numeric.h"
22 #include "s_debug.h"
23 #include "sprintf_irc.h"
24
25 #include <assert.h>
26
27 static Numeric local_replies[] = {
28 /* 000 */
29   { 0 },
30 /* 001 */
31   { RPL_WELCOME, ":Welcome to the Internet Relay Network %s", "001" },
32 /* 002 */
33   { RPL_YOURHOST, ":Your host is %s, running version %s", "002" },
34 /* 003 */
35   { RPL_CREATED, ":This server was created %s", "003" },
36 /* 004 */
37   { RPL_MYINFO, "%s %s dioswkg biklmnopstv", "004" },
38 /* 005 */
39   { RPL_ISUPPORT, "%s :are supported by this server", "005" },
40 /* 006 */
41   { 0 },
42 /* 007 */
43   { 0 },
44 /* 008 */
45   { RPL_SNOMASK, "%d :: Server notice mask (%#x)", "008" },
46 /* 009 */
47   { RPL_STATMEMTOT, "%u %u :Bytes Blocks", "009" },
48 /* 010 */
49 #ifdef MEMSIZESTATS
50   { RPL_STATMEM, "%u %u %s %u", "010" },
51 #else
52   { RPL_STATMEM, "%u %u %s", "010" },
53 #endif
54 /* 011 */
55   { 0 },
56 /* 012 */
57   { 0 },
58 /* 013 */
59   { 0 },
60 /* 014 */
61   { 0 },
62 /* 015 */
63   { RPL_MAP, ":%s%s:%s (%is) [%i clients]", "015" },
64 /* 016 */
65   { RPL_MAPMORE, ":%s%s --> *more*", "016" },
66 /* 017 */
67   { RPL_MAPEND, ":End of /MAP", "017" },
68   { 0 }
69 };
70
71 static Numeric numeric_errors[] = {
72 /* 400 */
73   { ERR_FIRSTERROR, "", "400" },
74 /* 401 */
75   { ERR_NOSUCHNICK, "%s :No such nick", "401" },
76 /* 402 */
77   { ERR_NOSUCHSERVER, "%s :No such server", "402" },
78 /* 403 */
79   { ERR_NOSUCHCHANNEL, "%s :No such channel", "403" },
80 /* 404 */
81   { ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel", "404" },
82 /* 405 */
83   { ERR_TOOMANYCHANNELS, "%s :You have joined too many channels", "405" },
84 /* 406 */
85   { ERR_WASNOSUCHNICK, "%s :There was no such nickname", "406" },
86 /* 407 */
87   { ERR_TOOMANYTARGETS, "%s :Duplicate recipients. No message delivered", "407" },
88 /* 408 */
89   { 0 },
90 /* 409 */
91   { ERR_NOORIGIN, ":No origin specified", "409" },
92 /* 410 */
93   { 0 },
94 /* 411 */
95   { ERR_NORECIPIENT, ":No recipient given (%s)", "411" },
96 /* 412 */
97   { ERR_NOTEXTTOSEND, ":No text to send", "412" },
98 /* 413 */
99   { ERR_NOTOPLEVEL, "%s :No toplevel domain specified", "413" },
100 /* 414 */
101   { ERR_WILDTOPLEVEL, "%s :Wildcard in toplevel Domain", "414" },
102 /* 415 */
103   { 0 },
104 /* 416 */
105   { ERR_QUERYTOOLONG, "%s :Too many lines in the output, restrict your query", "416" },
106 /* 417 */
107   { 0 },
108 /* 418 */
109   { 0 },
110 /* 419 */
111   { 0 },
112 /* 420 */
113   { 0 },
114 /* 421 */
115   { ERR_UNKNOWNCOMMAND, "%s :Unknown command", "421" },
116 /* 422 */
117   { ERR_NOMOTD, ":MOTD File is missing", "422" },
118 /* 423 */
119   { ERR_NOADMININFO, "%s :No administrative info available", "423" },
120 /* 424 */
121   { 0 },
122 /* 425 */
123   { 0 },
124 /* 426 */
125   { 0 },
126 /* 427 */
127   { 0 },
128 /* 428 */
129   { 0 },
130 /* 429 */
131   { 0 },
132 /* 430 */
133   { 0 },
134 /* 431 */
135   { ERR_NONICKNAMEGIVEN, ":No nickname given", "431" },
136 /* 432 */
137   { ERR_ERRONEUSNICKNAME, "%s :Erroneus Nickname", "432" },
138 /* 433 */
139   { ERR_NICKNAMEINUSE, "%s :Nickname is already in use.", "433" },
140 /* 434 */
141   { 0 },
142 /* 435 */
143   { 0 },
144 /* 436 */
145   { ERR_NICKCOLLISION, "%s :Nickname collision KILL", "436" },
146 /* 437 */
147   { ERR_BANNICKCHANGE, "%s :Cannot change nickname while banned on channel", "437" },
148 /* 438 */
149   { ERR_NICKTOOFAST, "%s :Nick change too fast. Please wait %d seconds.", "438" },
150 /* 439 */
151   { ERR_TARGETTOOFAST, "%s :Target change too fast. Please wait %d seconds.", "439" },
152 /* 440 */
153   { 0 },
154 /* 441 */
155   { ERR_USERNOTINCHANNEL, "%s %s :They aren't on that channel", "441" },
156 /* 442 */
157   { ERR_NOTONCHANNEL, "%s :You're not on that channel", "442" },
158 /* 443 */
159   { ERR_USERONCHANNEL, "%s %s :is already on channel", "443" },
160 /* 444 */
161   { 0 },
162 /* 445 */
163   { 0 },
164 /* 446 */
165   { 0 },
166 /* 447 */
167   { 0 },
168 /* 448 */
169   { 0 },
170 /* 449 */
171   { 0 },
172 /* 450 */
173   { 0 },
174 /* 451 */
175   { ERR_NOTREGISTERED, ":You have not registered", "451" },
176 /* 452 */
177   { 0 },
178 /* 453 */
179   { 0 },
180 /* 454 */
181   { 0 },
182 /* 455 */
183   { 0 },
184 /* 456 */
185   { 0 },
186 /* 457 */
187   { 0 },
188 /* 458 */
189   { 0 },
190 /* 459 */
191   { 0 },
192 /* 460 */
193   { 0 },
194 /* 461 */
195   { ERR_NEEDMOREPARAMS, "%s :Not enough parameters", "461" },
196 /* 462 */
197   { ERR_ALREADYREGISTRED, ":You may not reregister", "462" },
198 /* 463 */
199   { ERR_NOPERMFORHOST, ":Your host isn't among the privileged", "463" },
200 /* 464 */
201   { ERR_PASSWDMISMATCH, ":Password Incorrect", "464" },
202 /* 465 */
203   { ERR_YOUREBANNEDCREEP, ":You are banned from this server", "465" },
204 /* 466 */
205   { ERR_YOUWILLBEBANNED, "", "466" },
206 /* 467 */
207   { ERR_KEYSET, "%s :Channel key already set", "467" },
208 /* 468 */
209   { ERR_INVALIDUSERNAME, "", "468" },
210 /* 469 */
211   { 0 },
212 /* 470 */
213   { 0 },
214 /* 471 */
215   { ERR_CHANNELISFULL, "%s :Cannot join channel (+l)", "471" },
216 /* 472 */
217   { ERR_UNKNOWNMODE, "%c :is unknown mode char to me", "472" },
218 /* 473 */
219   { ERR_INVITEONLYCHAN, "%s :Cannot join channel (+i)", "473" },
220 /* 474 */
221   { ERR_BANNEDFROMCHAN, "%s :Cannot join channel (+b)", "474" },
222 /* 475 */
223   { ERR_BADCHANNELKEY, "%s :Cannot join channel (+k)", "475" },
224 /* 476 */
225   { ERR_BADCHANMASK, "%s :Bad Channel Mask", "476" },
226 /* 477 */
227   { 0 },
228 /* 478 */
229   { ERR_BANLISTFULL, "%s %s :Channel ban/ignore list is full", "478" },
230 /* 479 */
231   { ERR_BADCHANNAME, "%s :Cannot join channel (access denied on this server)", "479" },
232 /* 480 */
233   { 0 },
234 /* 481 */
235   { ERR_NOPRIVILEGES, ":Permission Denied: You're not an IRC operator", "481" },
236 /* 482 */
237   { ERR_CHANOPRIVSNEEDED, "%s :You're not channel operator", "482" },
238 /* 483 */
239   { ERR_CANTKILLSERVER, ":You cant kill a server!", "483" },
240 /* 484 */
241   { ERR_ISCHANSERVICE, "%s %s :Cannot kill, kick or deop channel service", "484" },
242 /* 485 */
243   { 0 },
244 /* 486 */
245   { 0 },
246 /* 487 */
247   { 0 },
248 /* 488 */
249   { 0 },
250 /* 489 */
251   { ERR_VOICENEEDED, "%s :You're neither voiced nor channel operator", "489" },
252 /* 490 */
253   { 0 },
254 /* 491 */
255   { ERR_NOOPERHOST, ":No O-lines for your host", "491" },
256 /* 492 */
257   { 0 },
258 /* 493 */
259   { 0 },
260 /* 494 */
261   { 0 },
262 /* 495 */
263   { 0 },
264 /* 496 */
265   { 0 },
266 /* 497 */
267   { 0 },
268 /* 498 */
269   { ERR_ISOPERLCHAN, "%s %s :Cannot kick or deop an IRC Operator on a local channel", "498" },
270 /* 499 */
271   { 0 },
272 /* 500 */
273   { 0 },
274 /* 501 */
275   { ERR_UMODEUNKNOWNFLAG, ":Unknown MODE flag", "501" },
276 /* 502 */
277   { ERR_USERSDONTMATCH, ":Cant change mode for other users", "502" },
278 /* 503 */
279   { 0 },
280 /* 504 */
281   { 0 },
282 /* 505 */
283   { 0 },
284 /* 506 */
285   { 0 },
286 /* 507 */
287   { 0 },
288 /* 508 */
289   { 0 },
290 /* 509 */
291   { 0 },
292 /* 510 */
293   { 0 },
294 /* 511 */
295   { ERR_SILELISTFULL, "%s :Your silence list is full", "511" },
296 /* 512 */
297   { ERR_NOSUCHGLINE, "%s@%s :No such gline", "512" },
298 /* 513 */
299   { ERR_BADPING, "", "513" }
300 };
301
302 static Numeric numeric_replies[] = {
303 /* 300 */
304   { RPL_NONE, 0, "300" },
305 /* 301 */
306   { RPL_AWAY, "%s :%s", "301" },
307 /* 302 */
308   { RPL_USERHOST, ":", "302" },
309 /* 303 */
310   { RPL_ISON, ":", "303" },
311 /* 304 */
312   { RPL_TEXT, 0, "304" },
313 /* 305 */
314   { RPL_UNAWAY, ":You are no longer marked as being away", "305" },
315 /* 306 */
316   { RPL_NOWAWAY, ":You have been marked as being away", "306" },
317 /* 307 */
318   { RPL_USERIP, ":", "307" },
319 /* 308 */
320   { 0 },
321 /* 309 */
322   { 0 },
323 /* 310 */
324   { 0 },
325 /* 311 */
326   { RPL_WHOISUSER, "%s %s %s * :%s", "311" },
327 /* 312 */
328   { RPL_WHOISSERVER, "%s %s :%s", "312" },
329 /* 313 */
330   { RPL_WHOISOPERATOR, "%s :is an IRC Operator", "313" },
331 /* 314 */
332   { RPL_WHOWASUSER, "%s %s %s * :%s", "314" },
333 /* 315 */
334   { RPL_ENDOFWHO, "%s :End of /WHO list.", "315" },
335 /* 316 */
336   { 0 },
337 /* 317 */
338   { RPL_WHOISIDLE, "%s %ld %ld :seconds idle, signon time", "317" },
339 /* 318 */
340   { RPL_ENDOFWHOIS, "%s :End of /WHOIS list.", "318" },
341 /* 319 */
342   { RPL_WHOISCHANNELS, "%s :%s", "319" },
343 /* 320 */
344   { 0 },
345 /* 321 */
346   { RPL_LISTSTART, "Channel :Users  Name", "321" },
347 /* 322 */
348   { RPL_LIST, "%s %d :%s", "322" },
349 /* 323 */
350   { RPL_LISTEND, ":End of /LIST", "323" },
351 /* 324 */
352   { RPL_CHANNELMODEIS, "%s %s %s", "324" },
353 /* 325 */
354   { 0 },
355 /* 326 */
356   { 0 },
357 /* 327 */
358   { 0 },
359 /* 328 */
360   { 0 },
361 /* 329 */
362   { RPL_CREATIONTIME, "%s " TIME_T_FMT, "329" },
363 /* 330 */
364   { 0 },
365 /* 331 */
366   { RPL_NOTOPIC, "%s :No topic is set.", "331" },
367 /* 332 */
368   { RPL_TOPIC, "%s :%s", "332" },
369 /* 333 */
370   { RPL_TOPICWHOTIME, "%s %s " TIME_T_FMT, "333" },
371 /* 334 */
372   { RPL_LISTUSAGE, ":%s", "334" },
373 /* 335 */
374   { 0 },
375 /* 336 */
376   { 0 },
377 /* 337 */
378   { 0 },
379 /* 338 */
380   { 0 },
381 /* 339 */
382   { 0 },
383 /* 340 */
384   { 0 },
385 /* 341 */
386   { RPL_INVITING, "%s %s", "341" },
387 /* 342 */
388   { 0 },
389 /* 343 */
390   { 0 },
391 /* 344 */
392   { 0 },
393 /* 345 */
394   { 0 },
395 /* 346 */
396   { RPL_INVITELIST, ":%s", "346" },
397 /* 347 */
398   { RPL_ENDOFINVITELIST, ":End of Invite List", "347" },
399 /* 348 */
400   { 0 },
401 /* 349 */
402   { 0 },
403 /* 350 */
404   { 0 },
405 /* 351 */
406   { RPL_VERSION, "%s.%s %s :%s", "351" },
407 /* 352 */
408   { RPL_WHOREPLY, "%s", "352" },
409 /* 353 */
410   { RPL_NAMREPLY, "%s", "353" },
411 /* 354 */
412   { RPL_WHOSPCRPL, "%s", "354" },
413 /* 355 */
414   { 0 },
415 /* 356 */
416   { 0 },
417 /* 357 */
418   { 0 },
419 /* 358 */
420   { 0 },
421 /* 359 */
422   { 0 },
423 /* 360 */
424   { 0 },
425 /* 361 */
426   { RPL_KILLDONE, 0, "361" },
427 /* 362 */
428   { RPL_CLOSING, "%s :Closed. Status = %d", "362" },
429 /* 363 */
430   { RPL_CLOSEEND, "%d: Connections Closed", "363" },
431 /* 364 */
432 #ifndef GODMODE
433   { RPL_LINKS, "%s %s :%d P%u %s", "364" },
434 #else /* GODMODE */
435   { RPL_LINKS, "%s %s :%d P%u " TIME_T_FMT " (%s) %s", "364" },
436 #endif /* GODMODE */
437 /* 365 */
438   { RPL_ENDOFLINKS, "%s :End of /LINKS list.", "365" },
439 /* 366 */
440   { RPL_ENDOFNAMES, "%s :End of /NAMES list.", "366" },
441 /* 367 */
442   { RPL_BANLIST, "%s %s %s " TIME_T_FMT, "367" },
443 /* 368 */
444   { RPL_ENDOFBANLIST, "%s :End of Channel Ban List", "368" },
445 /* 369 */
446   { RPL_ENDOFWHOWAS, "%s :End of WHOWAS", "369" },
447 /* 370 */
448   { 0 },
449 /* 371 */
450   { RPL_INFO, ":%s", "371" },
451 /* 372 */
452   { RPL_MOTD, ":- %s", "372" },
453 /* 373 */
454   { RPL_INFOSTART, ":Server INFO", "373" },
455 /* 374 */
456   { RPL_ENDOFINFO, ":End of /INFO list.", "374" },
457 /* 375 */
458   { RPL_MOTDSTART, ":- %s Message of the Day - ", "375" },
459 /* 376 */
460   { RPL_ENDOFMOTD, ":End of /MOTD command.", "376" },
461 /* 377 */
462   { 0 },
463 /* 378 */
464   { 0 },
465 /* 379 */
466   { 0 },
467 /* 380 */
468   { 0 },
469 /* 381 */
470   { RPL_YOUREOPER, ":You are now an IRC Operator", "381" },
471 /* 382 */
472   { RPL_REHASHING, "%s :Rehashing", "382" },
473 /* 383 */
474   { 0 },
475 /* 384 */
476   { RPL_MYPORTIS, "%d :Port to local server is", "384" },
477 /* 385 */
478   { RPL_NOTOPERANYMORE, 0, "385" },
479 /* 386 */
480   { 0 },
481 /* 387 */
482   { 0 },
483 /* 388 */
484   { 0 },
485 /* 389 */
486   { 0 },
487 /* 390 */
488   { 0 },
489 /* 391 */
490   { RPL_TIME, "%s " TIME_T_FMT " %ld :%s", "391" },
491 /* 392 */
492   { 0 },
493 /* 393 */
494   { 0 },
495 /* 394 */
496   { 0 },
497 /* 395 */
498   { 0 },
499 /* 396 */
500   { 0 },
501 /* 397 */
502   { 0 },
503 /* 398 */
504   { 0 },
505 /* 399 */
506   { 0 },
507 /* 200 */
508 #ifndef GODMODE
509   { RPL_TRACELINK, "Link %s%s %s %s", "200" },
510 #else /* GODMODE */
511   { RPL_TRACELINK, "Link %s%s %s %s " TIME_T_FMT, "200" },
512 #endif /* GODMODE */
513 /* 201 */
514   { RPL_TRACECONNECTING, "Try. %d %s", "201" },
515 /* 202 */
516   { RPL_TRACEHANDSHAKE, "H.S. %d %s", "202" },
517 /* 203 */
518   { RPL_TRACEUNKNOWN, "???? %d %s", "203" },
519 /* 204 */
520   { RPL_TRACEOPERATOR, "Oper %d %s %ld", "204" },
521 /* 205 */
522   { RPL_TRACEUSER, "User %d %s %ld", "205" },
523 /* 206 */
524   { RPL_TRACESERVER, "Serv %d %dS %dC %s %s!%s@%s %ld %ld", "206" },
525 /* 207 */
526   { 0 },
527 /* 208 */
528   { RPL_TRACENEWTYPE, "<newtype> 0 %s", "208" },
529 /* 209 */
530   { RPL_TRACECLASS, "Class %d %d", "209" },
531 /* 210 */
532   { 0 },
533 /* 211 */
534   { RPL_STATSLINKINFO, 0, "211" },
535 /* 212 */
536   { RPL_STATSCOMMANDS, "%s %u %u", "212" },
537 /* 213 */
538   { RPL_STATSCLINE, "%c %s * %s %d %d", "213" },
539 /* 214 */
540   { RPL_STATSNLINE, "%c %s * %s %d %d", "214" },
541 /* 215 */
542   { RPL_STATSILINE, "%c %s * %s %d %d", "215" },
543 /* 216 */
544   { RPL_STATSKLINE, "%c %s %s %s %d %d", "216" },
545 /* 217 */
546   { RPL_STATSPLINE, "P %d %d %s %s", "217" },
547 /* 218 */
548   { RPL_STATSYLINE, "%c %d %d %d %d %ld", "218" },
549 /* 219 */
550   { RPL_ENDOFSTATS, "%c :End of /STATS report", "219" },
551 /* 220 */
552   { 0 },
553 /* 221 */
554   { RPL_UMODEIS, "%s", "221" },
555 /* 222 */
556   { 0 },
557 /* 223 */
558   { 0 },
559 /* 224 */
560   { 0 },
561 /* 225 */
562   { 0 },
563 /* 226 */
564   { 0 },
565 /* 227 */
566   { 0 },
567 /* 228 */
568   { 0 },
569 /* 229 */
570   { 0 },
571 /* 230 */
572   { 0 },
573 /* 231 */
574   { RPL_SERVICEINFO, 0, "231" },
575 /* 232 */
576   { RPL_ENDOFSERVICES, 0, "232" },
577 /* 233 */
578   { RPL_SERVICE, 0, "233" },
579 /* 234 */
580   { RPL_SERVLIST, 0, "234" },
581 /* 235 */
582   { RPL_SERVLISTEND, 0, "235" },
583 /* 236 */
584   { 0 },
585 /* 237 */
586   { 0 },
587 /* 238 */
588   { 0 },
589 /* 239 */
590   { 0 },
591 /* 240 */
592   { 0 },
593 /* 241 */
594   { RPL_STATSLLINE, "%c %s * %s %d %d", "241" },
595 /* 242 */
596   { RPL_STATSUPTIME, ":Server Up %d days, %d:%02d:%02d", "242" },
597 /* 243 */
598   { RPL_STATSOLINE, "%c %s * %s %d %d", "243" },
599 /* 244 */
600   { RPL_STATSHLINE, "%c %s * %s %d %d", "244" },
601 /* 245 */
602   { 0 },
603 /* 246 */
604   { RPL_STATSTLINE, "%c %s %s", "246" },
605 /* 247 */
606   { RPL_STATSGLINE, "%c %s@%s " TIME_T_FMT " :%s", "247" },
607 /* 248 */
608   { RPL_STATSULINE, "%c %s %s %s %d %d", "248" },
609 /* 249 */
610   { 0 },
611 /* 250 */
612   { RPL_STATSCONN, ":Highest connection count: %d (%d clients)", "250" },
613 /* 251 */
614   { RPL_LUSERCLIENT, ":There are %d users and %d invisible on %d servers", "251" },
615 /* 252 */
616   { RPL_LUSEROP, "%d :operator(s) online", "252" },
617 /* 253 */
618   { RPL_LUSERUNKNOWN, "%d :unknown connection(s)", "253" },
619 /* 254 */
620   { RPL_LUSERCHANNELS, "%d :channels formed", "254" },
621 /* 255 */
622   { RPL_LUSERME, ":I have %d clients and %d servers", "255" },
623 /* 256 */
624   { RPL_ADMINME, ":Administrative info about %s", "256" },
625 /* 257 */
626   { RPL_ADMINLOC1, ":%s", "257" },
627 /* 258 */
628   { RPL_ADMINLOC2, ":%s", "258" },
629 /* 259 */
630   { RPL_ADMINEMAIL, ":%s", "259" },
631 /* 260 */
632   { 0 },
633 /* 261 */
634   { RPL_TRACELOG, "File %s %d", "261" },
635 /* 262 */
636   { RPL_TRACEPING, "Ping %s %s", "262" },
637 /* 263 */
638   { 0 },
639 /* 264 */
640   { 0 },
641 /* 265 */
642   { 0 },
643 /* 266 */
644   { 0 },
645 /* 267 */
646   { 0 },
647 /* 268 */
648   { 0 },
649 /* 269 */
650   { 0 },
651 /* 270 */
652   { 0 },
653 /* 271 */
654   { RPL_SILELIST, "%s %s", "271" },
655 /* 272 */
656   { RPL_ENDOFSILELIST, "%s :End of Silence List", "272" },
657 /* 273 */
658   { 0 },
659 /* 274 */
660   { 0 },
661 /* 275 */
662   { RPL_STATSDLINE, "%c %s %s", "275" },
663 /* 276 */
664   { 0 },
665 /* 277 */
666   { 0 },
667 /* 278 */
668   { 0 },
669 /* 279 */
670   { 0 },
671 /* 280 */
672   { RPL_GLIST, "%s@%s " TIME_T_FMT " %s%s", "280" },
673 /* 281 */
674   { RPL_ENDOFGLIST, ":End of G-line List", "281" },
675 /* 283 */
676   { 0 },
677 /* 284 */
678   { 0 }
679 };
680
681 const struct Numeric* get_error_numeric(int numeric)
682 {
683   int num = numeric;
684   assert(ERR_FIRSTERROR < num);
685   assert(num < ERR_INVALID_ERROR);
686
687   num -= ERR_FIRSTERROR;
688   assert(0 != numeric_errors[num].value);
689
690   return &numeric_errors[num];
691 }
692
693 static char numbuff[512];
694
695 /* "inline" */
696 #define prepbuf(buffer, num, tail)                      \
697 {                                                       \
698   char *s = buffer + 4;                 \
699   const char *ap = atoi_tab + (num << 2);       \
700                                                         \
701   strcpy(buffer, ":%s 000 %s ");                        \
702   *s++ = *ap++;                                         \
703   *s++ = *ap++;                                         \
704   *s = *ap;                                             \
705   strcpy(s + 5, tail);                                  \
706 }
707
708 char *err_str(int numeric)
709 {
710   Numeric *nptr;
711   int num = numeric;
712
713   num -= numeric_errors[0].value;
714
715 #ifdef DEBUGMODE
716   if (num < 0 || num > ERR_USERSDONTMATCH)
717     sprintf_irc(numbuff,
718         ":%%s %d %%s :INTERNAL ERROR: BAD NUMERIC! %d", numeric, num);
719   else
720   {
721     nptr = &numeric_errors[num];
722     if (!nptr->format || !nptr->value)
723       sprintf_irc(numbuff, ":%%s %d %%s :NO ERROR FOR NUMERIC ERROR %d",
724           numeric, num);
725     else
726       prepbuf(numbuff, nptr->value, nptr->format);
727   }
728 #else
729   nptr = &numeric_errors[num];
730   prepbuf(numbuff, nptr->value, nptr->format);
731 #endif
732
733   return numbuff;
734 }
735
736 char *rpl_str(int numeric)
737 {
738   Numeric *nptr;
739   int num = numeric;
740
741   if (num > (int)(sizeof(local_replies) / sizeof(Numeric) - 2))
742     num -= (num > 300) ? 300 : 100;
743
744 #ifdef DEBUGMODE
745   if (num < 0 || num > 200)
746     sprintf_irc(numbuff, ":%%s %d %%s :INTERNAL REPLY ERROR: BAD NUMERIC! %d",
747         numeric, num);
748   else
749   {
750     if (numeric > 99)
751       nptr = &numeric_replies[num];
752     else
753       nptr = &local_replies[num];
754     Debug((DEBUG_NUM, "rpl_str: numeric %d num %d %d %s",
755         numeric, num, nptr->value, nptr->format ? nptr->format : ""));
756     if (!nptr->format || !nptr->value)
757       sprintf_irc(numbuff, ":%%s %d %%s :NO REPLY FOR NUMERIC ERROR %d",
758           numeric, num);
759     else
760       prepbuf(numbuff, nptr->value, nptr->format);
761   }
762 #else
763   if (numeric > 99)
764     nptr = &numeric_replies[num];
765   else
766     nptr = &local_replies[num];
767   prepbuf(numbuff, nptr->value, nptr->format);
768 #endif
769
770   return numbuff;
771 }