Browse Source

History related options

Add history related options to clish binary. The clish can save history.
TODO: Restore history
Serj Kalichev 10 years ago
parent
commit
f5b0e4c29c

+ 38 - 2
bin/clish.c

@@ -26,6 +26,7 @@
 #endif
 
 #include "lub/list.h"
+#include "lub/system.h"
 #include "clish/shell.h"
 #include "clish/internal.h"
 
@@ -72,12 +73,15 @@ int main(int argc, char **argv)
 	bool_t cmd = BOOL_FALSE; /* -c option */
 	lub_list_t *cmds; /* Commands defined by -c */
 	lub_list_node_t *iter;
+	const char *histfile = "~/.clish_history";
+	char *histfile_expanded = NULL;
+	unsigned int histsize = 50;
 
 	/* Signal vars */
 	struct sigaction sigpipe_act;
 	sigset_t sigpipe_set;
 
-	static const char *shortopts = "hvs:ledx:w:i:bqu8okt:c:";
+	static const char *shortopts = "hvs:ledx:w:i:bqu8okt:c:f:z:";
 #ifdef HAVE_GETOPT_H
 	static const struct option longopts[] = {
 		{"help",	0, NULL, 'h'},
@@ -97,6 +101,8 @@ int main(int argc, char **argv)
 		{"check",	0, NULL, 'k'},
 		{"timeout",	1, NULL, 't'},
 		{"command",	1, NULL, 'c'},
+		{"histfile",	1, NULL, 'f'},
+		{"histsize",	1, NULL, 'z'},
 		{NULL,		0, NULL, 0}
 	};
 #endif
@@ -181,6 +187,23 @@ int main(int argc, char **argv)
 				lub_list_add(cmds, str);
 			}
 			break;
+		case 'f':
+			if (!strcmp(optarg, "/dev/null"))
+				histfile = NULL;
+			else
+				histfile = optarg;
+			break;
+		case 'z': {
+				int itmp = 0;
+				itmp = atoi(optarg);
+				if (itmp <= 0) {
+					fprintf(stderr, "Error: Illegal histsize option value.\n");
+					help(-1, argv[0]);
+					goto end;
+				}
+				histsize = itmp;
+			}
+			break;
 		case 'h':
 			help(0, argv[0]);
 			exit(0);
@@ -245,6 +268,12 @@ int main(int argc, char **argv)
 	/* Set idle timeout */
 	if (istimeout)
 		clish_shell__set_timeout(shell, timeout);
+	/* Set history settings */
+	clish_shell__stifle_history(shell, histsize);
+	if (histfile)
+		histfile_expanded = lub_system_tilde_expand(histfile);
+	if (histfile_expanded)
+		clish_shell__restore_history(shell, histfile_expanded);
 
 	/* Set source of command stream: files or interactive tty */
 	if(optind < argc) {
@@ -279,8 +308,13 @@ int main(int argc, char **argv)
 
 end:
 	/* Cleanup */
-	if (shell)
+	if (shell) {
+		if (histfile_expanded) {
+			clish_shell__save_history(shell, histfile_expanded);
+			free(histfile_expanded);
+		}
 		clish_shell_delete(shell);
+	}
 	if (quiet)
 		fclose(outfd);
 
@@ -337,5 +371,7 @@ static void help(int status, const char *argv0)
 		printf("\t-k, --check\tCheck input files for syntax errors only.\n");
 		printf("\t-t <timeout>, --timeout=<timeout>\tIdle timeout in seconds.\n");
 		printf("\t-c <command>, --command=<command>\tExecute specified command(s).\n\t\tMultiple options are possible.\n");
+		printf("\t-f <path>, --histfile=<path>\tFile to save command history.\n");
+		printf("\t-z <num>, --histsize=<num>\tCommand history size in lines.\n");
 	}
 }

+ 3 - 0
clish/shell.h

@@ -349,6 +349,9 @@ int clish_shell_wdog(clish_shell_t *instance);
 void clish_shell__set_wdog_timeout(clish_shell_t *instance,
 	unsigned int timeout);
 unsigned int clish_shell__get_wdog_timeout(const clish_shell_t *instance);
