misc.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396
  1. /*
  2. * Copyright (C) 1997 Robey Pointer
  3. * Copyright (C) 1999 - 2002 Eggheads Development Team
  4. * Copyright (C) 2002 - 2008 Bryan Drewery
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. /*
  21. * misc.c -- handles:
  22. * split() maskhost() dumplots() daysago() days() daysdur()
  23. * queueing output for the bot (msg and help)
  24. * resync buffers for sharebots
  25. * motd display and %var substitution
  26. *
  27. */
  28. #include "common.h"
  29. #include "misc.h"
  30. #include "settings.h"
  31. #include "binary.h"
  32. #include "rfc1459.h"
  33. #include "botnet.h"
  34. #include "misc_file.h"
  35. #include "egg_timer.h"
  36. #include "dcc.h"
  37. #include "users.h"
  38. #include "shell.h"
  39. #include "main.h"
  40. #include "debug.h"
  41. #include "dccutil.h"
  42. #include "chanprog.h"
  43. #include "color.h"
  44. #include "botmsg.h"
  45. #include "bg.h"
  46. #include "chan.h"
  47. #include "tandem.h"
  48. #include "src/mod/server.mod/server.h"
  49. #include "src/mod/irc.mod/irc.h"
  50. #include "userrec.h"
  51. #include "stat.h"
  52. #include "net.h"
  53. #include "EncryptedStream.h"
  54. #include <bdlib/src/String.h>
  55. #include <bdlib/src/Stream.h>
  56. #include <sys/wait.h>
  57. #include <stdarg.h>
  58. #include <sys/types.h>
  59. #include <signal.h>
  60. int server_lag = 0; /* GUESS! */
  61. bool use_invites = 0;
  62. bool use_exempts = 0;
  63. /*
  64. * Misc functions
  65. */
  66. /* low-level stuff for other modules
  67. */
  68. size_t my_strcpy(register char *a, register const char *b)
  69. {
  70. register const char *c = b;
  71. while (*b)
  72. *a++ = *b++;
  73. *a = *b;
  74. return b - c;
  75. }
  76. /* Split first word off of rest and put it in first
  77. */
  78. void splitc(char *first, char *rest, char divider)
  79. {
  80. char *p = strchr(rest, divider);
  81. if (p == NULL) {
  82. if (first != rest && first)
  83. first[0] = 0;
  84. return;
  85. }
  86. *p = 0;
  87. if (first != NULL)
  88. strcpy(first, rest);
  89. if (first != rest)
  90. /* In most circumstances, strcpy with src and dst being the same buffer
  91. * can produce undefined results. We're safe here, as the src is
  92. * guaranteed to be at least 2 bytes higher in memory than dest. <Cybah>
  93. */
  94. strcpy(rest, p + 1);
  95. }
  96. /* As above, but lets you specify the 'max' number of bytes (EXCLUDING the
  97. * terminating null).
  98. *
  99. * Example of use:
  100. *
  101. * char buf[HANDLEN + 1];
  102. *
  103. * splitcn(buf, input, "@", HANDLEN);
  104. *
  105. * <Cybah>
  106. */
  107. void splitcn(char *first, char *rest, char divider, size_t max)
  108. {
  109. char *p = strchr(rest, divider);
  110. if (p == NULL) {
  111. if (first != rest && first)
  112. first[0] = 0;
  113. return;
  114. }
  115. *p = 0;
  116. if (first != NULL)
  117. strlcpy(first, rest, max);
  118. if (first != rest)
  119. /* In most circumstances, strcpy with src and dst being the same buffer
  120. * can produce undefined results. We're safe here, as the src is
  121. * guaranteed to be at least 2 bytes higher in memory than dest. <Cybah>
  122. */
  123. strcpy(rest, p + 1);
  124. }
  125. char *splitnick(char **blah)
  126. {
  127. char *p = NULL, *q = *blah;
  128. p = strchr(*blah, '!');
  129. if (p) {
  130. *p = 0;
  131. *blah = p + 1;
  132. return q;
  133. }
  134. return "";
  135. }
  136. int remove_crlf(char *line)
  137. {
  138. char *p = NULL;
  139. int removed = 0;
  140. if ((p = strchr(line, '\n'))) {
  141. *p = 0;
  142. removed++;
  143. }
  144. if ((p = strchr(line, '\r'))) {
  145. *p = 0;
  146. removed++;
  147. }
  148. return removed;
  149. }
  150. int remove_crlf_r(char *line)
  151. {
  152. char *p = NULL;
  153. int removed = 0;
  154. if ((p = strrchr(line, '\n'))) {
  155. *p = 0;
  156. removed++;
  157. }
  158. if ((p = strrchr(line, '\r'))) {
  159. *p = 0;
  160. removed++;
  161. }
  162. return removed;
  163. }
  164. char *newsplit(char **rest, char delim, bool trim)
  165. {
  166. if (!rest)
  167. return *rest = "";
  168. register char *o = *rest, *r = NULL;
  169. while (*o == delim)
  170. ++o;
  171. r = o;
  172. while (*o && (*o != delim))
  173. ++o;
  174. if (*o)
  175. *o++ = 0;
  176. /* Trim whitespace */
  177. if (trim) {
  178. while (*o == ' ')
  179. ++o;
  180. }
  181. *rest = o;
  182. return r;
  183. }
  184. /* maskhost(), modified to support custom mask types, as defined
  185. * by mIRC.
  186. * Does not require a proper hostmask in 's'. Accepts any strings,
  187. * including empty ones and attempts to provide meaningful results.
  188. *
  189. * Strings containing no '@' character will be parsed as if the
  190. * whole string is a host.
  191. * Strings containing no '!' character will be interpreted as if
  192. * there is no nick.
  193. * '!' as a nick/user separator must precede any '@' characters.
  194. * Otherwise it will be considered a part of the host.
  195. * Supported types are listed in tcl-commands.doc in the maskhost
  196. * command section. Type 3 resembles the older maskhost() most closely.
  197. *
  198. * Specific examples (with type=3):
  199. *
  200. * "nick!user@is.the.lamest.bg" -> *!*user@*.the.lamest.bg (ccTLD)
  201. * "nick!user@is.the.lamest.com" -> *!*user@*.lamest.com (gTLD)
  202. * "lamest.example" -> *!*@lamest.example
  203. * "whatever@lamest.example" -> *!*whatever@lamest.example
  204. * "com.example@user!nick" -> *!*com.example@user!nick
  205. * "!" -> *!*@!
  206. * "@" -> *!*@*
  207. * "" -> *!*@*
  208. * "abc!user@2001:db8:618:5c0:263:15:dead:babe"
  209. * -> *!*user@2001:db8:618:5c0:263:15:dead:*
  210. * "abc!user@0:0:0:0:0:ffff:1.2.3.4"
  211. * -> *!*user@0:0:0:0:0:ffff:1.2.3.*
  212. */
  213. void maskaddr(const char *s, char *nw, int type)
  214. {
  215. int d = type % 5, num = 1;
  216. register const char *u = NULL, *h = NULL, *p = NULL;
  217. /* Look for user and host.. */
  218. if ((u = strchr(s, '!')))
  219. h = strchr(u, '@');
  220. if (!h)
  221. h = strchr(s, '@');
  222. /* Print nick if required and available */
  223. if (!u || (type % 10) < 5)
  224. *nw++ = '*';
  225. else {
  226. strncpy(nw, s, u - s);
  227. nw += u - s;
  228. }
  229. *nw++ = '!';
  230. /* Write user if required and available */
  231. u = (u ? u + 1 : s);
  232. if (!h || (d == 2) || (d == 4))
  233. *nw++ = '*';
  234. else {
  235. if (d) {
  236. *nw++ = '*';
  237. if (strchr("~+-^=", *u))
  238. u++; /* trim leading crap */
  239. }
  240. strncpy(nw, u, h - u);
  241. nw += h - u;
  242. }
  243. *nw++ = '@';
  244. /* The rest is for the host */
  245. h = (h ? h + 1 : s);
  246. for (p = h; *p; p++) /* hostname? */
  247. if ((*p > '9' || *p < '0') && *p != '.') {
  248. num = 0;
  249. break;
  250. }
  251. p = strrchr(h, ':'); /* IPv6? */
  252. /* Mask out after the last colon/dot */
  253. if (p && d > 2) {
  254. if ((u = strrchr(p, '.')))
  255. p = u;
  256. strncpy(nw, h, ++p - h);
  257. nw += p - h;
  258. strcpy(nw, "*");
  259. } else if (!p && !num && type >= 10) {
  260. /* we have a hostname and type
  261. requires us to replace numbers */
  262. num = 0;
  263. for (p = h; *p; p++) {
  264. if (*p < '0' || *p > '9') {
  265. *nw++ = *p;
  266. num = 0;
  267. } else {
  268. if (type < 20)
  269. *nw++ = '?';
  270. else if (!num) {
  271. *nw++ = '*';
  272. num = 1; /* place only one '*'
  273. per numeric sequence */
  274. }
  275. }
  276. }
  277. *nw = 0;
  278. } else if (d > 2 && (p = strrchr(h, '.'))) {
  279. if (num) { /* IPv4 */
  280. strncpy(nw, h, p - h);
  281. nw += p - h;
  282. strcpy(nw, ".*");
  283. return;
  284. }
  285. for (u = h, d = 0; (u = strchr(++u, '.')); d++) ;
  286. if (d < 2) { /* types < 2 don't mask the host */
  287. strcpy(nw, h);
  288. return;
  289. }
  290. u = strchr(h, '.');
  291. if (d > 3 || (d == 3 && strlen(p) > 3))
  292. u = strchr(++u, '.'); /* ccTLD or not? Look above. */
  293. simple_sprintf(nw, "*%s", u);
  294. } else if (!*h) {
  295. /* take care if the mask is empty or contains only '@' */
  296. strcpy(nw, "*");
  297. } else
  298. strcpy(nw, h);
  299. }
  300. /* Convert an interval (in seconds) to one of:
  301. * "19 days ago", "1 day ago", "18:12"
  302. */
  303. void daysago(time_t mynow, time_t then, char *out, size_t outsiz)
  304. {
  305. if (mynow - then > 86400) {
  306. int mydays = (mynow - then) / 86400;
  307. simple_snprintf(out, outsiz, "%d day%s ago", mydays, (mydays == 1) ? "" : "s");
  308. return;
  309. }
  310. strftime(out, 6, "%H:%M", gmtime(&then));
  311. }
  312. /* Convert an interval (in seconds) to one of:
  313. * "in 19 days", "in 1 day", "at 18:12"
  314. */
  315. void days(time_t mynow, time_t then, char *out, size_t outsiz)
  316. {
  317. if (mynow - then > 86400) {
  318. int mydays = (mynow - then) / 86400;
  319. simple_snprintf(out, outsiz, "in %d day%s", mydays, (mydays == 1) ? "" : "s");
  320. return;
  321. }
  322. strftime(out, 9, "at %H:%M", gmtime(&now));
  323. }
  324. /* Convert an interval (in seconds) to one of:
  325. * "for 19 days", "for 1 day", "for 09:10"
  326. */
  327. void daysdur(time_t mynow, time_t then, char *out, size_t outsiz)
  328. {
  329. if (mynow - then > 86400) {
  330. int mydays = (mynow - then) / 86400;
  331. simple_snprintf(out, outsiz, "for %d day%s", mydays, (mydays == 1) ? "" : "s");
  332. return;
  333. }
  334. char s[81] = "";
  335. strlcpy(out, "for ", outsiz);
  336. mynow -= then;
  337. int hrs = (int) (mynow / 3600);
  338. int mins = (int) ((mynow - (hrs * 3600)) / 60);
  339. simple_snprintf(s, sizeof(s), "%02d:%02d", hrs, mins);
  340. strlcat(out, s, outsiz);
  341. }
  342. /* show l33t banner */
  343. static const char *wbanner(void) {
  344. /*
  345. __ __ __
  346. __ _ ______________ |__|/ |_| |__
  347. \ \/ \/ /\_ __ \__ \ | \ _\ | \
  348. \ / | | \// __ \| || | | \ \
  349. \/\_/ |__| (____ /__||__| |___| /
  350. \/ \/
  351. */
  352. return STR(" __ __ __\n__ _ ______________ |__|/ |_| |__\n\\ \\/ \\/ /\\_ __ \\__ \\ | \\ _\\ | \\\n \\ / | | \\// __ \\| || | | \\ \\\n \\/\\_/ |__| (____ /__||__| |___| /\n \\/ \\/\n");
  353. }
  354. void show_banner(int idx)
  355. {
  356. /* we use sock so that colors aren't applied to banner */
  357. if (dcc[idx].status & STAT_BANNER)
  358. dumplots(-dcc[idx].sock, "", wbanner());
  359. dprintf(idx, " \n");
  360. dprintf(-dcc[idx].sock, STR(" -------------------------------------------------------- \n"));
  361. dprintf(-dcc[idx].sock, STR("| - http://wraith.botpack.net/ - |\n"));
  362. dprintf(-dcc[idx].sock, STR("| Get Shell/Irc/Web hosting @ http://www.xzibition.com |\n"));
  363. dprintf(-dcc[idx].sock, STR("| Use coupon code 'wraith' for 30%% off lifetime |\n"));
  364. dprintf(-dcc[idx].sock, STR(" -------------------------------------------------------- \n"));
  365. dprintf(idx, " \n");
  366. }
  367. /* show motd to dcc chatter */
  368. void show_motd(int idx)
  369. {
  370. if (motd[0]) {
  371. char *who = NULL, *buf = NULL, *buf_ptr = NULL, date[50] = "";
  372. time_t when;
  373. buf = buf_ptr = strdup(motd);
  374. who = newsplit(&buf);
  375. when = atoi(newsplit(&buf));
  376. strftime(date, sizeof date, "%c %Z", gmtime(&when));
  377. dprintf(idx, "Motd set by %s%s%s (%s)\n", BOLD(idx), who, BOLD_END(idx), date);
  378. dumplots(idx, "* ", replace(buf, "\\n", "\n"));
  379. dprintf(idx, " \n");
  380. free(buf_ptr);
  381. } else
  382. dprintf(idx, "Motd: none\n");
  383. }
  384. void show_channels(int idx, char *handle)
  385. {
  386. struct chanset_t *chan = NULL;
  387. struct flag_record fr = { FR_CHAN | FR_GLOBAL, 0, 0, 0 };
  388. struct userrec *u = NULL;
  389. int first = 0, total = 0;
  390. size_t l = 0;
  391. char format[120] = "";
  392. if (handle)
  393. u = get_user_by_handle(userlist, handle);
  394. else
  395. u = dcc[idx].user;
  396. for (chan = chanset;chan ;chan = chan->next) {
  397. get_user_flagrec(u, &fr, chan->dname);
  398. if (l < strlen(chan->dname)) {
  399. l = strlen(chan->dname);
  400. }
  401. if (real_chk_op(fr, chan, 0))
  402. total++;
  403. }
  404. simple_snprintf(format, sizeof(format), " %%c%%-%zus %%-s%%-s%%-s%%-s%%-s%%-s\n", (l+2));
  405. for (chan = chanset;chan;chan = chan->next) {
  406. get_user_flagrec(u, &fr, chan->dname);
  407. if (real_chk_op(fr, chan, 0)) {
  408. if (!first) {
  409. dprintf(idx, "%s %s access to %d channel%s:\n", handle ? u->handle : "You", handle ? "has" : "have", total, (total > 1) ? "s" : "");
  410. first = 1;
  411. }
  412. dprintf(idx, format, !conf.bot->hub && me_op(chan) ? '@' : ' ', chan->dname, !shouldjoin(chan) ? "(inactive) " : "",
  413. channel_privchan(chan) ? "(private) " : "", chan->manop ? "(no manop) " : "",
  414. channel_bitch(chan) && !channel_botbitch(chan) ? "(bitch) " : channel_botbitch(chan) ? "(botbitch) " : "",
  415. channel_closed(chan) ? "(closed) " : "", channel_backup(chan) ? "(backup)" : "");
  416. }
  417. }
  418. if (!first)
  419. dprintf(idx, "%s %s not have access to any channels.\n", handle ? u->handle : "You", handle ? "does" : "do");
  420. }
  421. /* Create a string with random letters and digits
  422. */
  423. void make_rand_str(char *s, size_t len, bool special)
  424. {
  425. int r = 0;
  426. size_t j = 0;
  427. for (j = 0; j < len; j++) {
  428. r = randint(special ? 4 : 3);
  429. if (r == 0)
  430. s[j] = '0' + randint(10);
  431. else if (r == 1)
  432. s[j] = 'a' + randint(26);
  433. else if (r == 2)
  434. s[j] = 'A' + randint(26);
  435. else if (r == 3)
  436. s[j] = RANDSPECIAL[randint(RANDSPECIALLEN)];
  437. if (j && strchr(BADREPEATEDRAND, s[j]) && s[j] == s[j - 1]) {
  438. while (s[j] == s[j - 1])
  439. s[j] = 'A' + randint(26);
  440. }
  441. }
  442. if (strchr(BADPASSCHARS, s[0]))
  443. s[0] = 'a' + randint(26);
  444. s[len] = '\0';
  445. }
  446. /* Return an allocated buffer which contains a copy of the string
  447. * 'str', with all 'div' characters escaped by 'mask'. 'mask'
  448. * characters are escaped too.
  449. *
  450. * Remember to free the returned memory block.
  451. */
  452. char *str_escape(const char *str, const char divc, const char mask)
  453. {
  454. const size_t len = strlen(str);
  455. size_t buflen = (2 * len), blen = 0;
  456. char *buf = NULL, *b = NULL;
  457. const char *s = NULL;
  458. b = buf = (char *) my_calloc(1, buflen + 1);
  459. for (s = str; *s; s++) {
  460. /* Resize buffer. */
  461. if ((buflen - blen) <= 3) {
  462. buflen <<= 1; /* * 2 */
  463. buf = (char *) my_realloc(buf, buflen + 1);
  464. if (!buf)
  465. return NULL;
  466. b = buf + blen;
  467. }
  468. if (*s == divc || *s == mask) {
  469. simple_snprintf(b, buflen, "%c%02x", mask, *s);
  470. b += 3;
  471. blen += 3;
  472. } else {
  473. *(b++) = *s;
  474. blen++;
  475. }
  476. }
  477. *b = 0;
  478. return buf;
  479. }
  480. /* Search for a certain character 'div' in the string 'str', while
  481. * ignoring escaped characters prefixed with 'mask'.
  482. *
  483. * The string
  484. *
  485. * "\\3a\\5c i am funny \\3a):further text\\5c):oink"
  486. *
  487. * as str, '\\' as mask and ':' as div would change the str buffer
  488. * to
  489. *
  490. * ":\\ i am funny :)"
  491. *
  492. * and return a pointer to "further text\\5c):oink".
  493. *
  494. * NOTE: If you look carefully, you'll notice that strchr_unescape()
  495. * behaves differently than strchr().
  496. */
  497. char *strchr_unescape(char *str, const char divc, register const char esc_char)
  498. {
  499. char buf[3] = "";
  500. register char *s = NULL, *p = NULL;
  501. for (s = p = str; *s; s++, p++) {
  502. if (*s == esc_char) { /* Found escape character. */
  503. /* Convert code to character. */
  504. buf[0] = s[1], buf[1] = s[2];
  505. *p = (unsigned char) strtol(buf, NULL, 16);
  506. s += 2;
  507. } else if (*s == divc) {
  508. *p = *s = 0;
  509. return (s + 1); /* Found searched for character. */
  510. } else
  511. *p = *s;
  512. }
  513. *p = 0;
  514. return NULL;
  515. }
  516. char s1_16[3] = "",s2_6[3] = "",s2_7[3] = "";
  517. /* As strchr_unescape(), but converts the complete string, without
  518. * searching for a specific delimiter character.
  519. */
  520. void str_unescape(char *str, register const char esc_char)
  521. {
  522. strchr_unescape(str, 0, esc_char);
  523. return;
  524. }
  525. /* Is every character in a string a digit? */
  526. int str_isdigit(const char *str)
  527. {
  528. if (!str || (str && !*str))
  529. return 0;
  530. if (*str == '-' && str[1])
  531. str++;
  532. for(; *str; ++str) {
  533. if (!egg_isdigit(*str))
  534. return 0;
  535. }
  536. return 1;
  537. }
  538. /* Kills the bot. s1 is the reason shown to other bots,
  539. * s2 the reason shown on the partyline. (Sup 25Jul2001)
  540. */
  541. void kill_bot(char *s1, char *s2)
  542. {
  543. if (conf.bot->hub)
  544. write_userfile(-1);
  545. else
  546. server_die();
  547. chatout("*** %s\n", s1);
  548. botnet_send_chat(-1, conf.bot->nick, s1);
  549. botnet_send_bye(s2);
  550. fatal(s2, 0);
  551. }
  552. void
  553. readsocks(const char *fname)
  554. {
  555. /* Don't bother setting this if a hub
  556. ... it is only intended to prevent parting channels (in bot_shouldjoin())
  557. */
  558. if (!conf.bot->hub)
  559. restarting = 1;
  560. char *nick = NULL, *jnick = NULL, *ip4 = NULL, *ip6 = NULL;
  561. time_t old_buildts = 0;
  562. bool cached_005 = 0;
  563. const char salt1[] = SALT1;
  564. EncryptedStream stream(salt1);
  565. stream.loadFile(fname);
  566. bd::String str, type;
  567. while (stream.tell() < stream.length()) {
  568. str = stream.getline().chomp();
  569. type = newsplit(str);
  570. // dprintf(DP_STDOUT, "read line: %s\n", buf.c_str());
  571. if (type == STR("-dcc"))
  572. dprintf(DP_STDOUT, STR("Added dcc: %d\n"), dcc_read(stream));
  573. else if (type == STR("-sock"))
  574. dprintf(DP_STDOUT, STR("Added fd: %d\n"), sock_read(stream));
  575. else if (type == STR("+online_since"))
  576. online_since = strtol(str.c_str(), NULL, 10);
  577. else if (type == STR("+server_floodless"))
  578. floodless = 1;
  579. else if (type == STR("+buildts"))
  580. old_buildts = strtol(str.c_str(), NULL, 10);
  581. else if (type == STR("+botname"))
  582. nick = strdup(str.c_str());
  583. else if (type == STR("+ip4"))
  584. ip4 = strdup(str.c_str());
  585. else if (type == STR("+ip6"))
  586. ip6 = strdup(str.c_str());
  587. else if (type == STR("+serv_cache")) {
  588. if (!cached_005 && str.find(STR("005")))
  589. cached_005 = 1;
  590. dprintf(DP_CACHE, "%s", str.c_str());
  591. }
  592. }
  593. restart_time = now;
  594. if (old_buildts && buildts > old_buildts)
  595. restart_was_update = 1;
  596. tell_dcc(DP_STDOUT);
  597. tell_netdebug(DP_STDOUT);
  598. unlink(fname);
  599. if (servidx >= 0) {
  600. char nserv[50] = "";
  601. if ((ip4 && ip6) && (strcmp(ip4, myipstr(AF_INET)) || strcmp(ip6, myipstr(AF_INET6)))) {
  602. if (tands > 0) { /* We're not linked yet.. but for future */
  603. botnet_send_chat(-1, conf.bot->nick, STR("IP changed."));
  604. botnet_send_bye(STR("IP changed."));
  605. }
  606. fatal("brb", 1);
  607. } else {
  608. simple_snprintf(nserv, sizeof(nserv), "%s:%d", dcc[servidx].host, dcc[servidx].port);
  609. add_server(nserv);
  610. curserv = 0;
  611. keepnick = 0; /* Wait to change nicks until relinking, fixes nick/jupenick switching issues during restart */
  612. rehash_server(dcc[servidx].host, nick);
  613. if (cached_005)
  614. replay_cache(servidx, NULL);
  615. else
  616. dprintf(DP_DUMP, "VERSION\n");
  617. reset_chans = 1;
  618. }
  619. }
  620. if (nick)
  621. free(nick);
  622. if (jnick)
  623. free(jnick);
  624. if (socksfile)
  625. free(socksfile);
  626. if (ip4)
  627. free(ip4);
  628. if (ip6)
  629. free(ip6);
  630. }
  631. /* Update system code
  632. */
  633. void
  634. restart(int idx)
  635. {
  636. const char *reason = updating ? STR("Updating...") : STR("Restarting...");
  637. Tempfile *socks = new Tempfile("socks");
  638. int fd = 0;
  639. sdprintf("%s", reason);
  640. if (tands > 0) {
  641. botnet_send_chat(-1, conf.bot->nick, (char *) reason);
  642. botnet_send_bye(reason);
  643. }
  644. /* kill all connections except STDOUT/server */
  645. for (fd = 0; fd < dcc_total; fd++) {
  646. if (dcc[fd].type && dcc[fd].type != &SERVER_SOCKET && dcc[fd].sock != STDOUT) {
  647. if (dcc[fd].sock >= 0)
  648. killsock(dcc[fd].sock);
  649. lostdcc(fd);
  650. }
  651. }
  652. const char salt1[] = SALT1;
  653. EncryptedStream stream(salt1);
  654. /* write out all leftover dcc[] entries */
  655. for (fd = 0; fd < dcc_total; fd++)
  656. if (dcc[fd].type && dcc[fd].sock != STDOUT)
  657. dcc_write(stream, fd);
  658. /* write out all leftover socklist[] entries */
  659. for (fd = 0; fd < MAXSOCKS; fd++)
  660. if (socklist[fd].sock != STDOUT)
  661. sock_write(stream, fd);
  662. bd::String buf;
  663. if (server_online) {
  664. if (botname[0])
  665. stream << buf.printf(STR("+botname %s\n"), botname);
  666. }
  667. stream << buf.printf(STR("+online_since %li\n"), online_since);
  668. if (floodless)
  669. stream << buf.printf(STR("+server_floodless %d\n"), floodless);
  670. stream << buf.printf(STR("+buildts %li\n"), buildts);
  671. stream << buf.printf(STR("+ip4 %s\n"), myipstr(AF_INET));
  672. stream << buf.printf(STR("+ip6 %s\n"), myipstr(AF_INET6));
  673. replay_cache(-1, &stream);
  674. stream.writeFile(socks->fd);
  675. socks->my_close();
  676. if (conf.bot->hub)
  677. write_userfile(idx);
  678. if (server_online) {
  679. do_chanset(NULL, NULL, STR("+inactive"), DO_LOCAL);
  680. dprintf(DP_DUMP, STR("JOIN 0\n"));
  681. }
  682. fixmod(binname);
  683. /* replace image now */
  684. char *argv[4] = { NULL, NULL, NULL, NULL };
  685. argv[0] = strdup(binname);
  686. if (!backgrd || term_z || sdebug) {
  687. char shit[7] = "";
  688. simple_snprintf(shit, sizeof(shit), STR("-%s%s%s"), !backgrd ? "n" : "", term_z ? "t" : "", sdebug ? "D" : "");
  689. argv[1] = strdup(shit);
  690. argv[2] = strdup(conf.bot->nick);
  691. } else {
  692. argv[1] = strdup(conf.bot->nick);
  693. }
  694. unlink(conf.bot->pid_file);
  695. FILE *fp = NULL;
  696. if (!(fp = fopen(conf.bot->pid_file, "w")))
  697. return;
  698. fprintf(fp, "%d %s\n", getpid(), socks->file);
  699. fclose(fp);
  700. execvp(argv[0], &argv[0]);
  701. /* hopefully this is never reached */
  702. putlog(LOG_MISC, "*", STR("Could not restart: %s"), strerror(errno));
  703. return;
  704. }
  705. #ifdef NO
  706. void
  707. hard_restart(int idx)
  708. {
  709. write_userfile(idx);
  710. if (!conf.bot->hub) {
  711. nuke_server((char *) reason); /* let's drop the server connection ASAP */
  712. cycle_time = 0;
  713. }
  714. fatal(idx <= 0x7FF0 ? reason : NULL, 1);
  715. usleep(2000 * 500);
  716. unlink(conf.bot->pid_file); /* if this fails it is ok, cron will restart the bot, *hopefully* */
  717. simple_exec(binname, conf.bot->nick);
  718. exit(0);
  719. }
  720. #endif
  721. int updatebin(int idx, char *par, int secs)
  722. {
  723. if (!par || !par[0]) {
  724. logidx(idx, "Not enough parameters.");
  725. return 1;
  726. }
  727. size_t path_siz = strlen(binname) + strlen(par) + 2;
  728. char *path = (char *) my_calloc(1, path_siz);
  729. char *newbin = NULL, buf[DIRMAX] = "";
  730. const char* argv[5];
  731. #ifndef CYGWIN_HACKS
  732. int i;
  733. #endif /* !CYGWIN_HACKS */
  734. strlcpy(path, binname, path_siz);
  735. newbin = strrchr(path, '/');
  736. if (!newbin) {
  737. free(path);
  738. logidx(idx, STR("Don't know current binary name"));
  739. return 1;
  740. }
  741. newbin++;
  742. if (strchr(par, '/')) {
  743. *newbin = 0;
  744. logidx(idx, STR("New binary must be in %s and name must be specified without path information"), path);
  745. free(path);
  746. return 1;
  747. }
  748. strcpy(newbin, par);
  749. #ifdef CYGWIN_HACKS
  750. /* tack on the .exe */
  751. if (!strstr(path, ".exe")) {
  752. path = (char *) my_realloc(path, strlen(path) + 4 + 1);
  753. strcat(path, ".exe");
  754. path[strlen(path)] = 0;
  755. }
  756. #endif /* CYGWIN_HACKS */
  757. if (!strcmp(path, binname)) {
  758. free(path);
  759. logidx(idx, STR("Can't update with the current binary"));
  760. return 1;
  761. }
  762. if (!can_stat(path)) {
  763. logidx(idx, STR("%s can't be accessed"), path);
  764. free(path);
  765. return 1;
  766. }
  767. if (fixmod(path)) {
  768. logidx(idx, STR("Can't set mode 0600 on %s"), path);
  769. free(path);
  770. return 1;
  771. }
  772. /* Check if the new binary is compatible */
  773. int initialized = (int)check_bin_initialized(path);
  774. if (!initialized && !check_bin_compat(path)) {
  775. logidx(idx, STR("New binary must be initialized as pack structure has been changed in new version."));
  776. free(path);
  777. return 1;
  778. }
  779. /* make a backup just in case. */
  780. simple_snprintf(buf, sizeof(buf), STR("%s/.bin.old"), conf.datadir);
  781. copyfile(binname, buf);
  782. write_settings(path, -1, 0, initialized); /* re-write the binary with our packdata */
  783. Tempfile *conffile = new Tempfile("conf");
  784. if (writeconf(NULL, conffile->fd, CONF_ENC)) {
  785. putlog(LOG_MISC, "*", STR("Failed to write temporary config file for update."));
  786. delete conffile;
  787. return 1;
  788. }
  789. /* The binary should return '2' when ran with -2, if not it's probably corrupt. */
  790. #ifndef CYGWIN_HACKS
  791. putlog(LOG_DEBUG, "*", STR("Running for update binary test: %s -2"), path);
  792. argv[0] = path;
  793. argv[1] = "-2";
  794. argv[2] = 0;
  795. i = simple_exec(argv);
  796. if (i == -1 || WEXITSTATUS(i) != 2) {
  797. dprintf(idx, STR("Couldn't restart new binary (error %d)\n"), i);
  798. putlog(LOG_MISC, "*", STR("Couldn't restart new binary (error %d)"), i);
  799. delete conffile;
  800. return i;
  801. }
  802. #endif /* !CYGWIN_HACKS */
  803. /* now to send our config to the new binary */
  804. #ifndef CYGWIN_HACKS
  805. putlog(LOG_DEBUG, "*", STR("Running for update conf: %s -4 %s"), path, conffile->file);
  806. argv[0] = path;
  807. argv[1] = "-4";
  808. argv[2] = conffile->file;
  809. argv[3] = 0;
  810. i = simple_exec(argv);
  811. delete conffile;
  812. if (i == -1 || WEXITSTATUS(i) != 6) { /* 6 for successfull config read/write */
  813. dprintf(idx, STR("Couldn't pass config to new binary (error %d)\n"), i);
  814. putlog(LOG_MISC, "*", STR("Couldn't pass config to new binary (error %d)"), i);
  815. return i;
  816. }
  817. #endif /* !CYGWIN_HACKS */
  818. #ifdef CYGWIN_HACKS
  819. {
  820. size_t binsize = conffile->len + 7 + 1;
  821. char *tmpbuf = (char *) my_calloc(1, binsize);
  822. simple_snprintf(tmpbuf, binsize, "%sbin.old.exe", conffile->file);
  823. tmpbuf[binsize - 1] = 0;
  824. movefile(binname, tmpbuf);
  825. free(tmpbuf);
  826. }
  827. #endif /* CYGWIN_HACKS */
  828. if (movefile(path, binname)) {
  829. logidx(idx, STR("Can't rename %s to %s"), path, binname);
  830. free(path);
  831. return 1;
  832. }
  833. if (updating == UPDATE_EXIT) { /* dont restart/kill/spawn bots, just die ! */
  834. printf(STR("* Moved binary to: %s\n"), binname);
  835. fatal(STR("Binary updated."), 0);
  836. }
  837. if (updating == UPDATE_AUTO) {
  838. /* Make all other bots do a soft restart */
  839. conf_checkpids(conf.bots);
  840. conf_killbot(conf.bots, NULL, NULL, SIGHUP);
  841. if (conf.bot->pid)
  842. kill(conf.bot->pid, SIGHUP);
  843. exit(0);
  844. }
  845. if (!conf.bot->hub && secs > 0) {
  846. /* Make all other bots do a soft restart */
  847. conf_checkpids(conf.bots);
  848. conf_killbot(conf.bots, NULL, NULL, SIGHUP);
  849. /* invoked with -u */
  850. if (updating == UPDATE_AUTO) {
  851. if (conf.bot->pid)
  852. kill(conf.bot->pid, SIGHUP);
  853. exit(0);
  854. }
  855. /* this odd statement makes it so specifying 1 sec will restart other bots running
  856. * and then just restart with no delay */
  857. updating = UPDATE_AUTO;
  858. if (secs > 1) {
  859. egg_timeval_t howlong;
  860. howlong.sec = secs;
  861. howlong.usec = 0;
  862. timer_create_complex(&howlong, STR("restarting for update"), (Function) restart, (void *) (long) idx, 0);
  863. } else
  864. restart(idx);
  865. return 0;
  866. } else
  867. restart(idx); /* no timer */
  868. /* this should never be reached */
  869. return 2;
  870. }
  871. int bot_aggressive_to(struct userrec *u)
  872. {
  873. if (conf.bot->localhub) {
  874. for (conf_bot* bot = conf.bots; bot && bot->nick; bot = bot->next) {
  875. if (!bot->hub && !strcmp(u->handle, bot->nick))
  876. return 1;
  877. }
  878. }
  879. char mypval[HANDLEN + 4] = "", botpval[HANDLEN + 4] = "";
  880. link_pref_val(u, botpval);
  881. link_pref_val(conf.bot->u, mypval);
  882. // sdprintf("botpval: %s", botpval);
  883. // sdprintf("mypval: %s", mypval);
  884. if (strcmp(mypval, botpval) < 0)
  885. return 1;
  886. else
  887. return 0;
  888. }
  889. int goodpass(char *pass, int idx, char *nick)
  890. {
  891. if (!pass[0])
  892. return 0;
  893. char tell[201] = "", last = 0;
  894. int nalpha = 0, lcase = 0, ucase = 0, ocase = 0, tc, repeats = 0, score = 0;
  895. size_t length = strlen(pass);
  896. if (strchr(BADPASSCHARS, pass[0])) {
  897. simple_snprintf(tell, sizeof(tell), "Passes may not begin with '-'");
  898. goto fail;
  899. }
  900. for (int i = 0; i < (signed) length; i++) {
  901. if (pass[i] == last)
  902. repeats++;
  903. tc = (int) pass[i];
  904. if (tc < 58 && tc > 47)
  905. ocase++; /* number */
  906. else if (tc < 91 && tc > 64)
  907. ucase++; /* upper case */
  908. else if (tc < 123 && tc > 96)
  909. lcase++; /* lower case */
  910. else
  911. nalpha++; /* non-alphabet/number */
  912. last = pass[i];
  913. }
  914. score += ocase * 3;
  915. score += nalpha * 2;
  916. score += ucase * 2;
  917. score += lcase * 1;
  918. score += length * 1;
  919. score -= repeats * 1;
  920. simple_snprintf(tell, sizeof(tell), "Password NOT set due to being too weak. Try more characters, numbers, capitals");
  921. if (score < 16) {
  922. fail:
  923. if (idx)
  924. dprintf(idx, "%s\n", tell);
  925. else if (nick[0])
  926. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, tell);
  927. return 0;
  928. }
  929. return 1;
  930. }
  931. #define REPLACES 10
  932. char *replace(const char *string, const char *oldie, const char *newbie)
  933. {
  934. if (string == NULL || !string[0])
  935. return (char *) string;
  936. if (oldie == NULL || !oldie[0])
  937. return (char *) string;
  938. char *c = NULL;
  939. if ((c = (char *) strstr(string, oldie)) == NULL)
  940. return (char *) string;
  941. static int n = 0;
  942. static char newstring_buf[REPLACES][1024];
  943. char *newstring = newstring_buf[n++];
  944. memset(newstring, 0, 1024);
  945. if (n == REPLACES)
  946. n = 0;
  947. const size_t new_len = strlen(newbie), old_len = strlen(oldie), end = (strlen(string) - old_len);
  948. size_t str_index = 0, newstr_index = 0, oldie_index = c - string, cpy_len;
  949. while(str_index <= end && c != NULL) {
  950. cpy_len = oldie_index-str_index;
  951. strncpy(newstring + newstr_index, string + str_index, cpy_len);
  952. newstr_index += cpy_len;
  953. str_index += cpy_len;
  954. strcpy(newstring + newstr_index, newbie);
  955. newstr_index += new_len;
  956. str_index += old_len;
  957. if((c = (char *) strstr(string + str_index, oldie)) != NULL)
  958. oldie_index = c - string;
  959. }
  960. strcpy(newstring + newstr_index, string + str_index);
  961. return (newstring);
  962. }
  963. char* replace_vars(char *buf) {
  964. return replace(buf, "$n", botname);
  965. }
  966. void showhelp(int idx, struct flag_record *flags, const char *string)
  967. {
  968. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  969. size_t help_siz = strlen(string) + 1000 + 1;
  970. char *helpstr = (char *) my_calloc(1, help_siz);
  971. char tmp[2] = "", flagstr[10] = "";
  972. bool ok = 1;
  973. while (string && string[0]) {
  974. if (*string == '%') {
  975. if (!strncmp(string + 1, "{+", 2)) {
  976. while (*string && *string != '+') {
  977. string++;
  978. }
  979. flagstr[0] = 0;
  980. while (*string && *string != '}') {
  981. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  982. strlcat(flagstr, tmp, sizeof(flagstr));
  983. string++;
  984. }
  985. string++;
  986. break_down_flags(flagstr, &fr, NULL);
  987. if (flagrec_ok(&fr, flags)) {
  988. ok = 1;
  989. while (*string && *string != '%') {
  990. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  991. strlcat(helpstr, tmp, help_siz);
  992. string++;
  993. }
  994. if (!strncmp(string + 1, "{-", 2)) {
  995. ok = 1;
  996. while (*string && *string != '}') {
  997. string++;
  998. }
  999. string++;
  1000. }
  1001. } else {
  1002. ok = 0;
  1003. }
  1004. } else if (!strncmp(string + 1, "{-", 2)) {
  1005. ok = 1;
  1006. while (*string && *string != '}') {
  1007. string++;
  1008. }
  1009. string++;
  1010. } else if (*string == '{') {
  1011. while (*string && *string != '}') {
  1012. string++;
  1013. }
  1014. } else if (*(string + 1) == 'd') {
  1015. string += 2;
  1016. if (dcc[idx].u.chat->channel >= 0)
  1017. strlcat(helpstr, settings.dcc_prefix, help_siz);
  1018. } else if (*(string + 1) == '%') {
  1019. string += 2;
  1020. strlcat(helpstr, "%", help_siz);
  1021. } else {
  1022. if (ok) {
  1023. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  1024. strlcat(helpstr, tmp, help_siz);
  1025. }
  1026. string++;
  1027. }
  1028. } else {
  1029. if (ok) {
  1030. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  1031. strlcat(helpstr, tmp, help_siz);
  1032. }
  1033. string++;
  1034. }
  1035. }
  1036. helpstr[strlen(helpstr)] = 0;
  1037. if (helpstr[0]) dumplots(idx, "", helpstr);
  1038. free(helpstr);
  1039. }
  1040. /* Arrange the N elements of ARRAY in random order. */
  1041. void shuffleArray(char* array[], size_t n)
  1042. {
  1043. for (size_t i = 0; i < n; i++) {
  1044. const size_t j = randint(n);
  1045. char* temp = array[j];
  1046. array[j] = array[i];
  1047. array[i] = temp;
  1048. }
  1049. }
  1050. void shuffle(char *string, char *delim, size_t str_len)
  1051. {
  1052. char *array[501], *str = NULL, *work = NULL;
  1053. size_t len = 0;
  1054. bzero(&array, sizeof array);
  1055. work = strdup(string);
  1056. str = strtok(work, delim);
  1057. while(str && *str)
  1058. {
  1059. array[len] = str;
  1060. len++;
  1061. str = strtok((char*) NULL, delim);
  1062. }
  1063. shuffleArray(array, len);
  1064. string[0] = 0;
  1065. for (size_t i = 0; i < len; i++) {
  1066. strlcat(string, array[i], str_len);
  1067. if (i != len - 1)
  1068. strlcat(string, delim, str_len);
  1069. }
  1070. free(work);
  1071. string[strlen(string)] = 0;
  1072. }
  1073. /* returns
  1074. 1: use ANSI
  1075. 2: use mIRC
  1076. 0: neither
  1077. */
  1078. int
  1079. coloridx(int idx)
  1080. {
  1081. if (idx == -1) { /* who cares, just show color! */
  1082. return 1; /* ANSI */
  1083. } else if (idx == -2) {
  1084. return 2; /* mIRC */
  1085. /* valid idx and NOT relaying */
  1086. } else if (idx >= 0) {
  1087. if (dcc[idx].irc || dcc[idx].bot) {
  1088. return 0;
  1089. } else if ((dcc[idx].status & STAT_COLOR) && (dcc[idx].type && dcc[idx].type != &DCC_RELAYING)) {
  1090. /* telnet probably wants ANSI, even though it might be a relay from an mIRC client; fuck`em */
  1091. if (dcc[idx].status & STAT_TELNET)
  1092. return 1;
  1093. /* non-telnet is probably a /dcc-chat, most irc clients support mIRC codes... */
  1094. else
  1095. return 2;
  1096. }
  1097. }
  1098. return 0;
  1099. }
  1100. const char *
  1101. color(int idx, int type, int which)
  1102. {
  1103. int ansi = 0;
  1104. /* if user is connected over TELNET or !backgrd, show ANSI
  1105. * if they are relaying, they are most likely on an IRC client and should have mIRC codes
  1106. */
  1107. if ((ansi = coloridx(idx)) == 0)
  1108. return "";
  1109. if (ansi == 2)
  1110. ansi = 0;
  1111. if (type == BOLD_OPEN) {
  1112. return ansi ? "\033[1m" : "\002";
  1113. } else if (type == BOLD_CLOSE) {
  1114. // return ansi ? "\033[22m" : "\002";
  1115. return ansi ? "\033[0m" : "\002";
  1116. } else if (type == UNDERLINE_OPEN) {
  1117. return ansi ? "\033[4m" : "\037";
  1118. } else if (type == UNDERLINE_CLOSE) {
  1119. return ansi ? "\033[24m" : "\037";
  1120. } else if (type == FLASH_OPEN) {
  1121. return ansi ? "\033[5m" : "\002\037";
  1122. } else if (type == FLASH_CLOSE) {
  1123. return ansi ? "\033[0m" : "\037\002";
  1124. } else if (type == COLOR_OPEN) {
  1125. switch (which) {
  1126. case C_BLACK: return ansi ? "\033[30m" : "\00301";
  1127. case C_RED: return ansi ? "\033[31m" : "\00305";
  1128. case C_GREEN: return ansi ? "\033[32m" : "\00303";
  1129. case C_BROWN: return ansi ? "\033[33m" : "\00307";
  1130. case C_BLUE: return ansi ? "\033[34m" : "\00302";
  1131. case C_PURPLE: return ansi ? "\033[35m" : "\00306";
  1132. case C_CYAN: return ansi ? "\033[36m" : "\00310";
  1133. case C_WHITE: return ansi ? "\033[1;37m" : "\00300";
  1134. case C_DARKGREY: return ansi ? "\033[1;30m" : "\00314";
  1135. case C_LIGHTRED: return ansi ? "\033[1;31m" : "\00304";
  1136. case C_LIGHTGREEN: return ansi ? "\033[1;32m" : "\00309";
  1137. case C_LIGHTBLUE: return ansi ? "\033[1;34m" : "\00312";
  1138. case C_LIGHTPURPLE: return ansi ? "\033[1;35m" : "\00313";
  1139. case C_LIGHTCYAN: return ansi ? "\033[1;36m" : "\00311";
  1140. case C_LIGHTGREY: return ansi ? "\033[37m" : "\00315";
  1141. case C_YELLOW: return ansi ? "\033[1;33m" : "\00308";
  1142. default: break;
  1143. }
  1144. } else if (type == COLOR_CLOSE) {
  1145. return ansi ? "\033[0m" : "\00300";
  1146. }
  1147. /* This should never be reached.. */
  1148. return "";
  1149. }
  1150. char *
  1151. strtolower(char *s)
  1152. {
  1153. char *p = s;
  1154. while (*p) {
  1155. *p = tolower(*p);
  1156. p++;
  1157. }
  1158. return s;
  1159. }
  1160. char *
  1161. strtoupper(char *s)
  1162. {
  1163. char *p = s;
  1164. while (*p) {
  1165. *p = toupper(*p);
  1166. p++;
  1167. }
  1168. return s;
  1169. }
  1170. char *step_thru_file(FILE *fd)
  1171. {
  1172. if (fd == NULL) {
  1173. return NULL;
  1174. }
  1175. char tempBuf[1024] = "", *retStr = NULL;
  1176. size_t ret_siz = 0;
  1177. while (!feof(fd)) {
  1178. if (fgets(tempBuf, sizeof(tempBuf), fd) && !feof(fd)) {
  1179. if (retStr == NULL) {
  1180. ret_siz = strlen(tempBuf) + 2;
  1181. retStr = (char *) my_calloc(1, ret_siz);
  1182. strlcpy(retStr, tempBuf, ret_siz);
  1183. } else {
  1184. ret_siz = strlen(retStr) + strlen(tempBuf);
  1185. retStr = (char *) my_realloc(retStr, ret_siz);
  1186. strlcat(retStr, tempBuf, ret_siz);
  1187. }
  1188. if (retStr[strlen(retStr)-1] == '\n') {
  1189. retStr[strlen(retStr)-1] = 0;
  1190. break;
  1191. }
  1192. }
  1193. }
  1194. return retStr;
  1195. }
  1196. char *trim(char *string)
  1197. {
  1198. if (string) {
  1199. char *ibuf = NULL, *obuf = NULL;
  1200. for (ibuf = obuf = string; *ibuf; ) {
  1201. while (*ibuf && (isspace (*ibuf)))
  1202. ibuf++;
  1203. if (*ibuf && (obuf != string))
  1204. *(obuf++) = ' ';
  1205. while (*ibuf && (!isspace (*ibuf)))
  1206. *(obuf++) = *(ibuf++);
  1207. }
  1208. *obuf = '\0';
  1209. }
  1210. return (string);
  1211. }
  1212. int skipline (char *line, int *skip) {
  1213. static int multi = 0;
  1214. if (strstr(line, "*/"))
  1215. multi = 0;
  1216. if ( (!strncmp(line, "#", 1)) || (!strncmp(line, ";", 1)) || (!strncmp(line, "//", 2)) ) {
  1217. (*skip)++;
  1218. } else if ( (strstr(line, "/*")) && (strstr(line, "*/")) ) {
  1219. multi = 0;
  1220. (*skip)++;
  1221. } else if ( (strstr(line, "/*")) ) {
  1222. (*skip)++;
  1223. multi = 1;
  1224. } else if ( (strstr(line, "*/")) ) {
  1225. multi = 0;
  1226. } else {
  1227. if (!multi) (*skip) = 0;
  1228. }
  1229. return (*skip);
  1230. }