Browse Source

API to execute C-strings as a CLI commands.

git-svn-id: https://klish.googlecode.com/svn/trunk@189 0eaa4687-2ee9-07dd-09d9-bcdd2d2dd5fb
Serj Kalichev 13 years ago
parent
commit
750d9371c8
5 changed files with 189 additions and 8 deletions
  1. 8 2
      clish/shell.h
  2. 83 2
      clish/shell/shell_spawn.c
  3. 7 4
      clish/shell/shell_tinyrl.c
  4. 84 0
      tinyrl/tinyrl.c
  5. 7 0
      tinyrl/tinyrl.h

+ 8 - 2
clish/shell.h

@@ -302,8 +302,9 @@ clish_shell_execute(clish_shell_t * instance,
 		    const clish_command_t * cmd, clish_pargv_t ** pargv);
 bool_t
 clish_shell_readline(clish_shell_t * shell,
-		     const char *prompt,
-		     const clish_command_t ** cmd, clish_pargv_t ** pargv);
+	const char *prompt,
+	const clish_command_t ** cmd, clish_pargv_t ** pargv,
+	const char * str);
 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);
@@ -334,6 +335,11 @@ FILE *clish_shell__get_ostream(const clish_shell_t * instance);
 /* Context */
 typedef struct clish_context_s clish_context_t;
 
+clish_context_t * clish_context_new(const clish_shell_hooks_t * hooks,
+	void *cookie, FILE * istream, FILE * ostream);
+void clish_context_del(clish_context_t *instance);
+bool_t clish_context_exec(clish_context_t *instance, const char *line);
+
 int clish_shell_wait(clish_context_t * instance);
 clish_context_t *clish_shell_spawn_stream(const pthread_attr_t * attr,
 	const clish_shell_hooks_t * hooks, void *cookie, 

+ 83 - 2
clish/shell/shell_spawn.c

@@ -211,8 +211,8 @@ static void *clish_shell_thread(void *arg)
 
 				/* get input from the user */
 				running =
-				    clish_shell_readline(this, context->prompt,
-							 &cmd, &context->pargv);
+					clish_shell_readline(this, context->prompt,
+						&cmd, &context->pargv, NULL);
 				lub_string_free(context->prompt);
 
 				context->prompt = NULL;
@@ -382,3 +382,84 @@ clish_shell_spawn_from_file(const clish_shell_hooks_t * hooks,
 }
 
 /*-------------------------------------------------------- */
+clish_context_t * clish_context_new(const clish_shell_hooks_t * hooks,
+	void *cookie, FILE * istream, FILE * ostream)
+{
+	bool_t running;
+	clish_context_t *this = malloc(sizeof(clish_context_t));
+	if (!this)
+		return NULL;
+
+	this->hooks = hooks;
+	this->cookie = cookie;
+	this->istream = istream;
+	this->ostream = ostream;
+	this->shell = NULL;
+	this->prompt = NULL;
+	this->pargv = NULL;
+
+	/* Create a shell */
+	this->shell = clish_shell_new(this->hooks, this->cookie,
+		this->istream, this->ostream);
+	/* Load the XML files */
+	clish_shell_load_files(this->shell);
+	/* Execute startup */
+	running = clish_shell_startup(this->shell);
+	if (!running) {
+		clish_context_del(this);
+		return NULL;
+	}
+
+	return this;
+}
+
+/*-------------------------------------------------------- */
+void clish_context_del(clish_context_t *this)
+{
+	if (this->shell) {
+		/* Clean shell */
+		clish_shell_delete(this->shell);
+		this->shell = NULL;
+	}
+	if (this->pargv) {
+		clish_pargv_delete(this->pargv);
+		this->pargv = NULL;
+	}
+	if (this->prompt) {
+		lub_string_free(this->prompt);
+		this->prompt = NULL;
+	}
+
+	free(this);
+}
+
+/*-------------------------------------------------------- */
+bool_t clish_context_exec(clish_context_t *context, const char *line)
+{
+	const clish_command_t *cmd;
+	const clish_view_t *view;
+	bool_t running = BOOL_TRUE;
+	clish_shell_t *this = context->shell;
+
+	/* obtain the prompt */
+	view = clish_shell__get_view(this);
+	assert(view);
+
+	context->prompt = clish_view__get_prompt(view,
+		clish_shell__get_viewid(this));
+	assert(context->prompt);
+
+	/* get input from the user */
+	running = clish_shell_readline(this, context->prompt,
+		&cmd, &context->pargv, line);
+	lub_string_free(context->prompt);
+	context->prompt = NULL;
+
+	if (running && cmd && context->pargv)
+	/* execute the provided command */
+		return clish_shell_execute(this, cmd, &context->pargv);
+
+	return running;
+}
+
+/*-------------------------------------------------------- */

+ 7 - 4
clish/shell/shell_tinyrl.c

@@ -357,11 +357,11 @@ void clish_shell_tinyrl_delete(tinyrl_t * this)
 }
 
 /*-------------------------------------------------------- */