+int clish_shell__save_history(const clish_shell_t *instance, const char *fname);
+int clish_shell__restore_history(const clish_shell_t *instance, const char *fname);
+void clish_shell__stifle_history(clish_shell_t *instance, unsigned int stifle);
 
 _END_C_DECL
 

+ 0 - 85
clish/shell/shell_spawn.c

@@ -9,91 +9,6 @@
 #include <string.h>
 #include <assert.h>
 #include <unistd.h>
-#include <dirent.h>
-
-/*
- * if CLISH_PATH is unset in the environment then this is the value used. 
- */
-const char *default_path = "/etc/clish;~/.clish";
-
-/*-------------------------------------------------------- */
-/* perform a simple tilde substitution for the home directory
- * defined in HOME
- */
-static char *clish_shell_tilde_expand(const char *path)
-{
-	char *home_dir = getenv("HOME");
-	char *result = NULL;
-	char *tilde;
-
-	while ((tilde = strchr(path, '~'))) {
-		lub_string_catn(&result, path, tilde - path);
-		lub_string_cat(&result, home_dir);
-		path = tilde + 1;
-	}
-	lub_string_cat(&result, path);
-
-	return result;
-}
-
-/*-------------------------------------------------------- */
-void clish_shell_load_scheme(clish_shell_t * this, const char *xml_path)
-{
-	const char *path = xml_path;
-	char *buffer;
-	char *dirname;
-	char *saveptr;
-
-	/* use the default path */
-	if (!path)
-		path = default_path;
-	/* take a copy of the path */
-	buffer = clish_shell_tilde_expand(path);
-
-	/* now loop though each directory */
-	for (dirname = strtok_r(buffer, ";", &saveptr);
-		dirname; dirname = strtok_r(NULL, ";", &saveptr)) {
-		DIR *dir;
-		struct dirent *entry;
-
-		/* search this directory for any XML files */
-		dir = opendir(dirname);
-		if (NULL == dir) {
-#ifdef DEBUG
-			tinyrl_printf(this->tinyrl,
-				"*** Failed to open '%s' directory\n",
-				dirname);
-#endif
-			continue;
-		}
-		for (entry = readdir(dir); entry; entry = readdir(dir)) {
-			const char *extension = strrchr(entry->d_name, '.');
-			/* check the filename */
-			if ((NULL != extension) &&
-				(0 == strcmp(".xml", extension))) {
-				char *filename = NULL;
-
-				/* build the filename */
-				lub_string_cat(&filename, dirname);
-				lub_string_cat(&filename, "/");
-				lub_string_cat(&filename, entry->d_name);
-
-				/* load this file */
-				(void)clish_shell_xml_read(this, filename);
-
-				/* release the resource */
-				lub_string_free(filename);
-			}
-		}
-		/* all done for this directory */
-		closedir(dir);
-	}
-	/* tidy up */
-	lub_string_free(buffer);
-#ifdef DEBUG
-	clish_shell_dump(this);
-#endif
-}
 
 /*-------------------------------------------------------- */
 int clish_shell_loop(clish_shell_t *this)

+ 18 - 0
clish/shell/shell_tinyrl.c

@@ -569,4 +569,22 @@ tinyrl_t *clish_shell__get_tinyrl(const clish_shell_t * this)
 	return this->tinyrl;
 }
 
+/*----------------------------------------------------------*/
+int clish_shell__save_history(const clish_shell_t *this, const char *fname)
+{
+	return tinyrl__save_history(this->tinyrl, fname);
+}
+
+/*----------------------------------------------------------*/
+int clish_shell__restore_history(const clish_shell_t *this, const char *fname)
+{
+	return tinyrl__restore_history(this->tinyrl, fname);
+}
+
+/*----------------------------------------------------------*/
+void clish_shell__stifle_history(clish_shell_t *this, unsigned int stifle)
+{
+	tinyrl__stifle_history(this->tinyrl, stifle);
+}
+
 /*-------------------------------------------------------- */

