4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
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.
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
20 * This was taken almost exactly from X-Chat. The power of the GPL.
21 * Translated from X-Chat to Gaim by Eric Warmenhoven.
22 * Originally by Erik Scrafford <eriks@chilisoft.com>.
23 * X-Chat Copyright (C) 1998 Peter Zelezny.
38 #ifndef _SEM_SEMUN_UNDEFINED
39 #define HAS_UNION_SEMUN
44 #include <sys/types.h>
53 /* perl module support */
54 extern void xs_init
_((void));
55 extern void boot_DynaLoader
_((CV
* cv
)); /* perl is so wacky */
67 char *shutdowncallback
; /* bleh */
70 struct _perl_event_handlers
{
75 struct _perl_timeout_handlers
{
81 static GList
*perl_list
= NULL
; /* should probably extern this at some point */
82 static GList
*perl_timeout_handlers
= NULL
;
83 static GList
*perl_event_handlers
= NULL
;
84 static PerlInterpreter
*my_perl
= NULL
;
85 static void perl_init();
87 /* dealing with gaim */
88 XS(XS_GAIM_register
); /* set up hooks for script */
89 XS(XS_GAIM_get_info
); /* version, last to attempt signon, protocol */
90 XS(XS_GAIM_print
); /* lemme figure this one out... */
91 XS(XS_GAIM_write_to_conv
); /* write into conversation window */
94 XS(XS_GAIM_buddy_list
); /* all buddies */
95 XS(XS_GAIM_online_list
); /* online buddies */
98 XS(XS_GAIM_command
); /* send command to server */
99 XS(XS_GAIM_user_info
); /* given name, return struct buddy members */
100 XS(XS_GAIM_print_to_conv
); /* send message to someone */
101 XS(XS_GAIM_print_to_chat
); /* send message to chat room */
102 XS(XS_GAIM_serv_send_im
); /* send message to someone (but do not display) */
104 /* handler commands */
105 XS(XS_GAIM_add_event_handler
); /* when servers talk */
106 XS(XS_GAIM_add_timeout_handler
); /* figure it out */
110 char *file
= __FILE__
;
111 newXS ("DynaLoader::boot_DynaLoader", boot_DynaLoader
, file
);
114 static char *escape_quotes(char *buf
)
116 static char *tmp_buf
= NULL
;
121 tmp_buf
= g_malloc(strlen(buf
) * 2 + 1);
122 for (i
= buf
, j
= tmp_buf
; *i
; i
++, j
++) {
123 if (*i
== '\'' || *i
== '\\')
132 static SV
*execute_perl(char *function
, char *args
)
134 static char *perl_cmd
= NULL
;
139 perl_cmd
= g_malloc(strlen(function
) + strlen(args
) + 4);
140 sprintf(perl_cmd
, "&%s(%s)", function
, args
);
141 #ifndef HAVE_PERL_EVAL_PV
142 i
= (perl_eval_pv(perl_cmd
, TRUE
));
144 i
= (Perl_eval_pv(perl_cmd
, TRUE
));
149 int perl_load_file(char *script_name
)
151 char *name
= g_strdup_printf("'%s'", escape_quotes(script_name
));
155 return_val
= execute_perl("load_file", name
);
157 return SvNV (return_val
);
160 static int is_pl_file(char *filename
)
163 if (!filename
) return 0;
164 if (!filename
[0]) return 0;
165 len
= strlen(filename
);
167 if (len
< 0) return 0;
168 return (!strncmp(filename
+ len
, ".pl", 3));
178 path
= gaim_user_dir();
181 while ((ent
= readdir(dir
))) {
182 if (strcmp(ent
->d_name
, ".") && strcmp(ent
->d_name
, "..")) {
183 if (is_pl_file(ent
->d_name
)) {
184 buf
= g_malloc(strlen(path
) + strlen(ent
->d_name
) + 2);
185 sprintf(buf
, "%s/%s", path
, ent
->d_name
);
196 static void perl_init()
198 char *perl_args
[] = {"", "-e", "0", "-w"};
202 " (my $file_name) = @_;\n"
203 " open FH, $file_name or return 2;\n"
205 " local($/) = undef;\n"
209 " $file = \"\\@ISA = qw(Exporter DynaLoader);\\n\" . $file;\n"
211 " eval $file if $@;\n"
216 my_perl
= perl_alloc();
217 perl_construct(my_perl
);
218 perl_parse(my_perl
, xs_init
, 4, perl_args
, NULL
);
219 #ifndef HAVE_PERL_EVAL_PV
220 perl_eval_pv(load_file
, TRUE
);
222 Perl_eval_pv(load_file
, TRUE
);
225 newXS ("GAIM::register", XS_GAIM_register
, "GAIM");
226 newXS ("GAIM::get_info", XS_GAIM_get_info
, "GAIM");
227 newXS ("GAIM::print", XS_GAIM_print
, "GAIM");
228 newXS ("GAIM::write_to_conv", XS_GAIM_write_to_conv
, "GAIM");
230 newXS ("GAIM::buddy_list", XS_GAIM_buddy_list
, "GAIM");
231 newXS ("GAIM::online_list", XS_GAIM_online_list
, "GAIM");
233 newXS ("GAIM::command", XS_GAIM_command
, "GAIM");
234 newXS ("GAIM::user_info", XS_GAIM_user_info
, "GAIM");
235 newXS ("GAIM::print_to_conv", XS_GAIM_print_to_conv
, "GAIM");
236 newXS ("GAIM::print_to_chat", XS_GAIM_print_to_chat
, "GAIM");
237 newXS ("GAIM::serv_send_im", XS_GAIM_serv_send_im
, "GAIM");
239 newXS ("GAIM::add_event_handler", XS_GAIM_add_event_handler
, "GAIM");
240 newXS ("GAIM::add_timeout_handler", XS_GAIM_add_timeout_handler
, "GAIM");
245 struct perlscript
*scp
;
246 struct _perl_timeout_handlers
*thn
;
247 struct _perl_event_handlers
*ehn
;
250 scp
= perl_list
->data
;
251 perl_list
= g_list_remove(perl_list
, scp
);
252 if (scp
->shutdowncallback
[0])
253 execute_perl(scp
->shutdowncallback
, "");
255 g_free(scp
->version
);
256 g_free(scp
->shutdowncallback
);
260 while (perl_timeout_handlers
) {
261 thn
= perl_timeout_handlers
->data
;
262 perl_timeout_handlers
= g_list_remove(perl_timeout_handlers
, thn
);
263 g_source_remove(thn
->iotag
);
264 g_free(thn
->handler_args
);
265 g_free(thn
->handler_name
);
269 while (perl_event_handlers
) {
270 ehn
= perl_event_handlers
->data
;
271 perl_event_handlers
= g_list_remove(perl_event_handlers
, ehn
);
272 g_free(ehn
->event_type
);
273 g_free(ehn
->handler_name
);
277 if (my_perl
!= NULL
) {
278 perl_destruct(my_perl
);
284 XS (XS_GAIM_register
)
286 char *name
, *ver
, *callback
, *unused
; /* exactly like X-Chat, eh? :) */
288 struct perlscript
*scp
;
292 name
= SvPV (ST (0), junk
);
293 ver
= SvPV (ST (1), junk
);
294 callback
= SvPV (ST (2), junk
);
295 unused
= SvPV (ST (3), junk
);
297 scp
= g_new0(struct perlscript
, 1);
298 scp
->name
= g_strdup(name
);
299 scp
->version
= g_strdup(ver
);
300 scp
->shutdowncallback
= g_strdup(callback
);
301 perl_list
= g_list_append(perl_list
, scp
);
303 XST_mPV (0, VERSION
);
307 XS (XS_GAIM_get_info
)
313 switch(SvIV(ST(0))) {
320 GSList
*c
= connections
;
321 struct gaim_connection
*gc
;
324 gc
= (struct gaim_connection
*)c
->data
;
325 XST_mIV(i
++, (guint
)gc
);
332 struct gaim_connection
*gc
= (struct gaim_connection
*)SvIV(ST(1));
333 if (g_slist_find(connections
, gc
))
334 XST_mIV(i
++, gc
->protocol
);
341 struct gaim_connection
*gc
= (struct gaim_connection
*)SvIV(ST(1));
342 if (g_slist_find(connections
, gc
))
343 XST_mPV(i
++, gc
->username
);
350 struct gaim_connection
*gc
= (struct gaim_connection
*)SvIV(ST(1));
351 if (g_slist_find(connections
, gc
))
352 XST_mIV(i
++, g_slist_index(aim_users
, gc
->user
));
359 GSList
*a
= aim_users
;
361 struct aim_user
*u
= a
->data
;
362 XST_mPV(i
++, u
->username
);
369 GSList
*a
= aim_users
;
371 struct aim_user
*u
= a
->data
;
372 XST_mIV(i
++, u
->protocol
);
379 struct gaim_connection
*gc
= (struct gaim_connection
*)SvIV(ST(1));
380 if (g_slist_find(connections
, gc
))
381 XST_mPV(i
++, gc
->prpl
->name());
383 XST_mPV(i
++, "Unknown");
387 XST_mPV(0, "Error2");
402 title
= SvPV(ST(0), junk
);
403 message
= SvPV(ST(1), junk
);
404 do_error_dialog(message
, title
);
408 XS (XS_GAIM_buddy_list
)
410 struct gaim_connection
*gc
;
419 gc
= (struct gaim_connection
*)SvIV(ST(0));
420 if (g_slist_find(connections
, gc
))
424 g
= (struct group
*)list
->data
;
427 buddy
= (struct buddy
*)mem
->data
;
428 XST_mPV(i
++, buddy
->name
);
431 list
= g_slist_next(list
);
436 XS (XS_GAIM_online_list
)
438 struct gaim_connection
*gc
;
447 gc
= (struct gaim_connection
*)SvIV(ST(0));
448 if (g_slist_find(connections
, gc
))
452 g
= (struct group
*)list
->data
;
455 b
= (struct buddy
*)mem
->data
;
456 if (b
->present
) XST_mPV(i
++, b
->name
);
459 list
= g_slist_next(list
);
467 char *command
= NULL
;
471 command
= SvPV(ST(0), junk
);
472 if (!command
) XSRETURN(0);
473 if (!strncasecmp(command
, "signon", 6)) {
474 int index
= SvIV(ST(1));
475 if (g_slist_nth_data(aim_users
, index
))
476 serv_login(g_slist_nth_data(aim_users
, index
));
477 } else if (!strncasecmp(command
, "signoff", 7)) {
478 struct gaim_connection
*gc
= (struct gaim_connection
*)SvIV(ST(1));
479 if (g_slist_find(connections
, gc
)) signoff(gc
);
480 else signoff_all(NULL
, NULL
);
481 } else if (!strncasecmp(command
, "info", 4)) {
482 struct gaim_connection
*gc
= (struct gaim_connection
*)SvIV(ST(1));
483 if (g_slist_find(connections
, gc
))
484 serv_set_info(gc
, SvPV(ST(2), junk
));
485 } else if (!strncasecmp(command
, "away", 4)) {
486 char *message
= SvPV(ST(1), junk
);
487 static struct away_message a
;
488 g_snprintf(a
.message
, sizeof(a
.message
), "%s", message
);
489 do_away_message(NULL
, &a
);
490 } else if (!strncasecmp(command
, "back", 4)) {
492 } else if (!strncasecmp(command
, "idle", 4)) {
493 GSList
*c
= connections
;
494 struct gaim_connection
*gc
;
497 gc
= (struct gaim_connection
*)c
->data
;
498 serv_set_idle(gc
, SvIV(ST(1)));
501 } else if (!strncasecmp(command
, "warn", 4)) {
502 GSList
*c
= connections
;
503 struct gaim_connection
*gc
;
506 gc
= (struct gaim_connection
*)c
->data
;
507 serv_warn(gc
, SvPV(ST(1), junk
), SvIV(ST(2)));
515 XS (XS_GAIM_user_info
)
517 struct gaim_connection
*gc
;
519 struct buddy
*buddy
= NULL
;
523 gc
= (struct gaim_connection
*)SvIV(ST(0));
524 if (g_slist_find(connections
, gc
))
525 buddy
= find_buddy(gc
, SvPV(ST(1), junk
));
529 XST_mPV(0, buddy
->name
);
530 XST_mPV(1, buddy
->show
);
531 XST_mPV(2, buddy
->present
? "Online" : "Offline");
532 XST_mIV(3, buddy
->evil
);
533 XST_mIV(4, buddy
->signon
);
534 XST_mIV(5, buddy
->idle
);
535 XST_mIV(6, buddy
->uc
);
536 XST_mIV(7, buddy
->caps
);
540 XS (XS_GAIM_write_to_conv
)
542 char *nick
, *who
, *what
;
543 struct conversation
*c
;
549 nick
= SvPV(ST(0), junk
);
551 what
= SvPV(ST(2), junk
);
552 who
= SvPV(ST(3), junk
);
557 case 0: wflags
=WFLAG_SEND
; break;
558 case 1: wflags
=WFLAG_RECV
; break;
559 case 2: wflags
=WFLAG_SYSTEM
; break;
560 default: wflags
=WFLAG_RECV
;
563 c
= find_conversation(nick
);
565 c
= new_conversation(nick
);
567 write_to_conv(c
, what
, wflags
, who
, time(NULL
), -1);
571 XS (XS_GAIM_serv_send_im
)
573 struct gaim_connection
*gc
;
580 gc
= (struct gaim_connection
*)SvIV(ST(0));
581 nick
= SvPV(ST(1), junk
);
582 what
= SvPV(ST(2), junk
);
583 isauto
= SvIV(ST(3));
585 if (!g_slist_find(connections
, gc
)) {
589 serv_send_im(gc
, nick
, what
, -1, isauto
);
593 XS (XS_GAIM_print_to_conv
)
595 struct gaim_connection
*gc
;
598 struct conversation
*c
;
603 gc
= (struct gaim_connection
*)SvIV(ST(0));
604 nick
= SvPV(ST(1), junk
);
605 what
= SvPV(ST(2), junk
);
606 isauto
= SvIV(ST(3));
607 if (!g_slist_find(connections
, gc
)) {
611 c
= find_conversation(nick
);
613 c
= new_conversation(nick
);
615 write_to_conv(c
, what
, WFLAG_SEND
| (isauto
? WFLAG_AUTO
: 0), NULL
, time(NULL
), -1);
616 serv_send_im(c
->gc
, nick
, what
, -1, isauto
? IM_FLAG_AWAY
: 0);
620 XS (XS_GAIM_print_to_chat
)
622 struct gaim_connection
*gc
;
625 struct conversation
*b
= NULL
;
631 gc
= (struct gaim_connection
*)SvIV(ST(0));
633 what
= SvPV(ST(2), junk
);
635 if (!g_slist_find(connections
, gc
)) {
639 bcs
= gc
->buddy_chats
;
641 b
= (struct conversation
*)bcs
->data
;
648 serv_chat_send(gc
, id
, what
);
652 int perl_event(enum gaim_event event
, void *arg1
, void *arg2
, void *arg3
, void *arg4
)
656 struct _perl_event_handlers
*data
;
662 buf
= g_strdup_printf("'%lu'", (unsigned long)arg1
);
665 buf
= g_strdup_printf("'%lu','%s'", (unsigned long)arg1
,
666 ((struct gaim_connection
*)arg1
)->away
?
667 escape_quotes(((struct gaim_connection
*)arg1
)->away
) : "");
671 char *tmp
= *(char **)arg2
? g_strdup(escape_quotes(*(char **)arg2
)) : g_malloc0(1);
672 buf
= g_strdup_printf("'%lu','%s','%s'", (unsigned long)arg1
, tmp
,
673 *(char **)arg3
? escape_quotes(*(char **)arg3
) : "");
679 char *tmp
= arg2
? g_strdup(escape_quotes(arg2
)) : g_malloc0(1);
680 buf
= g_strdup_printf("'%lu','%s','%s'", (unsigned long)arg1
, tmp
,
681 *(char **)arg3
? escape_quotes(*(char **)arg3
) : "");
685 case event_buddy_signon
:
686 case event_buddy_signoff
:
688 case event_buddy_away
:
689 case event_buddy_back
:
690 case event_buddy_idle
:
691 case event_buddy_unidle
:
692 buf
= g_strdup_printf("'%lu','%s'", (unsigned long)arg1
, escape_quotes(arg2
));
694 case event_chat_invited
:
696 char *tmp2
, *tmp3
, *tmp4
;
697 tmp2
= g_strdup(escape_quotes(arg2
));
698 tmp3
= g_strdup(escape_quotes(arg3
));
699 tmp4
= arg4
? g_strdup(escape_quotes(arg4
)) : g_malloc0(1);
700 buf
= g_strdup_printf("'%lu','%s','%s','%s'", (unsigned long)arg1
, tmp2
, tmp3
, tmp4
);
706 case event_chat_join
:
707 case event_chat_buddy_join
:
708 case event_chat_buddy_leave
:
709 buf
= g_strdup_printf("'%lu','%d','%s'", (unsigned long)arg1
, (int)arg2
,
710 escape_quotes(arg3
));
712 case event_chat_leave
:
713 buf
= g_strdup_printf("'%lu','%d'", (unsigned long)arg1
, (int)arg2
);
715 case event_chat_recv
:
718 t3
= g_strdup(escape_quotes(arg3
));
719 t4
= arg4
? g_strdup(escape_quotes(arg4
)) : g_malloc0(1);
720 buf
= g_strdup_printf("'%lu','%d','%s','%s'", (unsigned long)arg1
, (int)arg2
, t3
, t4
);
725 case event_chat_send_invite
:
728 t3
= g_strdup(escape_quotes(arg3
));
729 t4
= *(char **)arg4
? g_strdup(escape_quotes(*(char **)arg4
)) : g_malloc0(1);
730 buf
= g_strdup_printf("'%lu','%d','%s','%s'", (unsigned long)arg1
, (int)arg2
, t3
, t4
);
735 case event_chat_send
:
736 buf
= g_strdup_printf("'%lu','%d','%s'", (unsigned long)arg1
, (int)arg2
,
737 *(char **)arg3
? escape_quotes(*(char **)arg3
) : "");
740 buf
= g_strdup_printf("'%lu','%s','%d'", (unsigned long)arg1
,
741 arg2
? escape_quotes(arg2
) : "", (int)arg3
);
746 case event_new_conversation
:
747 buf
= g_strdup_printf("'%s'", escape_quotes(arg1
));
749 case event_im_displayed_sent
:
752 tmp2
= g_strdup(escape_quotes(arg2
));
753 tmp3
= *(char **)arg3
? g_strdup(escape_quotes(*(char **)arg3
)) : g_malloc0(1);
754 buf
= g_strdup_printf("'%lu','%s','%s'", (unsigned long)arg1
, tmp2
, tmp3
);
759 case event_im_displayed_rcvd
:
762 tmp2
= g_strdup(escape_quotes(arg2
));
763 tmp3
= arg3
? g_strdup(escape_quotes(arg3
)) : g_malloc0(1);
764 buf
= g_strdup_printf("'%lu','%s','%s'", (unsigned long)arg1
, tmp2
, tmp3
);
773 for (handler
= perl_event_handlers
; handler
!= NULL
; handler
= handler
->next
) {
774 data
= handler
->data
;
775 if (!strcmp(event_name(event
), data
->event_type
)) {
776 handler_return
= execute_perl(data
->handler_name
, buf
);
777 if (SvIV(handler_return
)) {
780 return SvIV(handler_return
);
791 XS (XS_GAIM_add_event_handler
)
794 struct _perl_event_handlers
*handler
;
798 handler
= g_new0(struct _perl_event_handlers
, 1);
799 handler
->event_type
= g_strdup(SvPV(ST(0), junk
));
800 handler
->handler_name
= g_strdup(SvPV(ST(1), junk
));
801 perl_event_handlers
= g_list_append(perl_event_handlers
, handler
);
802 debug_printf("registered perl event handler for %s\n", handler
->event_type
);
806 static int perl_timeout(gpointer data
)
808 struct _perl_timeout_handlers
*handler
= data
;
809 execute_perl(handler
->handler_name
, escape_quotes(handler
->handler_args
));
810 perl_timeout_handlers
= g_list_remove(perl_timeout_handlers
, handler
);
811 g_free(handler
->handler_args
);
812 g_free(handler
->handler_name
);
815 return 0; /* returning zero removes the timeout handler */
818 XS (XS_GAIM_add_timeout_handler
)
822 struct _perl_timeout_handlers
*handler
;
826 handler
= g_new0(struct _perl_timeout_handlers
, 1);
827 timeout
= 1000 * SvIV(ST(0));
828 debug_printf("Adding timeout for %d seconds.\n", timeout
/1000);
829 handler
->handler_name
= g_strdup(SvPV(ST(1), junk
));
830 handler
->handler_args
= g_strdup(SvPV(ST(2), junk
));
831 perl_timeout_handlers
= g_list_append(perl_timeout_handlers
, handler
);
832 handler
->iotag
= g_timeout_add(timeout
, perl_timeout
, handler
);
836 extern void unload_perl_scripts()
842 extern void list_perl_scripts()
844 GList
*s
= perl_list
;
845 struct perlscript
*p
;
846 char buf
[BUF_LONG
* 4];
849 at
+= g_snprintf(buf
+ at
, sizeof(buf
) - at
, "Loaded scripts:\n");
851 p
= (struct perlscript
*)s
->data
;
852 at
+= g_snprintf(buf
+ at
, sizeof(buf
) - at
, "%s\n", p
->name
);
856 do_error_dialog(buf
, _("Perl Scripts"));
859 #endif /* USE_PERL */