changeset 4029:31480901bf29

[gaim-migrate @ 4233] "with the change to .60 and the new method of using perl_call argument parsing was broken. What essentially happened is that the previous method of pre-parsing was to generate a string in the for 'arg one','arg two','arg three' and execute the perl function via &perlfunc(args). This would make the perl function in essense parse the variables for us. With the introduction of perl_call, however, that argument list was being treated as one long, singular argument. perl_call asks for lists of pointers to character arrays that are NULL terminated, and it passes them into the function using an internal method. With this said, I changed the function execute_perl from requiring (char* function, char* args) to (char* function, char** args). It no longer takes a single argument and inserts it into the appropriate data type that is terminated with a NULL element, instead you now have to pass it a pre-NULL terminated array of character pointers to accomodate some functions wanting to give it more than one argument. I modified the functions that use execute_perl to use this method, and commented those lines, as well chopping the multiple argument section into buf[0] = looking sections for clarity. Finally, I inserted a heft comment above execute_perl to try and explain what I did, I hope it is understandable. " -- Eric Timme (var1ety) committer: Tailor Script <tailor@pidgin.im>
author Luke Schierer <lschiere@pidgin.im>
date Sun, 01 Dec 2002 20:43:00 +0000
parents ab831dca298a
children a3466240218c
files src/perl.c
diffstat 1 files changed, 105 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/src/perl.c	Sun Dec 01 04:28:03 2002 +0000
+++ b/src/perl.c	Sun Dec 01 20:43:00 2002 +0000
@@ -182,12 +182,40 @@
   2001/06/14: execute_perl replaced by Martin Persson <mep@passagen.se>
               previous use of perl_eval leaked memory, replaced with
               a version that uses perl_call instead
+  30/11/2002: execute_perl modified by Eric Timme <timothy@voidnet.com>
+			  args changed to char** so that we can have preparsed
+  			  arguments again, and many headaches ensued! This essentially 
+			  means we replaced one hacked method with a messier hacked 
+			  method out of perceived necessity. Formerly execute_perl 
+			  required a single char_ptr, and it would insert it into an 
+			  array of character pointers and NULL terminate the new array.
+			  Now we have to pass in pre-terminated character pointer arrays
+			  to accomodate functions that want to pass in multiple arguments.
+
+			  Previously arguments were preparsed because an argument list
+			  was constructed in the form 'arg one','arg two' and was
+			  executed via a call like &funcname(arglist) (see .59.x), so
+			  the arglist was magically pre-parsed because of the method. 
+			  With Martin Persson's change to perl_call we now need to
+			  use a null terminated list of character pointers for arguments
+			  if we wish them to be parsed. Lacking a better way to allow
+			  for both single arguments and many I created a NULL terminated
+			  array in every function that called execute_perl and passed
+			  that list into the function.  In the former version a single
+			  character pointer was passed in, and was placed into an array
+			  of character pointers with two elements, with a NULL element
+			  tacked onto the back, but this method no longer seemed prudent.
+
+			  Enhancements in the future might be to get rid of pre-declaring
+			  the array sizes?  I am not comfortable enough with this
+			  subject to attempt it myself and hope it to stand the test
+			  of time.
 */
 
 static int 
