PageRenderTime 70ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/src/common/outbound.c

https://github.com/tuquito/xchat
C | 4403 lines | 3707 code | 532 blank | 164 comment | 767 complexity | 6d7ca8990a04d46f3a2d711c8fec74d9 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /* X-Chat
  2. * Copyright (C) 1998 Peter Zelezny.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  17. */
  18. #define _GNU_SOURCE /* for memrchr */
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <limits.h>
  24. #include <errno.h>
  25. #define WANTSOCKET
  26. #define WANTARPA
  27. #include "inet.h"
  28. #ifndef WIN32
  29. #include <sys/wait.h>
  30. #endif
  31. #include <unistd.h>
  32. #include <time.h>
  33. #include <signal.h>
  34. #include <sys/stat.h>
  35. #include <fcntl.h>
  36. #include "xchat.h"
  37. #include "plugin.h"
  38. #include "ignore.h"
  39. #include "util.h"
  40. #include "fe.h"
  41. #include "cfgfiles.h" /* xchat_fopen_file() */
  42. #include "network.h" /* net_ip() */
  43. #include "modes.h"
  44. #include "notify.h"
  45. #include "inbound.h"
  46. #include "text.h"
  47. #include "xchatc.h"
  48. #include "servlist.h"
  49. #include "server.h"
  50. #include "tree.h"
  51. #include "outbound.h"
  52. #ifdef USE_DEBUG
  53. extern int current_mem_usage;
  54. #endif
  55. #define TBUFSIZE 4096
  56. static void help (session *sess, char *tbuf, char *helpcmd, int quiet);
  57. static int cmd_server (session *sess, char *tbuf, char *word[], char *word_eol[]);
  58. static void handle_say (session *sess, char *text, int check_spch);
  59. static void
  60. notj_msg (struct session *sess)
  61. {
  62. PrintText (sess, _("No channel joined. Try /join #<channel>\n"));
  63. }
  64. void
  65. notc_msg (struct session *sess)
  66. {
  67. PrintText (sess, _("Not connected. Try /server <host> [<port>]\n"));
  68. }
  69. static char *
  70. random_line (char *file_name)
  71. {
  72. FILE *fh;
  73. char buf[512];
  74. int lines, ran;
  75. if (!file_name[0])
  76. goto nofile;
  77. fh = xchat_fopen_file (file_name, "r", 0);
  78. if (!fh)
  79. {
  80. nofile:
  81. /* reason is not a file, an actual reason! */
  82. return strdup (file_name);
  83. }
  84. /* count number of lines in file */
  85. lines = 0;
  86. while (fgets (buf, sizeof (buf), fh))
  87. lines++;
  88. if (lines < 1)
  89. goto nofile;
  90. /* go down a random number */
  91. rewind (fh);
  92. ran = RAND_INT (lines);
  93. do
  94. {
  95. fgets (buf, sizeof (buf), fh);
  96. lines--;
  97. }
  98. while (lines > ran);
  99. fclose (fh);
  100. buf[strlen (buf) - 1] = 0; /* remove the trailing '\n' */
  101. return strdup (buf);
  102. }
  103. void
  104. server_sendpart (server * serv, char *channel, char *reason)
  105. {
  106. if (!reason)
  107. {
  108. reason = random_line (prefs.partreason);
  109. serv->p_part (serv, channel, reason);
  110. free (reason);
  111. } else
  112. {
  113. /* reason set by /quit, /close argument */
  114. serv->p_part (serv, channel, reason);
  115. }
  116. }
  117. void
  118. server_sendquit (session * sess)
  119. {
  120. char *rea, *colrea;
  121. if (!sess->quitreason)
  122. {
  123. colrea = strdup (prefs.quitreason);
  124. check_special_chars (colrea, FALSE);
  125. rea = random_line (colrea);
  126. free (colrea);
  127. sess->server->p_quit (sess->server, rea);
  128. free (rea);
  129. } else
  130. {
  131. /* reason set by /quit, /close argument */
  132. sess->server->p_quit (sess->server, sess->quitreason);
  133. }
  134. }
  135. void
  136. process_data_init (char *buf, char *cmd, char *word[],
  137. char *word_eol[], gboolean handle_quotes,
  138. gboolean allow_escape_quotes)
  139. {
  140. int wordcount = 2;
  141. int space = FALSE;
  142. int quote = FALSE;
  143. int j = 0;
  144. int len;
  145. word[0] = "\000\000";
  146. word_eol[0] = "\000\000";
  147. word[1] = (char *)buf;
  148. word_eol[1] = (char *)cmd;
  149. while (1)
  150. {
  151. switch (*cmd)
  152. {
  153. case 0:
  154. buf[j] = 0;
  155. for (j = wordcount; j < PDIWORDS; j++)
  156. {
  157. word[j] = "\000\000";
  158. word_eol[j] = "\000\000";
  159. }
  160. return;
  161. case '\042':
  162. if (!handle_quotes)
  163. goto def;
  164. /* two quotes turn into 1 */
  165. if (allow_escape_quotes && cmd[1] == '\042')
  166. {
  167. cmd++;
  168. goto def;
  169. }
  170. if (quote)
  171. {
  172. quote = FALSE;
  173. space = FALSE;
  174. } else
  175. quote = TRUE;
  176. cmd++;
  177. break;
  178. case ' ':
  179. if (!quote)
  180. {
  181. if (!space)
  182. {
  183. buf[j] = 0;
  184. j++;
  185. if (wordcount < PDIWORDS)
  186. {
  187. word[wordcount] = &buf[j];
  188. word_eol[wordcount] = cmd + 1;
  189. wordcount++;
  190. }
  191. space = TRUE;
  192. }
  193. cmd++;
  194. break;
  195. }
  196. default:
  197. def:
  198. space = FALSE;
  199. len = g_utf8_skip[((unsigned char *)cmd)[0]];
  200. if (len == 1)
  201. {
  202. buf[j] = *cmd;
  203. j++;
  204. cmd++;
  205. } else
  206. {
  207. /* skip past a multi-byte utf8 char */
  208. memcpy (buf + j, cmd, len);
  209. j += len;
  210. cmd += len;
  211. }
  212. }
  213. }
  214. }
  215. static int
  216. cmd_addbutton (struct session *sess, char *tbuf, char *word[],
  217. char *word_eol[])
  218. {
  219. if (*word[2] && *word_eol[3])
  220. {
  221. if (sess->type == SESS_DIALOG)
  222. {
  223. list_addentry (&dlgbutton_list, word_eol[3], word[2]);
  224. fe_dlgbuttons_update (sess);
  225. } else
  226. {
  227. list_addentry (&button_list, word_eol[3], word[2]);
  228. fe_buttons_update (sess);
  229. }
  230. return TRUE;
  231. }
  232. return FALSE;
  233. }
  234. static int
  235. cmd_allchannels (session *sess, char *tbuf, char *word[], char *word_eol[])
  236. {
  237. GSList *list = sess_list;
  238. if (!*word_eol[2])
  239. return FALSE;
  240. while (list)
  241. {
  242. sess = list->data;
  243. if (sess->type == SESS_CHANNEL && sess->channel[0] && sess->server->connected)
  244. {
  245. handle_command (sess, word_eol[2], FALSE);
  246. }
  247. list = list->next;
  248. }
  249. return TRUE;
  250. }
  251. static int
  252. cmd_allchannelslocal (session *sess, char *tbuf, char *word[], char *word_eol[])
  253. {
  254. GSList *list = sess_list;
  255. server *serv = sess->server;
  256. if (!*word_eol[2])
  257. return FALSE;
  258. while (list)
  259. {
  260. sess = list->data;
  261. if (sess->type == SESS_CHANNEL && sess->channel[0] &&
  262. sess->server->connected && sess->server == serv)
  263. {
  264. handle_command (sess, word_eol[2], FALSE);
  265. }
  266. list = list->next;
  267. }
  268. return TRUE;
  269. }
  270. static int
  271. cmd_allservers (struct session *sess, char *tbuf, char *word[],
  272. char *word_eol[])
  273. {
  274. GSList *list;
  275. server *serv;
  276. if (!*word_eol[2])
  277. return FALSE;
  278. list = serv_list;
  279. while (list)
  280. {
  281. serv = list->data;
  282. if (serv->connected)
  283. handle_command (serv->front_session, word_eol[2], FALSE);
  284. list = list->next;
  285. }
  286. return TRUE;
  287. }
  288. static int
  289. cmd_away (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  290. {
  291. GSList *list;
  292. char *reason = word_eol[2];
  293. if (!(*reason))
  294. {
  295. if (sess->server->is_away)
  296. {
  297. if (sess->server->last_away_reason)
  298. PrintTextf (sess, _("Already marked away: %s\n"), sess->server->last_away_reason);
  299. return FALSE;
  300. }
  301. if (sess->server->reconnect_away)
  302. reason = sess->server->last_away_reason;
  303. else
  304. /* must manage memory pointed to by random_line() */
  305. reason = random_line (prefs.awayreason);
  306. }
  307. sess->server->p_set_away (sess->server, reason);
  308. if (prefs.show_away_message)
  309. {
  310. snprintf (tbuf, TBUFSIZE, "me is away: %s", reason);
  311. for (list = sess_list; list; list = list->next)
  312. {
  313. /* am I the right server and not a dialog box */
  314. if (((struct session *) list->data)->server == sess->server
  315. && ((struct session *) list->data)->type == SESS_CHANNEL
  316. && ((struct session *) list->data)->channel[0])
  317. {
  318. handle_command ((session *) list->data, tbuf, TRUE);
  319. }
  320. }
  321. }
  322. if (sess->server->last_away_reason != reason)
  323. {
  324. if (sess->server->last_away_reason)
  325. free (sess->server->last_away_reason);
  326. if (reason == word_eol[2])
  327. sess->server->last_away_reason = strdup (reason);
  328. else
  329. sess->server->last_away_reason = reason;
  330. }
  331. if (!sess->server->connected)
  332. sess->server->reconnect_away = 1;
  333. return TRUE;
  334. }
  335. static int
  336. cmd_back (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  337. {
  338. GSList *list;
  339. unsigned int gone;
  340. if (sess->server->is_away)
  341. {
  342. sess->server->p_set_back (sess->server);
  343. if (prefs.show_away_message)
  344. {
  345. gone = time (NULL) - sess->server->away_time;
  346. sprintf (tbuf, "me is back (gone %.2d:%.2d:%.2d)", gone / 3600,
  347. (gone / 60) % 60, gone % 60);
  348. for (list = sess_list; list; list = list->next)
  349. {
  350. /* am I the right server and not a dialog box */
  351. if (((struct session *) list->data)->server == sess->server
  352. && ((struct session *) list->data)->type == SESS_CHANNEL
  353. && ((struct session *) list->data)->channel[0])
  354. {
  355. handle_command ((session *) list->data, tbuf, TRUE);
  356. }
  357. }
  358. }
  359. }
  360. else
  361. {
  362. PrintText (sess, _("Already marked back.\n"));
  363. }
  364. if (sess->server->last_away_reason)
  365. free (sess->server->last_away_reason);
  366. sess->server->last_away_reason = NULL;
  367. return TRUE;
  368. }
  369. static void
  370. ban (session * sess, char *tbuf, char *mask, char *bantypestr, int deop)
  371. {
  372. int bantype;
  373. struct User *user;
  374. char *at, *dot, *lastdot;
  375. char username[64], fullhost[128], domain[128], *mode, *p2;
  376. server *serv = sess->server;
  377. user = userlist_find (sess, mask);
  378. if (user && user->hostname) /* it's a nickname, let's find a proper ban mask */
  379. {
  380. if (deop)
  381. {
  382. mode = "-o+b ";
  383. p2 = user->nick;
  384. } else
  385. {
  386. mode = "+b";
  387. p2 = "";
  388. }
  389. mask = user->hostname;
  390. at = strchr (mask, '@'); /* FIXME: utf8 */
  391. if (!at)
  392. return; /* can't happen? */
  393. *at = 0;
  394. if (mask[0] == '~' || mask[0] == '+' ||
  395. mask[0] == '=' || mask[0] == '^' || mask[0] == '-')
  396. {
  397. /* the ident is prefixed with something, we replace that sign with an * */
  398. safe_strcpy (username+1, mask+1, sizeof (username)-1);
  399. username[0] = '*';
  400. } else if (at - mask < USERNAMELEN)
  401. {
  402. /* we just add an * in the begining of the ident */
  403. safe_strcpy (username+1, mask, sizeof (username)-1);
  404. username[0] = '*';
  405. } else
  406. {
  407. /* ident might be too long, we just ban what it gives and add an * in the end */
  408. safe_strcpy (username, mask, sizeof (username));
  409. }
  410. *at = '@';
  411. safe_strcpy (fullhost, at + 1, sizeof (fullhost));
  412. dot = strchr (fullhost, '.');
  413. if (dot)
  414. {
  415. safe_strcpy (domain, dot, sizeof (domain));
  416. } else
  417. {
  418. safe_strcpy (domain, fullhost, sizeof (domain));
  419. }
  420. if (*bantypestr)
  421. bantype = atoi (bantypestr);
  422. else
  423. bantype = prefs.bantype;
  424. tbuf[0] = 0;
  425. if (inet_addr (fullhost) != -1) /* "fullhost" is really a IP number */
  426. {
  427. lastdot = strrchr (fullhost, '.');
  428. if (!lastdot)
  429. return; /* can't happen? */
  430. *lastdot = 0;
  431. strcpy (domain, fullhost);
  432. *lastdot = '.';
  433. switch (bantype)
  434. {
  435. case 0:
  436. snprintf (tbuf, TBUFSIZE, "%s%s *!*@%s.*", mode, p2, domain);
  437. break;
  438. case 1:
  439. snprintf (tbuf, TBUFSIZE, "%s%s *!*@%s", mode, p2, fullhost);
  440. break;
  441. case 2:
  442. snprintf (tbuf, TBUFSIZE, "%s%s *!%s@%s.*", mode, p2, username, domain);
  443. break;
  444. case 3:
  445. snprintf (tbuf, TBUFSIZE, "%s%s *!%s@%s", mode, p2, username, fullhost);
  446. break;
  447. }
  448. } else
  449. {
  450. switch (bantype)
  451. {
  452. case 0:
  453. snprintf (tbuf, TBUFSIZE, "%s%s *!*@*%s", mode, p2, domain);
  454. break;
  455. case 1:
  456. snprintf (tbuf, TBUFSIZE, "%s%s *!*@%s", mode, p2, fullhost);
  457. break;
  458. case 2:
  459. snprintf (tbuf, TBUFSIZE, "%s%s *!%s@*%s", mode, p2, username, domain);
  460. break;
  461. case 3:
  462. snprintf (tbuf, TBUFSIZE, "%s%s *!%s@%s", mode, p2, username, fullhost);
  463. break;
  464. }
  465. }
  466. } else
  467. {
  468. snprintf (tbuf, TBUFSIZE, "+b %s", mask);
  469. }
  470. serv->p_mode (serv, sess->channel, tbuf);
  471. }
  472. static int
  473. cmd_ban (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  474. {
  475. char *mask = word[2];
  476. if (*mask)
  477. {
  478. ban (sess, tbuf, mask, word[3], 0);
  479. } else
  480. {
  481. sess->server->p_mode (sess->server, sess->channel, "+b"); /* banlist */
  482. }
  483. return TRUE;
  484. }
  485. static int
  486. cmd_unban (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  487. {
  488. /* Allow more than one mask in /unban -- tvk */
  489. int i = 2;
  490. while (1)
  491. {
  492. if (!*word[i])
  493. {
  494. if (i == 2)
  495. return FALSE;
  496. send_channel_modes (sess, tbuf, word, 2, i, '-', 'b', 0);
  497. return TRUE;
  498. }
  499. i++;
  500. }
  501. }
  502. static int
  503. cmd_chanopt (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  504. {
  505. /* chanopt.c */
  506. return chanopt_command (sess, tbuf, word, word_eol);
  507. }
  508. static int
  509. cmd_charset (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  510. {
  511. server *serv = sess->server;
  512. const char *locale = NULL;
  513. int offset = 0;
  514. if (strcmp (word[2], "-quiet") == 0)
  515. offset++;
  516. if (!word[2 + offset][0])
  517. {
  518. g_get_charset (&locale);
  519. PrintTextf (sess, "Current charset: %s\n",
  520. serv->encoding ? serv->encoding : locale);
  521. return TRUE;
  522. }
  523. if (servlist_check_encoding (word[2 + offset]))
  524. {
  525. server_set_encoding (serv, word[2 + offset]);
  526. if (offset < 1)
  527. PrintTextf (sess, "Charset changed to: %s\n", word[2 + offset]);
  528. } else
  529. {
  530. PrintTextf (sess, "\0034Unknown charset:\017 %s\n", word[2 + offset]);
  531. }
  532. return TRUE;
  533. }
  534. static int
  535. cmd_clear (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  536. {
  537. GSList *list = sess_list;
  538. char *reason = word_eol[2];
  539. if (strcasecmp (reason, "HISTORY") == 0)
  540. {
  541. history_free (&sess->history);
  542. return TRUE;
  543. }
  544. if (strncasecmp (reason, "all", 3) == 0)
  545. {
  546. while (list)
  547. {
  548. sess = list->data;
  549. if (!sess->nick_said)
  550. fe_text_clear (list->data, 0);
  551. list = list->next;
  552. }
  553. return TRUE;
  554. }
  555. if (reason[0] != '-' && !isdigit (reason[0]) && reason[0] != 0)
  556. return FALSE;
  557. fe_text_clear (sess, atoi (reason));
  558. return TRUE;
  559. }
  560. static int
  561. cmd_close (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  562. {
  563. GSList *list;
  564. if (strcmp (word[2], "-m") == 0)
  565. {
  566. list = sess_list;
  567. while (list)
  568. {
  569. sess = list->data;
  570. list = list->next;
  571. if (sess->type == SESS_DIALOG)
  572. fe_close_window (sess);
  573. }
  574. } else
  575. {
  576. if (*word_eol[2])
  577. sess->quitreason = word_eol[2];
  578. fe_close_window (sess);
  579. }
  580. return TRUE;
  581. }
  582. static int
  583. cmd_ctcp (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  584. {
  585. int mbl;
  586. char *to = word[2];
  587. if (*to)
  588. {
  589. char *msg = word_eol[3];
  590. if (*msg)
  591. {
  592. unsigned char *cmd = (unsigned char *)msg;
  593. /* make the first word upper case (as per RFC) */
  594. while (1)
  595. {
  596. if (*cmd == ' ' || *cmd == 0)
  597. break;
  598. mbl = g_utf8_skip[*cmd];
  599. if (mbl == 1)
  600. *cmd = toupper (*cmd);
  601. cmd += mbl;
  602. }
  603. sess->server->p_ctcp (sess->server, to, msg);
  604. EMIT_SIGNAL (XP_TE_CTCPSEND, sess, to, msg, NULL, NULL, 0);
  605. return TRUE;
  606. }
  607. }
  608. return FALSE;
  609. }
  610. static int
  611. cmd_country (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  612. {
  613. char *code = word[2];
  614. if (*code)
  615. {
  616. /* search? */
  617. if (strcmp (code, "-s") == 0)
  618. {
  619. country_search (word[3], sess, (void *)PrintTextf);
  620. return TRUE;
  621. }
  622. /* search, but forgot the -s */
  623. if (strchr (code, '*'))
  624. {
  625. country_search (code, sess, (void *)PrintTextf);
  626. return TRUE;
  627. }
  628. sprintf (tbuf, "%s = %s\n", code, country (code));
  629. PrintText (sess, tbuf);
  630. return TRUE;
  631. }
  632. return FALSE;
  633. }
  634. static int
  635. cmd_cycle (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  636. {
  637. char *key = sess->channelkey;
  638. char *chan = word[2];
  639. if (!*chan)
  640. chan = sess->channel;
  641. if (*chan && sess->type == SESS_CHANNEL)
  642. {
  643. sess->server->p_cycle (sess->server, chan, key);
  644. return TRUE;
  645. }
  646. return FALSE;
  647. }
  648. static int
  649. cmd_dcc (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  650. {
  651. int goodtype;
  652. struct DCC *dcc = 0;
  653. char *type = word[2];
  654. if (*type)
  655. {
  656. if (!strcasecmp (type, "HELP"))
  657. return FALSE;
  658. if (!strcasecmp (type, "CLOSE"))
  659. {
  660. if (*word[3] && *word[4])
  661. {
  662. goodtype = 0;
  663. if (!strcasecmp (word[3], "SEND"))
  664. {
  665. dcc = find_dcc (word[4], word[5], TYPE_SEND);
  666. dcc_abort (sess, dcc);
  667. goodtype = TRUE;
  668. }
  669. if (!strcasecmp (word[3], "GET"))
  670. {
  671. dcc = find_dcc (word[4], word[5], TYPE_RECV);
  672. dcc_abort (sess, dcc);
  673. goodtype = TRUE;
  674. }
  675. if (!strcasecmp (word[3], "CHAT"))
  676. {
  677. dcc = find_dcc (word[4], "", TYPE_CHATRECV);
  678. if (!dcc)
  679. dcc = find_dcc (word[4], "", TYPE_CHATSEND);
  680. dcc_abort (sess, dcc);
  681. goodtype = TRUE;
  682. }
  683. if (!goodtype)
  684. return FALSE;
  685. if (!dcc)
  686. EMIT_SIGNAL (XP_TE_NODCC, sess, NULL, NULL, NULL, NULL, 0);
  687. return TRUE;
  688. }
  689. return FALSE;
  690. }
  691. if ((!strcasecmp (type, "CHAT")) || (!strcasecmp (type, "PCHAT")))
  692. {
  693. char *nick = word[3];
  694. int passive = (!strcasecmp(type, "PCHAT")) ? 1 : 0;
  695. if (*nick)
  696. dcc_chat (sess, nick, passive);
  697. return TRUE;
  698. }
  699. if (!strcasecmp (type, "LIST"))
  700. {
  701. dcc_show_list (sess);
  702. return TRUE;
  703. }
  704. if (!strcasecmp (type, "GET"))
  705. {
  706. char *nick = word[3];
  707. char *file = word[4];
  708. if (!*file)
  709. {
  710. if (*nick)
  711. dcc_get_nick (sess, nick);
  712. } else
  713. {
  714. dcc = find_dcc (nick, file, TYPE_RECV);
  715. if (dcc)
  716. dcc_get (dcc);
  717. else
  718. EMIT_SIGNAL (XP_TE_NODCC, sess, NULL, NULL, NULL, NULL, 0);
  719. }
  720. return TRUE;
  721. }
  722. if ((!strcasecmp (type, "SEND")) || (!strcasecmp (type, "PSEND")))
  723. {
  724. int i = 3, maxcps;
  725. char *nick, *file;
  726. int passive = (!strcasecmp(type, "PSEND")) ? 1 : 0;
  727. nick = word[i];
  728. if (!*nick)
  729. return FALSE;
  730. maxcps = prefs.dcc_max_send_cps;
  731. if (!strncasecmp(nick, "-maxcps=", 8))
  732. {
  733. maxcps = atoi(nick + 8);
  734. i++;
  735. nick = word[i];
  736. if (!*nick)
  737. return FALSE;
  738. }
  739. i++;
  740. file = word[i];
  741. if (!*file)
  742. {
  743. fe_dcc_send_filereq (sess, nick, maxcps, passive);
  744. return TRUE;
  745. }
  746. do
  747. {
  748. dcc_send (sess, nick, file, maxcps, passive);
  749. i++;
  750. file = word[i];
  751. }
  752. while (*file);
  753. return TRUE;
  754. }
  755. return FALSE;
  756. }
  757. dcc_show_list (sess);
  758. return TRUE;
  759. }
  760. static int
  761. cmd_debug (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  762. {
  763. struct session *s;
  764. struct server *v;
  765. GSList *list = sess_list;
  766. PrintText (sess, "Session T Channel WaitChan WillChan Server\n");
  767. while (list)
  768. {
  769. s = (struct session *) list->data;
  770. sprintf (tbuf, "%p %1x %-10.10s %-10.10s %-10.10s %p\n",
  771. s, s->type, s->channel, s->waitchannel,
  772. s->willjoinchannel, s->server);
  773. PrintText (sess, tbuf);
  774. list = list->next;
  775. }
  776. list = serv_list;
  777. PrintText (sess, "Server Sock Name\n");
  778. while (list)
  779. {
  780. v = (struct server *) list->data;
  781. sprintf (tbuf, "%p %-5d %s\n",
  782. v, v->sok, v->servername);
  783. PrintText (sess, tbuf);
  784. list = list->next;
  785. }
  786. sprintf (tbuf,
  787. "\nfront_session: %p\n"
  788. "current_tab: %p\n\n",
  789. sess->server->front_session, current_tab);
  790. PrintText (sess, tbuf);
  791. #ifdef USE_DEBUG
  792. sprintf (tbuf, "current mem: %d\n\n", current_mem_usage);
  793. PrintText (sess, tbuf);
  794. #endif /* !MEMORY_DEBUG */
  795. return TRUE;
  796. }
  797. static int
  798. cmd_delbutton (struct session *sess, char *tbuf, char *word[],
  799. char *word_eol[])
  800. {
  801. if (*word[2])
  802. {
  803. if (sess->type == SESS_DIALOG)
  804. {
  805. if (list_delentry (&dlgbutton_list, word[2]))
  806. fe_dlgbuttons_update (sess);
  807. } else
  808. {
  809. if (list_delentry (&button_list, word[2]))
  810. fe_buttons_update (sess);
  811. }
  812. return TRUE;
  813. }
  814. return FALSE;
  815. }
  816. static int
  817. cmd_dehop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  818. {
  819. int i = 2;
  820. while (1)
  821. {
  822. if (!*word[i])
  823. {
  824. if (i == 2)
  825. return FALSE;
  826. send_channel_modes (sess, tbuf, word, 2, i, '-', 'h', 0);
  827. return TRUE;
  828. }
  829. i++;
  830. }
  831. }
  832. static int
  833. cmd_deop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  834. {
  835. int i = 2;
  836. while (1)
  837. {
  838. if (!*word[i])
  839. {
  840. if (i == 2)
  841. return FALSE;
  842. send_channel_modes (sess, tbuf, word, 2, i, '-', 'o', 0);
  843. return TRUE;
  844. }
  845. i++;
  846. }
  847. }
  848. typedef struct
  849. {
  850. char **nicks;
  851. int i;
  852. session *sess;
  853. char *reason;
  854. char *tbuf;
  855. } multidata;
  856. static int
  857. mdehop_cb (struct User *user, multidata *data)
  858. {
  859. if (user->hop && !user->me)
  860. {
  861. data->nicks[data->i] = user->nick;
  862. data->i++;
  863. }
  864. return TRUE;
  865. }
  866. static int
  867. cmd_mdehop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  868. {
  869. char **nicks = malloc (sizeof (char *) * sess->hops);
  870. multidata data;
  871. data.nicks = nicks;
  872. data.i = 0;
  873. tree_foreach (sess->usertree, (tree_traverse_func *)mdehop_cb, &data);
  874. send_channel_modes (sess, tbuf, nicks, 0, data.i, '-', 'h', 0);
  875. free (nicks);
  876. return TRUE;
  877. }
  878. static int
  879. mdeop_cb (struct User *user, multidata *data)
  880. {
  881. if (user->op && !user->me)
  882. {
  883. data->nicks[data->i] = user->nick;
  884. data->i++;
  885. }
  886. return TRUE;
  887. }
  888. static int
  889. cmd_mdeop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  890. {
  891. char **nicks = malloc (sizeof (char *) * sess->ops);
  892. multidata data;
  893. data.nicks = nicks;
  894. data.i = 0;
  895. tree_foreach (sess->usertree, (tree_traverse_func *)mdeop_cb, &data);
  896. send_channel_modes (sess, tbuf, nicks, 0, data.i, '-', 'o', 0);
  897. free (nicks);
  898. return TRUE;
  899. }
  900. GSList *menu_list = NULL;
  901. static void
  902. menu_free (menu_entry *me)
  903. {
  904. free (me->path);
  905. if (me->label)
  906. free (me->label);
  907. if (me->cmd)
  908. free (me->cmd);
  909. if (me->ucmd)
  910. free (me->ucmd);
  911. if (me->group)
  912. free (me->group);
  913. if (me->icon)
  914. free (me->icon);
  915. free (me);
  916. }
  917. /* strings equal? but ignore underscores */
  918. int
  919. menu_streq (const char *s1, const char *s2, int def)
  920. {
  921. /* for separators */
  922. if (s1 == NULL && s2 == NULL)
  923. return 0;
  924. if (s1 == NULL || s2 == NULL)
  925. return 1;
  926. while (*s1)
  927. {
  928. if (*s1 == '_')
  929. s1++;
  930. if (*s2 == '_')
  931. s2++;
  932. if (*s1 != *s2)
  933. return 1;
  934. s1++;
  935. s2++;
  936. }
  937. if (!*s2)
  938. return 0;
  939. return def;
  940. }
  941. static menu_entry *
  942. menu_entry_find (char *path, char *label)
  943. {
  944. GSList *list;
  945. menu_entry *me;
  946. list = menu_list;
  947. while (list)
  948. {
  949. me = list->data;
  950. if (!strcmp (path, me->path))
  951. {
  952. if (me->label && label && !strcmp (label, me->label))
  953. return me;
  954. }
  955. list = list->next;
  956. }
  957. return NULL;
  958. }
  959. static void
  960. menu_del_children (char *path, char *label)
  961. {
  962. GSList *list, *next;
  963. menu_entry *me;
  964. char buf[512];
  965. if (!label)
  966. label = "";
  967. if (path[0])
  968. snprintf (buf, sizeof (buf), "%s/%s", path, label);
  969. else
  970. snprintf (buf, sizeof (buf), "%s", label);
  971. list = menu_list;
  972. while (list)
  973. {
  974. me = list->data;
  975. next = list->next;
  976. if (!menu_streq (buf, me->path, 0))
  977. {
  978. menu_list = g_slist_remove (menu_list, me);
  979. menu_free (me);
  980. }
  981. list = next;
  982. }
  983. }
  984. static int
  985. menu_del (char *path, char *label)
  986. {
  987. GSList *list;
  988. menu_entry *me;
  989. list = menu_list;
  990. while (list)
  991. {
  992. me = list->data;
  993. if (!menu_streq (me->label, label, 1) && !menu_streq (me->path, path, 1))
  994. {
  995. menu_list = g_slist_remove (menu_list, me);
  996. fe_menu_del (me);
  997. menu_free (me);
  998. /* delete this item's children, if any */
  999. menu_del_children (path, label);
  1000. return 1;
  1001. }
  1002. list = list->next;
  1003. }
  1004. return 0;
  1005. }
  1006. static char
  1007. menu_is_mainmenu_root (char *path, gint16 *offset)
  1008. {
  1009. static const char *menus[] = {"\x4$TAB","\x5$TRAY","\x4$URL","\x5$NICK","\x5$CHAN"};
  1010. int i;
  1011. for (i = 0; i < 5; i++)
  1012. {
  1013. if (!strncmp (path, menus[i] + 1, menus[i][0]))
  1014. {
  1015. *offset = menus[i][0] + 1; /* number of bytes to offset the root */
  1016. return 0; /* is not main menu */
  1017. }
  1018. }
  1019. *offset = 0;
  1020. return 1; /* is main menu */
  1021. }
  1022. static void
  1023. menu_add (char *path, char *label, char *cmd, char *ucmd, int pos, int state, int markup, int enable, int mod, int key, char *group, char *icon)
  1024. {
  1025. menu_entry *me;
  1026. /* already exists? */
  1027. me = menu_entry_find (path, label);
  1028. if (me)
  1029. {
  1030. /* update only */
  1031. me->state = state;
  1032. me->enable = enable;
  1033. fe_menu_update (me);
  1034. return;
  1035. }
  1036. me = malloc (sizeof (menu_entry));
  1037. me->pos = pos;
  1038. me->modifier = mod;
  1039. me->is_main = menu_is_mainmenu_root (path, &me->root_offset);
  1040. me->state = state;
  1041. me->markup = markup;
  1042. me->enable = enable;
  1043. me->key = key;
  1044. me->path = strdup (path);
  1045. me->label = NULL;
  1046. me->cmd = NULL;
  1047. me->ucmd = NULL;
  1048. me->group = NULL;
  1049. me->icon = NULL;
  1050. if (label)
  1051. me->label = strdup (label);
  1052. if (cmd)
  1053. me->cmd = strdup (cmd);
  1054. if (ucmd)
  1055. me->ucmd = strdup (ucmd);
  1056. if (group)
  1057. me->group = strdup (group);
  1058. if (icon)
  1059. me->icon = strdup (icon);
  1060. menu_list = g_slist_append (menu_list, me);
  1061. label = fe_menu_add (me);
  1062. if (label)
  1063. {
  1064. /* FE has given us a stripped label */
  1065. free (me->label);
  1066. me->label = strdup (label);
  1067. g_free (label); /* this is from pango */
  1068. }
  1069. }
  1070. static int
  1071. cmd_menu (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1072. {
  1073. int idx = 2;
  1074. int len;
  1075. int pos = 0xffff;
  1076. int state;
  1077. int toggle = FALSE;
  1078. int enable = TRUE;
  1079. int markup = FALSE;
  1080. int key = 0;
  1081. int mod = 0;
  1082. char *label;
  1083. char *group = NULL;
  1084. char *icon = NULL;
  1085. if (!word[2][0] || !word[3][0])
  1086. return FALSE;
  1087. /* -eX enabled or not? */
  1088. if (word[idx][0] == '-' && word[idx][1] == 'e')
  1089. {
  1090. enable = atoi (word[idx] + 2);
  1091. idx++;
  1092. }
  1093. /* -i<ICONFILE> */
  1094. if (word[idx][0] == '-' && word[idx][1] == 'i')
  1095. {
  1096. icon = word[idx] + 2;
  1097. idx++;
  1098. }
  1099. /* -k<mod>,<key> key binding */
  1100. if (word[idx][0] == '-' && word[idx][1] == 'k')
  1101. {
  1102. char *comma = strchr (word[idx], ',');
  1103. if (!comma)
  1104. return FALSE;
  1105. mod = atoi (word[idx] + 2);
  1106. key = atoi (comma + 1);
  1107. idx++;
  1108. }
  1109. /* -m to specify PangoMarkup language */
  1110. if (word[idx][0] == '-' && word[idx][1] == 'm')
  1111. {
  1112. markup = TRUE;
  1113. idx++;
  1114. }
  1115. /* -pX to specify menu position */
  1116. if (word[idx][0] == '-' && word[idx][1] == 'p')
  1117. {
  1118. pos = atoi (word[idx] + 2);
  1119. idx++;
  1120. }
  1121. /* -rSTATE,GROUP to specify a radio item */
  1122. if (word[idx][0] == '-' && word[idx][1] == 'r')
  1123. {
  1124. state = atoi (word[idx] + 2);
  1125. group = word[idx] + 4;
  1126. idx++;
  1127. }
  1128. /* -tX to specify toggle item with default state */
  1129. if (word[idx][0] == '-' && word[idx][1] == 't')
  1130. {
  1131. state = atoi (word[idx] + 2);
  1132. idx++;
  1133. toggle = TRUE;
  1134. }
  1135. if (word[idx+1][0] == 0)
  1136. return FALSE;
  1137. /* the path */
  1138. path_part (word[idx+1], tbuf, 512);
  1139. len = strlen (tbuf);
  1140. if (len)
  1141. tbuf[len - 1] = 0;
  1142. /* the name of the item */
  1143. label = file_part (word[idx + 1]);
  1144. if (label[0] == '-' && label[1] == 0)
  1145. label = NULL; /* separator */
  1146. if (markup)
  1147. {
  1148. char *p; /* to force pango closing tags through */
  1149. for (p = label; *p; p++)
  1150. if (*p == 3)
  1151. *p = '/';
  1152. }
  1153. if (!strcasecmp (word[idx], "ADD"))
  1154. {
  1155. if (toggle)
  1156. {
  1157. menu_add (tbuf, label, word[idx + 2], word[idx + 3], pos, state, markup, enable, mod, key, NULL, NULL);
  1158. } else
  1159. {
  1160. if (word[idx + 2][0])
  1161. menu_add (tbuf, label, word[idx + 2], NULL, pos, state, markup, enable, mod, key, group, icon);
  1162. else
  1163. menu_add (tbuf, label, NULL, NULL, pos, state, markup, enable, mod, key, group, icon);
  1164. }
  1165. return TRUE;
  1166. }
  1167. if (!strcasecmp (word[idx], "DEL"))
  1168. {
  1169. menu_del (tbuf, label);
  1170. return TRUE;
  1171. }
  1172. return FALSE;
  1173. }
  1174. static int
  1175. mkick_cb (struct User *user, multidata *data)
  1176. {
  1177. if (!user->op && !user->me)
  1178. data->sess->server->p_kick (data->sess->server, data->sess->channel, user->nick, data->reason);
  1179. return TRUE;
  1180. }
  1181. static int
  1182. mkickops_cb (struct User *user, multidata *data)
  1183. {
  1184. if (user->op && !user->me)
  1185. data->sess->server->p_kick (data->sess->server, data->sess->channel, user->nick, data->reason);
  1186. return TRUE;
  1187. }
  1188. static int
  1189. cmd_mkick (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1190. {
  1191. multidata data;
  1192. data.sess = sess;
  1193. data.reason = word_eol[2];
  1194. tree_foreach (sess->usertree, (tree_traverse_func *)mkickops_cb, &data);
  1195. tree_foreach (sess->usertree, (tree_traverse_func *)mkick_cb, &data);
  1196. return TRUE;
  1197. }
  1198. static int
  1199. cmd_devoice (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1200. {
  1201. int i = 2;
  1202. while (1)
  1203. {
  1204. if (!*word[i])
  1205. {
  1206. if (i == 2)
  1207. return FALSE;
  1208. send_channel_modes (sess, tbuf, word, 2, i, '-', 'v', 0);
  1209. return TRUE;
  1210. }
  1211. i++;
  1212. }
  1213. }
  1214. static int
  1215. cmd_discon (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1216. {
  1217. sess->server->disconnect (sess, TRUE, -1);
  1218. return TRUE;
  1219. }
  1220. static int
  1221. cmd_dns (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1222. {
  1223. #ifdef WIN32
  1224. PrintText (sess, "DNS is not implemented in Windows.\n");
  1225. return TRUE;
  1226. #else
  1227. char *nick = word[2];
  1228. struct User *user;
  1229. if (*nick)
  1230. {
  1231. if (strchr (nick, '.') == NULL)
  1232. {
  1233. user = userlist_find (sess, nick);
  1234. if (user && user->hostname)
  1235. {
  1236. do_dns (sess, user->nick, user->hostname);
  1237. } else
  1238. {
  1239. sess->server->p_get_ip (sess->server, nick);
  1240. sess->server->doing_dns = TRUE;
  1241. }
  1242. } else
  1243. {
  1244. snprintf (tbuf, TBUFSIZE, "exec -d %s %s", prefs.dnsprogram, nick);
  1245. handle_command (sess, tbuf, FALSE);
  1246. }
  1247. return TRUE;
  1248. }
  1249. return FALSE;
  1250. #endif
  1251. }
  1252. static int
  1253. cmd_echo (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1254. {
  1255. PrintText (sess, word_eol[2]);
  1256. return TRUE;
  1257. }
  1258. #ifndef WIN32
  1259. static void
  1260. exec_check_process (struct session *sess)
  1261. {
  1262. int val;
  1263. if (sess->running_exec == NULL)
  1264. return;
  1265. val = waitpid (sess->running_exec->childpid, NULL, WNOHANG);
  1266. if (val == -1 || val > 0)
  1267. {
  1268. close (sess->running_exec->myfd);
  1269. fe_input_remove (sess->running_exec->iotag);
  1270. free (sess->running_exec);
  1271. sess->running_exec = NULL;
  1272. }
  1273. }
  1274. #ifndef __EMX__
  1275. static int
  1276. cmd_execs (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1277. {
  1278. int r;
  1279. exec_check_process (sess);
  1280. if (sess->running_exec == NULL)
  1281. {
  1282. EMIT_SIGNAL (XP_TE_NOCHILD, sess, NULL, NULL, NULL, NULL, 0);
  1283. return FALSE;
  1284. }
  1285. r = kill (sess->running_exec->childpid, SIGSTOP);
  1286. if (r == -1)
  1287. PrintText (sess, "Error in kill(2)\n");
  1288. return TRUE;
  1289. }
  1290. static int
  1291. cmd_execc (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1292. {
  1293. int r;
  1294. exec_check_process (sess);
  1295. if (sess->running_exec == NULL)
  1296. {
  1297. EMIT_SIGNAL (XP_TE_NOCHILD, sess, NULL, NULL, NULL, NULL, 0);
  1298. return FALSE;
  1299. }
  1300. r = kill (sess->running_exec->childpid, SIGCONT);
  1301. if (r == -1)
  1302. PrintText (sess, "Error in kill(2)\n");
  1303. return TRUE;
  1304. }
  1305. static int
  1306. cmd_execk (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1307. {
  1308. int r;
  1309. exec_check_process (sess);
  1310. if (sess->running_exec == NULL)
  1311. {
  1312. EMIT_SIGNAL (XP_TE_NOCHILD, sess, NULL, NULL, NULL, NULL, 0);
  1313. return FALSE;
  1314. }
  1315. if (strcmp (word[2], "-9") == 0)
  1316. r = kill (sess->running_exec->childpid, SIGKILL);
  1317. else
  1318. r = kill (sess->running_exec->childpid, SIGTERM);
  1319. if (r == -1)
  1320. PrintText (sess, "Error in kill(2)\n");
  1321. return TRUE;
  1322. }
  1323. /* OS/2 Can't have the /EXECW command because it uses pipe(2) not socketpair
  1324. and thus it is simplex --AGL */
  1325. static int
  1326. cmd_execw (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1327. {
  1328. int len;
  1329. char *temp;
  1330. exec_check_process (sess);
  1331. if (sess->running_exec == NULL)
  1332. {
  1333. EMIT_SIGNAL (XP_TE_NOCHILD, sess, NULL, NULL, NULL, NULL, 0);
  1334. return FALSE;
  1335. }
  1336. len = strlen(word_eol[2]);
  1337. temp = malloc(len + 2);
  1338. sprintf(temp, "%s\n", word_eol[2]);
  1339. PrintText(sess, temp);
  1340. write(sess->running_exec->myfd, temp, len + 1);
  1341. free(temp);
  1342. return TRUE;
  1343. }
  1344. #endif /* !__EMX__ */
  1345. /* convert ANSI escape color codes to mIRC codes */
  1346. static short escconv[] =
  1347. /* 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 */
  1348. { 1,4,3,5,2,10,6,1, 1,7,9,8,12,11,13,1 };
  1349. static void
  1350. exec_handle_colors (char *buf, int len)
  1351. {
  1352. char numb[16];
  1353. char *nbuf;
  1354. int i = 0, j = 0, k = 0, firstn = 0, col, colf = 0, colb = 0;
  1355. int esc = FALSE, backc = FALSE, bold = FALSE;
  1356. /* any escape codes in this text? */
  1357. if (strchr (buf, 27) == 0)
  1358. return;
  1359. nbuf = malloc (len + 1);
  1360. while (i < len)
  1361. {
  1362. switch (buf[i])
  1363. {
  1364. case '\r':
  1365. break;
  1366. case 27:
  1367. esc = TRUE;
  1368. break;
  1369. case ';':
  1370. if (!esc)
  1371. goto norm;
  1372. backc = TRUE;
  1373. numb[k] = 0;
  1374. firstn = atoi (numb);
  1375. k = 0;
  1376. break;
  1377. case '[':
  1378. if (!esc)
  1379. goto norm;
  1380. break;
  1381. default:
  1382. if (esc)
  1383. {
  1384. if (buf[i] >= 'A' && buf[i] <= 'z')
  1385. {
  1386. if (buf[i] == 'm')
  1387. {
  1388. /* ^[[0m */
  1389. if (k == 0 || (numb[0] == '0' && k == 1))
  1390. {
  1391. nbuf[j] = '\017';
  1392. j++;
  1393. bold = FALSE;
  1394. goto cont;
  1395. }
  1396. numb[k] = 0;
  1397. col = atoi (numb);
  1398. backc = FALSE;
  1399. if (firstn == 1)
  1400. bold = TRUE;
  1401. if (firstn >= 30 && firstn <= 37)
  1402. colf = firstn - 30;
  1403. if (col >= 40)
  1404. {
  1405. colb = col - 40;
  1406. backc = TRUE;
  1407. }
  1408. if (col >= 30 && col <= 37)
  1409. colf = col - 30;
  1410. if (bold)
  1411. colf += 8;
  1412. if (backc)
  1413. {
  1414. colb = escconv[colb % 14];
  1415. colf = escconv[colf % 14];
  1416. j += sprintf (&nbuf[j], "\003%d,%02d", colf, colb);
  1417. } else
  1418. {
  1419. colf = escconv[colf % 14];
  1420. j += sprintf (&nbuf[j], "\003%02d", colf);
  1421. }
  1422. }
  1423. cont: esc = FALSE;
  1424. backc = FALSE;
  1425. k = 0;
  1426. } else
  1427. {
  1428. if (isdigit ((unsigned char) buf[i]) && k < (sizeof (numb) - 1))
  1429. {
  1430. numb[k] = buf[i];
  1431. k++;
  1432. }
  1433. }
  1434. } else
  1435. {
  1436. norm: nbuf[j] = buf[i];
  1437. j++;
  1438. }
  1439. }
  1440. i++;
  1441. }
  1442. nbuf[j] = 0;
  1443. memcpy (buf, nbuf, j + 1);
  1444. free (nbuf);
  1445. }
  1446. #ifndef HAVE_MEMRCHR
  1447. static void *
  1448. memrchr (const void *block, int c, size_t size)
  1449. {
  1450. unsigned char *p;
  1451. for (p = (unsigned char *)block + size; p != block; p--)
  1452. if (*p == c)
  1453. return p;
  1454. return 0;
  1455. }
  1456. #endif
  1457. static gboolean
  1458. exec_data (GIOChannel *source, GIOCondition condition, struct nbexec *s)
  1459. {
  1460. char *buf, *readpos, *rest;
  1461. int rd, len;
  1462. int sok = s->myfd;
  1463. len = s->buffill;
  1464. if (len) {
  1465. /* append new data to buffered incomplete line */
  1466. buf = malloc(len + 2050);
  1467. memcpy(buf, s->linebuf, len);
  1468. readpos = buf + len;
  1469. free(s->linebuf);
  1470. s->linebuf = NULL;
  1471. }
  1472. else
  1473. readpos = buf = malloc(2050);
  1474. rd = read (sok, readpos, 2048);
  1475. if (rd < 1)
  1476. {
  1477. /* The process has died */
  1478. kill(s->childpid, SIGKILL);
  1479. if (len) {
  1480. buf[len] = '\0';
  1481. exec_handle_colors(buf, len);
  1482. if (s->tochannel)
  1483. {
  1484. /* must turn off auto-completion temporarily */
  1485. unsigned int old = prefs.nickcompletion;
  1486. prefs.nickcompletion = 0;
  1487. handle_multiline (s->sess, buf, FALSE, TRUE);
  1488. prefs.nickcompletion = old;
  1489. }
  1490. else
  1491. PrintText (s->sess, buf);
  1492. }
  1493. free(buf);
  1494. waitpid (s->childpid, NULL, 0);
  1495. s->sess->running_exec = NULL;
  1496. fe_input_remove (s->iotag);
  1497. close (sok);
  1498. free (s);
  1499. return TRUE;
  1500. }
  1501. len += rd;
  1502. buf[len] = '\0';
  1503. rest = memrchr(buf, '\n', len);
  1504. if (rest)
  1505. rest++;
  1506. else
  1507. rest = buf;
  1508. if (*rest) {
  1509. s->buffill = len - (rest - buf); /* = strlen(rest) */
  1510. s->linebuf = malloc(s->buffill);
  1511. memcpy(s->linebuf, rest, s->buffill);
  1512. *rest = '\0';
  1513. len -= s->buffill; /* possibly 0 */
  1514. }
  1515. else
  1516. s->buffill = 0;
  1517. if (len) {
  1518. exec_handle_colors (buf, len);
  1519. if (s->tochannel)
  1520. handle_multiline (s->sess, buf, FALSE, TRUE);
  1521. else
  1522. PrintText (s->sess, buf);
  1523. }
  1524. free(buf);
  1525. return TRUE;
  1526. }
  1527. static int
  1528. cmd_exec (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1529. {
  1530. int tochannel = FALSE;
  1531. char *cmd = word_eol[2];
  1532. int fds[2], pid = 0;
  1533. struct nbexec *s;
  1534. int shell = TRUE;
  1535. int fd;
  1536. if (*cmd)
  1537. {
  1538. exec_check_process (sess);
  1539. if (sess->running_exec != NULL)
  1540. {
  1541. EMIT_SIGNAL (XP_TE_ALREADYPROCESS, sess, NULL, NULL, NULL, NULL, 0);
  1542. return TRUE;
  1543. }
  1544. if (!strcmp (word[2], "-d"))
  1545. {
  1546. if (!*word[3])
  1547. return FALSE;
  1548. cmd = word_eol[3];
  1549. shell = FALSE;
  1550. }
  1551. else if (!strcmp (word[2], "-o"))
  1552. {
  1553. if (!*word[3])
  1554. return FALSE;
  1555. cmd = word_eol[3];
  1556. tochannel = TRUE;
  1557. }
  1558. if (shell)
  1559. {
  1560. if (access ("/bin/sh", X_OK) != 0)
  1561. {
  1562. fe_message (_("I need /bin/sh to run!\n"), FE_MSG_ERROR);
  1563. return TRUE;
  1564. }
  1565. }
  1566. #ifdef __EMX__ /* if os/2 */
  1567. if (pipe (fds) < 0)
  1568. {
  1569. PrintText (sess, "Pipe create error\n");
  1570. return FALSE;
  1571. }
  1572. setmode (fds[0], O_BINARY);
  1573. setmode (fds[1], O_BINARY);
  1574. #else
  1575. if (socketpair (PF_UNIX, SOCK_STREAM, 0, fds) == -1)
  1576. {
  1577. PrintText (sess, "socketpair(2) failed\n");
  1578. return FALSE;
  1579. }
  1580. #endif
  1581. s = (struct nbexec *) malloc (sizeof (struct nbexec));
  1582. memset(s, 0, sizeof(*s));
  1583. s->myfd = fds[0];
  1584. s->tochannel = tochannel;
  1585. s->sess = sess;
  1586. pid = fork ();
  1587. if (pid == 0)
  1588. {
  1589. /* This is the child's context */
  1590. close (0);
  1591. close (1);
  1592. close (2);
  1593. /* Close parent's end of pipe */
  1594. close(s->myfd);
  1595. /* Copy the child end of the pipe to stdout and stderr */
  1596. dup2 (fds[1], 1);
  1597. dup2 (fds[1], 2);
  1598. /* Also copy it to stdin so we can write to it */
  1599. dup2 (fds[1], 0);
  1600. /* Now close all open file descriptors except stdin, stdout and stderr */
  1601. for (fd = 3; fd < 1024; fd++) close(fd);
  1602. /* Now we call /bin/sh to run our cmd ; made it more friendly -DC1 */
  1603. if (shell)
  1604. {
  1605. execl ("/bin/sh", "sh", "-c", cmd, NULL);
  1606. } else
  1607. {
  1608. char **argv;
  1609. int argc;
  1610. my_poptParseArgvString (cmd, &argc, &argv);
  1611. execvp (argv[0], argv);
  1612. }
  1613. /* not reached unless error */
  1614. /*printf("exec error\n");*/
  1615. fflush (stdout);
  1616. fflush (stdin);
  1617. _exit (0);
  1618. }
  1619. if (pid == -1)
  1620. {
  1621. /* Parent context, fork() failed */
  1622. PrintText (sess, "Error in fork(2)\n");
  1623. close(fds[0]);
  1624. close(fds[1]);
  1625. } else
  1626. {
  1627. /* Parent path */
  1628. close(fds[1]);
  1629. s->childpid = pid;
  1630. s->iotag = fe_input_add (s->myfd, FIA_READ|FIA_EX, exec_data, s);
  1631. sess->running_exec = s;
  1632. return TRUE;
  1633. }
  1634. }
  1635. return FALSE;
  1636. }
  1637. #endif
  1638. static int
  1639. cmd_flushq (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1640. {
  1641. sprintf (tbuf, "Flushing server send queue, %d bytes.\n", sess->server->sendq_len);
  1642. PrintText (sess, tbuf);
  1643. sess->server->flush_queue (sess->server);
  1644. return TRUE;
  1645. }
  1646. static int
  1647. cmd_quit (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1648. {
  1649. if (*word_eol[2])
  1650. sess->quitreason = word_eol[2];
  1651. sess->server->disconnect (sess, TRUE, -1);
  1652. sess->quitreason = NULL;
  1653. return 2;
  1654. }
  1655. static int
  1656. cmd_gate (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1657. {
  1658. char *server_name = word[2];
  1659. server *serv = sess->server;
  1660. if (*server_name)
  1661. {
  1662. char *port = word[3];
  1663. #ifdef USE_OPENSSL
  1664. serv->use_ssl = FALSE;
  1665. #endif
  1666. server_fill_her_up (serv);
  1667. if (*port)
  1668. serv->connect (serv, server_name, atoi (port), TRUE);
  1669. else
  1670. serv->connect (serv, server_name, 23, TRUE);
  1671. return TRUE;
  1672. }
  1673. return FALSE;
  1674. }
  1675. typedef struct
  1676. {
  1677. char *cmd;
  1678. session *sess;
  1679. } getvalinfo;
  1680. static void
  1681. get_int_cb (int cancel, int val, getvalinfo *info)
  1682. {
  1683. char buf[512];
  1684. if (!cancel)
  1685. {
  1686. snprintf (buf, sizeof (buf), "%s %d", info->cmd, val);
  1687. if (is_session (info->sess))
  1688. handle_command (info->sess, buf, FALSE);
  1689. }
  1690. free (info->cmd);
  1691. free (info);
  1692. }
  1693. static int
  1694. cmd_getint (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1695. {
  1696. getvalinfo *info;
  1697. if (!word[4][0])
  1698. return FALSE;
  1699. info = malloc (sizeof (*info));
  1700. info->cmd = strdup (word[3]);
  1701. info->sess = sess;
  1702. fe_get_int (word[4], atoi (word[2]), get_int_cb, info);
  1703. return TRUE;
  1704. }
  1705. static void
  1706. get_file_cb (char *cmd, char *file)
  1707. {
  1708. char buf[1024 + 128];
  1709. /* execute the command once per file, then once more with
  1710. no args */
  1711. if (file)
  1712. {
  1713. snprintf (buf, sizeof (buf), "%s %s", cmd, file);
  1714. handle_command (current_sess, buf, FALSE);
  1715. }
  1716. else
  1717. {
  1718. handle_command (current_sess, cmd, FALSE);
  1719. free (cmd);
  1720. }
  1721. }
  1722. static int
  1723. cmd_getfile (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1724. {
  1725. int idx = 2;
  1726. int flags = 0;
  1727. if (!word[3][0])
  1728. return FALSE;
  1729. if (!strcmp (word[2], "-folder"))
  1730. {
  1731. flags |= FRF_CHOOSEFOLDER;
  1732. idx++;
  1733. }
  1734. if (!strcmp (word[idx], "-multi"))
  1735. {
  1736. flags |= FRF_MULTIPLE;
  1737. idx++;
  1738. }
  1739. if (!strcmp (word[idx], "-save"))
  1740. {
  1741. flags |= FRF_WRITE;
  1742. idx++;
  1743. }
  1744. fe_get_file (word[idx+1], word[idx+2], (void *)get_file_cb, strdup (word[idx]), flags);
  1745. return TRUE;
  1746. }
  1747. static void
  1748. get_str_cb (int cancel, char *val, getvalinfo *info)
  1749. {
  1750. char buf[512];
  1751. if (!cancel)
  1752. {
  1753. snprintf (buf, sizeof (buf), "%s %s", info->cmd, val);
  1754. if (is_session (info->sess))
  1755. handle_command (info->sess, buf, FALSE);
  1756. }
  1757. free (info->cmd);
  1758. free (info);
  1759. }
  1760. static int
  1761. cmd_getstr (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1762. {
  1763. getvalinfo *info;
  1764. if (!word[4][0])
  1765. return FALSE;
  1766. info = malloc (sizeof (*info));
  1767. info->cmd = strdup (word[3]);
  1768. info->sess = sess;
  1769. fe_get_str (word[4], word[2], get_str_cb, info);
  1770. return TRUE;
  1771. }
  1772. static int
  1773. cmd_ghost (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1774. {
  1775. if (!word[2][0])
  1776. return FALSE;
  1777. sess->server->p_ns_ghost (sess->server, word[2], word[3]);
  1778. return TRUE;
  1779. }
  1780. static int
  1781. cmd_gui (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1782. {
  1783. switch (str_ihash (word[2]))
  1784. {
  1785. case 0x058b836e: fe_ctrl_gui (sess, 8, 0); break; /* APPLY */
  1786. case 0xac1eee45: fe_ctrl_gui (sess, 7, 2); break; /* ATTACH */
  1787. case 0x05a72f63: fe_ctrl_gui (sess, 4, atoi (word[3])); break; /* COLOR */
  1788. case 0xb06a1793: fe_ctrl_gui (sess, 7, 1); break; /* DETACH */
  1789. case 0x05cfeff0: fe_ctrl_gui (sess, 3, 0); break; /* FLASH */
  1790. case 0x05d154d8: fe_ctrl_gui (sess, 2, 0); break; /* FOCUS */
  1791. case 0x0030dd42: fe_ctrl_gui (sess, 0, 0); break; /* HIDE */
  1792. case 0x61addbe3: fe_ctrl_gui (sess, 5, 0); break; /* ICONIFY */
  1793. case 0xc0851aaa: fe_message (word[3], FE_MSG_INFO|FE_MSG_MARKUP); break; /* MSGBOX */
  1794. case 0x0035dafd: fe_ctrl_gui (sess, 1, 0); break; /* SHOW */
  1795. case 0x0033155f: /* MENU */
  1796. if (!strcasecmp (word[3], "TOGGLE"))
  1797. fe_ctrl_gui (sess, 6, 0);
  1798. else
  1799. return FALSE;
  1800. break;
  1801. default:
  1802. return FALSE;
  1803. }
  1804. return TRUE;
  1805. }
  1806. typedef struct
  1807. {
  1808. int longfmt;
  1809. int i, t;
  1810. char *buf;
  1811. } help_list;
  1812. static void
  1813. show_help_line (session *sess, help_list *hl, char *name, char *usage)
  1814. {
  1815. int j, len, max;
  1816. char *p;
  1817. if (name[0] == '.') /* hidden command? */
  1818. return;
  1819. if (hl->longfmt) /* long format for /HELP -l */
  1820. {
  1821. if (!usage || usage[0] == 0)
  1822. PrintTextf (sess, " \0034%s\003 :\n", name);
  1823. else
  1824. PrintTextf (sess, " \0034%s\003 : %s\n", name, _(usage));
  1825. return;
  1826. }
  1827. /* append the name into buffer, but convert to uppercase */
  1828. len = strlen (hl->buf);
  1829. p = name;
  1830. while (*p)
  1831. {
  1832. hl->buf[len] = toupper ((unsigned char) *p);
  1833. len++;
  1834. p++;
  1835. }
  1836. hl->buf[len] = 0;
  1837. hl->t++;
  1838. if (hl->t == 5)
  1839. {
  1840. hl->t = 0;
  1841. strcat (hl->buf, "\n");
  1842. PrintText (sess, hl->buf);
  1843. hl->buf[0] = ' ';
  1844. hl->buf[1] = ' ';
  1845. hl->buf[2] = 0;
  1846. } else
  1847. {
  1848. /* append some spaces after the command name */
  1849. max = strlen (name);
  1850. if (max < 10)
  1851. {
  1852. max = 10 - max;
  1853. for (j = 0; j < max; j++)
  1854. {
  1855. hl->buf[len] = ' ';
  1856. len++;
  1857. hl->buf[len] = 0;
  1858. }
  1859. }
  1860. }
  1861. }
  1862. static int
  1863. cmd_help (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1864. {
  1865. int i = 0, longfmt = 0;
  1866. char *helpcmd = "";
  1867. GSList *list;
  1868. if (tbuf)
  1869. helpcmd = word[2];
  1870. if (*helpcmd && strcmp (helpcmd, "-l") == 0)
  1871. longfmt = 1;
  1872. if (*helpcmd && !longfmt)
  1873. {
  1874. help (sess, tbuf, helpcmd, FALSE);
  1875. } else
  1876. {
  1877. struct popup *pop;
  1878. char *buf = malloc (4096);
  1879. help_list hl;
  1880. hl.longfmt = longfmt;
  1881. hl.buf = buf;
  1882. PrintTextf (sess, "\n%s\n\n", _("Commands Available:"));
  1883. buf[0] = ' ';
  1884. buf[1] = ' ';
  1885. buf[2] = 0;
  1886. hl.t = 0;
  1887. hl.i = 0;
  1888. while (xc_cmds[i].name)
  1889. {
  1890. show_help_line (sess, &hl, xc_cmds[i].name, xc_cmds[i].help);
  1891. i++;
  1892. }
  1893. strcat (buf, "\n");
  1894. PrintText (sess, buf);
  1895. PrintTextf (sess, "\n%s\n\n", _("User defined commands:"));
  1896. buf[0] = ' ';
  1897. buf[1] = ' ';
  1898. buf[2] = 0;
  1899. hl.t = 0;
  1900. hl.i = 0;
  1901. list = command_list;
  1902. while (list)
  1903. {
  1904. pop = list->data;
  1905. show_help_line (sess, &hl, pop->name, pop->cmd);
  1906. list = list->next;
  1907. }
  1908. strcat (buf, "\n");
  1909. PrintText (sess, buf);
  1910. PrintTextf (sess, "\n%s\n\n", _("Plugin defined commands:"));
  1911. buf[0] = ' ';
  1912. buf[1] = ' ';
  1913. buf[2] = 0;
  1914. hl.t = 0;
  1915. hl.i = 0;
  1916. plugin_command_foreach (sess, &hl, (void *)show_help_line);
  1917. strcat (buf, "\n");
  1918. PrintText (sess, buf);
  1919. free (buf);
  1920. PrintTextf (sess, "\n%s\n\n", _("Type /HELP <command> for more information, or /HELP -l"));
  1921. }
  1922. return TRUE;
  1923. }
  1924. static int
  1925. cmd_id (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1926. {
  1927. if (word[2][0])
  1928. {
  1929. sess->server->p_ns_identify (sess->server, word[2]);
  1930. return TRUE;
  1931. }
  1932. return FALSE;
  1933. }
  1934. static int
  1935. cmd_ignore (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  1936. {
  1937. int i;
  1938. int type = 0;
  1939. int quiet = 0;
  1940. char *mask;
  1941. if (!*word[2])
  1942. {
  1943. ignore_showlist (sess);
  1944. return TRUE;
  1945. }
  1946. if (!*word[3])
  1947. return FALSE;
  1948. i = 3;
  1949. while (1)
  1950. {
  1951. if (!*word[i])
  1952. {
  1953. if (type == 0)
  1954. return FALSE;
  1955. mask = word[2];
  1956. if (strchr (mask, '?') == NULL &&
  1957. strchr (mask, '*') == NULL &&
  1958. userlist_find (sess, mask))
  1959. {
  1960. mask = tbuf;
  1961. snprintf (tbuf, TBUFSIZE, "%s!*@*", word[2]);
  1962. }
  1963. i = ignore_add (mask, type);
  1964. if (quiet)
  1965. return TRUE;
  1966. switch (i)
  1967. {
  1968. case 1:
  1969. EMIT_SIGNAL (XP_TE_IGNOREADD, sess, mask, NULL, NULL, NULL, 0);
  1970. break;
  1971. case 2: /* old ignore changed */
  1972. EMIT_SIGNAL (XP_TE_IGNORECHANGE, sess, mask, NULL, NULL, NULL, 0);
  1973. }
  1974. return TRUE;
  1975. }
  1976. if (!strcasecmp (word[i], "UNIGNORE"))
  1977. type |= IG_UNIG;
  1978. else if (!strcasecmp (word[i], "ALL"))
  1979. type |= IG_PRIV | IG_NOTI | IG_CHAN | IG_CTCP | IG_INVI | IG_DCC;
  1980. else if (!strcasecmp (word[i], "PRIV"))
  1981. type |= IG_PRIV;
  1982. else if (!strcasecmp (word[i], "NOTI"))
  1983. type |= IG_NOTI;
  1984. else if (!strcasecmp (word[i], "CHAN"))
  1985. type |= IG_CHAN;
  1986. else if (!strcasecmp (word[i], "CTCP"))
  1987. type |= IG_CTCP;
  1988. else if (!strcasecmp (word[i], "INVI"))
  1989. type |= IG_INVI;
  1990. else if (!strcasecmp (word[i], "QUIET"))
  1991. quiet = 1;
  1992. else if (!strcasecmp (word[i], "NOSAVE"))
  1993. type |= IG_NOSAVE;
  1994. else if (!strcasecmp (word[i], "DCC"))
  1995. type |= IG_DCC;
  1996. else
  1997. {
  1998. sprintf (tbuf, _("Unknown arg '%s' ignored."), word[i]);
  1999. PrintText (sess, tbuf);
  2000. }
  2001. i++;
  2002. }
  2003. }
  2004. static int
  2005. cmd_invite (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  2006. {
  2007. if (!*word[2])
  2008. return FALSE;
  2009. if (*word[3])
  2010. sess->server->p_invite (sess->server, word[3], word[2]);
  2011. else
  2012. sess->server->p_invite (sess->server, sess->channel, word[2]);
  2013. return TRUE;
  2014. }
  2015. static int
  2016. cmd_join (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  2017. {
  2018. char *chan = word[2];
  2019. if (*chan)
  2020. {
  2021. char *po, *pass = word[3];
  2022. sess->server->p_join (sess->server, chan, pass);
  2023. if (sess->channel[0] == 0 && sess->waitchannel[0])
  2024. {
  2025. po = strchr (chan, ',');
  2026. if (po)
  2027. *po = 0;
  2028. safe_strcpy (sess->waitchannel, chan, CHANLEN);
  2029. }
  2030. return TRUE;
  2031. }
  2032. return FALSE;
  2033. }
  2034. static int
  2035. cmd_kick (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  2036. {
  2037. char *nick = word[2];
  2038. char *reason = word_eol[3];
  2039. if (*nick)
  2040. {
  2041. sess->server->p_kick (sess->server, sess->channel, nick, reason);
  2042. return TRUE;
  2043. }
  2044. return FALSE;
  2045. }
  2046. static int
  2047. cmd_kickban (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  2048. {
  2049. char *nick = word[2];
  2050. char *reason = word_eol[3];
  2051. struct User *user;
  2052. if (*nick)
  2053. {
  2054. /* if the reason is a 1 digit number, treat it as a bantype */
  2055. user = userlist_find (sess, nick);
  2056. if (isdigit ((unsigned char) reason[0]) && reason[1] == 0)
  2057. {
  2058. ban (sess, tbuf, nick, reason, (user && user->op));
  2059. reason[0] = 0;
  2060. } else
  2061. ban (sess, tbuf, nick, "", (user && user->op));
  2062. sess->server->p_kick (sess->server, sess->channel, nick, reason);
  2063. return TRUE;
  2064. }
  2065. return FALSE;
  2066. }
  2067. static int
  2068. cmd_killall (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  2069. {
  2070. xchat_exit();
  2071. return 2;
  2072. }
  2073. static int
  2074. cmd_lagcheck (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  2075. {
  2076. lag_check ();
  2077. return TRUE;
  2078. }
  2079. static void
  2080. lastlog (session *sess, char *search, gboolean regexp)
  2081. {
  2082. session *lastlog_sess;
  2083. if (!is_session (sess))
  2084. return;
  2085. lastlog_sess = find_dialog (sess->server, "(lastlog)");
  2086. if (!lastlog_sess)
  2087. lastlog_sess = new_ircwindow (sess->server, "(lastlog)", SESS_DIALOG, 0);
  2088. lastlog_sess->lastlog_sess = sess;
  2089. lastlog_sess->lastlog_regexp = regexp; /* remember the search type */
  2090. fe_text_clear (lastlog_sess, 0);
  2091. fe_lastlog (sess, lastlog_sess, search, regexp);
  2092. }
  2093. static int
  2094. cmd_lastlog (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  2095. {
  2096. if (*word_eol[2])
  2097. {
  2098. if (!strcmp (word[2], "-r"))
  2099. lastlog (sess, word_eol[3], TRUE);
  2100. else
  2101. lastlog (sess, word_eol[2], FALSE);
  2102. return TRUE;
  2103. }
  2104. return FALSE;
  2105. }
  2106. static int
  2107. cmd_list (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  2108. {
  2109. sess->server->p_list_channels (sess->server, word_eol[2], 1);
  2110. return TRUE;
  2111. }
  2112. gboolean
  2113. load_perform_file (session *sess, char *file)
  2114. {
  2115. char tbuf[1024 + 4];
  2116. char *nl;
  2117. FILE *fp;
  2118. fp = xchat_fopen_file (file, "r", XOF_FULLPATH);
  2119. if (!fp)
  2120. return FALSE;
  2121. tbuf[1024] = 0;
  2122. while (fgets (tbuf, 1024, fp))
  2123. {
  2124. nl = strchr (tbuf, '\n');
  2125. if (nl == tbuf) /* skip empty commands */
  2126. continue;
  2127. if (nl)
  2128. *nl = 0;
  2129. if (tbuf[0] == prefs.cmdchar[0])
  2130. handle_command (sess, tbuf + 1, TRUE);
  2131. else
  2132. handle_command (sess, tbuf, TRUE);
  2133. }
  2134. fclose (fp);
  2135. return TRUE;
  2136. }
  2137. static int
  2138. cmd_load (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  2139. {
  2140. char *error, *arg, *file;
  2141. int len;
  2142. if (!word[2][0])
  2143. return FALSE;
  2144. if (strcmp (word[2], "-e") == 0)
  2145. {
  2146. file = expand_homedir (word[3]);
  2147. if (!load_perform_file (sess, file))
  2148. {
  2149. PrintTextf (sess, _("Cannot access %s\n"), file);
  2150. PrintText (sess, errorstring (errno));
  2151. }
  2152. free (file);
  2153. return TRUE;
  2154. }
  2155. #ifdef USE_PLUGIN
  2156. len = strlen (word[2]);
  2157. #ifdef WIN32
  2158. if (len > 4 && strcasecmp (".dll", word[2] + len - 4) == 0)
  2159. #else
  2160. #if defined(__hpux)
  2161. if (len > 3 && strcasecmp (".sl", word[2] + len - 3) == 0)
  2162. #else
  2163. if (len > 3 && strcasecmp (".so", word[2] + len - 3) == 0)
  2164. #endif
  2165. #endif
  2166. {
  2167. arg = NULL;
  2168. if (word_eol[3][0])
  2169. arg = word_eol[3];
  2170. file = expand_homedir (word[2]);
  2171. error = plugin_load (sess, file, arg);
  2172. free (file);
  2173. if (error)
  2174. PrintText (sess, error);
  2175. return TRUE;
  2176. }
  2177. #endif
  2178. sprintf (tbuf, "Unknown file type %s. Maybe you need to install the Perl or Python plugin?\n", word[2]);
  2179. PrintText (sess, tbuf);
  2180. return FALSE;
  2181. }
  2182. static int
  2183. cmd_me (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  2184. {
  2185. char *act = word_eol[2];
  2186. if (!(*act))
  2187. return FALSE;
  2188. if (sess->type == SESS_SERVER)
  2189. {
  2190. notj_msg (sess);
  2191. return TRUE;
  2192. }
  2193. snprintf (tbuf, TBUFSIZE, "\001ACTION %s\001\r", act);
  2194. /* first try through DCC CHAT */
  2195. if (dcc_write_chat (sess->channel, tbuf))
  2196. {
  2197. /* print it to screen */
  2198. inbound_action (sess, sess->channel, sess->server->nick, "", act, TRUE, FALSE);
  2199. } else
  2200. {
  2201. /* DCC CHAT failed, try through server */
  2202. if (sess->server->connected)
  2203. {
  2204. sess->server->p_action (sess->server, sess->channel, act);
  2205. /* print it to screen */
  2206. inbound_action (sess, sess->channel, sess->server->nick, "", act, TRUE, FALSE);
  2207. } else
  2208. {
  2209. notc_msg (sess);
  2210. }
  2211. }
  2212. return TRUE;
  2213. }
  2214. static int
  2215. cmd_mode (struct session *sess, char *tbuf, char *word[], char *word_eol[])
  2216. {

Large files files are truncated, but you can click here to view the full file