+ 67 - 0
clish/shell/shell_xml.c

@@ -10,10 +10,13 @@
 #include "xmlapi.h"
 #include "lub/string.h"
 #include "lub/ctype.h"
+#include "lub/system.h"
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <dirent.h>
 
 typedef void (PROCESS_FN) (clish_shell_t * instance,
 	clish_xmlnode_t * element, void *parent);
@@ -58,6 +61,70 @@ static clish_xml_cb_t xml_elements[] = {
 	{NULL, NULL}
 };
 
+/*
+ * if CLISH_PATH is unset in the environment then this is the value used. 
+ */
+const char *default_path = "/etc/clish;~/.clish";
+
+/*-------------------------------------------------------- */
+void clish_shell_load_scheme(clish_shell_t *this, const char *xml_path)
+{
+	const char *path = xml_path;
+	char *buffer;
+	char *dirname;
+	char *saveptr;
+
+	/* use the default path */
+	if (!path)
+		path = default_path;
+	/* take a copy of the path */
+	buffer = lub_system_tilde_expand(path);
+
+	/* now loop though each directory */
+	for (dirname = strtok_r(buffer, ";", &saveptr);
+		dirname; dirname = strtok_r(NULL, ";", &saveptr)) {
+		DIR *dir;
+		struct dirent *entry;
+
+		/* search this directory for any XML files */
+		dir = opendir(dirname);
+		if (NULL == dir) {
+#ifdef DEBUG
+			tinyrl_printf(this->tinyrl,
+				"*** Failed to open '%s' directory\n",
+				dirname);
+#endif
+			continue;
+		}
+		for (entry = readdir(dir); entry; entry = readdir(dir)) {
+			const char *extension = strrchr(entry->d_name, '.');
+			/* check the filename */
+			if ((NULL != extension) &&
+				(0 == strcmp(".xml", extension))) {
+				char *filename = NULL;
+
+				/* build the filename */
+				lub_string_cat(&filename, dirname);
+				lub_string_cat(&filename, "/");
+				lub_string_cat(&filename, entry->d_name);
+
+				/* load this file */
+				(void)clish_shell_xml_read(this, filename);
+
+				/* release the resource */
+				lub_string_free(filename);
+			}
+		}
+		/* all done for this directory */
+		closedir(dir);
+	}
+	/* tidy up */
+	lub_string_free(buffer);
+#ifdef DEBUG
+	clish_shell_dump(this);
+#endif
+}
+
 /*
  * ------------------------------------------------------
  * This function reads an element from the XML stream and processes it.

+ 1 - 0
lub/system.h

@@ -14,6 +14,7 @@
 _BEGIN_C_DECL bool_t lub_system_test(int argc, char **argv);
 bool_t lub_system_argv_test(const lub_argv_t * argv);
 bool_t lub_system_line_test(const char *line);
+char *lub_system_tilde_expand(const char *path);
 
 _END_C_DECL
 #endif				/* _lub_system_h */

+ 1 - 0
lub/system/module.am

@@ -1,4 +1,5 @@
 liblub_la_SOURCES +=	lub/system/test.c \
 			lub/system/system_test.c \
+			lub/system/system_file.c \
 			lub/system/private.h
 

+ 29 - 0
lub/system/system_file.c

@@ -0,0 +1,29 @@
+/*
+ * system_file.c
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "private.h"
+#include "lub/string.h"
+
+/*-------------------------------------------------------- */
+/* perform a simple tilde substitution for the home directory
+ * defined in HOME
+ */
+char *lub_system_tilde_expand(const char *path)
+{
+	char *home_dir = getenv("HOME");
+	char *result = NULL;
+	char *tilde;
+
+	while ((tilde = strchr(path, '~'))) {
+		lub_string_catn(&result, path, tilde - path);
+		lub_string_cat(&result, home_dir);
+		path = tilde + 1;
+	}
+	lub_string_cat(&result, path);
+
+	return result;
+}

+ 3 - 0
tinyrl/history.h

