diff -ruN sash-3.6/Makefile sash-3.6.readline/Makefile --- sash-3.6/Makefile 2003-10-17 14:25:00.306848712 +0200 +++ sash-3.6.readline/Makefile 2003-10-17 14:27:34.529403320 +0200 @@ -19,10 +19,11 @@ -DHAVE_LINUX_ATTR=$(HAVE_LINUX_ATTR) \ -DHAVE_LINUX_MOUNT=$(HAVE_LINUX_MOUNT) \ -DHAVE_BSD_MOUNT=$(HAVE_BSD_MOUNT) \ - -DMOUNT_TYPE=$(MOUNT_TYPE) + -DMOUNT_TYPE=$(MOUNT_TYPE) \ + -DHAVE_READLINE LDFLAGS = --disable-shared -static -s -LIBS = -lz +LIBS = -lz -lreadline -lncurses BINDIR = /bin diff -ruN sash-3.6/sash.c sash-3.6.readline/sash.c --- sash-3.6/sash.c 2002-07-22 00:55:28.000000000 +0200 +++ sash-3.6.readline/sash.c 2003-10-17 14:26:26.184793280 +0200 @@ -384,6 +384,201 @@ static void usage(void); static Alias * findAlias(const char * name); +#ifdef HAVE_READLINE +/*--- Interface of readline 4.0 by vlk@vinf.ru ---*/ + +#include +#include +#include + +char * dupstr (char *s); +void initialize_readline (void); +char ** fileman_completion (char *text, int start, int end); +char *command_generator (char *text, int state); +void err_alloc(int ErrorNumber); +extern char *xmalloc (); + +static char ** listBase; +static long listSize; + +void +err_alloc(int ErrorNumber) +{ + fprintf(stderr, "Memory space failed: %d\n",ErrorNumber); + return; +} + +/* Add a one item to exec-command array */ +static int +listAdd(const char * new_item) +{ + if ((listBase = realloc(listBase, sizeof(char *) * ( listSize + 1 ))) == 0 ) + { + err_alloc(3); exit(1); + } + listBase[listSize] = strdup(new_item); + listSize++; + return(0); +} + +static int +genExecList(void) +{ + char * dirName; + char * path; + char * endPath; + char * fullName; + struct dirent **namelist; + int n; + + if (getenv("PATH") == 0) + return(1); + else + { + if ((path = strdup(getenv("PATH"))) == 0) + { + err_alloc(4); + return(1); + } + } + /* + * Check out each path to see if the program exists and is + * executable in that path. + */ + for ( ; path; path = endPath) + { + /* + * Find the end of the next path and NULL terminate + * it if necessary. + */ + endPath = strchr(path, ':'); + + if (endPath) + *endPath++ = '\0'; + + /* + * Get the directory name, defaulting it to DOT if + * it is null. + */ + dirName = path; + + /* + * See if the program exists and is executable. + */ + if (access(dirName, F_OK) < 0) + { + if (errno != ENOENT) + printf("%s: %s\n", dirName, strerror(errno)); + + continue; + } + n = scandir(dirName, &namelist, 0, alphasort); + if (n < 0) + perror("scandir"); + else + while(n--) + { + if (strncmp(namelist[n]->d_name,".",1) != 0) + { + fullName = malloc(sizeof(dirName) + 1 \ + + sizeof(namelist[n]->d_name)); + strcpy(fullName, dirName); + strcat(fullName, "/"); + strcat(fullName, namelist[n]->d_name); + if (access(fullName,X_OK|F_OK) == 0) + listAdd(namelist[n]->d_name); + } + } + } +return(0); +} + +/******************************************************************/ +/* BEGIN Interface to Readline Completion */ +/******************************************************************/ + +char * dupstr (char *s) +{ + char *r; + + r = xmalloc (strlen (s) + 1); + strcpy (r, s); + return (r); +} + +/* Tell the GNU Readline library how to complete. We want to try to complete + on command names if this is the first word in the line, or on filenames + if not. */ +void initialize_readline (void) +{ + /* Allow conditional parsing of the ~/.inputrc file. */ + rl_readline_name = "readline"; + + /* Tell the completer that we want a crack first. */ + rl_attempted_completion_function = (CPPFunction *)fileman_completion; +} + +/* Attempt to complete on the contents of TEXT. START and END bound the + region of rl_line_buffer that contains the word to complete. TEXT is + the word to complete. We can use the entire contents of rl_line_buffer + in case we want to do some simple parsing. Return the array of matches, + or NULL if there aren't any. */ +char ** fileman_completion (char *text, int start, int end) +{ + char **matches; + + matches = (char **)NULL; + + /* If this word is at the start of the line, then it is a command + to complete. Otherwise it is the name of a file in the current + directory. */ + if (start == 0) // is it the begin of string ? + matches = rl_completion_matches (text, command_generator); + return (matches); +} + +/* Generator function for command completion. STATE lets us know whether + to start from scratch; without any state (i.e. STATE == 0), then we + start at the top of the list. */ +char * command_generator (char *text, int state) +{ + static int list_index, len; + char *ename; + static long exec_count; + + /* If this is a new word to complete, initialize now. This includes + saving the length of TEXT for efficiency, and initializing the index + variable to 0. */ + if (!state) + { + exec_count = 0; + list_index = 0; + len = strlen (text); + } + + /* Return the next name which partially matches from the command list. */ + + while (ename = (char*)commandEntryTable[list_index].name) + { + list_index++; + if (strncmp (ename, text, len) == 0) + return (dupstr(ename)); + } + + while (exec_count < listSize) + { + ename = listBase[exec_count]; + exec_count++; + if (strncmp (ename, text, len) == 0) + return(dupstr(ename)); + } + /* If no names matched, then return NULL. */ + return ((char *)NULL); +} +/******************************************************************/ +/* END Interface to Readline Completion */ +/******************************************************************/ +#endif /* * Global interrupt flag. @@ -405,7 +600,16 @@ commandFile = NULL; quietFlag = FALSE; aliasFlag = FALSE; +#ifdef HAVE_READLINE + /* + * Default our path if it is not set. + */ + if (getenv("PATH") == NULL) + putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin"); + genExecList(); + initialize_readline (); /* Bind our completer. */ +#endif /* * Look for options. */ @@ -554,6 +758,9 @@ static void readFile(const char * name) { +#ifdef HAVE_READLINE + char *input_line = NULL; +#endif FILE * fp; int cc; BOOL ttyFlag; @@ -586,9 +793,10 @@ while (TRUE) { - if (ttyFlag) +#ifndef HAVE_READLINE + if (ttyFlag) showPrompt(); - +#endif if (intFlag && !ttyFlag && (fp != stdin)) { fclose(fp); @@ -805,17 +805,34 @@ return; } - if (fgets(buf, CMD_LEN - 1, fp) == NULL) +#ifdef HAVE_READLINE + if (name != NULL) { - if (ferror(fp) && (errno == EINTR)) +#endif + if (fgets(buf, CMD_LEN - 1, fp) == NULL) { - clearerr(fp); + if (ferror(fp) && (errno == EINTR)) + { + clearerr(fp); + continue; + } - continue; + break; } - - break; +#ifdef HAVE_READLINE } + if (name == NULL) + { + input_line = readline(prompt ? prompt : "$ "); + if (input_line) + { + if (*input_line) + add_history(input_line); + strcpy(buf,input_line); + } + free(input_line); + } +#endif cc = strlen(buf);