Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3366 → Rev 3364

/trunk/uspace/app/bdsh/cmds/modules/help/help.c
40,6 → 40,7
 
static char *cmdname = "help";
extern const char *progname;
extern unsigned int cli_interactive;
 
#define HELP_IS_MODULE 1
#define HELP_IS_BUILTIN 0
125,8 → 126,10
}
}
 
printf("\n Available commands are:\n");
printf(" ------------------------------------------------------------\n");
printf("%sAvailable commands are:\n", cli_interactive ? "\n " : "");
if (cli_interactive)
printf(
" ------------------------------------------------------------\n");
 
/* First, show a list of built in commands that are available in this mode */
for (cmd = builtins; cmd->name != NULL; cmd++, i++) {
152,8 → 155,11
}
}
 
printf("\n Try %s %s for more information on how `%s' works.\n\n",
cmdname, cmdname, cmdname);
/* 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);
 
return CMD_SUCCESS;
}
/trunk/uspace/app/bdsh/cmds/modules/quit/quit.c
35,8 → 35,9
#include "cmds.h"
 
static char *cmdname = "quit";
unsigned int cli_quit = 0;
 
extern volatile unsigned int cli_quit;
extern volatile int cli_lasterror;
extern const char *progname;
 
void * help_cmd_quit(unsigned int level)
/trunk/uspace/app/bdsh/cmds/modules/README
1,15 → 1,8
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.
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.
 
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.
Stuff that needs to write to the user structures contained in scli.h should be made as
built-in commands, not modules.
 
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,18 → 4,13
 
Examples of what should be a built-in and not a module would be:
 
cd (cliuser_t->cwd needs to be updated)
cd (the cwd needs to be updated)
prompt (the prompt needs to be updated)
enable (the euid 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 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.
Anything that does _not_ need to write to this structure should be included
as a module, not a built in.
 
 
 
For now, a skeleton directory of stuff that will exist lives here.
/trunk/uspace/app/bdsh/util.c
52,8 → 52,6
#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)
61,12 → 59,9
size_t len = strlen(s1) + 1;
void *ret = malloc(len);
 
if (ret == NULL) {
cli_errno = CL_ENOMEM;
if (ret == NULL)
return (char *) NULL;
}
 
cli_errno = CL_EOK;
return (char *) memcpy(ret, s1, len);
}
 
84,108 → 79,54
 
*s1 = realloc(*s1, len);
 
if (*s1 == NULL) {
cli_errno = CL_ENOMEM;
if (*s1 == NULL)
return -1;
}
 
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, s2, len);
cli_errno = CL_EOK;
return (int) len;
}
 
/* 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.
/* An asprintf() for concantenating paths. Allocates the system PATH_MAX value,
* expands the formatted string and re-sizes the block s1 points to accordingly.
*
* 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.
* 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.
*
* 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();
* }
*/
 
* FIXME: ugly hack to get around asprintf(), if you use this, CHECK ITS VALUE! */
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);
 
/* Don't even touch s1, not enough memory */
if (NULL == tmp) {
cli_errno = CL_ENOMEM;
if (NULL == tmp)
return -1;
}
 
/* If re-allocating s1, save a copy in case we fail */
if (NULL != *s1)
orig = cli_strdup(*s1);
char *orig = *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 will return the # of bytes not written */
skipped = vsnprintf(tmp, base, fmt, ap);
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;
}
195,10 → 136,8
char *spanp, *tok;
int c, sc;
 
if (s == NULL && (s = *last) == NULL) {
cli_errno = CL_EFAIL;
if (s == NULL && (s = *last) == NULL)
return (NULL);
}
 
cont:
c = *s++;
/trunk/uspace/app/bdsh/scli.h
14,5 → 14,7
} 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/scli.c
42,9 → 42,11
/* See scli.h */
static cliuser_t usr;
 
/* Globals that are modified during start-up that modules/builtins
* should be aware of. */
volatile unsigned int cli_quit = 0;
/* 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. */
volatile unsigned int cli_interactive = 1;
volatile unsigned int cli_verbocity = 1;
 
52,13 → 54,8
* (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);
80,16 → 77,15
if (NULL == usr->cwd)
snprintf(usr->cwd, PATH_MAX, "(unknown)");
 
if (1 < cli_psprintf(&usr->prompt, "%s # ", usr->cwd)) {
cli_error(cli_errno, "Failed to set prompt");
return 1;
}
snprintf(usr->prompt,
PATH_MAX,
"%s # ",
usr->cwd);
 
return 0;
}
 
/* Constructor */
static int cli_init(cliuser_t *usr)
int cli_init(cliuser_t *usr)
{
usr->line = (char *) NULL;
usr->name = "root";
102,7 → 98,7
}
 
/* Destructor */
static void cli_finit(cliuser_t *usr)
void cli_finit(cliuser_t *usr)
{
if (NULL != usr->line)
free(usr->line);
/trunk/uspace/app/bdsh/exec.c
65,7 → 65,7
* cmd as it was presented */
char *find_command(char *cmd)
{
char *path_tok;
char *path_orig, *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/input.c
46,7 → 46,7
/* More than a macro than anything */
void cli_restricted(char *cmd)
{
printf("%s is not available in %s mode\n", cmd,
cli_verbose("%s is not available in %s mode\n", cmd,
cli_interactive ? "interactive" : "non-interactive");
 
return;
/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,11 → 12,8
#define CL_ENOTSUP 6
#define CL_EEXEC 7
#define CL_EEXISTS 8
#define CL_ETOOBIG 9
 
/* Just like 'errno' */
extern volatile int cli_errno;
 
extern char *err2str(int);
extern void cli_error(int, const char *, ...);
 
extern void cli_verbose(const char *, ...);
#endif
/trunk/uspace/app/bdsh/errstr.h
13,11 → 13,8
"Method Not Supported",
"Bad command or file name",
"Entry already exists",
"Object too large",
NULL
};
 
static char *err2str(int);
 
#endif
 
/trunk/uspace/app/bdsh/errors.c
38,19 → 38,18
#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 */
static char *err2str(int err)
char *err2str(int errno)
{
 
if (NULL != cl_errors[err])
return cl_errors[err];
if (NULL != cl_errors[errno])
return cl_errors[errno];
 
return (char *)NULL;
}
59,7 → 58,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 err, const char *fmt, ...)
void cli_error(int errno, const char *fmt, ...)
{
va_list vargs;
va_start(vargs, fmt);
66,22 → 65,31
vprintf(fmt, vargs);
va_end(vargs);
 
if (NULL != err2str(err))
printf(" (%s)\n", err2str(err));
if (NULL != err2str(errno))
printf(" (%s)\n", err2str(errno));
else
printf(" (Unknown Error %d)\n", err);
printf(" (Unknown Error %d)\n", errno);
 
/* 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;
if (errno < 0)
exit(EXIT_FAILURE);
 
}
 
/* 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;
 
}