-execute_perl(char *function, char *args)
+execute_perl(char *function, char **args)
 {
-	char *perl_args[2] = { args, NULL }, buf[512];
+	char buf[512];
 	int count, ret_value = 1;
 	SV *sv;
 
@@ -195,7 +223,7 @@
         ENTER;
         SAVETMPS;
         PUSHMARK(sp);
-        count = perl_call_argv(function, G_EVAL | G_SCALAR, perl_args);
+        count = perl_call_argv(function, G_EVAL | G_SCALAR, args);
         SPAGAIN;
 
         sv = GvSV(gv_fetchpv("@", TRUE, SVt_PV));
@@ -220,6 +248,7 @@
 }
 
 void perl_unload_file(struct gaim_plugin *plug) {
+	char *atmp[2] = { "", NULL }; /* see execute_perl --et */
 	struct perlscript *scp = NULL;
 	struct _perl_timeout_handlers *thn;
 	struct _perl_event_handlers *ehn;
@@ -232,7 +261,7 @@
 		if (scp->plug == plug) {
 			perl_list = g_list_remove(perl_list, scp);
 			if (scp->shutdowncallback[0])
-				execute_perl(scp->shutdowncallback, "");
+				execute_perl(scp->shutdowncallback, atmp);
 			perl_list = g_list_remove(perl_list, scp);
 			g_free(scp->name);
 			g_free(scp->version);
@@ -274,6 +303,7 @@
 
 int perl_load_file(char *script_name)
 {
+	char *atmp[2] = { script_name, NULL }; /* see execute_perl --et */
 	struct gaim_plugin *plug;
 	GList *p = probed_plugins;
 	GList *s;
@@ -297,7 +327,7 @@
 	plug->handle = plug->path;
 	plugins = g_list_append(plugins, plug);
 
-	ret = execute_perl("load_n_eval", script_name);
+	ret = execute_perl("load_n_eval", atmp);
 
 	s = perl_list;
 	while (s) {
@@ -413,6 +443,7 @@
 
 void perl_end()
 {
+	char *atmp[2] = { "", NULL }; /* see execute_perl --et */
 	struct perlscript *scp;
 	struct _perl_timeout_handlers *thn;
 	struct _perl_event_handlers *ehn;
@@ -421,7 +452,7 @@
 		scp = perl_list->data;
 		perl_list = g_list_remove(perl_list, scp);
 		if (scp->shutdowncallback[0])
-			execute_perl(scp->shutdowncallback, "");
+			execute_perl(scp->shutdowncallback, atmp);
 		g_free(scp->name);
 		g_free(scp->version);
 		g_free(scp->shutdowncallback);
@@ -840,33 +871,47 @@
 
 int perl_event(enum gaim_event event, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5)
 {
-	char *buf = NULL;
+	/* changing buf to an array of char pointers so we get @_ back in	
+	 * order; basically scrapping legacy code in favor of blocky		 
+	 * unimaginative code. Additionally, assigned values one at a time 
+	 * for the sake of clarity. --Eric Timme (30 November 2002)	*/ 
+
+	char *buf[5] = { NULL, NULL, NULL, NULL, NULL }; 
+	/* 5 for max 4 arguments =\  Note, if you change the above,
+	 * change the two loops at the bottom that free up memory */
+
 	GList *handler;
 	struct _perl_event_handlers *data;
 	SV *handler_return;
+	int i=0; /* necessary counter variable? --et */
 
 	switch (event) {
 	case event_signon:
 	case event_signoff:
-		buf = g_strdup_printf("'%lu'", (unsigned long)arg1);
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
 		break;
 	case event_away:
-		buf = g_strdup_printf("'%lu','%s'", (unsigned long)arg1,
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%s", 
 				((struct gaim_connection *)arg1)->away ?
 					escape_quotes(((struct gaim_connection *)arg1)->away) : "");
 		break;
 	case event_im_recv:
 		{
 		char *tmp = *(char **)arg2 ? g_strdup(escape_quotes(*(char **)arg2)) : g_malloc0(1);
-		buf = g_strdup_printf("'%lu','%s','%s'", (unsigned long)arg1, tmp,
-			   *(char **)arg3 ? escape_quotes(*(char **)arg3) : "");
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%s", tmp);
+		buf[2] = g_strdup_printf("%s",
+				*(char **)arg3 ? escape_quotes(*(char **)arg3) : "");
 		g_free(tmp);
 		}
 		break;
 	case event_im_send:
 		{
 		char *tmp = arg2 ? g_strdup(escape_quotes(arg2)) : g_malloc0(1);
-		buf = g_strdup_printf("'%lu','%s','%s'", (unsigned long)arg1, tmp,
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%s", tmp);
+		buf[2] = g_strdup_printf("%s", 
 			   *(char **)arg3 ? escape_quotes(*(char **)arg3) : "");
 		g_free(tmp);
 		}
@@ -878,7 +923,8 @@
 	case event_buddy_back:
 	case event_buddy_idle:
 	case event_buddy_unidle:
-		buf = g_strdup_printf("'%lu','%s'", (unsigned long)arg1, escape_quotes(arg2));
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%s", escape_quotes(arg2));
 		break;
 	case event_chat_invited:
 		{
@@ -886,7 +932,10 @@
 		tmp2 = g_strdup(escape_quotes(arg2));
 		tmp3 = g_strdup(escape_quotes(arg3));
 		tmp4 = arg4 ? g_strdup(escape_quotes(arg4)) : g_malloc0(1);
-		buf = g_strdup_printf("'%lu','%s','%s','%s'", (unsigned long)arg1, tmp2, tmp3, tmp4);
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%s", tmp2);
+		buf[2] = g_strdup_printf("%s", tmp3);
+		buf[3] = g_strdup_printf("%s", tmp4);
 		g_free(tmp2);
 		g_free(tmp3);
 		g_free(tmp4);
@@ -895,18 +944,23 @@
 	case event_chat_join:
 	case event_chat_buddy_join:
 	case event_chat_buddy_leave:
-		buf = g_strdup_printf("'%lu','%d','%s'", (unsigned long)arg1, (int)arg2,
-				escape_quotes(arg3));
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%d", (int)arg2);
+		buf[2] = g_strdup_printf("%s", escape_quotes(arg3));
 		break;
 	case event_chat_leave:
-		buf = g_strdup_printf("'%lu','%d'", (unsigned long)arg1, (int)arg2);
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%d", (int)arg2);
 		break;
 	case event_chat_recv:
 		{
 		char *t3, *t4;
 		t3 = g_strdup(escape_quotes(*(char **)arg3));
 		t4 = *(char **)arg4 ? g_strdup(escape_quotes(*(char **)arg4)) : g_malloc0(1);
-		buf = g_strdup_printf("'%lu','%d','%s','%s'", (unsigned long)arg1, (int)arg2, t3, t4);
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%d", (int)arg2);
+		buf[2] = g_strdup_printf("%s", t3);
+		buf[3] = g_strdup_printf("%s", t4);
 		g_free(t3);
 		g_free(t4);
 		}
@@ -916,33 +970,41 @@
 		char *t3, *t4;
 		t3 = g_strdup(escape_quotes(arg3));
 		t4 = *(char **)arg4 ? g_strdup(escape_quotes(*(char **)arg4)) : g_malloc0(1);
-		buf = g_strdup_printf("'%lu','%d','%s','%s'", (unsigned long)arg1, (int)arg2, t3, t4);
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%d", (int)arg2);
+		buf[2] = g_strdup_printf("%s", t3);
+		buf[3] = g_strdup_printf("%s", t4);
 		g_free(t3);
 		g_free(t4);
 		}
 		break;
 	case event_chat_send:
-		buf = g_strdup_printf("'%lu','%d','%s'", (unsigned long)arg1, (int)arg2,
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%d", (int)arg2);
+		buf[2] = g_strdup_printf("%s", 
 				*(char **)arg3 ? escape_quotes(*(char **)arg3) : "");
 		break;
 	case event_warned:
-		buf = g_strdup_printf("'%lu','%s','%d'", (unsigned long)arg1,
-				arg2 ? escape_quotes(arg2) : "", (int)arg3);
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%s", arg2 ? escape_quotes(arg2) : "");
+		buf[2] = g_strdup_printf("%d", (int)arg3);
 		break;
 	case event_quit:
 	case event_blist_update:
-		buf = g_malloc0(1);
+		buf[0] = g_malloc0(1);
 		break;
 	case event_new_conversation:
 	case event_del_conversation:
-		buf = g_strdup_printf("'%s'", escape_quotes(arg1));
+		buf[0] = g_strdup_printf("%s", escape_quotes(arg1));
 		break;
 	case event_im_displayed_sent:
 		{
 		char *tmp2, *tmp3;
 		tmp2 = g_strdup(escape_quotes(arg2));
 		tmp3 = *(char **)arg3 ? g_strdup(escape_quotes(*(char **)arg3)) : g_malloc0(1);
-		buf = g_strdup_printf("'%lu','%s','%s'", (unsigned long)arg1, tmp2, tmp3);
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%s", tmp2);
+		buf[2] = g_strdup_printf("%s", tmp3);
 		g_free(tmp2);
 		g_free(tmp3);
 		}
@@ -952,7 +1014,9 @@
 		char *tmp2, *tmp3;
 		tmp2 = g_strdup(escape_quotes(arg2));
 		tmp3 = arg3 ? g_strdup(escape_quotes(arg3)) : g_malloc0(1);
-		buf = g_strdup_printf("'%lu','%s','%s'", (unsigned long)arg1, tmp2, tmp3);
+		buf[0] = g_strdup_printf("%lu", (unsigned long)arg1);
+		buf[1] = g_strdup_printf("%s", tmp2);
+		buf[2] = g_strdup_printf("%s", tmp3);
 		g_free(tmp2);
 		g_free(tmp3);
 		}
@@ -970,15 +1034,21 @@
 		if (!strcmp(event_name(event), data->event_type)) {
 			handler_return = execute_perl(data->handler_name, buf);
 			if (handler_return) {
-				if (buf)
-					g_free(buf);
+				/* loop to try and free up memory from the 
+				 * char pointer array? --et */
+				for (i=0;i<5;i++)
+					if (buf[i])
+						g_free(buf[i]);
 				return handler_return;
 			}
 		}
 	}
 
-	if (buf)
-		g_free(buf);
+	/* loop to try and free up memory from the 
+	 * char pointer array? --et */
+	for (i=0;i<5;i++)
+		if (buf[i])
+			g_free(buf[i]);
 
 	return 0;
 }
@@ -1041,8 +1111,12 @@
 
 static int perl_timeout(gpointer data)
 {
+	char *atmp[2] = { NULL, NULL }; /* see execute_perl --et */
 	struct _perl_timeout_handlers *handler = data;
-	execute_perl(handler->handler_name, escape_quotes(handler->handler_args));
+
+	atmp[0] = escape_quotes(handler->handler_args);
+	execute_perl(handler->handler_name, atmp);
+
 	perl_timeout_handlers = g_list_remove(perl_timeout_handlers, handler);
 	g_free(handler->handler_args);
 	g_free(handler->handler_name);