Browse Source

Fix issue #15. The default_shebang in STARTUP tag is implemented.

git-svn-id: https://klish.googlecode.com/svn/trunk@275 0eaa4687-2ee9-07dd-09d9-bcdd2d2dd5fb
Serj Kalichev 13 years ago
parent
commit
138b10ba64

+ 3 - 0
clish.xsd

@@ -169,6 +169,8 @@
 *
 * [viewid] - defined the new value of the ${VIEWID} variable to
 *          be used if a transition to a new view occurs.
+*
+* [default_shebang] - The default shebang for all commands.
 ********************************************************
 -->
     <xs:complexType name="startup_t">
@@ -178,6 +180,7 @@
         </xs:sequence>
         <xs:attribute name="view" type="xs:string" use="required"/>
         <xs:attribute name="viewid" type="xs:string" use="optional"/>
+        <xs:attribute name="default_shebang" type="xs:string" use="optional"/>
     </xs:complexType>
     <!--
 *******************************************************

+ 70 - 11
clish/clish_script_callback.c

@@ -6,8 +6,12 @@
  */
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <string.h>
 #include <assert.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 
 #include "private.h"
 
@@ -15,8 +19,17 @@
 bool_t clish_script_callback(const clish_shell_t * this,
 	const clish_command_t * cmd, const char *script)
 {
-	FILE *wpipe;
 	const char * shebang = NULL;
+	int pipefd[2];
+	pid_t cpid;
+	char buf;
+	int res;
+
+	/* Signal vars */
+	struct sigaction sig_old_int;
+	struct sigaction sig_old_quit;
+	struct sigaction sig_new;
+	sigset_t sig_set;
 
 	assert(this);
 	assert(cmd);
@@ -24,19 +37,65 @@ bool_t clish_script_callback(const clish_shell_t * this,
 		return BOOL_TRUE;
 
 	shebang = clish_command__get_shebang(cmd);
+	if (!shebang)
+		shebang = clish_shell__get_default_shebang(this);
+	assert(shebang);
 #ifdef DEBUG
-	if (shebang)
-		fprintf(stderr, "SHEBANG: #!%s\n", shebang);
-	fprintf(stderr, "SYSTEM: %s\n", script);
+	fprintf(stderr, "SHEBANG: #!%s\n", shebang);
+	fprintf(stderr, "SCRIPT: %s\n", script);
 #endif /* DEBUG */
-	if (!shebang)
-		return (0 == system(script)) ? BOOL_TRUE : BOOL_FALSE;
-	/* The shebang is specified */
-	wpipe = popen(shebang, "w");
-	if (!wpipe)
+
+	if (pipe(pipefd) < 0)
+		return BOOL_FALSE;
+
+	/* Ignore SIGINT and SIGQUIT */
+	sigemptyset(&sig_set);
+	sig_new.sa_flags = 0;
+	sig_new.sa_mask = sig_set;
+	sig_new.sa_handler = SIG_IGN;
+	sigaction(SIGINT, &sig_new, &sig_old_int);
+	sigaction(SIGQUIT, &sig_new, &sig_old_quit);
+
+	/* Create process to execute script */
+	cpid = fork();
+	if (cpid == -1) {
+		close(pipefd[0]);
+		close(pipefd[1]);
 		return BOOL_FALSE;
-	fwrite(script, strlen(script) + 1, 1, wpipe);
-	return (0 == pclose(wpipe)) ? BOOL_TRUE : BOOL_FALSE;
+	}
+
+	/* Child */
+	if (cpid == 0) {
+		FILE *wpipe;
+		int retval;
+		close(pipefd[0]); /* Close unused read end */
+		dup2(pipefd[1], STDOUT_FILENO);
+		wpipe = popen(shebang, "w");
+		close(pipefd[1]); /* Close write end */
+		if (!wpipe)
+			_exit(-1);
+		fwrite(script, strlen(script) + 1, 1, wpipe);
+		retval = pclose(wpipe);
+		_exit(WEXITSTATUS(retval));
+	}
+
+	/* Parent */
+
+	/* Read the result of script execution */
+	close(pipefd[1]); /* Close unused write end */
+	while (read(pipefd[0], &buf, 1) > 0)
+		write(fileno(clish_shell__get_ostream(this)), &buf, 1);
+	close(pipefd[0]);
+	waitpid(cpid, &res, 0);
+
+	/* Restore SIGINT and SIGQUIT */
+	sigaction(SIGINT, &sig_old_int, NULL);
+	sigaction(SIGQUIT, &sig_old_quit, NULL);
+
+#ifdef DEBUG
+	fprintf(stderr, "RETCODE: %d\n", WEXITSTATUS(res));
+#endif /* DEBUG */
+	return (0 == res) ? BOOL_TRUE : BOOL_FALSE;
 }
 
 /*--------------------------------------------------------- */

+ 0 - 2
clish/command/command.c

@@ -635,7 +635,5 @@ void clish_command__set_shebang(clish_command_t * this, const char * shebang)
 	assert(NULL == this->shebang);
 	if (lub_string_nocasestr(shebang, prefix) == shebang)
 		prog += strlen(prefix);
-	if (lub_string_nocasecmp(prog, "/bin/sh") == 0) /* the default */
-		return;
 	this->shebang = lub_string_dup(prog);
 }