-
 bool_t
 clish_shell_readline(clish_shell_t * this,
-		     const char *prompt,
-		     const clish_command_t ** cmd, clish_pargv_t ** pargv)
+	const char *prompt,
+	const clish_command_t ** cmd, clish_pargv_t ** pargv,
+	const char *str)
 {
 	char *line = NULL;
 	bool_t result = BOOL_FALSE;
@@ -375,7 +375,10 @@ clish_shell_readline(clish_shell_t * this,
 	if (SHELL_STATE_CLOSING != this->state) {
 		this->state = SHELL_STATE_READY;
 
-		line = tinyrl_readline(this->tinyrl, prompt, &context);
+		if (str)
+			line = tinyrl_forceline(this->tinyrl, prompt, &context, str);
+		else
+			line = tinyrl_readline(this->tinyrl, prompt, &context);
 		if (NULL != line) {
 			tinyrl_history_t *history =
 			    tinyrl__get_history(this->tinyrl);

+ 84 - 0
tinyrl/tinyrl.c

@@ -802,6 +802,90 @@ tinyrl_readline(tinyrl_t   *this,
         return result;
     }
 }
+
+/*----------------------------------------------------------------------- */
+char *
+tinyrl_forceline(tinyrl_t   *this,
+                const char *prompt,
+                void       *context,
+                const char *line)
+{
+    char *s = 0, *buffer = NULL;
+    char *p;
+
+    /* initialise for reading a line */
+    this->done             = BOOL_FALSE;
+    this->point            = 0;
+    this->end              = 0;
+    this->buffer           = lub_string_dup("");
+    this->buffer_size      = strlen(this->buffer);
+    this->line             = this->buffer;
+    this->prompt           = prompt;
+    this->prompt_size      = strlen(prompt);
+    this->context          = context;
+
+    /* manually reset the line state without redisplaying */
+    lub_string_free(this->last_buffer);
+    this->last_buffer = NULL;
+
+    buffer = lub_string_dup(line);
+    s = buffer;
+    /* strip any spurious '\r' or '\n' */
+    p = strchr(buffer,'\r');
+    if(NULL == p)
+    {
+        p = strchr(buffer,'\n');
+    }
+    if (NULL != p)
+    {
+        *p = '\0';
+    }
+    /* skip any whitespace at the beginning of the line */
+    if(0 == this->point)
+    {
+        while(*s && isspace(*s))
+        {
+            s++;
+        }
+    }
+    if(*s)
+    {
+        /* append this string to the input buffer */
+        (void) tinyrl_insert_text(this,s);
+        /* echo the command to the output stream */
+        tinyrl_redisplay(this);
+    }
+    lub_string_free(buffer);
+
+    /* call the handler for the newline key */
+    if(BOOL_FALSE == this->handlers[KEY_LF](this,KEY_LF))
+    {
+        /* an issue has occured */
+        this->line = NULL;
+    }
+
+    /*
+     * duplicate the string for return to the client 
+     * we have to duplicate as we may be referencing a
+     * history entry or our internal buffer
+     */
+    {
+        char *result = this->line ? lub_string_dup(this->line) : NULL;
+
+        /* free our internal buffer */
+        free(this->buffer);
+        this->buffer = NULL;
+
+        if((NULL == result) || '\0' == *result)
+        {
+            /* make sure we're not left on a prompt line */
+            tinyrl_crlf(this);
+        }
+        return result;
+    }
+}
+
+
 /*----------------------------------------------------------------------- */
 /*
  * Ensure that buffer has enough space to hold len characters,

+ 7 - 0
tinyrl/tinyrl.h

@@ -138,6 +138,13 @@ extern char *
     tinyrl_readline(tinyrl_t   *instance,
                     const char *prompt,
                     void       *context);
+
+extern char *
+    tinyrl_forceline(tinyrl_t   *instance,
+                     const char *prompt,
+                     void       *context,
+                     const char *line);
+
 extern bool_t
     tinyrl_bind_key(tinyrl_t          *instance,
                     int                key,