@@ -71,6 +71,9 @@ extern void tinyrl_history_stifle(tinyrl_history_t * instance, unsigned stifle);
 extern unsigned tinyrl_history_unstifle(tinyrl_history_t * instance);
 extern bool_t tinyrl_history_is_stifled(const tinyrl_history_t * instance);
 
+extern int tinyrl_history_save(const tinyrl_history_t *instance, const char *fname);
+extern int tinyrl_history_restore(const tinyrl_history_t *instance, const char *fname);
+
     /*
        INFORMATION ABOUT THE HISTORY LIST 
      */

+ 52 - 2
tinyrl/history/history.c

@@ -3,14 +3,14 @@
  * 
  * Simple non-readline hooks for the cli library
  */
+#include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <assert.h>
+#include <errno.h>
 
 #include "private.h"
 #include "lub/string.h"
-#include <stdlib.h>
-
 #include "tinyrl/history.h"
 
 struct _tinyrl_history {
@@ -409,4 +409,54 @@ tinyrl_history_entry_t *tinyrl_history_getprevious(tinyrl_history_iterator_t *
 	return result;
 }
 
+/*-------------------------------------*/
+/* Save command history to specified file */
+int tinyrl_history_save(const tinyrl_history_t *this, const char *fname)
+{
+	tinyrl_history_entry_t *entry;
+	tinyrl_history_iterator_t iter;
+	FILE *f;
+
+	if (!fname) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (!(f = fopen(fname, "w")))
+		return -1;
+	for (entry = tinyrl_history_getfirst(this, &iter);
+		entry; entry = tinyrl_history_getnext(&iter)) {
+		if (fprintf(f, "%s\n", tinyrl_history_entry__get_line(entry)) < 0)
+			return -1;
+	}
+	fclose(f);
+
+	return 0;
+}
+
+/*-------------------------------------*/
+/* Restore command history from specified file */
+int tinyrl_history_restore(const tinyrl_history_t *this, const char *fname)
+{
+/*
+	tinyrl_history_entry_t *entry;
+	tinyrl_history_iterator_t iter;
+	FILE *f;
+
+	if (!fname) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (!(f = fopen(fname, "w")))
+		return -1;
+	for (entry = tinyrl_history_getfirst(this, &iter);
+		entry; entry = tinyrl_history_getnext(&iter)) {
+		if (fprintf(f, "%s\n", tinyrl_history_entry__get_line(entry)) < 0)
+			return -1;
+	}
+	fclose(f);
+*/
+	return 0;
+}
+
+
 /*-------------------------------------*/

+ 17 - 0
tinyrl/tinyrl.c

@@ -1397,4 +1397,21 @@ extern unsigned tinyrl__get_height(const tinyrl_t *this)
 	return tinyrl_vt100__get_height(this->term);
 }
 
+/*----------------------------------------------------------*/
+int tinyrl__save_history(const tinyrl_t *this, const char *fname)
+{
+	return tinyrl_history_save(this->history, fname);
+}
+
+/*----------------------------------------------------------*/
+int tinyrl__restore_history(const tinyrl_t *this, const char *fname)
+{
+	return tinyrl_history_restore(this->history, fname);
+}
+
+/*----------------------------------------------------------*/
+void tinyrl__stifle_history(tinyrl_t *this, unsigned int stifle)
+{
+	tinyrl_history_stifle(this->history, stifle);
+}
 /*--------------------------------------------------------- */

+ 3 - 0
tinyrl/tinyrl.h

@@ -216,6 +216,9 @@ extern void tinyrl_limit_line_length(
 
 extern unsigned tinyrl__get_width(const tinyrl_t *instance);
 extern unsigned tinyrl__get_height(const tinyrl_t *instance);
+extern int tinyrl__save_history(const tinyrl_t *instance, const char *fname);
+extern int tinyrl__restore_history(const tinyrl_t *instance, const char *fname);
+extern void tinyrl__stifle_history(tinyrl_t *instance, unsigned int stifle);
 
 _END_C_DECL
 #endif				/* _tinyrl_tinyrl_h */