浏览代码

Fix file stack to get commands from. The shell can be inited without instream.

git-svn-id: https://klish.googlecode.com/svn/trunk@254 0eaa4687-2ee9-07dd-09d9-bcdd2d2dd5fb
Serj Kalichev 14 年之前
父节点
当前提交
a941ca386a

+ 8 - 6
bin/clish.cpp

@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <getopt.h>
+#include <unistd.h>
 
 #include "clish/shell.h"
 #include "clish/internal.h"
@@ -40,6 +41,7 @@ int main(int argc, char **argv)
 	/* Command line options */
 	const char *socket_path = KONFD_SOCKET_PATH;
 	bool_t lockless = BOOL_FALSE;
+	bool_t stop_on_error = BOOL_FALSE;
 
 	static const char *shortopts = "hvs:l";
 /*	static const struct option longopts[] = {
@@ -80,7 +82,7 @@ int main(int argc, char **argv)
 		}
 	}
 
-	shell = clish_shell_new(&my_hooks, NULL, stdin, stdout);
+	shell = clish_shell_new(&my_hooks, NULL, NULL, stdout, stop_on_error);
 	if (!shell) {
 		fprintf(stderr, "Cannot run clish.\n");
 		return -1;
@@ -102,14 +104,14 @@ int main(int argc, char **argv)
 
 	if(optind < argc) {
 		int i;
-		for (i = optind; i < argc; i++) {
-			/* Run the commands from the file */
-			result = clish_shell_from_file(shell, argv[i]);
-		}
+		/* Run the commands from the files */
+		for (i = argc - 1; i >= optind; i--)
+			clish_shell_push_file(shell, argv[i], stop_on_error);
 	} else {
 		/* The interactive shell */
-		result = clish_shell_loop(shell);
+		clish_shell_push_fd(shell, fdopen(dup(fileno(stdin)), "r"), stop_on_error);
 	}
+	result = clish_shell_loop(shell);
 
 	/* Cleanup */
 	clish_shell_delete(shell);

+ 32 - 6
clish/shell.h

@@ -30,7 +30,15 @@
 typedef struct clish_context_s clish_context_t;
 typedef struct clish_shell_s clish_shell_t;
 
-_BEGIN_C_DECL 
+typedef enum {
+	SHELL_STATE_INITIALISING,
+	SHELL_STATE_READY,
+	SHELL_STATE_HELPING,
+	SHELL_STATE_SCRIPT_ERROR,
+	SHELL_STATE_CLOSING
+} clish_shell_state_t;
+
+_BEGIN_C_DECL
 
 /*=====================================
  * SHELL INTERFACE
@@ -282,7 +290,10 @@ bool_t clish_shell_spawn(
 #endif
 
 clish_shell_t *clish_shell_new(const clish_shell_hooks_t * hooks,
-	void *cookie, FILE * istream, FILE * ostream);
+	void *cookie,
+	FILE * istream,
+	FILE * ostream,
+	bool_t stop_on_error);
 /*-----------------
  * methods
  *----------------- */
@@ -311,8 +322,22 @@ bool_t clish_shell_readline(clish_shell_t *instance);
 void clish_shell_set_context(clish_shell_t * instance, const char *viewname);
 void clish_shell_dump(clish_shell_t * instance);
 void clish_shell_close(clish_shell_t * instance);
+/** 
+ * Push the specified file handle on to the stack of file handles
+ * for this shell. The specified file will become the source of 
+ * commands, until it is exhausted.
+ *
+ * \return
+ * BOOL_TRUE - the file was successfully associated with the shell.
+ * BOOL_FALSE - there was insufficient resource to associate this file.
+ */
+bool_t clish_shell_push_file(clish_shell_t * instance, const char * fname,
+	bool_t stop_on_error);
+bool_t clish_shell_push_fd(clish_shell_t * instance, FILE * file,
+	bool_t stop_on_error);
+
 /*-----------------
- * attributes 
+ * attributes
  *----------------- */
 const clish_view_t *clish_shell__get_view(const clish_shell_t * instance);
 unsigned clish_shell__get_depth(const clish_shell_t * instance);
