misc.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296
  1. /*
  2. * misc.c -- handles:
  3. * split() maskhost() dumplots() daysago() days() daysdur()
  4. * queueing output for the bot (msg and help)
  5. * resync buffers for sharebots
  6. * motd display and %var substitution
  7. *
  8. */
  9. #include "common.h"
  10. #include "misc.h"
  11. #include "settings.h"
  12. #include "rfc1459.h"
  13. #include "misc_file.h"
  14. #include "egg_timer.h"
  15. #include "dcc.h"
  16. #include "users.h"
  17. #include "main.h"
  18. #include "debug.h"
  19. #include "dccutil.h"
  20. #include "chanprog.h"
  21. #include "color.h"
  22. #include "botmsg.h"
  23. #include "bg.h"
  24. #include "chan.h"
  25. #include "tandem.h"
  26. #ifdef LEAF
  27. #include "src/mod/server.mod/server.h"
  28. #include "src/mod/irc.mod/irc.h"
  29. #endif /* LEAF */
  30. #include "userrec.h"
  31. #include "stat.h"
  32. #include <sys/wait.h>
  33. #include <stdarg.h>
  34. int server_lag = 0; /* GUESS! */
  35. int use_invites = 1; /* Jason/drummer */
  36. int use_exempts = 1; /* Jason/drummer */
  37. /*
  38. * Misc functions
  39. */
  40. /* low-level stuff for other modules
  41. */
  42. /* This implementation wont overrun dst - 'max' is the max bytes that dst
  43. * can be, including the null terminator. So if 'dst' is a 128 byte buffer,
  44. * pass 128 as 'max'. The function will _always_ null-terminate 'dst'.
  45. *
  46. * Returns: The number of characters appended to 'dst'.
  47. *
  48. * Usage eg.
  49. *
  50. * char buf[128];
  51. * size_t bufsize = sizeof(buf);
  52. *
  53. * buf[0] = 0, bufsize--;
  54. *
  55. * while (blah && bufsize) {
  56. * bufsize -= egg_strcatn(buf, <some-long-string>, sizeof(buf));
  57. * }
  58. *
  59. * <Cybah>
  60. */
  61. int egg_strcatn(char *dst, const char *src, size_t max)
  62. {
  63. size_t tmpmax = 0;
  64. /* find end of 'dst' */
  65. while (*dst && max > 0) {
  66. dst++;
  67. max--;
  68. }
  69. /* Store 'max', so we can use it to workout how many characters were
  70. * written later on.
  71. */
  72. tmpmax = max;
  73. /* copy upto, but not including the null terminator */
  74. while (*src && max > 1) {
  75. *dst++ = *src++;
  76. max--;
  77. }
  78. /* null-terminate the buffer */
  79. *dst = 0;
  80. /* Don't include the terminating null in our count, as it will cumulate
  81. * in loops - causing a headache for the caller.
  82. */
  83. return tmpmax - max;
  84. }
  85. int my_strcpy(register char *a, register char *b)
  86. {
  87. register char *c = b;
  88. while (*b)
  89. *a++ = *b++;
  90. *a = *b;
  91. return b - c;
  92. }
  93. /* Split first word off of rest and put it in first
  94. */
  95. void splitc(char *first, char *rest, char divider)
  96. {
  97. char *p = NULL;
  98. p = strchr(rest, divider);
  99. if (p == NULL) {
  100. if (first != rest && first)
  101. first[0] = 0;
  102. return;
  103. }
  104. *p = 0;
  105. if (first != NULL)
  106. strcpy(first, rest);
  107. if (first != rest)
  108. /* In most circumstances, strcpy with src and dst being the same buffer
  109. * can produce undefined results. We're safe here, as the src is
  110. * guaranteed to be at least 2 bytes higher in memory than dest. <Cybah>
  111. */
  112. strcpy(rest, p + 1);
  113. }
  114. /* As above, but lets you specify the 'max' number of bytes (EXCLUDING the
  115. * terminating null).
  116. *
  117. * Example of use:
  118. *
  119. * char buf[HANDLEN + 1];
  120. *
  121. * splitcn(buf, input, "@", HANDLEN);
  122. *
  123. * <Cybah>
  124. */
  125. void splitcn(char *first, char *rest, char divider, size_t max)
  126. {
  127. char *p = NULL;
  128. p = strchr(rest, divider);
  129. if (p == NULL) {
  130. if (first != rest && first)
  131. first[0] = 0;
  132. return;
  133. }
  134. *p = 0;
  135. if (first != NULL)
  136. strncpyz(first, rest, max);
  137. if (first != rest)
  138. /* In most circumstances, strcpy with src and dst being the same buffer
  139. * can produce undefined results. We're safe here, as the src is
  140. * guaranteed to be at least 2 bytes higher in memory than dest. <Cybah>
  141. */
  142. strcpy(rest, p + 1);
  143. }
  144. char *splitnick(char **blah)
  145. {
  146. char *p = NULL, *q = *blah;
  147. p = strchr(*blah, '!');
  148. if (p) {
  149. *p = 0;
  150. *blah = p + 1;
  151. return q;
  152. }
  153. return "";
  154. }
  155. void remove_crlf(char **line)
  156. {
  157. char *p = NULL;
  158. p = strchr(*line, '\n');
  159. if (p != NULL)
  160. *p = 0;
  161. p = strchr(*line, '\r');
  162. if (p != NULL)
  163. *p = 0;
  164. }
  165. char *newsplit(char **rest)
  166. {
  167. register char *o = NULL, *r = NULL;
  168. if (!rest)
  169. return *rest = "";
  170. o = *rest;
  171. while (*o == ' ')
  172. o++;
  173. r = o;
  174. while (*o && (*o != ' '))
  175. o++;
  176. if (*o)
  177. *o++ = 0;
  178. *rest = o;
  179. return r;
  180. }
  181. /* Convert "abc!user@a.b.host" into "*!user@*.b.host"
  182. * or "abc!user@1.2.3.4" into "*!user@1.2.3.*"
  183. * or "abc!user@0:0:0:0:0:ffff:1.2.3.4" into "*!user@0:0:0:0:0:ffff:1.2.3.*"
  184. * or "abc!user@3ffe:604:2:b02e:6174:7265:6964:6573" into
  185. * "*!user@3ffe:604:2:b02e:6174:7265:6964:*"
  186. */
  187. void maskhost(const char *s, char *nw)
  188. {
  189. register const char *p, *q, *e, *f;
  190. int i;
  191. *nw++ = '*';
  192. *nw++ = '!';
  193. p = (q = strchr(s, '!')) ? q + 1 : s;
  194. /* Strip of any nick, if a username is found, use last 8 chars */
  195. if ((q = strchr(p, '@'))) {
  196. int fl = 0;
  197. if ((q - p) > 9) {
  198. nw[0] = '*';
  199. p = q - 7;
  200. i = 1;
  201. } else
  202. i = 0;
  203. while (*p != '@') {
  204. if (!fl && strchr("~+-^=", *p)) {
  205. if (strict_host)
  206. nw[i] = '?';
  207. else
  208. i--;
  209. } else
  210. nw[i] = *p;
  211. fl++;
  212. p++;
  213. i++;
  214. }
  215. nw[i++] = '@';
  216. q++;
  217. } else {
  218. nw[0] = '*';
  219. nw[1] = '@';
  220. i = 2;
  221. q = s;
  222. }
  223. nw += i;
  224. e = NULL;
  225. /* Now q points to the hostname, i point to where to put the mask */
  226. if ((!(p = strchr(q, '.')) || !(e = strchr(p + 1, '.'))) && !strchr(q, ':'))
  227. /* TLD or 2 part host */
  228. strcpy(nw, q);
  229. else {
  230. if (e == NULL) { /* IPv6 address? */
  231. const char *mask_str;
  232. f = strrchr(q, ':');
  233. if (strchr(f, '.')) { /* IPv4 wrapped in an IPv6? */
  234. f = strrchr(f, '.');
  235. mask_str = ".*";
  236. } else /* ... no, true IPv6. */
  237. mask_str = ":*";
  238. strncpy(nw, q, f - q);
  239. /* No need to nw[f-q] = 0 here, as the strcpy below will
  240. * terminate the string for us.
  241. */
  242. nw += (f - q);
  243. strcpy(nw, mask_str);
  244. } else {
  245. for (f = e; *f; f++);
  246. f--;
  247. if (*f >= '0' && *f <= '9') { /* Numeric IP address */
  248. while (*f != '.')
  249. f--;
  250. strncpy(nw, q, f - q);
  251. /* No need to nw[f-q] = 0 here, as the strcpy below will
  252. * terminate the string for us.
  253. */
  254. nw += (f - q);
  255. strcpy(nw, ".*");
  256. } else { /* Normal host >= 3 parts */
  257. /* a.b.c -> *.b.c
  258. * a.b.c.d -> *.b.c.d if tld is a country (2 chars)
  259. * OR *.c.d if tld is com/edu/etc (3 chars)
  260. * a.b.c.d.e -> *.c.d.e etc
  261. */
  262. const char *x = strchr(e + 1, '.');
  263. if (!x)
  264. x = p;
  265. else if (strchr(x + 1, '.'))
  266. x = e;
  267. else if (strlen(x) == 3)
  268. x = p;
  269. else
  270. x = e;
  271. sprintf(nw, "*%s", x);
  272. }
  273. }
  274. }
  275. }
  276. /* Dump a potentially super-long string of text.
  277. */
  278. void dumplots(int idx, const char *prefix, char *data)
  279. {
  280. char *p = data, *q = NULL, *n = NULL, c = 0;
  281. const int max_data_len = 500 - strlen(prefix);
  282. if (!*data) {
  283. dprintf(idx, "%s\n", prefix);
  284. return;
  285. }
  286. while (strlen(p) > max_data_len) {
  287. q = p + max_data_len;
  288. /* Search for embedded linefeed first */
  289. n = strchr(p, '\n');
  290. if (n && n < q) {
  291. /* Great! dump that first line then start over */
  292. *n = 0;
  293. dprintf(idx, "%s%s\n", prefix, p);
  294. *n = '\n';
  295. p = n + 1;
  296. } else {
  297. /* Search backwards for the last space */
  298. while (*q != ' ' && q != p)
  299. q--;
  300. if (q == p)
  301. q = p + max_data_len;
  302. c = *q;
  303. *q = 0;
  304. dprintf(idx, "%s%s\n", prefix, p);
  305. *q = c;
  306. p = q;
  307. if (c == ' ')
  308. p++;
  309. }
  310. }
  311. /* Last trailing bit: split by linefeeds if possible */
  312. n = strchr(p, '\n');
  313. while (n) {
  314. *n = 0;
  315. dprintf(idx, "%s%s\n", prefix, p);
  316. *n = '\n';
  317. p = n + 1;
  318. n = strchr(p, '\n');
  319. }
  320. if (*p)
  321. dprintf(idx, "%s%s\n", prefix, p); /* Last trailing bit */
  322. }
  323. /* Convert an interval (in seconds) to one of:
  324. * "19 days ago", "1 day ago", "18:12"
  325. */
  326. void daysago(time_t now, time_t then, char *out)
  327. {
  328. if (now - then > 86400) {
  329. int days = (now - then) / 86400;
  330. sprintf(out, "%d day%s ago", days, (days == 1) ? "" : "s");
  331. return;
  332. }
  333. #ifdef S_UTCTIME
  334. egg_strftime(out, 6, "%H:%M", gmtime(&then));
  335. #else /* !S_UTCTIME */
  336. egg_strftime(out, 6, "%H:%M", localtime(&then));
  337. #endif /* S_UTCTIME */
  338. }
  339. /* Convert an interval (in seconds) to one of:
  340. * "in 19 days", "in 1 day", "at 18:12"
  341. */
  342. void days(time_t now, time_t then, char *out)
  343. {
  344. if (now - then > 86400) {
  345. int days = (now - then) / 86400;
  346. sprintf(out, "in %d day%s", days, (days == 1) ? "" : "s");
  347. return;
  348. }
  349. #ifdef S_UTCTIME
  350. egg_strftime(out, 9, "at %H:%M", gmtime(&now));
  351. #else /* !S_UTCTIME */
  352. egg_strftime(out, 9, "at %H:%M", localtime(&now));
  353. #endif /* S_UTCTIME */
  354. }
  355. /* Convert an interval (in seconds) to one of:
  356. * "for 19 days", "for 1 day", "for 09:10"
  357. */
  358. void daysdur(time_t now, time_t then, char *out)
  359. {
  360. char s[81] = "";
  361. int hrs, mins;
  362. if (now - then > 86400) {
  363. int days = (now - then) / 86400;
  364. sprintf(out, "for %d day%s", days, (days == 1) ? "" : "s");
  365. return;
  366. }
  367. strcpy(out, "for ");
  368. now -= then;
  369. hrs = (int) (now / 3600);
  370. mins = (int) ((now - (hrs * 3600)) / 60);
  371. sprintf(s, "%02d:%02d", hrs, mins);
  372. strcat(out, s);
  373. }
  374. /* show l33t banner */
  375. static char *fuckyou = " _ _ _ __ _ ____\n| | | (_) / _|_ _ ___| | __ _ _ ___ _ _ _| _ \\\n| |_| | | | |_| | | |/ __| |/ / | | | |/ _ \\| | | | (_) | | |\n| _ | |_ | _| |_| | (__| < | |_| | (_) | |_| | _| |_| |\n|_| |_|_( ) |_| \\__,_|\\___|_|\\_\\ \\__, |\\___/ \\__,_| (_)____/\n |/ |___/\n";
  376. char *wbanner() {
  377. if (fuckyou) ;
  378. switch (randint(9)) {
  379. case 0: return STR(" .__ __ .__\n__ _ ______________ |__|/ |_| |__\n\\ \\/ \\/ /\\_ __ \\__ \\ | \\ __\\ | \\\n \\ / | | \\// __ \\| || | | Y \\\n \\/\\_/ |__| (____ /__||__| |___| /\n \\/ \\/\n");
  380. case 1: return STR(" _ _ _ \n__ ___ __ __ _(_) |_| |__ \n\\ \\ /\\ / / '__/ _` | | __| '_ \\ \n \\ V V /| | | (_| | | |_| | | |\n \\_/\\_/ |_| \\__,_|_|\\__|_| |_|\n");
  381. case 2: return STR("@@@ @@@ @@@ @@@@@@@ @@@@@@ @@@ @@@@@@@ @@@ @@@\n@@@ @@@ @@@ @@@@@@@@ @@@@@@@@ @@@ @@@@@@@ @@@ @@@\n@@! @@! @@! @@! @@@ @@! @@@ @@! @@! @@! @@@\n!@! !@! !@! !@! @!@ !@! @!@ !@! !@! !@! @!@\n@!! !!@ @!@ @!@!!@! @!@!@!@! !!@ @!! @!@!@!@!\n!@! !!! !@! !!@!@! !!!@!!!! !!! !!! !!!@!!!!\n!!: !!: !!: !!: :!! !!: !!! !!: !!: !!: !!!\n:!: :!: :!: :!: !:! :!: !:! :!: :!: :!: !:!\n :::: :: ::: :: ::: :: ::: :: :: :: :::\n :: : : : : : : : : : : : : : :\n");
  382. case 3: return STR(" o8o . oooo\n `'' .o8 `888\noooo oooo ooo oooo d8b .oooo. oooo .o888oo 888 .oo.\n `88. `88. .8' `888''8P `P )88b `888 888 888P'Y88b\n `88..]88..8' 888 .oP'888 888 888 888 888\n `888'`888' 888 d8( 888 888 888 . 888 888\n `8' `8' d888b `Y888''8o o888o '888' o888o o888o\n");
  383. case 4: return STR(" *\n * * **\n** *** ** **\n** * ** **\n ** *** **** *** **** ******** **\n ** *** *** * **** **** * **** *** ******** ** ***\n ** *** **** ** **** * *** * *** ** ** * ***\n ** ** ** ** * **** ** ** *** ***\n ** ** ** ** ** ** ** ** ** **\n ** ** ** ** ** ** ** ** ** **\n ** ** ** ** ** ** ** ** ** **\n ** ** * ** ** ** ** ** ** **\n ******* ******* *** ** ** ** ** ** **\n ***** ***** *** ***** ** *** * ** ** **\n *** ** *** ** **\n *\n *\n *\n *\n");
  384. case 5: return STR(" ::: === === :::==== :::==== ::: :::==== ::: ===\n ::: === === ::: === ::: === ::: :::==== ::: ===\n === === === ======= ======== === === ========\n =========== === === === === === === === ===\n ==== ==== === === === === === === === ===\n");
  385. case 6: return STR(" _ _ _ ______ _______ _____ _______ _ _\n | | | |_____/ |_____| | | |_____|\n |__|__| | \\_ | | __|__ | | |\n");
  386. case 7: return STR(" dBPdBPdBP dBBBBBb dBBBBBb dBP dBBBBBBP dBP dBP\n dBP BB\n dBPdBPdBP dBBBBK dBP BB dBP dBP dBBBBBP\n dBPdBPdBP dBP BB dBP BB dBP dBP dBP dBP\n dBBBBBBBP dBP dB' dBBBBBBB dBP dBP dBP dBP\n");
  387. case 8: return STR(" /\n # #/\n ### # ##\n## # ## ##\n## ## ##\n ## ### #### ### /### /### ### ########## /##\n ## ### ###/ ###/ #### / ###/ ########### ## / ###\n ## ### ### ## ###/ ### ## ## ##/ ###\n ## ## ## ## ## ## ## ## ## ##\n ## ## ## ## ## ## ## ## ## ##\n ## ## ## ## ## ## ## ## ## ##\n ## ## ## ## ## ## ## ## ## ##\n ## /# / ## ## /# ## ## ## ##\n ######/ ######/ ### ####/ ## ### /## ## ##\n ##### ##### ### ### ##/##/ ## ## ##\n /\n /\n /\n /");
  388. }
  389. return "";
  390. }
  391. void show_banner(int idx)
  392. {
  393. dumplots(-dcc[idx].sock, "", wbanner()); /* we use sock so that colors aren't applied to banner */
  394. dprintf(idx, "\n \n");
  395. dprintf(idx, STR("%sConributions welcomed by paypal: bryan@shatow.net%s\n"), BOLD(idx), BOLD_END(idx));
  396. dprintf(idx, STR("info, bugs, suggestions, comments:\n- http://wraith.shatow.net/ -\n \n"));
  397. }
  398. /* show motd to dcc chatter */
  399. void show_motd(int idx)
  400. {
  401. if (CFG_MOTD.gdata && *(char *) CFG_MOTD.gdata) {
  402. char *who = NULL, *buf = NULL, *buf_ptr = NULL, date[50] = "";
  403. time_t time;
  404. buf = buf_ptr = strdup(CFG_MOTD.gdata);
  405. who = newsplit(&buf);
  406. time = atoi(newsplit(&buf));
  407. #ifdef S_UTCTIME
  408. egg_strftime(date, sizeof date, "%c %Z", gmtime(&time));
  409. #else /* !S_UTCTIME */
  410. egg_strftime(date, sizeof date, "%c %Z", localtime(&time));
  411. #endif /* S_UTCTIME */
  412. dprintf(idx, "Motd set by \002%s\002 (%s)\n", who, date);
  413. dumplots(idx, "* ", replace(buf, "\\n", "\n"));
  414. dprintf(idx, " \n");
  415. free(buf_ptr);
  416. } else
  417. dprintf(idx, "Motd: none\n");
  418. }
  419. void show_channels(int idx, char *handle)
  420. {
  421. struct chanset_t *chan = NULL;
  422. struct flag_record fr = { FR_CHAN | FR_GLOBAL, 0, 0, 0, 0 };
  423. struct userrec *u = NULL;
  424. int first = 0, l = 0, total = 0;
  425. char format[120] = "";
  426. if (handle)
  427. u = get_user_by_handle(userlist, handle);
  428. else
  429. u = dcc[idx].user;
  430. for (chan = chanset;chan;chan = chan->next) {
  431. get_user_flagrec(u, &fr, chan->dname);
  432. if (l < strlen(chan->dname)) {
  433. l = strlen(chan->dname);
  434. }
  435. if (chk_op(fr, chan))
  436. total++;
  437. }
  438. egg_snprintf(format, sizeof format, " %%c%%-%us %%-s%%-s%%-s%%-s%%-s\n", (l+2));
  439. for (chan = chanset;chan;chan = chan->next) {
  440. int opped = 0;
  441. #ifdef LEAF
  442. opped = me_op(chan);
  443. #endif /* LEAF */
  444. get_user_flagrec(u, &fr, chan->dname);
  445. if (chk_op(fr, chan)) {
  446. if (!first) {
  447. dprintf(idx, "%s %s access to %d channel%s:\n", handle ? u->handle : "You", handle ? "has" : "have", total, (total > 1) ? "s" : "");
  448. first = 1;
  449. }
  450. dprintf(idx, format, opped ? '@' : ' ', chan->dname, !shouldjoin(chan) ? "(inactive) " : "",
  451. channel_private(chan) ? "(private) " : "", !channel_manop(chan) ? "(no manop) " : "",
  452. channel_bitch(chan) ? "(bitch) " : "", channel_closed(chan) ? "(closed)" : "");
  453. }
  454. }
  455. if (!first)
  456. dprintf(idx, "%s %s not have access to any channels.\n", handle ? u->handle : "You", handle ? "does" : "do");
  457. }
  458. int getting_users()
  459. {
  460. int i;
  461. for (i = 0; i < dcc_total; i++)
  462. if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_GETTING))
  463. return 1;
  464. return 0;
  465. }
  466. char *extracthostname(char *hostmask)
  467. {
  468. char *p = NULL;
  469. p = strrchr(hostmask, '@');
  470. return p ? p + 1 : "";
  471. }
  472. /* Create a string with random letters and digits
  473. */
  474. void make_rand_str(char *s, int len)
  475. {
  476. int j, r = 0;
  477. for (j = 0; j < len; j++) {
  478. r = randint(4);
  479. if (r == 0)
  480. s[j] = '0' + randint(10);
  481. else if (r == 1)
  482. s[j] = 'a' + randint(26);
  483. else if (r == 2)
  484. s[j] = 'A' + randint(26);
  485. else if (r == 3)
  486. s[j] = '!' + randint(15);
  487. if (s[j] == 33 || s[j] == 37 || s[j] == 34 || s[j] == 40 || s[j] == 41 || s[j] == 38 || s[j] == 36) /* no % ( ) & */
  488. s[j] = 35;
  489. }
  490. s[len] = '\0';
  491. }
  492. /* Convert an octal string into a decimal integer value. If the string
  493. * is empty or contains non-octal characters, -1 is returned.
  494. */
  495. int oatoi(const char *octal)
  496. {
  497. register int i;
  498. if (!*octal)
  499. return -1;
  500. for (i = 0; ((*octal >= '0') && (*octal <= '7')); octal++)
  501. i = (i * 8) + (*octal - '0');
  502. if (*octal)
  503. return -1;
  504. return i;
  505. }
  506. /* Return an allocated buffer which contains a copy of the string
  507. * 'str', with all 'div' characters escaped by 'mask'. 'mask'
  508. * characters are escaped too.
  509. *
  510. * Remember to free the returned memory block.
  511. */
  512. char *str_escape(const char *str, const char div, const char mask)
  513. {
  514. const int len = strlen(str);
  515. int buflen = (2 * len), blen = 0;
  516. char *buf = NULL, *b = NULL;
  517. const char *s = NULL;
  518. b = buf = malloc(buflen + 1);
  519. if (!buf)
  520. return NULL;
  521. for (s = str; *s; s++) {
  522. /* Resize buffer. */
  523. if ((buflen - blen) <= 3) {
  524. buflen = (buflen * 2);
  525. buf = realloc(buf, buflen + 1);
  526. if (!buf)
  527. return NULL;
  528. b = buf + blen;
  529. }
  530. if (*s == div || *s == mask) {
  531. sprintf(b, "%c%02x", mask, *s);
  532. b += 3;
  533. blen += 3;
  534. } else {
  535. *(b++) = *s;
  536. blen++;
  537. }
  538. }
  539. *b = 0;
  540. return buf;
  541. }
  542. /* Is every character in a string a digit? */
  543. int str_isdigit(const char *str)
  544. {
  545. if (!str || (str && !*str))
  546. return 0;
  547. for(; *str; ++str) {
  548. if (!egg_isdigit(*str))
  549. return 0;
  550. }
  551. return 1;
  552. }
  553. /* Search for a certain character 'div' in the string 'str', while
  554. * ignoring escaped characters prefixed with 'mask'.
  555. *
  556. * The string
  557. *
  558. * "\\3a\\5c i am funny \\3a):further text\\5c):oink"
  559. *
  560. * as str, '\\' as mask and ':' as div would change the str buffer
  561. * to
  562. *
  563. * ":\\ i am funny :)"
  564. *
  565. * and return a pointer to "further text\\5c):oink".
  566. *
  567. * NOTE: If you look carefully, you'll notice that strchr_unescape()
  568. * behaves differently than strchr().
  569. */
  570. char *strchr_unescape(char *str, const char div, register const char esc_char)
  571. {
  572. char buf[3] = "";
  573. register char *s = NULL, *p = NULL;
  574. for (s = p = str; *s; s++, p++) {
  575. if (*s == esc_char) { /* Found escape character. */
  576. /* Convert code to character. */
  577. buf[0] = s[1], buf[1] = s[2];
  578. *p = (unsigned char) strtol(buf, NULL, 16);
  579. s += 2;
  580. } else if (*s == div) {
  581. *p = *s = 0;
  582. return (s + 1); /* Found searched for character. */
  583. } else
  584. *p = *s;
  585. }
  586. *p = 0;
  587. return NULL;
  588. }
  589. /* As strchr_unescape(), but converts the complete string, without
  590. * searching for a specific delimiter character.
  591. */
  592. void str_unescape(char *str, register const char esc_char)
  593. {
  594. (void) strchr_unescape(str, 0, esc_char);
  595. }
  596. /* Kills the bot. s1 is the reason shown to other bots,
  597. * s2 the reason shown on the partyline. (Sup 25Jul2001)
  598. */
  599. void kill_bot(char *s1, char *s2)
  600. {
  601. #ifdef HUB
  602. write_userfile(-1);
  603. #endif /* HUB */
  604. #ifdef LEAF
  605. server_die();
  606. #endif /* LEAF */
  607. chatout("*** %s\n", s1);
  608. botnet_send_chat(-1, conf.bot->nick, s1);
  609. botnet_send_bye();
  610. fatal(s2, 0);
  611. }
  612. /* Update system code
  613. */
  614. #ifdef LEAF
  615. static void updatelocal(void)
  616. {
  617. /* let's drop the server connection ASAP */
  618. nuke_server("Updating...");
  619. botnet_send_chat(-1, conf.bot->nick, "Updating...");
  620. botnet_send_bye();
  621. fatal("Updating...", 1);
  622. usleep(2000 * 500);
  623. unlink(conf.bot->pid_file); /* if this fails it is ok, cron will restart the bot, *hopefully* */
  624. system(binname); /* start new bot. */
  625. exit(0);
  626. }
  627. #endif /* LEAF */
  628. int updatebin(int idx, char *par, int autoi)
  629. {
  630. char *path = NULL, *newbin = NULL;
  631. char buf[DIRMAX] = "", old[DIRMAX] = "", testbuf[DIRMAX] = "";
  632. struct stat sb;
  633. int i;
  634. path = newsplit(&par);
  635. par = path;
  636. if (!par[0]) {
  637. logidx(idx, "Not enough parameters.");
  638. return 1;
  639. }
  640. path = calloc(1, strlen(binname) + strlen(par) + 2);
  641. strcpy(path, binname);
  642. newbin = strrchr(path, '/');
  643. if (!newbin) {
  644. free(path);
  645. logidx(idx, "Don't know current binary name");
  646. return 1;
  647. }
  648. newbin++;
  649. if (strchr(par, '/')) {
  650. *newbin = 0;
  651. logidx(idx, "New binary must be in %s and name must be specified without path information", path);
  652. free(path);
  653. return 1;
  654. }
  655. strcpy(newbin, par);
  656. if (!strcmp(path, binname)) {
  657. free(path);
  658. logidx(idx, "Can't update with the current binary");
  659. return 1;
  660. }
  661. if (stat(path, &sb)) {
  662. logidx(idx, "%s can't be accessed", path);
  663. free(path);
  664. return 1;
  665. }
  666. if (chmod(path, S_IRUSR | S_IWUSR | S_IXUSR)) {
  667. logidx(idx, "Can't set mode 0600 on %s", path);
  668. free(path);
  669. return 1;
  670. }
  671. /* make a backup just in case. */
  672. egg_snprintf(old, sizeof old, "%s.bin.old", tempdir);
  673. copyfile(binname, old);
  674. /* The binary should return '2' when ran with -2, if not it's probably corrupt. */
  675. egg_snprintf(testbuf, sizeof testbuf, "%s -2", path);
  676. i = system(testbuf);
  677. if (i == -1 || WEXITSTATUS(i) != 2) {
  678. dprintf(idx, "Couldn't restart new binary (error %d)\n", i);
  679. putlog(LOG_MISC, "*", "Couldn't restart new binary (error %d)", i);
  680. return i;
  681. }
  682. if (movefile(path, binname)) {
  683. logidx(idx, "Can't rename %s to %s", path, binname);
  684. free(path);
  685. return 1;
  686. }
  687. egg_snprintf(buf, sizeof buf, "%s", binname);
  688. /* safe to run new binary.. */
  689. #ifdef HUB
  690. listen_all(my_port, 1); /* close the listening port... */
  691. usleep(5000);
  692. #endif /* HUB */
  693. #ifdef LEAF
  694. if (!autoi && localhub) {
  695. /* let's drop the server connection ASAP */
  696. nuke_server("Updating...");
  697. #endif /* LEAF */
  698. putlog(LOG_DEBUG, "*", "Running for update: %s", buf);
  699. logidx(idx, "Updating...bye");
  700. putlog(LOG_MISC, "*", "Updating...");
  701. botnet_send_chat(-1, conf.bot->nick, "Updating...");
  702. botnet_send_bye();
  703. fatal("Updating...", 1);
  704. usleep(2000 * 500);
  705. unlink(conf.bot->pid_file); /* delete pid so new binary doesnt exit. */
  706. system(buf); /* run the binary, it SHOULD work from earlier tests.. */
  707. exit(0);
  708. #ifdef LEAF
  709. } else if (localhub && autoi) {
  710. egg_timeval_t howlong;
  711. egg_snprintf(buf, sizeof buf, "%s -L %s -P %d", binname, conf.bot->nick, getpid());
  712. putlog(LOG_DEBUG, "*", "Running for update: %s", buf);
  713. /* will exit after run, cron will restart us later */
  714. system(buf);
  715. howlong.sec = 300;
  716. howlong.usec = 0;
  717. timer_create(&howlong, "updatelocal()", (Function) updatelocal);
  718. return 0;
  719. }
  720. #endif /* LEAF */
  721. /* this should never be reached */
  722. return 2;
  723. }
  724. int bot_aggressive_to(struct userrec *u)
  725. {
  726. char mypval[20] = "", botpval[20] = "";
  727. link_pref_val(u, botpval);
  728. link_pref_val(conf.bot->u, mypval);
  729. if (strcmp(mypval, botpval) < 0)
  730. return 1;
  731. else
  732. return 0;
  733. }
  734. char kickprefix[25] = "";
  735. char bankickprefix[25] = "";
  736. char *kickreason(int kind) {
  737. switch (kind) {
  738. case KICK_BANNED:
  739. switch (randint(6)) {
  740. case 0: return "bye";
  741. case 1: return "banned";
  742. case 2: return "see you in hell";
  743. case 3: return "go away";
  744. case 4: return "cya around lewser";
  745. case 5: return "unwanted!";
  746. }
  747. case KICK_KUSER:
  748. switch (randint(4)) {
  749. case 0: return "not wanted";
  750. case 1: return "something tells me you're annoying";
  751. case 2: return "don't bug me lewser";
  752. case 3: return "creep";
  753. }
  754. case KICK_KICKBAN:
  755. switch (randint(4)) {
  756. case 0: return "gone";
  757. case 1: return "stupid";
  758. case 2: return "lewser";
  759. case 3: return "...";
  760. }
  761. case KICK_MASSDEOP:
  762. switch (randint(8)) {
  763. case 0: return "spammer!";
  764. case 1: return "easy on the modes now";
  765. case 2: return "mode this";
  766. case 3: return "nice try";
  767. case 4: return "really?";
  768. case 5: return "you lose";
  769. case 6: return "scary... really scary...";
  770. case 7: return "i win kthx";
  771. }
  772. case KICK_BADOP:
  773. switch (randint(5)) {
  774. case 0: return "neat...";
  775. case 1: return "oh, no you don't. go away.";
  776. case 2: return "didn't you forget something now?";
  777. case 3: return "no";
  778. case 4: return "hijack this";
  779. }
  780. case KICK_BADOPPED:
  781. switch (randint(5)) {
  782. case 0: return "fuck off kid";
  783. case 1: return "asl?";
  784. case 2: return "whoa... what a hacker... skills!";
  785. case 3: return "yes! yes! yes! hit me baby one more time!";
  786. case 4: return "with your skills, you're better off jacking off than hijacking";
  787. }
  788. case KICK_MANUALOP:
  789. switch (randint(6)) {
  790. case 0: return "naughty kid";
  791. case 1: return "didn't someone tell you that is bad?";
  792. case 2: return "want perm?";
  793. case 3: return "see how much good that did you?";
  794. case 4: return "not a smart move...";
  795. case 5: return "jackass!";
  796. }
  797. case KICK_MANUALOPPED:
  798. switch (randint(8)) {
  799. case 0: return "your pal got mean friends. like me.";
  800. case 1: return "uhh now.. don't wake me up...";
  801. case 2: return "hi hun. missed me?";
  802. case 3: return "spammer! die!";
  803. case 4: return "boo!";
  804. case 5: return "that @ was useful, don't ya think?";
  805. case 6: return "not in my book";
  806. case 7: return "lol, really?";
  807. }
  808. case KICK_CLOSED:
  809. switch (randint(17)) {
  810. case 0: return "locked";
  811. case 1: return "later";
  812. case 2: return "closed for now";
  813. case 3: return "come back later";
  814. case 4: return "better safe than sorry";
  815. case 5: return "cleanup, come back later";
  816. case 6: return "this channel is closed";
  817. case 7: return "shutting down for now";
  818. case 8: return "lockdown";
  819. case 9: return "reopening later";
  820. case 10: return "not for the public atm";
  821. case 11: return "private channel for now";
  822. case 12: return "might reopen soon, might reopen later";
  823. case 13: return "you're not supposed to be here right now";
  824. case 14: return "sorry, closed";
  825. case 15: return "try us later, atm we're locked down";
  826. case 16: return "closed. try tomorrow";
  827. }
  828. case KICK_FLOOD:
  829. switch (randint(7)) {
  830. case 0: return "so much bullshit in such a short time. amazing.";
  831. case 1: return "slow down. i'm trying to read here.";
  832. case 2: return "uhm... you actually think irc is for talking?";
  833. case 3: return "talk talk talk";
  834. case 4: return "blabbering are we?";
  835. case 5: return "... and i don't even like you!";
  836. case 6: return "and you're outa here...";
  837. }
  838. case KICK_NICKFLOOD:
  839. switch (randint(7)) {
  840. case 0: return "make up your mind?";
  841. case 1: return "be schizofrenic elsewhere";
  842. case 2: return "I'm loosing track of you... not!";
  843. case 3: return "that is REALLY annoying";
  844. case 4: return "try this: /NICK n00b";
  845. case 5: return "playing hide 'n' seek?";
  846. case 6: return "gotcha!";
  847. }
  848. case KICK_KICKFLOOD:
  849. switch (randint(6)) {
  850. case 0: return "easier to just leave if you wan't to be alone";
  851. case 1: return "cool down";
  852. case 2: return "don't be so damned aggressive. that's my job.";
  853. case 3: return "kicking's fun, isn't it?";
  854. case 4: return "what's the rush?";
  855. case 5: return "next time you do that, i'll kick you again";
  856. }
  857. case KICK_BOGUSUSERNAME:
  858. return "bogus username";
  859. case KICK_MEAN:
  860. switch (randint(11)) {
  861. case 0: return "hey! that wasn't very nice!";
  862. case 1: return "don't fuck with my pals";
  863. case 2: return "meanie!";
  864. case 3: return "I can be a bitch too...";
  865. case 4: return "leave the bots alone, will ya?";
  866. case 5: return "not very clever";
  867. case 6: return "watch it";
  868. case 7: return "fuck off";
  869. case 8: return "easy now. that's a friend.";
  870. case 9: return "abuse of power. leave that to me, will ya?";
  871. case 10: return "there as some things you cannot do, and that was one of them...";
  872. }
  873. case KICK_BOGUSKEY:
  874. return "I have a really hard time reading that key";
  875. default:
  876. return "OMFG@YUO";
  877. }
  878. }
  879. /*
  880. plain cookie:
  881. Last 6 digits of time
  882. Last 5 chars of nick
  883. Last 4 regular chars of chan
  884. */
  885. void makeplaincookie(char *chname, char *nick, char *buf)
  886. {
  887. char work[256] = "", work2[256] = "";
  888. int i, n;
  889. sprintf(work, "%010li", (now + timesync));
  890. strcpy(buf, (char *) &work[4]);
  891. work[0] = 0;
  892. if (strlen(nick) < 5)
  893. while (strlen(work) + strlen(nick) < 5)
  894. strcat(work, " ");
  895. else
  896. strcpy(work, (char *) &nick[strlen(nick) - 5]);
  897. strcat(buf, work);
  898. n = 3;
  899. for (i = strlen(chname) - 1; (i >= 0) && (n >= 0); i--)
  900. if (((unsigned char) chname[i] < 128) && ((unsigned char) chname[i] > 32)) {
  901. work2[n] = tolower(chname[i]);
  902. n--;
  903. }
  904. while (n >= 0)
  905. work2[n--] = ' ';
  906. work2[4] = 0;
  907. strcat(buf, work2);
  908. }
  909. int goodpass(char *pass, int idx, char *nick)
  910. {
  911. char tell[501] = "";
  912. #ifdef S_NAZIPASS
  913. int i, nalpha = 0, lcase = 0, ucase = 0, ocase = 0, tc;
  914. #endif /* S_NAZIPASS */
  915. if (!pass[0])
  916. return 0;
  917. #ifdef S_NAZIPASS
  918. for (i = 0; i < strlen(pass); i++) {
  919. tc = (int) pass[i];
  920. if (tc < 58 && tc > 47)
  921. ocase++; /* number */
  922. else if (tc < 91 && tc > 64)
  923. ucase++; /* upper case */
  924. else if (tc < 123 && tc > 96)
  925. lcase++; /* lower case */
  926. else
  927. nalpha++; /* non-alphabet/number */
  928. }
  929. /* if (ocase < 1 || lcase < 2 || ucase < 2 || nalpha < 1 || strlen(pass) < 8) { */
  930. if (ocase < 1 || lcase < 2 || ucase < 2 || strlen(pass) < 8) {
  931. #else /* !S_NAZIPASS */
  932. if (strlen(pass) < 8) {
  933. #endif /* S_NAZIPASS */
  934. sprintf(tell, "Insecure pass, must be: ");
  935. #ifdef S_NAZIPASS
  936. if (ocase < 1)
  937. strcat(tell, "\002>= 1 number\002, ");
  938. else
  939. strcat(tell, ">= 1 number, ");
  940. if (lcase < 2)
  941. strcat(tell, "\002>= 2 lcase\002, ");
  942. else
  943. strcat(tell, ">= 2 lowercase, ");
  944. if (ucase < 2)
  945. strcat(tell, "\002>= 2 ucase\002, ");
  946. else
  947. strcat(tell, ">= 2 uppercase, ");
  948. /* This is annoying as hell
  949. if (nalpha < 1)
  950. strcat(tell, "\002>= 1 non-alpha/num\002, ");
  951. else
  952. strcat(tell, ">= 1 non-alpha/num, ");
  953. */
  954. #endif /* S_NAZIPASS */
  955. if (strlen(pass) < 8)
  956. strcat(tell, "\002>= 8 chars.\002");
  957. else
  958. strcat(tell, ">= 8 chars.");
  959. if (idx)
  960. dprintf(idx, "%s\n", tell);
  961. else if (nick[0])
  962. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, tell);
  963. return 0;
  964. }
  965. return 1;
  966. }
  967. char *replace(const char *string, char *oldie, char *newbie)
  968. {
  969. static char newstring[1024] = "";
  970. int str_index, newstr_index, oldie_index, end, new_len, old_len, cpy_len;
  971. char *c = NULL;
  972. if (string == NULL) return "";
  973. if ((c = (char *) strstr(string, oldie)) == NULL) return (char *) string;
  974. new_len = strlen(newbie);
  975. old_len = strlen(oldie);
  976. end = strlen(string) - old_len;
  977. oldie_index = c - string;
  978. newstr_index = 0;
  979. str_index = 0;
  980. while(str_index <= end && c != NULL) {
  981. cpy_len = oldie_index-str_index;
  982. strncpy(newstring + newstr_index, string + str_index, cpy_len);
  983. newstr_index += cpy_len;
  984. str_index += cpy_len;
  985. strcpy(newstring + newstr_index, newbie);
  986. newstr_index += new_len;
  987. str_index += old_len;
  988. if((c = (char *) strstr(string + str_index, oldie)) != NULL)
  989. oldie_index = c - string;
  990. }
  991. strcpy(newstring + newstr_index, string + str_index);
  992. return (newstring);
  993. }
  994. #define HELP_BOLD 1
  995. #define HELP_REV 2
  996. #define HELP_UNDER 4
  997. #define HELP_FLASH 8
  998. /* so many string++ is making the problem */
  999. void showhelp (int idx, struct flag_record *flags, char *string)
  1000. {
  1001. static int help_flags;
  1002. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
  1003. char helpstr[12288] = "", tmp[2] = "", flagstr[10] = "";
  1004. int ok = 1;
  1005. while (string && string[0]) {
  1006. if (*string == '%') {
  1007. if (!strncmp(string + 1, "{+", 2)) {
  1008. while (*string && *string != '+') {
  1009. string++;
  1010. }
  1011. flagstr[0] = 0;
  1012. while (*string && *string != '}') {
  1013. sprintf(tmp, "%c", *string);
  1014. strcat(flagstr, tmp);
  1015. string++;
  1016. }
  1017. string++;
  1018. break_down_flags(flagstr, &fr, NULL);
  1019. if (flagrec_ok(&fr, flags)) {
  1020. ok = 1;
  1021. while (*string && *string != '%') {
  1022. sprintf(tmp, "%c", *string);
  1023. strcat(helpstr, tmp);
  1024. string++;
  1025. }
  1026. if (!strncmp(string + 1, "{-", 2)) {
  1027. ok = 1;
  1028. while (*string && *string != '}') {
  1029. string++;
  1030. }
  1031. string++;
  1032. }
  1033. } else {
  1034. ok = 0;
  1035. }
  1036. } else if (!strncmp(string + 1, "{-", 2)) {
  1037. ok = 1;
  1038. while (*string && *string != '}') {
  1039. string++;
  1040. }
  1041. string++;
  1042. } else if (*string == '{') {
  1043. while (*string && *string != '}') {
  1044. string++;
  1045. }
  1046. } else if (*(string + 1) == 'b') {
  1047. string += 2;
  1048. if (help_flags & HELP_BOLD) {
  1049. help_flags &= ~HELP_BOLD;
  1050. strcat(helpstr, color(idx, BOLD_CLOSE, 0));
  1051. } else {
  1052. help_flags |= HELP_BOLD;
  1053. strcat(helpstr, color(idx, BOLD_OPEN, 0));
  1054. }
  1055. } else if (*(string + 1) == 'f') {
  1056. string += 2;
  1057. if (help_flags & HELP_FLASH) {
  1058. strcat(helpstr, color(idx, FLASH_CLOSE, 0));
  1059. help_flags &= ~HELP_FLASH;
  1060. } else {
  1061. help_flags |= HELP_FLASH;
  1062. strcat(helpstr, color(idx, FLASH_OPEN, 0));
  1063. }
  1064. } else if (*(string + 1) == 'd') {
  1065. string += 2;
  1066. strcat(helpstr, dcc_prefix);
  1067. } else if (*(string + 1) == '%') {
  1068. string += 2;
  1069. strcat(helpstr, "%");
  1070. } else {
  1071. if (ok) {
  1072. sprintf(tmp, "%c", *string);
  1073. strcat(helpstr, tmp);
  1074. }
  1075. string++;
  1076. }
  1077. } else {
  1078. if (ok) {
  1079. sprintf(tmp, "%c", *string);
  1080. strcat(helpstr, tmp);
  1081. }
  1082. string++;
  1083. }
  1084. }
  1085. helpstr[strlen(helpstr)] = 0;
  1086. if (helpstr[0]) dumplots(idx, "", helpstr);
  1087. }
  1088. /* Arrange the N elements of ARRAY in random order. */
  1089. static void shuffleArray(char *array[], int n)
  1090. {
  1091. int i;
  1092. for (i = 0; i < n; i++) {
  1093. int j = i + random() / (RAND_MAX / (n - i) + 1);
  1094. char *t = array[j];
  1095. array[j] = array[i];
  1096. array[i] = t;
  1097. }
  1098. }
  1099. void shuffle(char *string, char *delim)
  1100. {
  1101. char *array[501], *str = NULL, *work = NULL;
  1102. int len = 0, i = 0;
  1103. egg_bzero(&array, sizeof array);
  1104. work = strdup(string);
  1105. str = strtok(work, delim);
  1106. while(str && *str)
  1107. {
  1108. array[len] = str;
  1109. len++;
  1110. str = strtok((char*) NULL, delim);
  1111. }
  1112. shuffleArray(array, len);
  1113. string[0] = 0;
  1114. for (i = 0; i < len; i++) {
  1115. strcat(string, array[i]);
  1116. if (i != len - 1)
  1117. strcat(string, delim);
  1118. }
  1119. free(work);
  1120. string[strlen(string)] = 0;
  1121. }
  1122. char *color(int idx, int type, int color)
  1123. {
  1124. int ansi = 0;
  1125. /* if user is connected over TELNET or !backgrd, show ANSI
  1126. * if they are relaying, they are most likely on an IRC client and should have mIRC codes
  1127. */
  1128. if (idx == -1) { /* who cares, just show color! */
  1129. ansi++;
  1130. } else if (idx && dcc[idx].status & STAT_COLOR) {
  1131. /* over telnet but not relaying */
  1132. if (dcc[idx].type != &DCC_RELAYING && dcc[idx].status & STAT_TELNET)
  1133. ansi++;
  1134. /* else: use mIRC color codes. */
  1135. } else {
  1136. return "";
  1137. }
  1138. if (type == BOLD_OPEN) {
  1139. return ansi ? "\033[1m" : "\002";
  1140. } else if (type == BOLD_CLOSE) {
  1141. return ansi ? "\033[22m" : "\002";
  1142. } else if (type == UNDERLINE_OPEN) {
  1143. return ansi ? "\033[4m" : "\037";
  1144. } else if (type == UNDERLINE_CLOSE) {
  1145. return ansi ? "\033[24m" : "\037";
  1146. } else if (type == FLASH_OPEN) {
  1147. return ansi ? "\033[5m" : "\002\037";
  1148. } else if (type == FLASH_CLOSE) {
  1149. return ansi ? "\033[0m" : "\037\002";
  1150. } else if (type == COLOR_OPEN) {
  1151. switch (color) {
  1152. case C_BLACK: return ansi ? "\033[30m" : "\00301";
  1153. case C_RED: return ansi ? "\033[31m" : "\00305";
  1154. case C_GREEN: return ansi ? "\033[32m" : "\00303";
  1155. case C_BROWN: return ansi ? "\033[33m" : "\00307";
  1156. case C_BLUE: return ansi ? "\033[34m" : "\00302";
  1157. case C_PURPLE: return ansi ? "\033[35m" : "\00306";
  1158. case C_CYAN: return ansi ? "\033[36m" : "\00310";
  1159. case C_WHITE: return ansi ? "\033[1;37m" : "\00300";
  1160. case C_DARKGREY: return ansi ? "\033[1;30m" : "\00314";
  1161. case C_LIGHTRED: return ansi ? "\033[1;31m" : "\00304";
  1162. case C_LIGHTGREEN: return ansi ? "\033[1;32m" : "\00309";
  1163. case C_LIGHTBLUE: return ansi ? "\033[1;34m" : "\00312";
  1164. case C_LIGHTPURPLE: return ansi ? "\033[1;35m" : "\00313";
  1165. case C_LIGHTCYAN: return ansi ? "\033[1;36m" : "\00311";
  1166. case C_LIGHTGREY: return ansi ? "\033[37m" : "\00315";
  1167. case C_YELLOW: return ansi ? "\033[1;33m" : "\00308";
  1168. default: break;
  1169. }
  1170. } else if (type == COLOR_CLOSE) {
  1171. return ansi ? "\033[0m" : "\00300";
  1172. }
  1173. /* This should never be reached.. */
  1174. return "";
  1175. }