Some more stuff.
-Erik
This commit is contained in:
parent
6c41c44898
commit
c7c634bd88
185
cmdedit.c
185
cmdedit.c
@ -1,3 +1,4 @@
|
|||||||
|
/* vi: set sw=4 ts=4: */
|
||||||
/*
|
/*
|
||||||
* Termios command line History and Editting for NetBSD sh (ash)
|
* Termios command line History and Editting for NetBSD sh (ash)
|
||||||
* Copyright (c) 1999
|
* Copyright (c) 1999
|
||||||
@ -40,8 +41,6 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "cmdedit.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define MAX_HISTORY 15 /* Maximum length of the linked list for the command line history */
|
#define MAX_HISTORY 15 /* Maximum length of the linked list for the command line history */
|
||||||
|
|
||||||
@ -95,6 +94,7 @@ int xwrite(int fd, char *buf, int nbytes)
|
|||||||
int xioctl(int fd, unsigned long request, char *arg)
|
int xioctl(int fd, unsigned long request, char *arg)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
|
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -177,20 +177,27 @@ void input_backspace(int outputFd, int *cursor, int *len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char **username_completion_matches( char* matchBuf)
|
char** username_completion_matches(char* command, int *num_matches)
|
||||||
{
|
{
|
||||||
|
char **matches = (char **) NULL;
|
||||||
|
*num_matches=0;
|
||||||
fprintf(stderr, "\nin username_completion_matches\n");
|
fprintf(stderr, "\nin username_completion_matches\n");
|
||||||
return ( (char**) NULL);
|
return (matches);
|
||||||
}
|
}
|
||||||
char **command_completion_matches( char* matchBuf)
|
char** find_path_executable_n_cwd_matches(char* command, int *num_matches)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nin command_completion_matches\n");
|
char **matches = (char **) NULL;
|
||||||
return ( (char**) NULL);
|
matches = malloc(sizeof(char*)*100);
|
||||||
}
|
|
||||||
char **directory_completion_matches( char* matchBuf)
|
matches[0] = malloc(sizeof(char)*50);
|
||||||
{
|
matches[1] = malloc(sizeof(char)*50);
|
||||||
fprintf(stderr, "\nin directory_completion_matches\n");
|
|
||||||
return ( (char**) NULL);
|
sprintf(matches[0], "Hello");
|
||||||
|
sprintf(matches[1], "Howdy");
|
||||||
|
*num_matches=2;
|
||||||
|
|
||||||
|
// fprintf(stderr, "\nin find_path_executable_n_cwd_matches\n");
|
||||||
|
return (matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -211,7 +218,7 @@ char **directory_completion_matches( char* matchBuf)
|
|||||||
* TODO: implement TAB command completion. :)
|
* TODO: implement TAB command completion. :)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
extern int cmdedit_read_input(int inputFd, int outputFd,
|
extern int cmdedit_read_input(char* prompt, int inputFd, int outputFd,
|
||||||
char command[BUFSIZ])
|
char command[BUFSIZ])
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -222,7 +229,6 @@ extern int cmdedit_read_input(int inputFd, int outputFd,
|
|||||||
int break_out = 0;
|
int break_out = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int lastWasTab = FALSE;
|
int lastWasTab = FALSE;
|
||||||
char **matches = (char **)NULL;
|
|
||||||
char c = 0;
|
char c = 0;
|
||||||
struct history *hp = his_end;
|
struct history *hp = his_end;
|
||||||
|
|
||||||
@ -231,6 +237,7 @@ extern int cmdedit_read_input(int inputFd, int outputFd,
|
|||||||
if (!reset_term) {
|
if (!reset_term) {
|
||||||
xioctl(inputFd, TCGETA, (void *) &old_term);
|
xioctl(inputFd, TCGETA, (void *) &old_term);
|
||||||
memcpy(&new_term, &old_term, sizeof(struct termio));
|
memcpy(&new_term, &old_term, sizeof(struct termio));
|
||||||
|
|
||||||
new_term.c_cc[VMIN] = 1;
|
new_term.c_cc[VMIN] = 1;
|
||||||
new_term.c_cc[VTIME] = 0;
|
new_term.c_cc[VTIME] = 0;
|
||||||
new_term.c_lflag &= ~ICANON; /* unbuffered input */
|
new_term.c_lflag &= ~ICANON; /* unbuffered input */
|
||||||
@ -283,7 +290,7 @@ extern int cmdedit_read_input(int inputFd, int outputFd,
|
|||||||
case 14:
|
case 14:
|
||||||
/* Control-n -- Get next command */
|
/* Control-n -- Get next command */
|
||||||
if (hp && hp->n && hp->n->s) {
|
if (hp && hp->n && hp->n->s) {
|
||||||
free( hp->s);
|
free(hp->s);
|
||||||
hp->s = strdup(parsenextc);
|
hp->s = strdup(parsenextc);
|
||||||
hp = hp->n;
|
hp = hp->n;
|
||||||
goto hop;
|
goto hop;
|
||||||
@ -292,7 +299,7 @@ extern int cmdedit_read_input(int inputFd, int outputFd,
|
|||||||
case 16:
|
case 16:
|
||||||
/* Control-p -- Get previous command */
|
/* Control-p -- Get previous command */
|
||||||
if (hp && hp->p) {
|
if (hp && hp->p) {
|
||||||
free( hp->s);
|
free(hp->s);
|
||||||
hp->s = strdup(parsenextc);
|
hp->s = strdup(parsenextc);
|
||||||
hp = hp->p;
|
hp = hp->p;
|
||||||
goto hop;
|
goto hop;
|
||||||
@ -301,87 +308,99 @@ extern int cmdedit_read_input(int inputFd, int outputFd,
|
|||||||
case '\t':
|
case '\t':
|
||||||
{
|
{
|
||||||
/* Do TAB completion */
|
/* Do TAB completion */
|
||||||
int in_command_position=0, ti=len-1;
|
static int num_matches=0;
|
||||||
|
static char **matches = (char **) NULL;
|
||||||
|
int pos = cursor;
|
||||||
|
|
||||||
|
|
||||||
if (lastWasTab == FALSE) {
|
if (lastWasTab == FALSE) {
|
||||||
char *tmp;
|
char *tmp, *tmp1, *matchBuf;
|
||||||
char *matchBuf;
|
|
||||||
|
|
||||||
if (matches) {
|
/* For now, we will not bother with trying to distinguish
|
||||||
free(matches);
|
* whether the cursor is in/at a command extression -- we
|
||||||
matches = (char **)NULL;
|
* will always try all possable matches. If you don't like
|
||||||
}
|
* that, feel free to fix it.
|
||||||
|
*/
|
||||||
matchBuf = (char *) calloc(BUFSIZ, sizeof(char));
|
|
||||||
|
|
||||||
/* Make a local copy of the string -- up
|
/* Make a local copy of the string -- up
|
||||||
* to the the position of the cursor */
|
* to the the position of the cursor */
|
||||||
strcpy( matchBuf, parsenextc);
|
matchBuf = (char *) calloc(BUFSIZ, sizeof(char));
|
||||||
matchBuf[cursor+1] = '\0';
|
strncpy(matchBuf, parsenextc, cursor);
|
||||||
|
tmp=matchBuf;
|
||||||
|
|
||||||
fprintf(stderr, "matchBuf='%s'\n", matchBuf);
|
/* skip past any command seperator tokens */
|
||||||
|
while (*tmp && (tmp1=strpbrk(tmp, ";|&{(`")) != NULL) {
|
||||||
/* skip leading white space */
|
tmp=++tmp1;
|
||||||
tmp = matchBuf;
|
/* skip any leading white space */
|
||||||
while (*tmp && isspace(*tmp)) {
|
while (*tmp && isspace(*tmp))
|
||||||
(tmp)++;
|
++tmp;
|
||||||
ti++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine if this is a command word or not */
|
/* skip any leading white space */
|
||||||
//while ((ti > -1) && (whitespace (matchBuf[ti]))) {
|
while (*tmp && isspace(*tmp))
|
||||||
//printf("\nti=%d\n", ti);
|
++tmp;
|
||||||
// ti--;
|
|
||||||
// }
|
|
||||||
printf("\nti=%d\n", ti);
|
|
||||||
|
|
||||||
if (ti < 0) {
|
/* Free up any memory already allocated */
|
||||||
in_command_position++;
|
if (matches) {
|
||||||
} else if (member(matchBuf[ti], ";|&{(`")) {
|
free(matches);
|
||||||
int this_char, prev_char;
|
matches = (char **) NULL;
|
||||||
in_command_position++;
|
}
|
||||||
/* Handle the two character tokens `>&', `<&', and `>|'.
|
|
||||||
We are not in a command position after one of these. */
|
|
||||||
this_char = matchBuf[ti];
|
|
||||||
prev_char = matchBuf[ti - 1];
|
|
||||||
|
|
||||||
if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
|
|
||||||
(this_char == '|' && prev_char == '>')) {
|
|
||||||
in_command_position = 0;
|
|
||||||
}
|
|
||||||
/* For now, do not bother with catching quoted
|
|
||||||
* expressions and marking them as not in command
|
|
||||||
* positions. Some other day. Or not.
|
|
||||||
*/
|
|
||||||
//else if (char_is_quoted (matchBuf, ti)) {
|
|
||||||
// in_command_position = 0;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
printf("\nin_command_position=%d\n", in_command_position);
|
|
||||||
/* If the word starts in `~', and there is no slash in the word,
|
/* If the word starts in `~', and there is no slash in the word,
|
||||||
* then try completing this word as a username. */
|
* then try completing this word as a username. */
|
||||||
if (*matchBuf == '~' && !strchr (matchBuf, '/'))
|
if (*tmp == '~' && !strchr(tmp, '/'))
|
||||||
matches = username_completion_matches(matchBuf);
|
matches = username_completion_matches(tmp, &num_matches);
|
||||||
|
|
||||||
/* If this word is in a command position, then complete over possible
|
/* Try to match any executable in our patch, and everything
|
||||||
* command names, including aliases, built-ins, and executables. */
|
* in the current working directory that matches.
|
||||||
if (!matches && in_command_position) {
|
*/
|
||||||
matches = command_completion_matches(matchBuf);
|
|
||||||
|
|
||||||
/* If we are attempting command completion and nothing matches,
|
|
||||||
* then try and match directories as a last resort... */
|
|
||||||
if (!matches)
|
if (!matches)
|
||||||
matches = directory_completion_matches(matchBuf);
|
matches = find_path_executable_n_cwd_matches(tmp, &num_matches);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
printf("\nprinting match list\n");
|
if ( matches && num_matches>0 ) {
|
||||||
|
int i, col;
|
||||||
|
|
||||||
|
fprintf(stderr, "\nTabbing...\n");
|
||||||
|
|
||||||
|
/* Make a list of the matches */
|
||||||
|
col += xwrite(outputFd, "\n", 1);
|
||||||
|
for (i=0,col=0; i<num_matches; i++) {
|
||||||
|
col += xwrite(outputFd, prompt, strlen(matches[i]));
|
||||||
|
if (col > 60 && matches[i+1] != NULL) {
|
||||||
|
xwrite(outputFd, "\n", 1);
|
||||||
|
col = 0;
|
||||||
}
|
}
|
||||||
/* Rewrite the whole line (for debugging) */
|
}
|
||||||
for (; cursor > 0; cursor--)
|
xwrite(outputFd, "\n", 1);
|
||||||
xwrite(outputFd, "\b", 1);
|
|
||||||
|
len+=strlen(prompt);
|
||||||
|
fprintf(stderr, "len=%d\n", len);
|
||||||
|
|
||||||
|
/* Move to the beginning of the line */
|
||||||
|
input_home(outputFd, &len);
|
||||||
|
|
||||||
|
/* erase everything */
|
||||||
|
for (j = 0; j < len; j++)
|
||||||
|
xwrite(outputFd, " ", 1);
|
||||||
|
|
||||||
|
/* return to begining of line */
|
||||||
|
input_home(outputFd, &cursor);
|
||||||
|
|
||||||
|
/* Rewrite the prompt) */
|
||||||
|
xwrite(outputFd, prompt, strlen(prompt));
|
||||||
|
|
||||||
|
/* Rewrite the command */
|
||||||
len = strlen(parsenextc);
|
len = strlen(parsenextc);
|
||||||
xwrite(outputFd, parsenextc, len);
|
xwrite(outputFd, parsenextc, len);
|
||||||
cursor = len;
|
|
||||||
|
/* Move back to where the cursor used to be */
|
||||||
|
for (cursor=pos; cursor > 0; cursor--)
|
||||||
|
xwrite(outputFd, "\b", 1);
|
||||||
|
cursor = pos;
|
||||||
|
|
||||||
|
//fprintf(stderr, "\nprompt='%s'\n", prompt);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '\b':
|
case '\b':
|
||||||
@ -395,7 +414,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
xwrite(outputFd, &c, 1);
|
xwrite(outputFd, &c, 1);
|
||||||
break_out = 1;
|
break_out = 1;
|
||||||
break;
|
break;
|
||||||
case ESC: {
|
case ESC:{
|
||||||
/* escape sequence follows */
|
/* escape sequence follows */
|
||||||
if ((ret = read(inputFd, &c, 1)) < 1)
|
if ((ret = read(inputFd, &c, 1)) < 1)
|
||||||
return ret;
|
return ret;
|
||||||
@ -408,7 +427,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
case 'A':
|
case 'A':
|
||||||
/* Up Arrow -- Get previous command */
|
/* Up Arrow -- Get previous command */
|
||||||
if (hp && hp->p) {
|
if (hp && hp->p) {
|
||||||
free( hp->s);
|
free(hp->s);
|
||||||
hp->s = strdup(parsenextc);
|
hp->s = strdup(parsenextc);
|
||||||
hp = hp->p;
|
hp = hp->p;
|
||||||
goto hop;
|
goto hop;
|
||||||
@ -417,7 +436,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
case 'B':
|
case 'B':
|
||||||
/* Down Arrow -- Get next command */
|
/* Down Arrow -- Get next command */
|
||||||
if (hp && hp->n && hp->n->s) {
|
if (hp && hp->n && hp->n->s) {
|
||||||
free( hp->s);
|
free(hp->s);
|
||||||
hp->s = strdup(parsenextc);
|
hp->s = strdup(parsenextc);
|
||||||
hp = hp->n;
|
hp = hp->n;
|
||||||
goto hop;
|
goto hop;
|
||||||
@ -530,7 +549,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
xwrite(outputFd, &c, 1);
|
xwrite(outputFd, &c, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (c=='\t')
|
if (c == '\t')
|
||||||
lastWasTab = TRUE;
|
lastWasTab = TRUE;
|
||||||
else
|
else
|
||||||
lastWasTab = FALSE;
|
lastWasTab = FALSE;
|
||||||
@ -553,6 +572,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
/* No previous history */
|
/* No previous history */
|
||||||
h = his_front = malloc(sizeof(struct history));
|
h = his_front = malloc(sizeof(struct history));
|
||||||
h->n = malloc(sizeof(struct history));
|
h->n = malloc(sizeof(struct history));
|
||||||
|
|
||||||
h->p = NULL;
|
h->p = NULL;
|
||||||
h->s = strdup(parsenextc);
|
h->s = strdup(parsenextc);
|
||||||
h->n->p = h;
|
h->n->p = h;
|
||||||
@ -563,6 +583,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
} else {
|
} else {
|
||||||
/* Add a new history command */
|
/* Add a new history command */
|
||||||
h->n = malloc(sizeof(struct history));
|
h->n = malloc(sizeof(struct history));
|
||||||
|
|
||||||
h->n->p = h;
|
h->n->p = h;
|
||||||
h->n->n = NULL;
|
h->n->n = NULL;
|
||||||
h->n->s = NULL;
|
h->n->s = NULL;
|
||||||
|
@ -12,6 +12,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern int cmdedit_read_input(int inputFd, int outputFd, char command[BUFSIZ]);
|
extern int cmdedit_read_input(char* prompt, int inputFd, int outputFd, char command[BUFSIZ]);
|
||||||
extern void cmdedit_init(void);
|
extern void cmdedit_init(void);
|
||||||
|
|
||||||
|
@ -216,6 +216,12 @@ extern int check_wildcard_match(const char* text, const char* pattern);
|
|||||||
extern long getNum (const char *cp);
|
extern long getNum (const char *cp);
|
||||||
extern pid_t findPidByName( char* pidName);
|
extern pid_t findPidByName( char* pidName);
|
||||||
extern void *xmalloc (size_t size);
|
extern void *xmalloc (size_t size);
|
||||||
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
|
#include <stdio.h>
|
||||||
|
extern int cmdedit_read_input(char* prompt, int inputFd, int outputFd, char command[BUFSIZ]);
|
||||||
|
extern void cmdedit_init(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined BB_INIT || defined BB_SYSLOGD
|
#if defined BB_INIT || defined BB_SYSLOGD
|
||||||
extern int device_open(char *device, int mode);
|
extern int device_open(char *device, int mode);
|
||||||
#endif
|
#endif
|
||||||
|
21
lash.c
21
lash.c
@ -39,10 +39,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
|
||||||
#include "cmdedit.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
|
#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
|
||||||
|
|
||||||
|
|
||||||
@ -123,8 +119,7 @@ static struct builtInCommand bltins[] = {
|
|||||||
{"export", "Set environment variable", "export [VAR=value]", shell_export},
|
{"export", "Set environment variable", "export [VAR=value]", shell_export},
|
||||||
{"unset", "Unset environment variable", "unset VAR", shell_unset},
|
{"unset", "Unset environment variable", "unset VAR", shell_unset},
|
||||||
|
|
||||||
{".", "Source-in and run commands in a file", ". filename",
|
{".", "Source-in and run commands in a file", ". filename", shell_source},
|
||||||
shell_source},
|
|
||||||
{"help", "List shell built-in commands", "help", shell_help},
|
{"help", "List shell built-in commands", "help", shell_help},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
@ -396,11 +391,19 @@ static void checkJobs(struct jobSet *jobList)
|
|||||||
static int getCommand(FILE * source, char *command)
|
static int getCommand(FILE * source, char *command)
|
||||||
{
|
{
|
||||||
if (source == stdin) {
|
if (source == stdin) {
|
||||||
fprintf(stdout, "BBSHELL %s %s", cwd, prompt);
|
|
||||||
fflush(stdout);
|
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
cmdedit_read_input(fileno(stdin), fileno(stdout), command);
|
int len;
|
||||||
|
char *promptStr;
|
||||||
|
len=fprintf(stdout, "BBSHELL %s %s", cwd, prompt);
|
||||||
|
fflush(stdout);
|
||||||
|
promptStr=(char*)malloc(sizeof(char)*(len+1));
|
||||||
|
sprintf(promptStr, "BBSHELL %s %s", cwd, prompt);
|
||||||
|
cmdedit_read_input(promptStr, fileno(stdin), fileno(stdout), command);
|
||||||
|
free( promptStr);
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
fprintf(stdout, "%s %s", cwd, prompt);
|
||||||
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
sh.c
21
sh.c
@ -39,10 +39,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
|
||||||
#include "cmdedit.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
|
#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
|
||||||
|
|
||||||
|
|
||||||
@ -123,8 +119,7 @@ static struct builtInCommand bltins[] = {
|
|||||||
{"export", "Set environment variable", "export [VAR=value]", shell_export},
|
{"export", "Set environment variable", "export [VAR=value]", shell_export},
|
||||||
{"unset", "Unset environment variable", "unset VAR", shell_unset},
|
{"unset", "Unset environment variable", "unset VAR", shell_unset},
|
||||||
|
|
||||||
{".", "Source-in and run commands in a file", ". filename",
|
{".", "Source-in and run commands in a file", ". filename", shell_source},
|
||||||
shell_source},
|
|
||||||
{"help", "List shell built-in commands", "help", shell_help},
|
{"help", "List shell built-in commands", "help", shell_help},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
@ -396,11 +391,19 @@ static void checkJobs(struct jobSet *jobList)
|
|||||||
static int getCommand(FILE * source, char *command)
|
static int getCommand(FILE * source, char *command)
|
||||||
{
|
{
|
||||||
if (source == stdin) {
|
if (source == stdin) {
|
||||||
fprintf(stdout, "BBSHELL %s %s", cwd, prompt);
|
|
||||||
fflush(stdout);
|
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
cmdedit_read_input(fileno(stdin), fileno(stdout), command);
|
int len;
|
||||||
|
char *promptStr;
|
||||||
|
len=fprintf(stdout, "BBSHELL %s %s", cwd, prompt);
|
||||||
|
fflush(stdout);
|
||||||
|
promptStr=(char*)malloc(sizeof(char)*(len+1));
|
||||||
|
sprintf(promptStr, "BBSHELL %s %s", cwd, prompt);
|
||||||
|
cmdedit_read_input(promptStr, fileno(stdin), fileno(stdout), command);
|
||||||
|
free( promptStr);
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
fprintf(stdout, "%s %s", cwd, prompt);
|
||||||
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
185
shell/cmdedit.c
185
shell/cmdedit.c
@ -1,3 +1,4 @@
|
|||||||
|
/* vi: set sw=4 ts=4: */
|
||||||
/*
|
/*
|
||||||
* Termios command line History and Editting for NetBSD sh (ash)
|
* Termios command line History and Editting for NetBSD sh (ash)
|
||||||
* Copyright (c) 1999
|
* Copyright (c) 1999
|
||||||
@ -40,8 +41,6 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "cmdedit.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define MAX_HISTORY 15 /* Maximum length of the linked list for the command line history */
|
#define MAX_HISTORY 15 /* Maximum length of the linked list for the command line history */
|
||||||
|
|
||||||
@ -95,6 +94,7 @@ int xwrite(int fd, char *buf, int nbytes)
|
|||||||
int xioctl(int fd, unsigned long request, char *arg)
|
int xioctl(int fd, unsigned long request, char *arg)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
|
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -177,20 +177,27 @@ void input_backspace(int outputFd, int *cursor, int *len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char **username_completion_matches( char* matchBuf)
|
char** username_completion_matches(char* command, int *num_matches)
|
||||||
{
|
{
|
||||||
|
char **matches = (char **) NULL;
|
||||||
|
*num_matches=0;
|
||||||
fprintf(stderr, "\nin username_completion_matches\n");
|
fprintf(stderr, "\nin username_completion_matches\n");
|
||||||
return ( (char**) NULL);
|
return (matches);
|
||||||
}
|
}
|
||||||
char **command_completion_matches( char* matchBuf)
|
char** find_path_executable_n_cwd_matches(char* command, int *num_matches)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nin command_completion_matches\n");
|
char **matches = (char **) NULL;
|
||||||
return ( (char**) NULL);
|
matches = malloc(sizeof(char*)*100);
|
||||||
}
|
|
||||||
char **directory_completion_matches( char* matchBuf)
|
matches[0] = malloc(sizeof(char)*50);
|
||||||
{
|
matches[1] = malloc(sizeof(char)*50);
|
||||||
fprintf(stderr, "\nin directory_completion_matches\n");
|
|
||||||
return ( (char**) NULL);
|
sprintf(matches[0], "Hello");
|
||||||
|
sprintf(matches[1], "Howdy");
|
||||||
|
*num_matches=2;
|
||||||
|
|
||||||
|
// fprintf(stderr, "\nin find_path_executable_n_cwd_matches\n");
|
||||||
|
return (matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -211,7 +218,7 @@ char **directory_completion_matches( char* matchBuf)
|
|||||||
* TODO: implement TAB command completion. :)
|
* TODO: implement TAB command completion. :)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
extern int cmdedit_read_input(int inputFd, int outputFd,
|
extern int cmdedit_read_input(char* prompt, int inputFd, int outputFd,
|
||||||
char command[BUFSIZ])
|
char command[BUFSIZ])
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -222,7 +229,6 @@ extern int cmdedit_read_input(int inputFd, int outputFd,
|
|||||||
int break_out = 0;
|
int break_out = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int lastWasTab = FALSE;
|
int lastWasTab = FALSE;
|
||||||
char **matches = (char **)NULL;
|
|
||||||
char c = 0;
|
char c = 0;
|
||||||
struct history *hp = his_end;
|
struct history *hp = his_end;
|
||||||
|
|
||||||
@ -231,6 +237,7 @@ extern int cmdedit_read_input(int inputFd, int outputFd,
|
|||||||
if (!reset_term) {
|
if (!reset_term) {
|
||||||
xioctl(inputFd, TCGETA, (void *) &old_term);
|
xioctl(inputFd, TCGETA, (void *) &old_term);
|
||||||
memcpy(&new_term, &old_term, sizeof(struct termio));
|
memcpy(&new_term, &old_term, sizeof(struct termio));
|
||||||
|
|
||||||
new_term.c_cc[VMIN] = 1;
|
new_term.c_cc[VMIN] = 1;
|
||||||
new_term.c_cc[VTIME] = 0;
|
new_term.c_cc[VTIME] = 0;
|
||||||
new_term.c_lflag &= ~ICANON; /* unbuffered input */
|
new_term.c_lflag &= ~ICANON; /* unbuffered input */
|
||||||
@ -283,7 +290,7 @@ extern int cmdedit_read_input(int inputFd, int outputFd,
|
|||||||
case 14:
|
case 14:
|
||||||
/* Control-n -- Get next command */
|
/* Control-n -- Get next command */
|
||||||
if (hp && hp->n && hp->n->s) {
|
if (hp && hp->n && hp->n->s) {
|
||||||
free( hp->s);
|
free(hp->s);
|
||||||
hp->s = strdup(parsenextc);
|
hp->s = strdup(parsenextc);
|
||||||
hp = hp->n;
|
hp = hp->n;
|
||||||
goto hop;
|
goto hop;
|
||||||
@ -292,7 +299,7 @@ extern int cmdedit_read_input(int inputFd, int outputFd,
|
|||||||
case 16:
|
case 16:
|
||||||
/* Control-p -- Get previous command */
|
/* Control-p -- Get previous command */
|
||||||
if (hp && hp->p) {
|
if (hp && hp->p) {
|
||||||
free( hp->s);
|
free(hp->s);
|
||||||
hp->s = strdup(parsenextc);
|
hp->s = strdup(parsenextc);
|
||||||
hp = hp->p;
|
hp = hp->p;
|
||||||
goto hop;
|
goto hop;
|
||||||
@ -301,87 +308,99 @@ extern int cmdedit_read_input(int inputFd, int outputFd,
|
|||||||
case '\t':
|
case '\t':
|
||||||
{
|
{
|
||||||
/* Do TAB completion */
|
/* Do TAB completion */
|
||||||
int in_command_position=0, ti=len-1;
|
static int num_matches=0;
|
||||||
|
static char **matches = (char **) NULL;
|
||||||
|
int pos = cursor;
|
||||||
|
|
||||||
|
|
||||||
if (lastWasTab == FALSE) {
|
if (lastWasTab == FALSE) {
|
||||||
char *tmp;
|
char *tmp, *tmp1, *matchBuf;
|
||||||
char *matchBuf;
|
|
||||||
|
|
||||||
if (matches) {
|
/* For now, we will not bother with trying to distinguish
|
||||||
free(matches);
|
* whether the cursor is in/at a command extression -- we
|
||||||
matches = (char **)NULL;
|
* will always try all possable matches. If you don't like
|
||||||
}
|
* that, feel free to fix it.
|
||||||
|
*/
|
||||||
matchBuf = (char *) calloc(BUFSIZ, sizeof(char));
|
|
||||||
|
|
||||||
/* Make a local copy of the string -- up
|
/* Make a local copy of the string -- up
|
||||||
* to the the position of the cursor */
|
* to the the position of the cursor */
|
||||||
strcpy( matchBuf, parsenextc);
|
matchBuf = (char *) calloc(BUFSIZ, sizeof(char));
|
||||||
matchBuf[cursor+1] = '\0';
|
strncpy(matchBuf, parsenextc, cursor);
|
||||||
|
tmp=matchBuf;
|
||||||
|
|
||||||
fprintf(stderr, "matchBuf='%s'\n", matchBuf);
|
/* skip past any command seperator tokens */
|
||||||
|
while (*tmp && (tmp1=strpbrk(tmp, ";|&{(`")) != NULL) {
|
||||||
/* skip leading white space */
|
tmp=++tmp1;
|
||||||
tmp = matchBuf;
|
/* skip any leading white space */
|
||||||
while (*tmp && isspace(*tmp)) {
|
while (*tmp && isspace(*tmp))
|
||||||
(tmp)++;
|
++tmp;
|
||||||
ti++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine if this is a command word or not */
|
/* skip any leading white space */
|
||||||
//while ((ti > -1) && (whitespace (matchBuf[ti]))) {
|
while (*tmp && isspace(*tmp))
|
||||||
//printf("\nti=%d\n", ti);
|
++tmp;
|
||||||
// ti--;
|
|
||||||
// }
|
|
||||||
printf("\nti=%d\n", ti);
|
|
||||||
|
|
||||||
if (ti < 0) {
|
/* Free up any memory already allocated */
|
||||||
in_command_position++;
|
if (matches) {
|
||||||
} else if (member(matchBuf[ti], ";|&{(`")) {
|
free(matches);
|
||||||
int this_char, prev_char;
|
matches = (char **) NULL;
|
||||||
in_command_position++;
|
}
|
||||||
/* Handle the two character tokens `>&', `<&', and `>|'.
|
|
||||||
We are not in a command position after one of these. */
|
|
||||||
this_char = matchBuf[ti];
|
|
||||||
prev_char = matchBuf[ti - 1];
|
|
||||||
|
|
||||||
if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
|
|
||||||
(this_char == '|' && prev_char == '>')) {
|
|
||||||
in_command_position = 0;
|
|
||||||
}
|
|
||||||
/* For now, do not bother with catching quoted
|
|
||||||
* expressions and marking them as not in command
|
|
||||||
* positions. Some other day. Or not.
|
|
||||||
*/
|
|
||||||
//else if (char_is_quoted (matchBuf, ti)) {
|
|
||||||
// in_command_position = 0;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
printf("\nin_command_position=%d\n", in_command_position);
|
|
||||||
/* If the word starts in `~', and there is no slash in the word,
|
/* If the word starts in `~', and there is no slash in the word,
|
||||||
* then try completing this word as a username. */
|
* then try completing this word as a username. */
|
||||||
if (*matchBuf == '~' && !strchr (matchBuf, '/'))
|
if (*tmp == '~' && !strchr(tmp, '/'))
|
||||||
matches = username_completion_matches(matchBuf);
|
matches = username_completion_matches(tmp, &num_matches);
|
||||||
|
|
||||||
/* If this word is in a command position, then complete over possible
|
/* Try to match any executable in our patch, and everything
|
||||||
* command names, including aliases, built-ins, and executables. */
|
* in the current working directory that matches.
|
||||||
if (!matches && in_command_position) {
|
*/
|
||||||
matches = command_completion_matches(matchBuf);
|
|
||||||
|
|
||||||
/* If we are attempting command completion and nothing matches,
|
|
||||||
* then try and match directories as a last resort... */
|
|
||||||
if (!matches)
|
if (!matches)
|
||||||
matches = directory_completion_matches(matchBuf);
|
matches = find_path_executable_n_cwd_matches(tmp, &num_matches);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
printf("\nprinting match list\n");
|
if ( matches && num_matches>0 ) {
|
||||||
|
int i, col;
|
||||||
|
|
||||||
|
fprintf(stderr, "\nTabbing...\n");
|
||||||
|
|
||||||
|
/* Make a list of the matches */
|
||||||
|
col += xwrite(outputFd, "\n", 1);
|
||||||
|
for (i=0,col=0; i<num_matches; i++) {
|
||||||
|
col += xwrite(outputFd, prompt, strlen(matches[i]));
|
||||||
|
if (col > 60 && matches[i+1] != NULL) {
|
||||||
|
xwrite(outputFd, "\n", 1);
|
||||||
|
col = 0;
|
||||||
}
|
}
|
||||||
/* Rewrite the whole line (for debugging) */
|
}
|
||||||
for (; cursor > 0; cursor--)
|
xwrite(outputFd, "\n", 1);
|
||||||
xwrite(outputFd, "\b", 1);
|
|
||||||
|
len+=strlen(prompt);
|
||||||
|
fprintf(stderr, "len=%d\n", len);
|
||||||
|
|
||||||
|
/* Move to the beginning of the line */
|
||||||
|
input_home(outputFd, &len);
|
||||||
|
|
||||||
|
/* erase everything */
|
||||||
|
for (j = 0; j < len; j++)
|
||||||
|
xwrite(outputFd, " ", 1);
|
||||||
|
|
||||||
|
/* return to begining of line */
|
||||||
|
input_home(outputFd, &cursor);
|
||||||
|
|
||||||
|
/* Rewrite the prompt) */
|
||||||
|
xwrite(outputFd, prompt, strlen(prompt));
|
||||||
|
|
||||||
|
/* Rewrite the command */
|
||||||
len = strlen(parsenextc);
|
len = strlen(parsenextc);
|
||||||
xwrite(outputFd, parsenextc, len);
|
xwrite(outputFd, parsenextc, len);
|
||||||
cursor = len;
|
|
||||||
|
/* Move back to where the cursor used to be */
|
||||||
|
for (cursor=pos; cursor > 0; cursor--)
|
||||||
|
xwrite(outputFd, "\b", 1);
|
||||||
|
cursor = pos;
|
||||||
|
|
||||||
|
//fprintf(stderr, "\nprompt='%s'\n", prompt);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '\b':
|
case '\b':
|
||||||
@ -395,7 +414,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
xwrite(outputFd, &c, 1);
|
xwrite(outputFd, &c, 1);
|
||||||
break_out = 1;
|
break_out = 1;
|
||||||
break;
|
break;
|
||||||
case ESC: {
|
case ESC:{
|
||||||
/* escape sequence follows */
|
/* escape sequence follows */
|
||||||
if ((ret = read(inputFd, &c, 1)) < 1)
|
if ((ret = read(inputFd, &c, 1)) < 1)
|
||||||
return ret;
|
return ret;
|
||||||
@ -408,7 +427,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
case 'A':
|
case 'A':
|
||||||
/* Up Arrow -- Get previous command */
|
/* Up Arrow -- Get previous command */
|
||||||
if (hp && hp->p) {
|
if (hp && hp->p) {
|
||||||
free( hp->s);
|
free(hp->s);
|
||||||
hp->s = strdup(parsenextc);
|
hp->s = strdup(parsenextc);
|
||||||
hp = hp->p;
|
hp = hp->p;
|
||||||
goto hop;
|
goto hop;
|
||||||
@ -417,7 +436,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
case 'B':
|
case 'B':
|
||||||
/* Down Arrow -- Get next command */
|
/* Down Arrow -- Get next command */
|
||||||
if (hp && hp->n && hp->n->s) {
|
if (hp && hp->n && hp->n->s) {
|
||||||
free( hp->s);
|
free(hp->s);
|
||||||
hp->s = strdup(parsenextc);
|
hp->s = strdup(parsenextc);
|
||||||
hp = hp->n;
|
hp = hp->n;
|
||||||
goto hop;
|
goto hop;
|
||||||
@ -530,7 +549,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
xwrite(outputFd, &c, 1);
|
xwrite(outputFd, &c, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (c=='\t')
|
if (c == '\t')
|
||||||
lastWasTab = TRUE;
|
lastWasTab = TRUE;
|
||||||
else
|
else
|
||||||
lastWasTab = FALSE;
|
lastWasTab = FALSE;
|
||||||
@ -553,6 +572,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
/* No previous history */
|
/* No previous history */
|
||||||
h = his_front = malloc(sizeof(struct history));
|
h = his_front = malloc(sizeof(struct history));
|
||||||
h->n = malloc(sizeof(struct history));
|
h->n = malloc(sizeof(struct history));
|
||||||
|
|
||||||
h->p = NULL;
|
h->p = NULL;
|
||||||
h->s = strdup(parsenextc);
|
h->s = strdup(parsenextc);
|
||||||
h->n->p = h;
|
h->n->p = h;
|
||||||
@ -563,6 +583,7 @@ printf("\nin_command_position=%d\n", in_command_position);
|
|||||||
} else {
|
} else {
|
||||||
/* Add a new history command */
|
/* Add a new history command */
|
||||||
h->n = malloc(sizeof(struct history));
|
h->n = malloc(sizeof(struct history));
|
||||||
|
|
||||||
h->n->p = h;
|
h->n->p = h;
|
||||||
h->n->n = NULL;
|
h->n->n = NULL;
|
||||||
h->n->s = NULL;
|
h->n->s = NULL;
|
||||||
|
@ -12,6 +12,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern int cmdedit_read_input(int inputFd, int outputFd, char command[BUFSIZ]);
|
extern int cmdedit_read_input(char* prompt, int inputFd, int outputFd, char command[BUFSIZ]);
|
||||||
extern void cmdedit_init(void);
|
extern void cmdedit_init(void);
|
||||||
|
|
||||||
|
21
shell/lash.c
21
shell/lash.c
@ -39,10 +39,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
|
||||||
#include "cmdedit.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
|
#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
|
||||||
|
|
||||||
|
|
||||||
@ -123,8 +119,7 @@ static struct builtInCommand bltins[] = {
|
|||||||
{"export", "Set environment variable", "export [VAR=value]", shell_export},
|
{"export", "Set environment variable", "export [VAR=value]", shell_export},
|
||||||
{"unset", "Unset environment variable", "unset VAR", shell_unset},
|
{"unset", "Unset environment variable", "unset VAR", shell_unset},
|
||||||
|
|
||||||
{".", "Source-in and run commands in a file", ". filename",
|
{".", "Source-in and run commands in a file", ". filename", shell_source},
|
||||||
shell_source},
|
|
||||||
{"help", "List shell built-in commands", "help", shell_help},
|
{"help", "List shell built-in commands", "help", shell_help},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
@ -396,11 +391,19 @@ static void checkJobs(struct jobSet *jobList)
|
|||||||
static int getCommand(FILE * source, char *command)
|
static int getCommand(FILE * source, char *command)
|
||||||
{
|
{
|
||||||
if (source == stdin) {
|
if (source == stdin) {
|
||||||
fprintf(stdout, "BBSHELL %s %s", cwd, prompt);
|
|
||||||
fflush(stdout);
|
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
cmdedit_read_input(fileno(stdin), fileno(stdout), command);
|
int len;
|
||||||
|
char *promptStr;
|
||||||
|
len=fprintf(stdout, "BBSHELL %s %s", cwd, prompt);
|
||||||
|
fflush(stdout);
|
||||||
|
promptStr=(char*)malloc(sizeof(char)*(len+1));
|
||||||
|
sprintf(promptStr, "BBSHELL %s %s", cwd, prompt);
|
||||||
|
cmdedit_read_input(promptStr, fileno(stdin), fileno(stdout), command);
|
||||||
|
free( promptStr);
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
fprintf(stdout, "%s %s", cwd, prompt);
|
||||||
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user