@@ -342,12 +367,13 @@ int clish_shell_spawn(clish_shell_t * instance,
 int clish_shell_wait(clish_shell_t * instance);
 int clish_shell_spawn_and_wait(clish_shell_t * instance,
 	const pthread_attr_t * attr);
-bool_t clish_shell_spawn_from_file(clish_shell_t * instance,
-	const pthread_attr_t * attr, const char *filename);
-bool_t clish_shell_from_file(clish_shell_t * instance, const char *filename);
 void clish_shell_load_files(clish_shell_t * instance);
 bool_t clish_shell_loop(clish_shell_t * instance);
+clish_shell_state_t clish_shell__get_state(const clish_shell_t * instance);
+void clish_shell__set_state(clish_shell_t * instance,
+	clish_shell_state_t state);
 
 _END_C_DECL
+
 #endif				/* _clish_shell_h */
 /** @} clish_shell */

+ 1 - 21
clish/shell/private.h

@@ -13,14 +13,6 @@
 
 /*-------------------------------------------------------- */
 
-typedef enum {
-	SHELL_STATE_INITIALISING,
-	SHELL_STATE_READY,
-	SHELL_STATE_HELPING,
-	SHELL_STATE_SCRIPT_ERROR,
-	SHELL_STATE_CLOSING
-} shell_state_t;
-
 /*
  * iterate around commands
  */
@@ -61,7 +53,7 @@ struct clish_shell_s {
 	clish_view_t *global;	/* Reference to the global view. */
 	clish_view_t *view;	/* Reference to the current view. */
 	clish_command_t *startup;	/* This is the startup command   */
-	shell_state_t state;	/* The current state               */
+	clish_shell_state_t state;	/* The current state               */
 	char *overview;		/* Overview text for this shell.  */
 	char *viewid;		/* The current view ID string     */
 	tinyrl_t *tinyrl;	/* Tiny readline instance          */
@@ -88,18 +80,6 @@ clish_shell_iterator_init(clish_shell_iterator_t * iter,
  */
 const clish_command_t *clish_shell_find_next_completion(const clish_shell_t *
 	instance, const char *line, clish_shell_iterator_t * iter);
-/** 
- * Push the specified file handle on to the stack of file handles
- * for this shell. The specified file will become the source of 
- * commands, until it is exhausted.
- *
- * \return
- * BOOL_TRUE - the file was successfully associated with the shell.
- * BOOL_FALSE - there was insufficient resource to associate this file.
- */
-bool_t
-clish_shell_push_file(clish_shell_t * instance,
-		      FILE * file, bool_t stop_on_error);
 /** 
  * Pop the current file handle from the stack of file handles, shutting
  * the file down and freeing any associated memory. The next file handle

+ 9 - 20
clish/shell/shell_execute.c

@@ -71,26 +71,15 @@ clish_source_internal(const clish_shell_t * shell,
 	/*
 	 * Check file specified is not a directory 
 	 */
-	if (0 == stat((char *)filename, &fileStat)) {
-		if (!S_ISDIR(fileStat.st_mode)) {
-			file = fopen(filename, "r");
-			if (NULL != file) {
-
-				/* 
-				 * push this file onto the file stack associated with this
-				 * session. This will be closed by clish_shell_pop_file() 
-				 * when it is finished with. 
-				 */
-				result =
-				    clish_shell_push_file((clish_shell_t *)
-							  this, file,
-							  stop_on_error);
-				if (BOOL_FALSE == result) {
-					/* close the file here */
-					fclose(file);
-				}
-			}
-		}
+	if ((0 == stat((char *)filename, &fileStat)) &&
+		(!S_ISDIR(fileStat.st_mode))) {
+		/* 
+		 * push this file onto the file stack associated with this
+		 * session. This will be closed by clish_shell_pop_file() 
+		 * when it is finished with.
+		 */
+		result = clish_shell_push_file(this, filename,
+			stop_on_error);
 	}
 	return result;
 }

+ 18 - 9
clish/shell/shell_new.c

@@ -11,20 +11,22 @@
 /*-------------------------------------------------------- */
 static void
 clish_shell_init(clish_shell_t * this,
-		 const clish_shell_hooks_t * hooks,
-		 void *cookie, FILE * istream, FILE * ostream)
+	const clish_shell_hooks_t * hooks,
+	void *cookie, FILE * istream,
+	FILE * ostream,
+	bool_t stop_on_error)
 {
 	clish_ptype_t *tmp_ptype = NULL;
 
 	/* initialise the tree of views */
 	lub_bintree_init(&this->view_tree,
-			 clish_view_bt_offset(),
-			 clish_view_bt_compare, clish_view_bt_getkey);
+		clish_view_bt_offset(),
+		clish_view_bt_compare, clish_view_bt_getkey);
 
 	/* initialise the tree of ptypes */
 	lub_bintree_init(&this->ptype_tree,
-			 clish_ptype_bt_offset(),
-			 clish_ptype_bt_compare, clish_ptype_bt_getkey);
+		clish_ptype_bt_offset(),
+		clish_ptype_bt_compare, clish_ptype_bt_getkey);
 
 	assert((NULL != hooks) && (NULL != hooks->script_fn));
 
@@ -65,17 +67,24 @@ clish_shell_init(clish_shell_t * this,
 	/* Initialize context */
 	this->context.completion_pargv = NULL;
 	clish_shell_iterator_init(&this->context.iter, CLISH_NSPACE_NONE);
+
+	/* Push non-NULL istream */
+	if (istream)
+		clish_shell_push_fd(this, istream, stop_on_error);
 }
 
 /*-------------------------------------------------------- */
 clish_shell_t *clish_shell_new(const clish_shell_hooks_t * hooks,
-		void *cookie, FILE * istream, FILE * ostream)
+		void *cookie,
+		FILE * istream,
+		FILE * ostream,
+		bool_t stop_on_error)
 {
 	clish_shell_t *this = malloc(sizeof(clish_shell_t));
 
 	if (this) {
-		clish_shell_init(this, hooks, cookie, 
-			istream, ostream);
+		clish_shell_init(this, hooks, cookie,
+			istream, ostream, stop_on_error);
 
 		if (hooks->init_fn) {
 			/* now call the client initialisation */

+ 16 - 0
clish/shell/shell_parse.c

@@ -5,6 +5,8 @@
 #include "lub/string.h"
 
 #include <string.h>
+#include <assert.h>
+
 /*----------------------------------------------------------- */
 clish_pargv_status_t clish_shell_parse(
 	const clish_shell_t * this, const char *line,
@@ -33,3 +35,17 @@ clish_pargv_status_t clish_shell_parse(
 }
 
 /*----------------------------------------------------------- */
+clish_shell_state_t clish_shell__get_state(const clish_shell_t * this)
+{
+	return this->state;
+}
+
+/*----------------------------------------------------------- */
+void clish_shell__set_state(clish_shell_t * this,
+	clish_shell_state_t state)
+{
+	assert(this);
+	this->state = state;
+}
+
+/*----------------------------------------------------------- */

+ 23 - 1
clish/shell/shell_push_file.c

@@ -1,10 +1,32 @@
 #include <stdlib.h>
+#include <assert.h>
 
 #include "private.h"
 
 bool_t
-clish_shell_push_file(clish_shell_t * this, FILE * file, bool_t stop_on_error)
+clish_shell_push_file(clish_shell_t * this, const char * fname, bool_t stop_on_error)
 {
+	FILE *file;
+	bool_t res;
+
+	assert(this);
+	if (!fname)
+		return BOOL_FALSE;
+	file = fopen(fname, "r");
+	if (!file)
+		return BOOL_FALSE;
+	res = clish_shell_push_fd(this, file, stop_on_error);
+	if (!res)
+		fclose(file);
+
+	return res;
+}
+
+bool_t
+clish_shell_push_fd(clish_shell_t * this, FILE * file, bool_t stop_on_error)
+{
+	assert(this);
+
 	/* allocate a control node */
 	clish_shell_file_t *node = malloc(sizeof(clish_shell_file_t));
 	bool_t result = BOOL_TRUE;

+ 4 - 47
clish/shell/shell_spawn.c

@@ -115,14 +115,14 @@ void clish_shell_load_files(clish_shell_t * this)
 static bool_t _loop(clish_shell_t * this, bool_t is_thread)
 {
 	bool_t running = BOOL_TRUE;
+
+	assert(this);
+	if (!tinyrl__get_istream(this->tinyrl))
+		return BOOL_FALSE;
 	/*
 	 * Check the shell isn't closing down
 	 */
 	if (this && (SHELL_STATE_CLOSING != this->state)) {
-		/* start off with the default inputs stream */
-		(void)clish_shell_push_file(this,
-			fdopen(fileno(tinyrl__get_istream(this->tinyrl)),"r"), BOOL_TRUE);
-
 		if (is_thread)
 			pthread_testcancel();
 
@@ -229,49 +229,6 @@ int clish_shell_spawn_and_wait(clish_shell_t * this,
 	return clish_shell_wait(this);
 }
 
-
-/*-------------------------------------------------------- */
-static bool_t _from_file(clish_shell_t * this,
-	bool_t is_thread, const pthread_attr_t * attr,
-	const char *filename)
-{
-	bool_t result = BOOL_FALSE;
-	FILE *file;
-
-	if (!this || !filename)
-		return result;
-
-	file = fopen(filename, "r");
-	if (NULL == file)
-		return result;
-	tinyrl__set_istream(this->tinyrl, file);
-	if (is_thread) {
-		/* spawn the thread and wait for it to exit */
-		result = clish_shell_spawn_and_wait(this, attr) ?
-			BOOL_TRUE : BOOL_FALSE;
-	} else {
-		/* Don't use thread */
-		result = clish_shell_loop(this);
-	}
-	fclose(file);
-
-	return result;
-}
-
-/*-------------------------------------------------------- */
-bool_t clish_shell_spawn_from_file(clish_shell_t * this,
-	const pthread_attr_t * attr, const char *filename)
-{
-	return _from_file(this, BOOL_TRUE, attr, filename);
-}
-
-/*-------------------------------------------------------- */
-bool_t clish_shell_from_file(clish_shell_t * this,
-	const char *filename)
-{
-	return _from_file(this, BOOL_FALSE, NULL, filename);
-}
-
 /*-------------------------------------------------------- */
 bool_t clish_shell_loop(clish_shell_t * this)
 {

+ 5 - 3
clish/shell/shell_tinyrl.c

@@ -406,7 +406,8 @@ bool_t clish_shell_execline(clish_shell_t *this, const char *line)
 	const clish_view_t *view;
 	bool_t running = BOOL_TRUE;
 
-	if (!this)
+	assert(this);
+	if (!line && !tinyrl__get_istream(this->tinyrl))
 		return BOOL_FALSE;
 
 	/* obtain the prompt */
@@ -430,8 +431,9 @@ bool_t clish_shell_execline(clish_shell_t *this, const char *line)
 	/* execute the provided command */
 	if (running && cmd && pargv) {
 		if (BOOL_FALSE == clish_shell_execute(this, cmd, pargv)) {
-			if((BOOL_TRUE == this->current_file->stop_on_error) &&
-				(BOOL_FALSE == tinyrl__get_isatty(this->tinyrl))) {
+			if((!this->current_file && line) ||
+				(this->current_file &&
+				this->current_file->stop_on_error)) {
 				this->state = SHELL_STATE_SCRIPT_ERROR;
 			}
 		}

+ 4 - 1
tinyrl/tinyrl.c

@@ -439,7 +439,10 @@ tinyrl_init(tinyrl_t                 *this,
     this->kill_string                   = NULL;
     this->echo_char                     = '\0';
     this->echo_enabled                  = BOOL_TRUE;
-    this->isatty                        = isatty(fileno(instream)) ? BOOL_TRUE : BOOL_FALSE;
+    if (instream)
+        this->isatty = isatty(fileno(instream)) ? BOOL_TRUE : BOOL_FALSE;
+    else
+        this->isatty = BOOL_FALSE;
     this->last_buffer                   = NULL;
     this->last_point                    = 0;