misc.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365
  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. /* Convert "abc!user@a.b.host" into "*!user@*.b.host"
  185. * or "abc!user@1.2.3.4" into "*!user@1.2.3.*"
  186. * or "abc!user@0:0:0:0:0:ffff:1.2.3.4" into "*!user@0:0:0:0:0:ffff:1.2.3.*"
  187. * or "abc!user@3ffe:604:2:b02e:6174:7265:6964:6573" into
  188. * "*!user@3ffe:604:2:b02e:6174:7265:6964:*"
  189. */
  190. void maskhost(const char *s, char *nw)
  191. {
  192. register const char *p, *q, *e, *f;
  193. int i;
  194. *nw++ = '*';
  195. *nw++ = '!';
  196. p = (q = strchr(s, '!')) ? q + 1 : s;
  197. /* Strip of any nick, if a username is found, use last 8 chars */
  198. if ((q = strchr(p, '@'))) {
  199. int fl = 0;
  200. if ((q - p) > 9) {
  201. nw[0] = '*';
  202. p = q - 7;
  203. i = 1;
  204. } else
  205. i = 0;
  206. while (*p != '@') {
  207. if (!fl && strchr("~+-^=", *p))
  208. nw[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. ;
  247. f--;
  248. if (*f >= '0' && *f <= '9') { /* Numeric IP address */
  249. while (*f != '.')
  250. f--;
  251. strncpy(nw, q, f - q);
  252. /* No need to nw[f-q] = 0 here, as the strcpy below will
  253. * terminate the string for us.
  254. */
  255. nw += (f - q);
  256. strcpy(nw, ".*");
  257. } else { /* Normal host >= 3 parts */
  258. /* a.b.c -> *.b.c
  259. * a.b.c.d -> *.b.c.d if tld is a country (2 chars)
  260. * OR *.c.d if tld is com/edu/etc (3 chars)
  261. * a.b.c.d.e -> *.c.d.e etc
  262. */
  263. const char *x = strchr(e + 1, '.');
  264. if (!x)
  265. x = p;
  266. else if (strchr(x + 1, '.'))
  267. x = e;
  268. else if (strlen(x) == 3)
  269. x = p;
  270. else
  271. x = e;
  272. simple_sprintf(nw, "*%s", x);
  273. }
  274. }
  275. }
  276. }
  277. /* Convert an interval (in seconds) to one of:
  278. * "19 days ago", "1 day ago", "18:12"
  279. */
  280. void daysago(time_t mynow, time_t then, char *out, size_t outsiz)
  281. {
  282. if (mynow - then > 86400) {
  283. int mydays = (mynow - then) / 86400;
  284. simple_snprintf(out, outsiz, "%d day%s ago", mydays, (mydays == 1) ? "" : "s");
  285. return;
  286. }
  287. strftime(out, 6, "%H:%M", gmtime(&then));
  288. }
  289. /* Convert an interval (in seconds) to one of:
  290. * "in 19 days", "in 1 day", "at 18:12"
  291. */
  292. void days(time_t mynow, time_t then, char *out, size_t outsiz)
  293. {
  294. if (mynow - then > 86400) {
  295. int mydays = (mynow - then) / 86400;
  296. simple_snprintf(out, outsiz, "in %d day%s", mydays, (mydays == 1) ? "" : "s");
  297. return;
  298. }
  299. strftime(out, 9, "at %H:%M", gmtime(&now));
  300. }
  301. /* Convert an interval (in seconds) to one of:
  302. * "for 19 days", "for 1 day", "for 09:10"
  303. */
  304. void daysdur(time_t mynow, time_t then, char *out, size_t outsiz)
  305. {
  306. if (mynow - then > 86400) {
  307. int mydays = (mynow - then) / 86400;
  308. simple_snprintf(out, outsiz, "for %d day%s", mydays, (mydays == 1) ? "" : "s");
  309. return;
  310. }
  311. char s[81] = "";
  312. strlcpy(out, "for ", outsiz);
  313. mynow -= then;
  314. int hrs = (int) (mynow / 3600);
  315. int mins = (int) ((mynow - (hrs * 3600)) / 60);
  316. simple_snprintf(s, sizeof(s), "%02d:%02d", hrs, mins);
  317. strlcat(out, s, outsiz);
  318. }
  319. /* show l33t banner */
  320. static const char *wbanner(void) {
  321. /*
  322. __ __ __
  323. __ _ ______________ |__|/ |_| |__
  324. \ \/ \/ /\_ __ \__ \ | \ _\ | \
  325. \ / | | \// __ \| || | | \ \
  326. \/\_/ |__| (____ /__||__| |___| /
  327. \/ \/
  328. */
  329. return STR(" __ __ __\n__ _ ______________ |__|/ |_| |__\n\\ \\/ \\/ /\\_ __ \\__ \\ | \\ _\\ | \\\n \\ / | | \\// __ \\| || | | \\ \\\n \\/\\_/ |__| (____ /__||__| |___| /\n \\/ \\/\n");
  330. }
  331. void show_banner(int idx)
  332. {
  333. /* we use sock so that colors aren't applied to banner */
  334. if (dcc[idx].status & STAT_BANNER)
  335. dumplots(-dcc[idx].sock, "", wbanner());
  336. dprintf(idx, " \n");
  337. dprintf(-dcc[idx].sock, STR(" -------------------------------------------------------- \n"));
  338. dprintf(-dcc[idx].sock, STR("| - http://wraith.botpack.net/ - |\n"));
  339. dprintf(-dcc[idx].sock, STR("| Get Shell/Irc/Web hosting @ http://www.xzibition.com |\n"));
  340. dprintf(-dcc[idx].sock, STR("| Use coupon code 'wraith' for 30%% off lifetime |\n"));
  341. dprintf(-dcc[idx].sock, STR(" -------------------------------------------------------- \n"));
  342. dprintf(idx, " \n");
  343. }
  344. /* show motd to dcc chatter */
  345. void show_motd(int idx)
  346. {
  347. if (motd[0]) {
  348. char *who = NULL, *buf = NULL, *buf_ptr = NULL, date[50] = "";
  349. time_t when;
  350. buf = buf_ptr = strdup(motd);
  351. who = newsplit(&buf);
  352. when = atoi(newsplit(&buf));
  353. strftime(date, sizeof date, "%c %Z", gmtime(&when));
  354. dprintf(idx, "Motd set by %s%s%s (%s)\n", BOLD(idx), who, BOLD_END(idx), date);
  355. dumplots(idx, "* ", replace(buf, "\\n", "\n"));
  356. dprintf(idx, " \n");
  357. free(buf_ptr);
  358. } else
  359. dprintf(idx, "Motd: none\n");
  360. }
  361. void show_channels(int idx, char *handle)
  362. {
  363. struct chanset_t *chan = NULL;
  364. struct flag_record fr = { FR_CHAN | FR_GLOBAL, 0, 0, 0 };
  365. struct userrec *u = NULL;
  366. int first = 0, total = 0;
  367. size_t l = 0;
  368. char format[120] = "";
  369. if (handle)
  370. u = get_user_by_handle(userlist, handle);
  371. else
  372. u = dcc[idx].user;
  373. for (chan = chanset;chan ;chan = chan->next) {
  374. get_user_flagrec(u, &fr, chan->dname);
  375. if (l < strlen(chan->dname)) {
  376. l = strlen(chan->dname);
  377. }
  378. if (real_chk_op(fr, chan, 0))
  379. total++;
  380. }
  381. simple_snprintf(format, sizeof(format), " %%c%%-%zus %%-s%%-s%%-s%%-s%%-s%%-s\n", (l+2));
  382. for (chan = chanset;chan;chan = chan->next) {
  383. get_user_flagrec(u, &fr, chan->dname);
  384. if (real_chk_op(fr, chan, 0)) {
  385. if (!first) {
  386. dprintf(idx, "%s %s access to %d channel%s:\n", handle ? u->handle : "You", handle ? "has" : "have", total, (total > 1) ? "s" : "");
  387. first = 1;
  388. }
  389. dprintf(idx, format, !conf.bot->hub && me_op(chan) ? '@' : ' ', chan->dname, !shouldjoin(chan) ? "(inactive) " : "",
  390. channel_privchan(chan) ? "(private) " : "", chan->manop ? "(no manop) " : "",
  391. channel_bitch(chan) && !channel_botbitch(chan) ? "(bitch) " : channel_botbitch(chan) ? "(botbitch) " : "",
  392. channel_closed(chan) ? "(closed) " : "", channel_backup(chan) ? "(backup)" : "");
  393. }
  394. }
  395. if (!first)
  396. dprintf(idx, "%s %s not have access to any channels.\n", handle ? u->handle : "You", handle ? "does" : "do");
  397. }
  398. /* Create a string with random letters and digits
  399. */
  400. void make_rand_str(char *s, size_t len, bool special)
  401. {
  402. int r = 0;
  403. size_t j = 0;
  404. for (j = 0; j < len; j++) {
  405. r = randint(special ? 4 : 3);
  406. if (r == 0)
  407. s[j] = '0' + randint(10);
  408. else if (r == 1)
  409. s[j] = 'a' + randint(26);
  410. else if (r == 2)
  411. s[j] = 'A' + randint(26);
  412. else if (r == 3)
  413. s[j] = RANDSPECIAL[randint(RANDSPECIALLEN)];
  414. if (j && strchr(BADREPEATEDRAND, s[j]) && s[j] == s[j - 1]) {
  415. while (s[j] == s[j - 1])
  416. s[j] = 'A' + randint(26);
  417. }
  418. }
  419. if (strchr(BADPASSCHARS, s[0]))
  420. s[0] = 'a' + randint(26);
  421. s[len] = '\0';
  422. }
  423. /* Return an allocated buffer which contains a copy of the string
  424. * 'str', with all 'div' characters escaped by 'mask'. 'mask'
  425. * characters are escaped too.
  426. *
  427. * Remember to free the returned memory block.
  428. */
  429. char *str_escape(const char *str, const char divc, const char mask)
  430. {
  431. const size_t len = strlen(str);
  432. size_t buflen = (2 * len), blen = 0;
  433. char *buf = NULL, *b = NULL;
  434. const char *s = NULL;
  435. b = buf = (char *) my_calloc(1, buflen + 1);
  436. for (s = str; *s; s++) {
  437. /* Resize buffer. */
  438. if ((buflen - blen) <= 3) {
  439. buflen <<= 1; /* * 2 */
  440. buf = (char *) my_realloc(buf, buflen + 1);
  441. if (!buf)
  442. return NULL;
  443. b = buf + blen;
  444. }
  445. if (*s == divc || *s == mask) {
  446. simple_snprintf(b, buflen, "%c%02x", mask, *s);
  447. b += 3;
  448. blen += 3;
  449. } else {
  450. *(b++) = *s;
  451. blen++;
  452. }
  453. }
  454. *b = 0;
  455. return buf;
  456. }
  457. /* Search for a certain character 'div' in the string 'str', while
  458. * ignoring escaped characters prefixed with 'mask'.
  459. *
  460. * The string
  461. *
  462. * "\\3a\\5c i am funny \\3a):further text\\5c):oink"
  463. *
  464. * as str, '\\' as mask and ':' as div would change the str buffer
  465. * to
  466. *
  467. * ":\\ i am funny :)"
  468. *
  469. * and return a pointer to "further text\\5c):oink".
  470. *
  471. * NOTE: If you look carefully, you'll notice that strchr_unescape()
  472. * behaves differently than strchr().
  473. */
  474. char *strchr_unescape(char *str, const char divc, register const char esc_char)
  475. {
  476. char buf[3] = "";
  477. register char *s = NULL, *p = NULL;
  478. for (s = p = str; *s; s++, p++) {
  479. if (*s == esc_char) { /* Found escape character. */
  480. /* Convert code to character. */
  481. buf[0] = s[1], buf[1] = s[2];
  482. *p = (unsigned char) strtol(buf, NULL, 16);
  483. s += 2;
  484. } else if (*s == divc) {
  485. *p = *s = 0;
  486. return (s + 1); /* Found searched for character. */
  487. } else
  488. *p = *s;
  489. }
  490. *p = 0;
  491. return NULL;
  492. }
  493. char s1_16[3] = "",s2_6[3] = "",s2_7[3] = "";
  494. /* As strchr_unescape(), but converts the complete string, without
  495. * searching for a specific delimiter character.
  496. */
  497. void str_unescape(char *str, register const char esc_char)
  498. {
  499. strchr_unescape(str, 0, esc_char);
  500. return;
  501. }
  502. /* Is every character in a string a digit? */
  503. int str_isdigit(const char *str)
  504. {
  505. if (!str || (str && !*str))
  506. return 0;
  507. if (*str == '-' && str[1])
  508. str++;
  509. for(; *str; ++str) {
  510. if (!egg_isdigit(*str))
  511. return 0;
  512. }
  513. return 1;
  514. }
  515. /* Kills the bot. s1 is the reason shown to other bots,
  516. * s2 the reason shown on the partyline. (Sup 25Jul2001)
  517. */
  518. void kill_bot(char *s1, char *s2)
  519. {
  520. if (conf.bot->hub)
  521. write_userfile(-1);
  522. else
  523. server_die();
  524. chatout("*** %s\n", s1);
  525. botnet_send_chat(-1, conf.bot->nick, s1);
  526. botnet_send_bye(s2);
  527. fatal(s2, 0);
  528. }
  529. void
  530. readsocks(const char *fname)
  531. {
  532. /* Don't bother setting this if a hub
  533. ... it is only intended to prevent parting channels (in bot_shouldjoin())
  534. */
  535. if (!conf.bot->hub)
  536. restarting = 1;
  537. char *nick = NULL, *jnick = NULL, *ip4 = NULL, *ip6 = NULL;
  538. time_t old_buildts = 0;
  539. bool cached_005 = 0;
  540. const char salt1[] = SALT1;
  541. EncryptedStream stream(salt1);
  542. stream.loadFile(fname);
  543. bd::String str, type;
  544. while (stream.tell() < stream.length()) {
  545. str = stream.getline().chomp();
  546. type = newsplit(str);
  547. // dprintf(DP_STDOUT, "read line: %s\n", buf.c_str());
  548. if (type == STR("-dcc"))
  549. dprintf(DP_STDOUT, STR("Added dcc: %d\n"), dcc_read(stream));
  550. else if (type == STR("-sock"))
  551. dprintf(DP_STDOUT, STR("Added fd: %d\n"), sock_read(stream));
  552. else if (type == STR("+online_since"))
  553. online_since = strtol(str.c_str(), NULL, 10);
  554. else if (type == STR("+server_floodless"))
  555. floodless = 1;
  556. else if (type == STR("+buildts"))
  557. old_buildts = strtol(str.c_str(), NULL, 10);
  558. else if (type == STR("+botname"))
  559. nick = strdup(str.c_str());
  560. else if (type == STR("+ip4"))
  561. ip4 = strdup(str.c_str());
  562. else if (type == STR("+ip6"))
  563. ip6 = strdup(str.c_str());
  564. else if (type == STR("+serv_cache")) {
  565. if (!cached_005 && str.find(STR("005")))
  566. cached_005 = 1;
  567. dprintf(DP_CACHE, "%s", str.c_str());
  568. }
  569. }
  570. restart_time = now;
  571. if (old_buildts && buildts > old_buildts)
  572. restart_was_update = 1;
  573. tell_dcc(DP_STDOUT);
  574. tell_netdebug(DP_STDOUT);
  575. unlink(fname);
  576. if (servidx >= 0) {
  577. char nserv[50] = "";
  578. if ((ip4 && ip6) && (strcmp(ip4, myipstr(AF_INET)) || strcmp(ip6, myipstr(AF_INET6)))) {
  579. if (tands > 0) { /* We're not linked yet.. but for future */
  580. botnet_send_chat(-1, conf.bot->nick, STR("IP changed."));
  581. botnet_send_bye(STR("IP changed."));
  582. }
  583. fatal("brb", 1);
  584. } else {
  585. simple_snprintf(nserv, sizeof(nserv), "%s:%d", dcc[servidx].host, dcc[servidx].port);
  586. add_server(nserv);
  587. curserv = 0;
  588. keepnick = 0; /* Wait to change nicks until relinking, fixes nick/jupenick switching issues during restart */
  589. rehash_server(dcc[servidx].host, nick);
  590. if (cached_005)
  591. replay_cache(servidx, NULL);
  592. else
  593. dprintf(DP_DUMP, "VERSION\n");
  594. reset_chans = 1;
  595. }
  596. }
  597. if (nick)
  598. free(nick);
  599. if (jnick)
  600. free(jnick);
  601. if (socksfile)
  602. free(socksfile);
  603. if (ip4)
  604. free(ip4);
  605. if (ip6)
  606. free(ip6);
  607. }
  608. /* Update system code
  609. */
  610. void
  611. restart(int idx)
  612. {
  613. const char *reason = updating ? STR("Updating...") : STR("Restarting...");
  614. Tempfile *socks = new Tempfile("socks");
  615. int fd = 0;
  616. sdprintf("%s", reason);
  617. if (tands > 0) {
  618. botnet_send_chat(-1, conf.bot->nick, (char *) reason);
  619. botnet_send_bye(reason);
  620. }
  621. /* kill all connections except STDOUT/server */
  622. for (fd = 0; fd < dcc_total; fd++) {
  623. if (dcc[fd].type && dcc[fd].type != &SERVER_SOCKET && dcc[fd].sock != STDOUT) {
  624. if (dcc[fd].sock >= 0)
  625. killsock(dcc[fd].sock);
  626. lostdcc(fd);
  627. }
  628. }
  629. const char salt1[] = SALT1;
  630. EncryptedStream stream(salt1);
  631. /* write out all leftover dcc[] entries */
  632. for (fd = 0; fd < dcc_total; fd++)
  633. if (dcc[fd].type && dcc[fd].sock != STDOUT)
  634. dcc_write(stream, fd);
  635. /* write out all leftover socklist[] entries */
  636. for (fd = 0; fd < MAXSOCKS; fd++)
  637. if (socklist[fd].sock != STDOUT)
  638. sock_write(stream, fd);
  639. bd::String buf;
  640. if (server_online) {
  641. if (botname[0])
  642. stream << buf.printf(STR("+botname %s\n"), botname);
  643. }
  644. stream << buf.printf(STR("+online_since %li\n"), online_since);
  645. if (floodless)
  646. stream << buf.printf(STR("+server_floodless %d\n"), floodless);
  647. stream << buf.printf(STR("+buildts %li\n"), buildts);
  648. stream << buf.printf(STR("+ip4 %s\n"), myipstr(AF_INET));
  649. stream << buf.printf(STR("+ip6 %s\n"), myipstr(AF_INET6));
  650. replay_cache(-1, &stream);
  651. stream.writeFile(socks->fd);
  652. socks->my_close();
  653. if (conf.bot->hub)
  654. write_userfile(idx);
  655. if (server_online) {
  656. do_chanset(NULL, NULL, STR("+inactive"), DO_LOCAL);
  657. dprintf(DP_DUMP, STR("JOIN 0\n"));
  658. }
  659. fixmod(binname);
  660. /* replace image now */
  661. char *argv[4] = { NULL, NULL, NULL, NULL };
  662. argv[0] = strdup(binname);
  663. if (!backgrd || term_z || sdebug) {
  664. char shit[7] = "";
  665. simple_snprintf(shit, sizeof(shit), STR("-%s%s%s"), !backgrd ? "n" : "", term_z ? "t" : "", sdebug ? "D" : "");
  666. argv[1] = strdup(shit);
  667. argv[2] = strdup(conf.bot->nick);
  668. } else {
  669. argv[1] = strdup(conf.bot->nick);
  670. }
  671. unlink(conf.bot->pid_file);
  672. FILE *fp = NULL;
  673. if (!(fp = fopen(conf.bot->pid_file, "w")))
  674. return;
  675. fprintf(fp, "%d %s\n", getpid(), socks->file);
  676. fclose(fp);
  677. execvp(argv[0], &argv[0]);
  678. /* hopefully this is never reached */
  679. putlog(LOG_MISC, "*", STR("Could not restart: %s"), strerror(errno));
  680. return;
  681. }
  682. #ifdef NO
  683. void
  684. hard_restart(int idx)
  685. {
  686. write_userfile(idx);
  687. if (!conf.bot->hub) {
  688. nuke_server((char *) reason); /* let's drop the server connection ASAP */
  689. cycle_time = 0;
  690. }
  691. fatal(idx <= 0x7FF0 ? reason : NULL, 1);
  692. usleep(2000 * 500);
  693. unlink(conf.bot->pid_file); /* if this fails it is ok, cron will restart the bot, *hopefully* */
  694. simple_exec(binname, conf.bot->nick);
  695. exit(0);
  696. }
  697. #endif
  698. int updatebin(int idx, char *par, int secs)
  699. {
  700. if (!par || !par[0]) {
  701. logidx(idx, "Not enough parameters.");
  702. return 1;
  703. }
  704. size_t path_siz = strlen(binname) + strlen(par) + 2;
  705. char *path = (char *) my_calloc(1, path_siz);
  706. char *newbin = NULL, buf[DIRMAX] = "";
  707. const char* argv[5];
  708. #ifndef CYGWIN_HACKS
  709. int i;
  710. #endif /* !CYGWIN_HACKS */
  711. strlcpy(path, binname, path_siz);
  712. newbin = strrchr(path, '/');
  713. if (!newbin) {
  714. free(path);
  715. logidx(idx, STR("Don't know current binary name"));
  716. return 1;
  717. }
  718. newbin++;
  719. if (strchr(par, '/')) {
  720. *newbin = 0;
  721. logidx(idx, STR("New binary must be in %s and name must be specified without path information"), path);
  722. free(path);
  723. return 1;
  724. }
  725. strcpy(newbin, par);
  726. #ifdef CYGWIN_HACKS
  727. /* tack on the .exe */
  728. if (!strstr(path, ".exe")) {
  729. path = (char *) my_realloc(path, strlen(path) + 4 + 1);
  730. strcat(path, ".exe");
  731. path[strlen(path)] = 0;
  732. }
  733. #endif /* CYGWIN_HACKS */
  734. if (!strcmp(path, binname)) {
  735. free(path);
  736. logidx(idx, STR("Can't update with the current binary"));
  737. return 1;
  738. }
  739. if (!can_stat(path)) {
  740. logidx(idx, STR("%s can't be accessed"), path);
  741. free(path);
  742. return 1;
  743. }
  744. if (fixmod(path)) {
  745. logidx(idx, STR("Can't set mode 0600 on %s"), path);
  746. free(path);
  747. return 1;
  748. }
  749. /* Check if the new binary is compatible */
  750. int initialized = (int)check_bin_initialized(path);
  751. if (!initialized && !check_bin_compat(path)) {
  752. logidx(idx, STR("New binary must be initialized as pack structure has been changed in new version."));
  753. free(path);
  754. return 1;
  755. }
  756. /* make a backup just in case. */
  757. simple_snprintf(buf, sizeof(buf), STR("%s/.bin.old"), conf.datadir);
  758. copyfile(binname, buf);
  759. write_settings(path, -1, 0, initialized); /* re-write the binary with our packdata */
  760. Tempfile *conffile = new Tempfile("conf");
  761. if (writeconf(NULL, conffile->fd, CONF_ENC)) {
  762. putlog(LOG_MISC, "*", STR("Failed to write temporary config file for update."));
  763. delete conffile;
  764. return 1;
  765. }
  766. /* The binary should return '2' when ran with -2, if not it's probably corrupt. */
  767. #ifndef CYGWIN_HACKS
  768. putlog(LOG_DEBUG, "*", STR("Running for update binary test: %s -2"), path);
  769. argv[0] = path;
  770. argv[1] = "-2";
  771. argv[2] = 0;
  772. i = simple_exec(argv);
  773. if (i == -1 || WEXITSTATUS(i) != 2) {
  774. dprintf(idx, STR("Couldn't restart new binary (error %d)\n"), i);
  775. putlog(LOG_MISC, "*", STR("Couldn't restart new binary (error %d)"), i);
  776. delete conffile;
  777. return i;
  778. }
  779. #endif /* !CYGWIN_HACKS */
  780. /* now to send our config to the new binary */
  781. #ifndef CYGWIN_HACKS
  782. putlog(LOG_DEBUG, "*", STR("Running for update conf: %s -4 %s"), path, conffile->file);
  783. argv[0] = path;
  784. argv[1] = "-4";
  785. argv[2] = conffile->file;
  786. argv[3] = 0;
  787. i = simple_exec(argv);
  788. delete conffile;
  789. if (i == -1 || WEXITSTATUS(i) != 6) { /* 6 for successfull config read/write */
  790. dprintf(idx, STR("Couldn't pass config to new binary (error %d)\n"), i);
  791. putlog(LOG_MISC, "*", STR("Couldn't pass config to new binary (error %d)"), i);
  792. return i;
  793. }
  794. #endif /* !CYGWIN_HACKS */
  795. #ifdef CYGWIN_HACKS
  796. {
  797. size_t binsize = conffile->len + 7 + 1;
  798. char *tmpbuf = (char *) my_calloc(1, binsize);
  799. simple_snprintf(tmpbuf, binsize, "%sbin.old.exe", conffile->file);
  800. tmpbuf[binsize - 1] = 0;
  801. movefile(binname, tmpbuf);
  802. free(tmpbuf);
  803. }
  804. #endif /* CYGWIN_HACKS */
  805. if (movefile(path, binname)) {
  806. logidx(idx, STR("Can't rename %s to %s"), path, binname);
  807. free(path);
  808. return 1;
  809. }
  810. if (updating == UPDATE_EXIT) { /* dont restart/kill/spawn bots, just die ! */
  811. printf(STR("* Moved binary to: %s\n"), binname);
  812. fatal(STR("Binary updated."), 0);
  813. }
  814. if (updating == UPDATE_AUTO) {
  815. /* Make all other bots do a soft restart */
  816. conf_checkpids(conf.bots);
  817. conf_killbot(conf.bots, NULL, NULL, SIGHUP);
  818. if (conf.bot->pid)
  819. kill(conf.bot->pid, SIGHUP);
  820. exit(0);
  821. }
  822. if (!conf.bot->hub && secs > 0) {
  823. /* Make all other bots do a soft restart */
  824. conf_checkpids(conf.bots);
  825. conf_killbot(conf.bots, NULL, NULL, SIGHUP);
  826. /* invoked with -u */
  827. if (updating == UPDATE_AUTO) {
  828. if (conf.bot->pid)
  829. kill(conf.bot->pid, SIGHUP);
  830. exit(0);
  831. }
  832. /* this odd statement makes it so specifying 1 sec will restart other bots running
  833. * and then just restart with no delay */
  834. updating = UPDATE_AUTO;
  835. if (secs > 1) {
  836. egg_timeval_t howlong;
  837. howlong.sec = secs;
  838. howlong.usec = 0;
  839. timer_create_complex(&howlong, STR("restarting for update"), (Function) restart, (void *) (long) idx, 0);
  840. } else
  841. restart(idx);
  842. return 0;
  843. } else
  844. restart(idx); /* no timer */
  845. /* this should never be reached */
  846. return 2;
  847. }
  848. int bot_aggressive_to(struct userrec *u)
  849. {
  850. char mypval[HANDLEN + 4] = "", botpval[HANDLEN + 4] = "";
  851. link_pref_val(u, botpval);
  852. link_pref_val(conf.bot->u, mypval);
  853. // sdprintf("botpval: %s", botpval);
  854. // sdprintf("mypval: %s", mypval);
  855. if (strcmp(mypval, botpval) < 0)
  856. return 1;
  857. else
  858. return 0;
  859. }
  860. int goodpass(char *pass, int idx, char *nick)
  861. {
  862. if (!pass[0])
  863. return 0;
  864. char tell[201] = "", last = 0;
  865. int nalpha = 0, lcase = 0, ucase = 0, ocase = 0, tc, repeats = 0, score = 0;
  866. size_t length = strlen(pass);
  867. if (strchr(BADPASSCHARS, pass[0])) {
  868. simple_snprintf(tell, sizeof(tell), "Passes may not begin with '-'");
  869. goto fail;
  870. }
  871. for (int i = 0; i < (signed) length; i++) {
  872. if (pass[i] == last)
  873. repeats++;
  874. tc = (int) pass[i];
  875. if (tc < 58 && tc > 47)
  876. ocase++; /* number */
  877. else if (tc < 91 && tc > 64)
  878. ucase++; /* upper case */
  879. else if (tc < 123 && tc > 96)
  880. lcase++; /* lower case */
  881. else
  882. nalpha++; /* non-alphabet/number */
  883. last = pass[i];
  884. }
  885. score += ocase * 3;
  886. score += nalpha * 2;
  887. score += ucase * 2;
  888. score += lcase * 1;
  889. score += length * 1;
  890. score -= repeats * 1;
  891. simple_snprintf(tell, sizeof(tell), "Password NOT set due to being too weak. Try more characters, numbers, capitals");
  892. if (score < 16) {
  893. fail:
  894. if (idx)
  895. dprintf(idx, "%s\n", tell);
  896. else if (nick[0])
  897. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, tell);
  898. return 0;
  899. }
  900. return 1;
  901. }
  902. #define REPLACES 10
  903. char *replace(const char *string, const char *oldie, const char *newbie)
  904. {
  905. if (string == NULL || !string[0])
  906. return (char *) string;
  907. if (oldie == NULL || !oldie[0])
  908. return (char *) string;
  909. char *c = NULL;
  910. if ((c = (char *) strstr(string, oldie)) == NULL)
  911. return (char *) string;
  912. static int n = 0;
  913. static char newstring_buf[REPLACES][1024];
  914. char *newstring = newstring_buf[n++];
  915. memset(newstring, 0, 1024);
  916. if (n == REPLACES)
  917. n = 0;
  918. const size_t new_len = strlen(newbie), old_len = strlen(oldie), end = (strlen(string) - old_len);
  919. size_t str_index = 0, newstr_index = 0, oldie_index = c - string, cpy_len;
  920. while(str_index <= end && c != NULL) {
  921. cpy_len = oldie_index-str_index;
  922. strncpy(newstring + newstr_index, string + str_index, cpy_len);
  923. newstr_index += cpy_len;
  924. str_index += cpy_len;
  925. strcpy(newstring + newstr_index, newbie);
  926. newstr_index += new_len;
  927. str_index += old_len;
  928. if((c = (char *) strstr(string + str_index, oldie)) != NULL)
  929. oldie_index = c - string;
  930. }
  931. strcpy(newstring + newstr_index, string + str_index);
  932. return (newstring);
  933. }
  934. char* replace_vars(char *buf) {
  935. return replace(buf, "$n", botname);
  936. }
  937. void showhelp(int idx, struct flag_record *flags, const char *string)
  938. {
  939. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  940. size_t help_siz = strlen(string) + 1000 + 1;
  941. char *helpstr = (char *) my_calloc(1, help_siz);
  942. char tmp[2] = "", flagstr[10] = "";
  943. bool ok = 1;
  944. while (string && string[0]) {
  945. if (*string == '%') {
  946. if (!strncmp(string + 1, "{+", 2)) {
  947. while (*string && *string != '+') {
  948. string++;
  949. }
  950. flagstr[0] = 0;
  951. while (*string && *string != '}') {
  952. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  953. strlcat(flagstr, tmp, sizeof(flagstr));
  954. string++;
  955. }
  956. string++;
  957. break_down_flags(flagstr, &fr, NULL);
  958. if (flagrec_ok(&fr, flags)) {
  959. ok = 1;
  960. while (*string && *string != '%') {
  961. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  962. strlcat(helpstr, tmp, help_siz);
  963. string++;
  964. }
  965. if (!strncmp(string + 1, "{-", 2)) {
  966. ok = 1;
  967. while (*string && *string != '}') {
  968. string++;
  969. }
  970. string++;
  971. }
  972. } else {
  973. ok = 0;
  974. }
  975. } else if (!strncmp(string + 1, "{-", 2)) {
  976. ok = 1;
  977. while (*string && *string != '}') {
  978. string++;
  979. }
  980. string++;
  981. } else if (*string == '{') {
  982. while (*string && *string != '}') {
  983. string++;
  984. }
  985. } else if (*(string + 1) == 'd') {
  986. string += 2;
  987. if (dcc[idx].u.chat->channel >= 0)
  988. strlcat(helpstr, settings.dcc_prefix, help_siz);
  989. } else if (*(string + 1) == '%') {
  990. string += 2;
  991. strlcat(helpstr, "%", help_siz);
  992. } else {
  993. if (ok) {
  994. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  995. strlcat(helpstr, tmp, help_siz);
  996. }
  997. string++;
  998. }
  999. } else {
  1000. if (ok) {
  1001. simple_snprintf(tmp, sizeof(tmp), "%c", *string);
  1002. strlcat(helpstr, tmp, help_siz);
  1003. }
  1004. string++;
  1005. }
  1006. }
  1007. helpstr[strlen(helpstr)] = 0;
  1008. if (helpstr[0]) dumplots(idx, "", helpstr);
  1009. free(helpstr);
  1010. }
  1011. /* Arrange the N elements of ARRAY in random order. */
  1012. void shuffleArray(char* array[], size_t n)
  1013. {
  1014. for (size_t i = 0; i < n; i++) {
  1015. const size_t j = randint(n);
  1016. char* temp = array[j];
  1017. array[j] = array[i];
  1018. array[i] = temp;
  1019. }
  1020. }
  1021. void shuffle(char *string, char *delim, size_t str_len)
  1022. {
  1023. char *array[501], *str = NULL, *work = NULL;
  1024. size_t len = 0;
  1025. bzero(&array, sizeof array);
  1026. work = strdup(string);
  1027. str = strtok(work, delim);
  1028. while(str && *str)
  1029. {
  1030. array[len] = str;
  1031. len++;
  1032. str = strtok((char*) NULL, delim);
  1033. }
  1034. shuffleArray(array, len);
  1035. string[0] = 0;
  1036. for (size_t i = 0; i < len; i++) {
  1037. strlcat(string, array[i], str_len);
  1038. if (i != len - 1)
  1039. strlcat(string, delim, str_len);
  1040. }
  1041. free(work);
  1042. string[strlen(string)] = 0;
  1043. }
  1044. /* returns
  1045. 1: use ANSI
  1046. 2: use mIRC
  1047. 0: neither
  1048. */
  1049. int
  1050. coloridx(int idx)
  1051. {
  1052. if (idx == -1) { /* who cares, just show color! */
  1053. return 1; /* ANSI */
  1054. } else if (idx == -2) {
  1055. return 2; /* mIRC */
  1056. /* valid idx and NOT relaying */
  1057. } else if (idx >= 0) {
  1058. if (dcc[idx].irc || dcc[idx].bot) {
  1059. return 0;
  1060. } else if ((dcc[idx].status & STAT_COLOR) && (dcc[idx].type && dcc[idx].type != &DCC_RELAYING)) {
  1061. /* telnet probably wants ANSI, even though it might be a relay from an mIRC client; fuck`em */
  1062. if (dcc[idx].status & STAT_TELNET)
  1063. return 1;
  1064. /* non-telnet is probably a /dcc-chat, most irc clients support mIRC codes... */
  1065. else
  1066. return 2;
  1067. }
  1068. }
  1069. return 0;
  1070. }
  1071. const char *
  1072. color(int idx, int type, int which)
  1073. {
  1074. int ansi = 0;
  1075. /* if user is connected over TELNET or !backgrd, show ANSI
  1076. * if they are relaying, they are most likely on an IRC client and should have mIRC codes
  1077. */
  1078. if ((ansi = coloridx(idx)) == 0)
  1079. return "";
  1080. if (ansi == 2)
  1081. ansi = 0;
  1082. if (type == BOLD_OPEN) {
  1083. return ansi ? "\033[1m" : "\002";
  1084. } else if (type == BOLD_CLOSE) {
  1085. // return ansi ? "\033[22m" : "\002";
  1086. return ansi ? "\033[0m" : "\002";
  1087. } else if (type == UNDERLINE_OPEN) {
  1088. return ansi ? "\033[4m" : "\037";
  1089. } else if (type == UNDERLINE_CLOSE) {
  1090. return ansi ? "\033[24m" : "\037";
  1091. } else if (type == FLASH_OPEN) {
  1092. return ansi ? "\033[5m" : "\002\037";
  1093. } else if (type == FLASH_CLOSE) {
  1094. return ansi ? "\033[0m" : "\037\002";
  1095. } else if (type == COLOR_OPEN) {
  1096. switch (which) {
  1097. case C_BLACK: return ansi ? "\033[30m" : "\00301";
  1098. case C_RED: return ansi ? "\033[31m" : "\00305";
  1099. case C_GREEN: return ansi ? "\033[32m" : "\00303";
  1100. case C_BROWN: return ansi ? "\033[33m" : "\00307";
  1101. case C_BLUE: return ansi ? "\033[34m" : "\00302";
  1102. case C_PURPLE: return ansi ? "\033[35m" : "\00306";
  1103. case C_CYAN: return ansi ? "\033[36m" : "\00310";
  1104. case C_WHITE: return ansi ? "\033[1;37m" : "\00300";
  1105. case C_DARKGREY: return ansi ? "\033[1;30m" : "\00314";
  1106. case C_LIGHTRED: return ansi ? "\033[1;31m" : "\00304";
  1107. case C_LIGHTGREEN: return ansi ? "\033[1;32m" : "\00309";
  1108. case C_LIGHTBLUE: return ansi ? "\033[1;34m" : "\00312";
  1109. case C_LIGHTPURPLE: return ansi ? "\033[1;35m" : "\00313";
  1110. case C_LIGHTCYAN: return ansi ? "\033[1;36m" : "\00311";
  1111. case C_LIGHTGREY: return ansi ? "\033[37m" : "\00315";
  1112. case C_YELLOW: return ansi ? "\033[1;33m" : "\00308";
  1113. default: break;
  1114. }
  1115. } else if (type == COLOR_CLOSE) {
  1116. return ansi ? "\033[0m" : "\00300";
  1117. }
  1118. /* This should never be reached.. */
  1119. return "";
  1120. }
  1121. char *
  1122. strtolower(char *s)
  1123. {
  1124. char *p = s;
  1125. while (*p) {
  1126. *p = tolower(*p);
  1127. p++;
  1128. }
  1129. return s;
  1130. }
  1131. char *
  1132. strtoupper(char *s)
  1133. {
  1134. char *p = s;
  1135. while (*p) {
  1136. *p = toupper(*p);
  1137. p++;
  1138. }
  1139. return s;
  1140. }
  1141. char *step_thru_file(FILE *fd)
  1142. {
  1143. if (fd == NULL) {
  1144. return NULL;
  1145. }
  1146. char tempBuf[1024] = "", *retStr = NULL;
  1147. size_t ret_siz = 0;
  1148. while (!feof(fd)) {
  1149. if (fgets(tempBuf, sizeof(tempBuf), fd) && !feof(fd)) {
  1150. if (retStr == NULL) {
  1151. ret_siz = strlen(tempBuf) + 2;
  1152. retStr = (char *) my_calloc(1, ret_siz);
  1153. strlcpy(retStr, tempBuf, ret_siz);
  1154. } else {
  1155. ret_siz = strlen(retStr) + strlen(tempBuf);
  1156. retStr = (char *) my_realloc(retStr, ret_siz);
  1157. strlcat(retStr, tempBuf, ret_siz);
  1158. }
  1159. if (retStr[strlen(retStr)-1] == '\n') {
  1160. retStr[strlen(retStr)-1] = 0;
  1161. break;
  1162. }
  1163. }
  1164. }
  1165. return retStr;
  1166. }
  1167. char *trim(char *string)
  1168. {
  1169. if (string) {
  1170. char *ibuf = NULL, *obuf = NULL;
  1171. for (ibuf = obuf = string; *ibuf; ) {
  1172. while (*ibuf && (isspace (*ibuf)))
  1173. ibuf++;
  1174. if (*ibuf && (obuf != string))
  1175. *(obuf++) = ' ';
  1176. while (*ibuf && (!isspace (*ibuf)))
  1177. *(obuf++) = *(ibuf++);
  1178. }
  1179. *obuf = '\0';
  1180. }
  1181. return (string);
  1182. }
  1183. int skipline (char *line, int *skip) {
  1184. static int multi = 0;
  1185. if (strstr(line, "*/"))
  1186. multi = 0;
  1187. if ( (!strncmp(line, "#", 1)) || (!strncmp(line, ";", 1)) || (!strncmp(line, "//", 2)) ) {
  1188. (*skip)++;
  1189. } else if ( (strstr(line, "/*")) && (strstr(line, "*/")) ) {
  1190. multi = 0;
  1191. (*skip)++;
  1192. } else if ( (strstr(line, "/*")) ) {
  1193. (*skip)++;
  1194. multi = 1;
  1195. } else if ( (strstr(line, "*/")) ) {
  1196. multi = 0;
  1197. } else {
  1198. if (!multi) (*skip) = 0;
  1199. }
  1200. return (*skip);
  1201. }