/trunk/uspace/app/bdsh/scli.h |
---|
14,7 → 14,5 |
} cliuser_t; |
extern unsigned int cli_set_prompt(cliuser_t *usr); |
extern int cli_init(cliuser_t *usr); |
extern void cli_finit(cliuser_t *usr); |
#endif |
/trunk/uspace/app/bdsh/input.c |
---|
46,7 → 46,7 |
/* More than a macro than anything */ |
void cli_restricted(char *cmd) |
{ |
cli_verbose("%s is not available in %s mode\n", cmd, |
printf("%s is not available in %s mode\n", cmd, |
cli_interactive ? "interactive" : "non-interactive"); |
return; |
/trunk/uspace/app/bdsh/cmds/modules/quit/quit.c |
---|
35,9 → 35,8 |
#include "cmds.h" |
static char *cmdname = "quit"; |
unsigned int cli_quit = 0; |
extern volatile int cli_lasterror; |
extern volatile unsigned int cli_quit; |
extern const char *progname; |
void * help_cmd_quit(unsigned int level) |
/trunk/uspace/app/bdsh/cmds/modules/help/help.c |
---|
40,7 → 40,6 |
static char *cmdname = "help"; |
extern const char *progname; |
extern unsigned int cli_interactive; |
#define HELP_IS_MODULE 1 |
#define HELP_IS_BUILTIN 0 |
126,10 → 125,8 |
} |
} |
printf("%sAvailable commands are:\n", cli_interactive ? "\n " : ""); |
if (cli_interactive) |
printf( |
" ------------------------------------------------------------\n"); |
printf("\n Available commands are:\n"); |
printf(" ------------------------------------------------------------\n"); |
/* First, show a list of built in commands that are available in this mode */ |
for (cmd = builtins; cmd->name != NULL; cmd++, i++) { |
155,11 → 152,8 |
} |
} |
/* Provide a little more information and inform them of history / line |
* editing features if they are present */ |
if (cli_interactive) |
printf("\n Try %s %s for more information on how `%s' works.\n\n", |
cmdname, cmdname, cmdname); |
printf("\n Try %s %s for more information on how `%s' works.\n\n", |
cmdname, cmdname, cmdname); |
return CMD_SUCCESS; |
} |
/trunk/uspace/app/bdsh/cmds/modules/README |
---|
1,8 → 1,15 |
Modules are commands or full programs (anything can be made into a module that can return |
int type) should go here. Note, modules do not update the structures containing user info |
such as the working directory, euid, etc. |
Modules are commands or full programs (anything can be made into a module |
that can return int type) should go here. Note, modules do not (can not) |
update or read cliuser_t. |
Stuff that needs to write to the user structures contained in scli.h should be made as |
built-in commands, not modules. |
Stuff that needs to write to the user structures contained in scli.h should |
be made as built-in commands, not modules, but there are very few times when |
you would want to do that. |
See the README file in the bdsh root directory for a quick overview of how to |
write a new command, or convert an existig stand-alone program into a module |
for BDSH. |
/trunk/uspace/app/bdsh/cmds/builtins/README |
---|
4,13 → 4,18 |
Examples of what should be a built-in and not a module would be: |
cd (the cwd needs to be updated) |
prompt (the prompt needs to be updated) |
enable (the euid needs to be updated) |
cd (cliuser_t->cwd needs to be updated) |
In the future, more user preferences will be set via built-in commands, |
such as the formatting of the prompt string (HelenOS doesn't yet have |
an environment, much less PS*, even if it did we'd likely do it a little |
differently). |
.... etc. |
Anything that does _not_ need to write to this structure should be included |
as a module, not a built in. |
Anything that does _not_ need to use this structure should be included |
as a module, not a built in. If you want to include a new command, there |
is a 99% chance that you want it to be a module. |
For now, a skeleton directory of stuff that will exist lives here. |
/trunk/uspace/app/bdsh/errors.c |
---|
38,18 → 38,19 |
#include "errors.h" |
#include "errstr.h" |
volatile int cli_errno = CL_EOK; |
extern volatile unsigned int cli_quit; |
/* Error printing, translation and handling functions */ |
volatile int cli_lasterr = 0; |
extern volatile unsigned int cli_verbocity; |
/* Look up errno in cl_errors and return the corresponding string. |
* Return NULL if not found */ |
char *err2str(int errno) |
static char *err2str(int err) |
{ |
if (NULL != cl_errors[errno]) |
return cl_errors[errno]; |
if (NULL != cl_errors[err]) |
return cl_errors[err]; |
return (char *)NULL; |
} |
58,7 → 59,7 |
* its corresponding human readable string. If errno > 0, raise the |
* cli_quit int that tells the main program loop to exit immediately */ |
void cli_error(int errno, const char *fmt, ...) |
void cli_error(int err, const char *fmt, ...) |
{ |
va_list vargs; |
va_start(vargs, fmt); |
65,31 → 66,22 |
vprintf(fmt, vargs); |
va_end(vargs); |
if (NULL != err2str(errno)) |
printf(" (%s)\n", err2str(errno)); |
if (NULL != err2str(err)) |
printf(" (%s)\n", err2str(err)); |
else |
printf(" (Unknown Error %d)\n", errno); |
printf(" (Unknown Error %d)\n", err); |
if (errno < 0) |
exit(EXIT_FAILURE); |
/* If fatal, raise cli_quit so that we try to exit |
* gracefully. This will break the main loop and |
* invoke the destructor */ |
if (err == CL_EFATAL) |
cli_quit = 1; |
return; |
} |
/* Just a smart printf(), print the string only if cli_verbocity is high */ |
void cli_verbose(const char *fmt, ...) |
{ |
if (cli_verbocity) { |
va_list vargs; |
printf("[*] "); |
va_start(vargs, fmt); |
vprintf(fmt, vargs); |
va_end(vargs); |
printf("\n"); |
} |
return; |
} |
/trunk/uspace/app/bdsh/util.c |
---|
52,6 → 52,8 |
#include "errors.h" |
#include "util.h" |
extern volatile int cli_errno; |
/* some platforms do not have strdup, implement it here. |
* Returns a pointer to an allocated string or NULL on failure */ |
char * cli_strdup(const char *s1) |
59,9 → 61,12 |
size_t len = strlen(s1) + 1; |
void *ret = malloc(len); |
if (ret == NULL) |
if (ret == NULL) { |
cli_errno = CL_ENOMEM; |
return (char *) NULL; |
} |
cli_errno = CL_EOK; |
return (char *) memcpy(ret, s1, len); |
} |
79,54 → 84,108 |
*s1 = realloc(*s1, len); |
if (*s1 == NULL) |
if (*s1 == NULL) { |
cli_errno = CL_ENOMEM; |
return -1; |
} |
memset(*s1, 0, sizeof(*s1)); |
memcpy(*s1, s2, len); |
cli_errno = CL_EOK; |
return (int) len; |
} |
/* An asprintf() for concantenating paths. Allocates the system PATH_MAX value, |
* expands the formatted string and re-sizes the block s1 points to accordingly. |
/* An asprintf() for formatting paths, similar to asprintf() but ensures |
* the returned allocated string is <= PATH_MAX. On failure, an attempt |
* is made to return the original string (if not null) unmodified. |
* |
* Returns the length of the new s1 on success, -1 on failure. On failure, an |
* attempt is made to return s1 unmodified for sanity, in this case 0 is returned. |
* to indicate that s1 was not modified. |
* Returns: Length of the new string on success, 0 if the string was handed |
* back unmodified, -1 on failure. On failure, cli_errno is set. |
* |
* FIXME: ugly hack to get around asprintf(), if you use this, CHECK ITS VALUE! */ |
* We do not use POSIX_PATH_MAX, as it is typically much smaller than the |
* PATH_MAX defined by the kernel. |
* |
* Use this like: |
* if (1 > cli_psprintf(&char, "%s/%s", foo, bar)) { |
* cli_error(cli_errno, "Failed to format path"); |
* stop_what_your_doing_as_your_out_of_memory(); |
* } |
*/ |
int cli_psprintf(char **s1, const char *fmt, ...) |
{ |
va_list ap; |
size_t needed, base = PATH_MAX + 1; |
int skipped = 0; |
char *orig = NULL; |
char *tmp = (char *) malloc(base); |
if (NULL == tmp) |
/* Don't even touch s1, not enough memory */ |
if (NULL == tmp) { |
cli_errno = CL_ENOMEM; |
return -1; |
} |
char *orig = *s1; |
/* If re-allocating s1, save a copy in case we fail */ |
if (NULL != *s1) |
orig = cli_strdup(*s1); |
/* Print the string to tmp so we can determine the size that |
* we actually need */ |
memset(tmp, 0, sizeof(tmp)); |
va_start(ap, fmt); |
vsnprintf(tmp, base, fmt, ap); |
/* vsnprintf will return the # of bytes not written */ |
skipped = vsnprintf(tmp, base, fmt, ap); |
va_end(ap); |
/* realloc/alloc s1 to be just the size that we need */ |
needed = strlen(tmp) + 1; |
*s1 = realloc(*s1, needed); |
if (NULL == *s1) { |
/* No string lived here previously, or we failed to |
* make a copy of it, either way there's nothing we |
* can do. */ |
if (NULL == *orig) { |
cli_errno = CL_ENOMEM; |
return -1; |
} |
/* We can't even allocate enough size to restore the |
* saved copy, just give up */ |
*s1 = realloc(*s1, strlen(orig) + 1); |
if (NULL == *s1) { |
free(tmp); |
free(orig); |
cli_errno = CL_ENOMEM; |
return -1; |
} |
/* Give the string back as we found it */ |
memset(*s1, 0, sizeof(*s1)); |
memcpy(*s1, orig, strlen(orig) + 1); |
free(tmp); |
free(orig); |
cli_errno = CL_ENOMEM; |
return 0; |
} |
/* Ok, great, we have enough room */ |
memset(*s1, 0, sizeof(*s1)); |
memcpy(*s1, tmp, needed); |
free(tmp); |
/* Free tmp only if s1 was reallocated instead of allocated */ |
if (NULL != orig) |
free(orig); |
if (skipped) { |
/* s1 was bigger than PATH_MAX when expanded, however part |
* of the string was printed. Tell the caller not to use it */ |
cli_errno = CL_ETOOBIG; |
return -1; |
} |
/* Success! */ |
cli_errno = CL_EOK; |
return (int) needed; |
} |
136,8 → 195,10 |
char *spanp, *tok; |
int c, sc; |
if (s == NULL && (s = *last) == NULL) |
if (s == NULL && (s = *last) == NULL) { |
cli_errno = CL_EFAIL; |
return (NULL); |
} |
cont: |
c = *s++; |
/trunk/uspace/app/bdsh/errors.h |
---|
2,7 → 2,7 |
#define ERRORS_H |
/* Various error levels */ |
#define CL_EFATAL -1 |
#define CL_EFATAL -1 |
#define CL_EOK 0 |
#define CL_EFAIL 1 |
#define CL_EBUSY 2 |
12,8 → 12,11 |
#define CL_ENOTSUP 6 |
#define CL_EEXEC 7 |
#define CL_EEXISTS 8 |
#define CL_ETOOBIG 9 |
extern char *err2str(int); |
/* Just like 'errno' */ |
extern volatile int cli_errno; |
extern void cli_error(int, const char *, ...); |
extern void cli_verbose(const char *, ...); |
#endif |
/trunk/uspace/app/bdsh/exec.c |
---|
65,7 → 65,7 |
* cmd as it was presented */ |
char *find_command(char *cmd) |
{ |
char *path_orig, *path_tok; |
char *path_tok; |
char *path[PATH_MAX]; |
int n = 0, i = 0; |
size_t x = strlen(cmd) + 2; |
76,9 → 76,9 |
if (-1 != try_access(cmd)) { |
return (char *) cmd; |
} |
path_orig = PATH; |
path_tok = cli_strdup(path_orig); |
path_tok = cli_strdup(PATH); |
/* Extract the PATH env to a path[] array */ |
path[n] = cli_strtok(path_tok, PATH_DELIM); |
while (NULL != path[n]) { |
/trunk/uspace/app/bdsh/errstr.h |
---|
13,8 → 13,11 |
"Method Not Supported", |
"Bad command or file name", |
"Entry already exists", |
"Object too large", |
NULL |
}; |
static char *err2str(int); |
#endif |
/trunk/uspace/app/bdsh/scli.c |
---|
42,11 → 42,9 |
/* See scli.h */ |
static cliuser_t usr; |
/* Modified by the 'quit' module, which is compiled before this */ |
extern unsigned int cli_quit; |
/* Globals that are modified during start-up that modules/builtins should |
* be aware of. */ |
/* Globals that are modified during start-up that modules/builtins |
* should be aware of. */ |
volatile unsigned int cli_quit = 0; |
volatile unsigned int cli_interactive = 1; |
volatile unsigned int cli_verbocity = 1; |
54,8 → 52,13 |
* (change to your liking in configure.ac and re-run autoconf) */ |
const char *progname = PACKAGE_NAME; |
/* These are not exposed, even to builtins */ |
static int cli_init(cliuser_t *usr); |
static void cli_finit(cliuser_t *usr); |
/* (re)allocates memory to store the current working directory, gets |
* and updates the current working directory, formats the prompt string */ |
* and updates the current working directory, formats the prompt |
* string */ |
unsigned int cli_set_prompt(cliuser_t *usr) |
{ |
usr->prompt = (char *) realloc(usr->prompt, PATH_MAX); |
77,15 → 80,16 |
if (NULL == usr->cwd) |
snprintf(usr->cwd, PATH_MAX, "(unknown)"); |
snprintf(usr->prompt, |
PATH_MAX, |
"%s # ", |
usr->cwd); |
if (1 < cli_psprintf(&usr->prompt, "%s # ", usr->cwd)) { |
cli_error(cli_errno, "Failed to set prompt"); |
return 1; |
} |
return 0; |
} |
int cli_init(cliuser_t *usr) |
/* Constructor */ |
static int cli_init(cliuser_t *usr) |
{ |
usr->line = (char *) NULL; |
usr->name = "root"; |
98,7 → 102,7 |
} |
/* Destructor */ |
void cli_finit(cliuser_t *usr) |
static void cli_finit(cliuser_t *usr) |
{ |
if (NULL != usr->line) |
free(usr->line); |