+ 2 - 0
clish/shell.h

@@ -378,6 +378,8 @@ void clish_shell__set_state(clish_shell_t * instance,
 	clish_shell_state_t state);
 void clish_shell__set_startup_view(clish_shell_t * instance, const char * viewname);
 void clish_shell__set_startup_viewid(clish_shell_t * instance, const char * viewid);
+void clish_shell__set_default_shebang(clish_shell_t * instance, const char * shebang);
+const char * clish_shell__get_default_shebang(const clish_shell_t * instance);
 
 _END_C_DECL
 

+ 1 - 0
clish/shell/private.h

@@ -66,6 +66,7 @@ struct clish_shell_s {
 	char * lockfile;
 	pthread_t pthread;
 	clish_context_t context;
+	char * default_shebang;
 };
 
 /**

+ 1 - 0
clish/shell/shell_delete.c

@@ -61,6 +61,7 @@ static void clish_shell_fini(clish_shell_t * this)
 	clish_param_delete(this->param_pwd);
 
 	lub_string_free(this->lockfile);
+	lub_string_free(this->default_shebang);
 
 	/* Clear the context */
 	if (this->context.completion_pargv) {

+ 1 - 0
clish/shell/shell_new.c

@@ -45,6 +45,7 @@ clish_shell_init(clish_shell_t * this,
 	this->cfg_pwdc = 0;
 	this->client = NULL;
 	this->lockfile = lub_string_dup(CLISH_LOCK_PATH);
+	this->default_shebang = lub_string_dup("/bin/sh");
 
 	/* Create internal ptypes and params */
 	/* Current depth */

+ 17 - 0
clish/shell/shell_startup.c

@@ -4,6 +4,8 @@
 #include "private.h"
 #include <assert.h>
 
+#include "lub/string.h"
+
 /*----------------------------------------------------------- */
 bool_t clish_shell_startup(clish_shell_t * this)
 {
@@ -40,3 +42,18 @@ void clish_shell__set_startup_viewid(clish_shell_t * this, const char * viewid)
 }
 
 /*----------------------------------------------------------- */
+void clish_shell__set_default_shebang(clish_shell_t * this, const char * shebang)
+{
+	assert(this);
+	lub_string_free(this->default_shebang);
+	this->default_shebang = lub_string_dup(shebang);
+}
+
+/*----------------------------------------------------------- */
+const char * clish_shell__get_default_shebang(const clish_shell_t * this)
+{
+	assert(this);
+	return this->default_shebang;
+}
+
+/*----------------------------------------------------------- */

+ 6 - 1
clish/shell/shell_tinyxml_read.cpp

@@ -273,6 +273,7 @@ process_startup(clish_shell_t * shell, TiXmlElement * element, void *parent)
 	clish_command_t *cmd = NULL;
 	const char *view = element->Attribute("view");
 	const char *viewid = element->Attribute("viewid");
+	const char *default_shebang = element->Attribute("default_shebang");
 
 	assert(NULL == shell->startup);
 	assert(view);
@@ -290,7 +291,11 @@ process_startup(clish_shell_t * shell, TiXmlElement * element, void *parent)
 	if (NULL != viewid) {
 		clish_command__set_viewid(cmd, viewid);
 	}
-	// remember this command 
+
+	if (NULL != default_shebang)
+		clish_shell__set_default_shebang(shell, default_shebang);
+
+	// remember this command
 	shell->startup = cmd;
 
 	process_children(shell, element, cmd);