/branches/network/uspace/app/bdsh/input.c |
---|
33,6 → 33,7 |
#include <stdlib.h> |
#include <string.h> |
#include <io/stream.h> |
#include <console.h> |
#include "config.h" |
#include "util.h" |
41,21 → 42,8 |
#include "errors.h" |
#include "exec.h" |
extern volatile unsigned int cli_interactive; |
/* Not exposed in input.h */ |
static void cli_restricted(char *); |
static void read_line(char *, int); |
/* More than a macro than anything */ |
static void cli_restricted(char *cmd) |
{ |
printf("%s is not available in %s mode\n", cmd, |
cli_interactive ? "interactive" : "non-interactive"); |
return; |
} |
/* Tokenizes input from console, sees if the first word is a built-in, if so |
* invokes the built-in entry point (a[0]) passing all arguments in a[] to |
* the handler */ |
69,14 → 57,11 |
if (NULL == usr->line) |
return CL_EFAIL; |
tmp = cli_strdup(usr->line); |
tmp = strdup(usr->line); |
/* Break up what the user typed, space delimited */ |
/* TODO: Protect things in quotes / ticks, expand wildcards */ |
cmd[n] = cli_strtok(tmp, " "); |
cmd[n] = strtok(tmp, " "); |
while (cmd[n] && n < WORD_MAX) { |
cmd[++n] = cli_strtok(NULL, " "); |
cmd[++n] = strtok(NULL, " "); |
} |
/* We have rubbish */ |
85,39 → 70,19 |
goto finit; |
} |
/* Its a builtin command */ |
/* Its a builtin command ? */ |
if ((i = (is_builtin(cmd[0]))) > -1) { |
/* Its not available in this mode, see what try_exec() thinks */ |
if (builtin_is_restricted(i)) { |
rc = try_exec(cmd[0], cmd); |
if (rc) |
/* No external matching it could be found, tell the |
* user that the command does exist, but is not |
* available in this mode. */ |
cli_restricted(cmd[0]); |
goto finit; |
} |
/* Its a builtin, its available, run it */ |
rc = run_builtin(i, cmd, usr); |
goto finit; |
/* We repeat the same dance for modules */ |
/* Its a module ? */ |
} else if ((i = (is_module(cmd[0]))) > -1) { |
if (module_is_restricted(i)) { |
rc = try_exec(cmd[0], cmd); |
if (rc) |
cli_restricted(cmd[0]); |
goto finit; |
} |
rc = run_module(i, cmd); |
goto finit; |
} else { |
/* Its not a module or builtin, restricted or otherwise. |
* See what try_exec() thinks of it and just pass its return |
* value back to the caller */ |
rc = try_exec(cmd[0], cmd); |
goto finit; |
} |
/* See what try_exec thinks of it */ |
rc = try_exec(cmd[0], cmd); |
finit: |
if (NULL != usr->line) { |
free(usr->line); |
129,7 → 94,6 |
return rc; |
} |
/* Borrowed from Jiri Svoboda's 'cli' uspace app */ |
static void read_line(char *buffer, int n) |
{ |
char c; |
149,8 → 113,10 |
} |
continue; |
} |
putchar(c); |
buffer[chars++] = c; |
if (c >= ' ') { |
putchar(c); |
buffer[chars++] = c; |
} |
} |
putchar('\n'); |
buffer[chars] = '\0'; |
164,13 → 130,16 |
char line[INPUT_MAX]; |
size_t len = 0; |
console_set_style(STYLE_EMPHASIS); |
printf("%s", usr->prompt); |
console_set_style(STYLE_NORMAL); |
read_line(line, INPUT_MAX); |
len = strlen(line); |
/* Make sure we don't have rubbish or a C/R happy user */ |
if (len == 0 || line[0] == '\n') |
return; |
usr->line = cli_strdup(line); |
usr->line = strdup(line); |
return; |
} |
/branches/network/uspace/app/bdsh/AUTHORS |
---|
8,9 → 8,6 |
* Based on the HelenOS testing sub-system written by Martin Decky |
* cli_strtok() and cli_strtok_r() (util.c) were adapted from the FreeBSD |
strtok() and strtok_r() functions written by Wes Peters. |
* read_line() (input.c) was written by Jiri Svoboda |
Individual author copyrights are listed in the headers of each file. |
/branches/network/uspace/app/bdsh/cmds/mknewcmd |
---|
46,8 → 46,6 |
-e, --entry Entry function of the command (def: cmd_${def}) |
-h, --help-entry Entry function for command help (def: help_cmd_${def}) |
-a, --alias Alias (nickname) for this command (def: none) |
-r, --restrict Restriction level (interactive, non-interactive, both) |
(def: module is both, builtin is interactive only) |
-t, --type Type of command (module or builtin) (def: module) |
-H, --help This help summary |
-V, --version Print $PROGNAME version and exit normally |
67,8 → 65,7 |
$PROGNAME -n foo -d "Foo power" -a bar -r both -t module modules/foo |
The example would generate a modular command named 'foo', which is also |
reached by typing 'bar' and available in either interactive or noninteractive |
mode. |
reached by typing 'bar'. |
Skeletal files do *not* depend on the autoconf generated "config.h" unless you |
include it. This may or may not be desirable depending on your use. |
97,7 → 94,6 |
"${CMDDESC}", |
&${CMDENTRY}, |
&${HELPENTRY}, |
${CMDRESTRICT} |
}, |
EOF |
107,7 → 103,6 |
NULL, |
&${CMDENTRY}, |
&${HELPENTRY}, |
${CMDRESTRICT} |
}, |
EOF |
120,8 → 115,8 |
EOF |
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/entry.h |
/* Entry points for the ${CMDNAME} command */ |
extern int * ${CMDENTRY}(char **); |
extern void * ${HELPENTRY}(unsigned int); |
extern int ${CMDENTRY}(char **); |
extern void ${HELPENTRY}(unsigned int); |
#endif /* ${defname}_ENTRY_H */ |
167,25 → 162,25 |
#include "${CMDNAME}.h" |
#include "cmds.h" |
static char *cmdname = "${CMDNAME}"; |
static const char *cmdname = "${CMDNAME}"; |
/* Dispays help for ${CMDNAME} in various levels */ |
void * ${HELPENTRY}(unsigned int level) |
void ${HELPENTRY}(unsigned int level) |
{ |
printf("This is the %s help for '%s'.\n", |
level ? EXT_HELP : SHORT_HELP, cmdname); |
return CMD_VOID; |
return; |
} |
EOF |
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c |
/* Main entry point for ${CMDNAME}, accepts an array of arguments */ |
int * ${CMDENTRY}(char **argv) |
int ${CMDENTRY}(char **argv) |
EOF |
[ "${CMDTYPE}" = "builtin" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c |
/* Main entry point for ${CMDNAME}, accepts an array of arguments and a |
* pointer to the cliuser_t structure */ |
int * ${CMDENTRY}(char **argv, cliuser_t *usr) |
int ${CMDENTRY}(char **argv, cliuser_t *usr) |
EOF |
cat << EOF >> ${OUTDIR}/${CMDNAME}.c |
{ |
234,8 → 229,8 |
# We need at least one |
[ $# = 0 ] && usage && exit 1; |
TEMP=$(getopt -o n:d:e:h:a:r:t:HV \ |
--long name:,desc:,entry:,help-entry:,alias:,restrict:,type:,help,version \ |
TEMP=$(getopt -o n:d:e:h:a:t:HV \ |
--long name:,desc:,entry:,help-entry:,alias:,type:,help,version \ |
-- "$@") || { |
echo "Try $PROGNAME --help for help" |
} |
269,11 → 264,6 |
shift 2 |
continue |
;; |
-r | --restrict) |
CMDRESTRICT="$2" |
shift 2 |
continue |
;; |
-t | --type) |
CMDTYPE="$2" |
shift 2 |
305,30 → 295,7 |
[ -n "$CMDTYPE" ] || CMDTYPE="module" |
[ -n "$OUTDIR" ] || OUTDIR="${CMDTYPE}s/${CMDNAME}" |
# Builtins typically only need to be available in interactive mode, |
# set the default accordingly. |
[ -n "$CMDRESTRICT" ] || { |
[ "$CMDTYPE" = "module" ] && CMDRESTRICT="both" |
[ "$CMDTYPE" = "builtin" ] && CMDRESTRICT="interactive" |
} |
# Set the restriction level as the structure expects to see it |
case "$CMDRESTRICT" in |
0 | both) |
CMDRESTRICT="0" |
;; |
1 | non-interactive) |
CMDRESTRICT="1" |
;; |
-1 | interactive) |
CMDRESTRICT="-1" |
;; |
*) |
usage |
exit 1 |
;; |
esac |
# Do a little sanity |
[ -d $OUTDIR ] && { |
echo "$OUTDIR already exists, remove it to proceed." |
/branches/network/uspace/app/bdsh/cmds/mod_cmds.c |
---|
53,26 → 53,6 |
extern volatile unsigned int cli_interactive; |
int module_is_restricted(int pos) |
{ |
/* Restriction Levels: |
* -1 -> Available only in interactive mode |
* 0 -> Available in any mode |
* 1 -> Available only in non-interactive mode */ |
module_t *mod = modules; |
mod += pos; |
/* We're interactive, and the module is OK to run */ |
if (cli_interactive && mod->restricted <= 0) |
return 0; |
/* We're not interactive, and the module is OK to run */ |
if (!cli_interactive && mod->restricted >= 0) |
return 0; |
/* Anything else is just a big fat no :) */ |
return 1; |
} |
/* Checks if an entry function matching command exists in modules[], if so |
* its position in the array is returned */ |
int is_module(const char *command) |
/branches/network/uspace/app/bdsh/cmds/modules/touch/touch.c |
---|
37,6 → 37,7 |
#include <fcntl.h> |
#include <dirent.h> |
#include <sys/types.h> |
#include <string.h> |
#include "config.h" |
#include "errors.h" |
48,7 → 49,7 |
static char *cmdname = "touch"; |
/* Dispays help for touch in various levels */ |
void * help_cmd_touch(unsigned int level) |
void help_cmd_touch(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' updates access times for files\n", cmdname); |
58,11 → 59,11 |
"created\n", cmdname); |
} |
return CMD_VOID; |
return; |
} |
/* Main entry point for touch, accepts an array of arguments */ |
int * cmd_touch(char **argv) |
int cmd_touch(char **argv) |
{ |
unsigned int argc, i = 0, ret = 0; |
int fd; |
79,7 → 80,7 |
} |
for (i = 1; i < argc; i ++) { |
buff = cli_strdup(argv[i]); |
buff = strdup(argv[i]); |
dirp = opendir(buff); |
if (dirp) { |
cli_error(CL_ENOTSUP, "%s is a directory", buff); |
/branches/network/uspace/app/bdsh/cmds/modules/touch/touch_def.h |
---|
3,6 → 3,5 |
"Create files or update access times", |
&cmd_touch, |
&help_cmd_touch, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/touch/entry.h |
---|
2,8 → 2,8 |
#define TOUCH_ENTRY_H |
/* Entry points for the touch command */ |
extern int * cmd_touch(char **); |
extern void * help_cmd_touch(unsigned int); |
extern int cmd_touch(char **); |
extern void help_cmd_touch(unsigned int); |
#endif /* TOUCH_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/cp/cp.c |
---|
0,0 → 1,231 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <getopt.h> |
#include <string.h> |
#include <fcntl.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "cp.h" |
#include "cmds.h" |
#define CP_VERSION "0.0.1" |
#define CP_DEFAULT_BUFLEN 1024 |
static const char *cmdname = "cp"; |
static struct option const long_options[] = { |
{ "buffer", required_argument, 0, 'b' }, |
{ "force", no_argument, 0, 'f' }, |
{ "recursive", no_argument, 0, 'r' }, |
{ "help", no_argument, 0, 'h' }, |
{ "version", no_argument, 0, 'v' }, |
{ "verbose", no_argument, 0, 'V' }, |
{ 0, 0, 0, 0 } |
}; |
static int strtoint(const char *s1) |
{ |
long t1; |
if (-1 == (t1 = strtol(s1, (char **) NULL, 10))) |
return -1; |
if (t1 <= 0) |
return -1; |
return (int) t1; |
} |
static int64_t copy_file(const char *src, const char *dest, |
size_t blen, int vb) |
{ |
int fd1, fd2, bytes = 0; |
off_t total = 0; |
int64_t copied = 0; |
char *buff = NULL; |
if (vb) |
printf("Copying %s to %s\n", src, dest); |
if (-1 == (fd1 = open(src, O_RDONLY))) { |
printf("Unable to open source file %s\n", src); |
return -1; |
} |
if (-1 == (fd2 = open(dest, O_CREAT))) { |
printf("Unable to open destination file %s\n", dest); |
close(fd1); |
return -1; |
} |
total = lseek(fd1, 0, SEEK_END); |
if (vb) |
printf("%d bytes to copy\n", total); |
lseek(fd1, 0, SEEK_SET); |
if (NULL == (buff = (char *) malloc(blen))) { |
printf("Unable to allocate enough memory to read %s\n", |
src); |
copied = -1; |
goto out; |
} |
for (;;) { |
ssize_t res; |
bytes = read(fd1, buff, blen); |
if (bytes <= 0) |
break; |
copied += bytes; |
res = bytes; |
do { |
/* |
* Theoretically, it may not be enough to call write() |
* only once. Also the previous read() may have |
* returned less data than requested. |
*/ |
bytes = write(fd2, buff, res); |
if (bytes < 0) |
goto err; |
res -= bytes; |
} while (res > 0); |
/* TODO: re-insert assert() once this is stand alone, |
* removed as abort() exits the entire shell |
*/ |
if (res != 0) { |
printf("\n%d more bytes than actually exist were copied\n", res); |
goto err; |
} |
} |
if (bytes < 0) { |
err: |
printf("\nError copying %s, (%d)\n", src, bytes); |
copied = bytes; |
} |
out: |
close(fd1); |
close(fd2); |
if (buff) |
free(buff); |
return copied; |
} |
void help_cmd_cp(unsigned int level) |
{ |
static char helpfmt[] = |
"Usage: %s [options] <source> <dest>\n" |
"Options: (* indicates not yet implemented)\n" |
" -h, --help A short option summary\n" |
" -v, --version Print version information and exit\n" |
"* -V, --verbose Be annoyingly noisy about what's being done\n" |
"* -f, --force Do not complain when <dest> exists\n" |
"* -r, --recursive Copy entire directories\n" |
" -b, --buffer ## Set the read buffer size to ##\n" |
"Currently, %s is under development, some options may not work.\n"; |
if (level == HELP_SHORT) { |
printf("`%s' copies files and directories\n", cmdname); |
} else { |
help_cmd_cp(HELP_SHORT); |
printf(helpfmt, cmdname, cmdname); |
} |
return; |
} |
int cmd_cp(char **argv) |
{ |
unsigned int argc, buffer = 0, verbose = 0; |
int c, opt_ind; |
int64_t ret; |
argc = cli_count_args(argv); |
for (c = 0, optind = 0, opt_ind = 0; c != -1;) { |
c = getopt_long(argc, argv, "hvVfrb:", long_options, &opt_ind); |
switch (c) { |
case 'h': |
help_cmd_cp(1); |
return CMD_SUCCESS; |
case 'v': |
printf("%d\n", CP_VERSION); |
return CMD_SUCCESS; |
case 'V': |
verbose = 1; |
break; |
case 'f': |
break; |
case 'r': |
break; |
case 'b': |
if (-1 == (buffer = strtoint(optarg))) { |
printf("%s: Invalid buffer specification, " |
"(should be a number greater than zero)\n", |
cmdname); |
return CMD_FAILURE; |
} |
if (verbose) |
printf("Buffer = %d\n", buffer); |
break; |
} |
} |
if (buffer == 0) |
buffer = CP_DEFAULT_BUFLEN; |
argc -= optind; |
if (argc != 2) { |
printf("%s: invalid number of arguments. Try %s --help\n", |
cmdname, cmdname); |
return CMD_FAILURE; |
} |
ret = copy_file(argv[optind], argv[optind + 1], buffer, verbose); |
if (verbose) |
printf("%d bytes copied\n", ret); |
if (ret >= 0) |
return CMD_SUCCESS; |
else |
return CMD_FAILURE; |
} |
/branches/network/uspace/app/bdsh/cmds/modules/cp/cp_def.h |
---|
0,0 → 1,7 |
{ |
"cp", |
"Copy files and directories", |
&cmd_cp, |
&help_cmd_cp, |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/cp/entry.h |
---|
0,0 → 1,9 |
#ifndef CP_ENTRY_H |
#define CP_ENTRY_H |
/* Entry points for the cp command */ |
extern int cmd_cp(char **); |
extern void help_cmd_cp(unsigned int); |
#endif /* CP_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/cp/cp.h |
---|
0,0 → 1,8 |
#ifndef CP_H |
#define CP_H |
/* Prototypes for the cp command, excluding entry points */ |
#endif /* CP_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/mkdir/entry.h |
---|
2,8 → 2,8 |
#define MKDIR_ENTRY_H |
/* Entry points for the mkdir command */ |
extern int * cmd_mkdir(char **); |
extern void * help_cmd_mkdir(unsigned int); |
extern int cmd_mkdir(char **); |
extern void help_cmd_mkdir(unsigned int); |
#endif /* MKDIR_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c |
---|
60,7 → 60,7 |
}; |
void * help_cmd_mkdir(unsigned int level) |
void help_cmd_mkdir(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' creates a new directory\n", cmdname); |
79,7 → 79,7 |
cmdname, cmdname); |
} |
return CMD_VOID; |
return; |
} |
/* This is kind of clunky, but effective for now */ |
93,7 → 93,7 |
/* Its a good idea to allocate path, plus we (may) need a copy of |
* path to tokenize if parents are specified */ |
if (NULL == (tmp = cli_strdup(path))) { |
if (NULL == (tmp = strdup(path))) { |
cli_error(CL_ENOMEM, "%s: path too big?", cmdname); |
return 1; |
} |
128,9 → 128,9 |
absolute = 1; |
/* TODO: Canonify the path prior to tokenizing it, see below */ |
dirs[i] = cli_strtok(tmp, "/"); |
dirs[i] = strtok(tmp, "/"); |
while (dirs[i] && i < 255) |
dirs[++i] = cli_strtok(NULL, "/"); |
dirs[++i] = strtok(NULL, "/"); |
if (NULL == dirs[0]) |
return 1; |
181,7 → 181,7 |
return ret; |
} |
int * cmd_mkdir(char **argv) |
int cmd_mkdir(char **argv) |
{ |
unsigned int argc, create_parents = 0, i, ret = 0, follow = 0; |
unsigned int verbose = 0; |
/branches/network/uspace/app/bdsh/cmds/modules/mkdir/mkdir_def.h |
---|
3,14 → 3,6 |
"Create new directories", |
&cmd_mkdir, |
&help_cmd_mkdir, |
0 |
}, |
{ |
"md", |
NULL, |
&cmd_mkdir, |
&help_cmd_mkdir, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/cat/entry.h |
---|
2,8 → 2,8 |
#define CAT_ENTRY_H |
/* Entry points for the cat command */ |
extern int * cmd_cat(char **); |
extern void * help_cmd_cat(unsigned int); |
extern int cmd_cat(char **); |
extern void help_cmd_cat(unsigned int); |
#endif /* CAT_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/cat/cat.c |
---|
59,7 → 59,7 |
}; |
/* Dispays help for cat in various levels */ |
void * help_cmd_cat(unsigned int level) |
void help_cmd_cat(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' shows the contents of files\n", cmdname); |
78,7 → 78,7 |
cmdname, cmdname); |
} |
return CMD_VOID; |
return; |
} |
static unsigned int cat_file(const char *fname, size_t blen) |
103,13 → 103,11 |
} |
do { |
memset(buff, 0, sizeof(buff)); |
bytes = read(fd, buff, blen); |
if (bytes > 0) { |
count += bytes; |
if (bytes < blen) |
buff[bytes] = '\0'; |
printf(buff); |
buff[bytes] = '\0'; |
printf("%s", buff); |
reads++; |
} |
} while (bytes > 0); |
121,12 → 119,6 |
return 1; |
} |
/* Debug stuff, newline not added purposefully */ |
printf("** %s is a file with the size of %ld bytes\n", |
fname, total); |
printf( "** %d bytes were read in a buffer of %d bytes in %d reads\n", |
count, blen, reads); |
printf("** Read %s\n", count == total ? "Succeeded" : "Failed"); |
free(buff); |
return 0; |
133,7 → 125,7 |
} |
/* Main entry point for cat, accepts an array of arguments */ |
int * cmd_cat(char **argv) |
int cmd_cat(char **argv) |
{ |
unsigned int argc, i, ret = 0, buffer = 0; |
int c, opt_ind; |
/branches/network/uspace/app/bdsh/cmds/modules/cat/cat_def.h |
---|
3,6 → 3,5 |
"Show the contents of a file", |
&cmd_cat, |
&help_cmd_cat, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/help/entry.h |
---|
2,7 → 2,7 |
#define HELP_ENTRY_H_ |
/* Entry points for the help command */ |
extern void * help_cmd_help(unsigned int); |
extern int * cmd_help(char *[]); |
extern void help_cmd_help(unsigned int); |
extern int cmd_help(char *[]); |
#endif |
/branches/network/uspace/app/bdsh/cmds/modules/help/help.c |
---|
69,7 → 69,7 |
return HELP_IS_RUBBISH; |
} |
void *help_cmd_help(unsigned int level) |
void help_cmd_help(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf( |
86,10 → 86,10 |
cmdname, cmdname, cmdname, cmdname); |
} |
return CMD_VOID; |
return; |
} |
int *cmd_help(char *argv[]) |
int cmd_help(char *argv[]) |
{ |
module_t *mod; |
builtin_t *cmd; |
133,13 → 133,11 |
/* First, show a list of built in commands that are available in this mode */ |
for (cmd = builtins; cmd->name != NULL; cmd++, i++) { |
if (!builtin_is_restricted(i)) { |
if (is_builtin_alias(cmd->name)) |
printf(" %-16s\tAlias for `%s'\n", cmd->name, |
alias_for_builtin(cmd->name)); |
else |
printf(" %-16s\t%s\n", cmd->name, cmd->desc); |
} |
} |
i = 0; |
146,13 → 144,11 |
/* Now, show a list of module commands that are available in this mode */ |
for (mod = modules; mod->name != NULL; mod++, i++) { |
if (!module_is_restricted(i)) { |
if (is_module_alias(mod->name)) |
printf(" %-16s\tAlias for `%s'\n", mod->name, |
alias_for_module(mod->name)); |
else |
printf(" %-16s\t%s\n", mod->name, mod->desc); |
} |
} |
printf("\n Try %s %s for more information on how `%s' works.\n\n", |
/branches/network/uspace/app/bdsh/cmds/modules/help/help_def.h |
---|
3,5 → 3,4 |
"Show help for commands", |
&cmd_help, |
&help_cmd_help, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/sleep/sleep_def.h |
---|
0,0 → 1,7 |
{ |
"sleep", |
"Pause for given time interval (in seconds)", |
&cmd_sleep, |
&help_cmd_sleep, |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/sleep/entry.h |
---|
0,0 → 1,9 |
#ifndef SLEEP_ENTRY_H |
#define SLEEP_ENTRY_H |
/* Entry points for the sleep command */ |
extern int cmd_sleep(char **); |
extern void help_cmd_sleep(unsigned int); |
#endif /* SLEEP_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/sleep/sleep.c |
---|
0,0 → 1,73 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include "config.h" |
#include "util.h" |
#include "errors.h" |
#include "entry.h" |
#include "sleep.h" |
#include "cmds.h" |
static char *cmdname = "sleep"; |
/* Dispays help for sleep in various levels */ |
void help_cmd_sleep(unsigned int level) |
{ |
printf("This is the %s help for '%s'.\n", |
level ? EXT_HELP : SHORT_HELP, cmdname); |
return; |
} |
/* Main entry point for sleep, accepts an array of arguments */ |
int cmd_sleep(char **argv) |
{ |
unsigned int argc; |
unsigned int i; |
/* Count the arguments */ |
for (argc = 0; argv[argc] != NULL; argc ++); |
printf("%s %s\n", TEST_ANNOUNCE, cmdname); |
printf("%d arguments passed to %s", argc - 1, cmdname); |
if (argc < 2) { |
printf("\n"); |
return CMD_SUCCESS; |
} |
printf(":\n"); |
for (i = 1; i < argc; i++) |
printf("[%d] -> %s\n", i, argv[i]); |
return CMD_SUCCESS; |
} |
/branches/network/uspace/app/bdsh/cmds/modules/sleep/sleep.h |
---|
0,0 → 1,8 |
#ifndef SLEEP_H |
#define SLEEP_H |
/* Prototypes for the sleep command, excluding entry points */ |
#endif /* SLEEP_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/pwd/entry.h |
---|
4,8 → 4,8 |
#include "scli.h" |
/* Entry points for the pwd command */ |
extern void * help_cmd_pwd(unsigned int); |
extern int * cmd_pwd(char **); |
extern void help_cmd_pwd(unsigned int); |
extern int cmd_pwd(char **); |
#endif |
/branches/network/uspace/app/bdsh/cmds/modules/pwd/pwd.c |
---|
39,13 → 39,13 |
static char * cmdname = "pwd"; |
void * help_cmd_pwd(unsigned int level) |
void help_cmd_pwd(unsigned int level) |
{ |
printf("`%s' prints your current working directory.\n", cmdname); |
return CMD_VOID; |
return; |
} |
int * cmd_pwd(char *argv[]) |
int cmd_pwd(char *argv[]) |
{ |
char *buff; |
/branches/network/uspace/app/bdsh/cmds/modules/pwd/pwd_def.h |
---|
3,5 → 3,4 |
"Prints the current working directory", |
&cmd_pwd, |
&help_cmd_pwd, |
-1 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/module_aliases.h |
---|
12,10 → 12,6 |
* the entry point being reached. */ |
char *mod_aliases[] = { |
"exit", "quit", |
"md", "mkdir", |
"del", "rm", |
"dir", "ls", |
NULL, NULL |
}; |
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls.c |
---|
50,6 → 50,24 |
static char *cmdname = "ls"; |
static inline off_t flen(const char *f) |
{ |
int fd; |
off_t size; |
fd = open(f, O_RDONLY); |
if (fd == -1) |
return 0; |
size = lseek(fd, 0, SEEK_END); |
close(fd); |
if (size < 0) |
size = 0; |
return size; |
} |
static unsigned int ls_scope(const char *path) |
{ |
int fd; |
96,7 → 114,7 |
ls_print_dir(dp->d_name); |
break; |
case LS_FILE: |
ls_print_file(dp->d_name); |
ls_print_file(dp->d_name, buff); |
break; |
case LS_BOGUS: |
/* Odd chance it was deleted from the time readdir() found |
120,19 → 138,19 |
static void ls_print_dir(const char *d) |
{ |
printf("%-40s\t<DIR>\n", d); |
printf("%-40s\t<dir>\n", d); |
return; |
} |
static void ls_print_file(const char *f) |
static void ls_print_file(const char *name, const char *pathname) |
{ |
printf("%-40s\n", f); |
printf("%-40s\t%llu\n", name, (long long) flen(pathname)); |
return; |
} |
void * help_cmd_ls(unsigned int level) |
void help_cmd_ls(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' lists files and directories.\n", cmdname); |
142,10 → 160,10 |
"working directory is used.\n", cmdname); |
} |
return CMD_VOID; |
return; |
} |
int * cmd_ls(char **argv) |
int cmd_ls(char **argv) |
{ |
unsigned int argc; |
unsigned int scope; |
174,7 → 192,7 |
free(buff); |
return CMD_FAILURE; |
case LS_FILE: |
ls_print_file(buff); |
ls_print_file(buff, buff); |
break; |
case LS_DIR: |
dirp = opendir(buff); |
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls_def.h |
---|
3,14 → 3,4 |
"List files and directories", |
&cmd_ls, |
&help_cmd_ls, |
0 |
}, |
{ |
"dir", |
NULL, |
&cmd_ls, |
&help_cmd_ls, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/ls/ls.h |
---|
10,7 → 10,7 |
static unsigned int ls_scope(const char *); |
static void ls_scan_dir(const char *, DIR *); |
static void ls_print_dir(const char *); |
static void ls_print_file(const char *); |
static void ls_print_file(const char *, const char *); |
#endif /* LS_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/ls/entry.h |
---|
2,8 → 2,8 |
#define LS_ENTRY_H |
/* Entry points for the ls command */ |
extern int * cmd_ls(char **); |
extern void * help_cmd_ls(unsigned int); |
extern int cmd_ls(char **); |
extern void help_cmd_ls(unsigned int); |
#endif /* LS_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/modules/modules.h |
---|
18,7 → 18,6 |
/* Prototypes for each module's entry (help/exec) points */ |
#include "help/entry.h" |
#include "quit/entry.h" |
#include "mkdir/entry.h" |
#include "rm/entry.h" |
#include "cat/entry.h" |
25,6 → 24,8 |
#include "touch/entry.h" |
#include "ls/entry.h" |
#include "pwd/entry.h" |
#include "sleep/entry.h" |
#include "cp/entry.h" |
/* Each .def function fills the module_t struct with the individual name, entry |
* point, help entry point, etc. You can use config.h to control what modules |
32,7 → 33,6 |
module_t modules[] = { |
#include "help/help_def.h" |
#include "quit/quit_def.h" |
#include "mkdir/mkdir_def.h" |
#include "rm/rm_def.h" |
#include "cat/cat_def.h" |
39,6 → 39,8 |
#include "touch/touch_def.h" |
#include "ls/ls_def.h" |
#include "pwd/pwd_def.h" |
#include "sleep/sleep_def.h" |
#include "cp/cp_def.h" |
{NULL, NULL, NULL, NULL} |
}; |
/branches/network/uspace/app/bdsh/cmds/modules/rm/rm.c |
---|
33,7 → 33,6 |
#include <unistd.h> |
#include <fcntl.h> |
#include <dirent.h> |
#include <assert.h> |
#include <getopt.h> |
#include "config.h" |
144,7 → 143,7 |
} |
/* Dispays help for rm in various levels */ |
void * help_cmd_rm(unsigned int level) |
void help_cmd_rm(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' removes files and directories.\n", cmdname); |
161,11 → 160,11 |
"Currently, %s is under development, some options don't work.\n", |
cmdname, cmdname); |
} |
return CMD_VOID; |
return; |
} |
/* Main entry point for rm, accepts an array of arguments */ |
int * cmd_rm(char **argv) |
int cmd_rm(char **argv) |
{ |
unsigned int argc; |
unsigned int i, scope, ret = 0; |
219,7 → 218,11 |
while (NULL != argv[i]) { |
len = strlen(argv[i]) + 2; |
buff = (char *) realloc(buff, len); |
assert(buff != NULL); |
if (buff == NULL) { |
printf("rm: out of memory\n"); |
ret = 1; |
break; |
} |
memset(buff, 0, sizeof(buff)); |
snprintf(buff, len, argv[i]); |
/branches/network/uspace/app/bdsh/cmds/modules/rm/rm_def.h |
---|
3,14 → 3,5 |
"Remove files and directories", |
&cmd_rm, |
&help_cmd_rm, |
0 |
}, |
{ |
"del", |
NULL, |
&cmd_rm, |
&help_cmd_rm, |
0 |
}, |
/branches/network/uspace/app/bdsh/cmds/modules/rm/entry.h |
---|
2,8 → 2,8 |
#define RM_ENTRY_H |
/* Entry points for the rm command */ |
extern int * cmd_rm(char **); |
extern void * help_cmd_rm(unsigned int); |
extern int cmd_rm(char **); |
extern void help_cmd_rm(unsigned int); |
#endif /* RM_ENTRY_H */ |
/branches/network/uspace/app/bdsh/cmds/builtins/builtins.h |
---|
4,9 → 4,11 |
#include "config.h" |
#include "cd/entry.h" |
#include "exit/entry.h" |
builtin_t builtins[] = { |
#include "cd/cd_def.h" |
#include "exit/exit_def.h" |
{NULL, NULL, NULL, NULL} |
}; |
/branches/network/uspace/app/bdsh/cmds/builtins/cd/cd.c |
---|
42,7 → 42,7 |
static char * cmdname = "cd"; |
void * help_cmd_cd(unsigned int level) |
void help_cmd_cd(unsigned int level) |
{ |
if (level == HELP_SHORT) { |
printf("`%s' changes the current working directory.\n", cmdname); |
53,12 → 53,12 |
cmdname, cmdname); |
} |
return CMD_VOID; |
return; |
} |
/* This is a very rudamentary 'cd' command. It is not 'link smart' (yet) */ |
int * cmd_cd(char **argv, cliuser_t *usr) |
int cmd_cd(char **argv, cliuser_t *usr) |
{ |
int argc, rc = 0; |
/branches/network/uspace/app/bdsh/cmds/builtins/cd/entry.h |
---|
4,8 → 4,8 |
#include "scli.h" |
/* Entry points for the cd command */ |
extern void * help_cmd_cd(unsigned int); |
extern int * cmd_cd(char **, cliuser_t *); |
extern void help_cmd_cd(unsigned int); |
extern int cmd_cd(char **, cliuser_t *); |
#endif |
/branches/network/uspace/app/bdsh/cmds/builtins/cd/cd_def.h |
---|
3,12 → 3,4 |
"Change the current working directory", |
&cmd_cd, |
&help_cmd_cd, |
-1 |
}, |
{ |
"chdir", |
NULL, |
&cmd_cd, |
&help_cmd_cd, |
-1 |
}, |
/branches/network/uspace/app/bdsh/cmds/builtins/exit/exit.h |
---|
0,0 → 1,6 |
#ifndef EXIT_H |
#define EXIT_H |
/* Prototypes for the quit command (excluding entry points) */ |
#endif |
/branches/network/uspace/app/bdsh/cmds/builtins/exit/entry.h |
---|
0,0 → 1,12 |
#ifndef EXIT_ENTRY_H_ |
#define EXIT_ENTRY_H_ |
#include "scli.h" |
/* Entry points for the quit command */ |
extern void help_cmd_exit(unsigned int); |
extern int cmd_exit(char *[], cliuser_t *); |
#endif |
/branches/network/uspace/app/bdsh/cmds/builtins/exit/exit.c |
---|
0,0 → 1,55 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* |
* Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* Neither the name of the original program's authors nor the names of its |
* contributors may be used to endorse or promote products derived from this |
* software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include "entry.h" |
#include "exit.h" |
#include "cmds.h" |
static const char *cmdname = "exit"; |
extern volatile unsigned int cli_quit; |
extern const char *progname; |
void help_cmd_exit(unsigned int level) |
{ |
printf("Type `%s' to exit %s\n", cmdname, progname); |
return; |
} |
/* Quits the program and returns the status of whatever command |
* came before invoking 'quit' */ |
int cmd_exit(char *argv[], cliuser_t *usr) |
{ |
/* Inform that we're outta here */ |
cli_quit = 1; |
return CMD_SUCCESS; |
} |
/branches/network/uspace/app/bdsh/cmds/builtins/exit/exit_def.h |
---|
0,0 → 1,6 |
{ |
"exit", |
"Exit the shell", |
&cmd_exit, |
&help_cmd_exit, |
}, |
/branches/network/uspace/app/bdsh/cmds/builtins/builtin_aliases.h |
---|
4,7 → 4,6 |
/* See modules/module_aliases.h for an explanation of this file */ |
char *builtin_aliases[] = { |
"chdir", "cd", |
NULL, NULL |
}; |
/branches/network/uspace/app/bdsh/cmds/cmds.h |
---|
19,17 → 19,16 |
#define BUFF_SMALL 255 |
/* Return macros for int type entry points */ |
#define CMD_FAILURE (int*)1 |
#define CMD_FAILURE 1 |
#define CMD_SUCCESS 0 |
#define CMD_VOID (void *)NULL |
/* Types for module command entry and help */ |
typedef int * (* mod_entry_t)(char **); |
typedef void * (* mod_help_t)(unsigned int); |
typedef int (* mod_entry_t)(char **); |
typedef void (* mod_help_t)(unsigned int); |
/* Built-in commands need to be able to modify cliuser_t */ |
typedef int * (* builtin_entry_t)(char **, cliuser_t *); |
typedef void * (* builtin_help_t)(unsigned int); |
typedef int (* builtin_entry_t)(char **, cliuser_t *); |
typedef void (* builtin_help_t)(unsigned int); |
/* Module structure */ |
typedef struct { |
37,7 → 36,6 |
char *desc; /* Description of the command */ |
mod_entry_t entry; /* Command (exec) entry function */ |
mod_help_t help; /* Command (help) entry function */ |
int restricted; /* Restricts to interactive/non-interactive only */ |
} module_t; |
/* Builtin structure, same as modules except different types of entry points */ |
/branches/network/uspace/app/bdsh/cmds/builtin_cmds.c |
---|
40,19 → 40,6 |
extern volatile unsigned int cli_interactive; |
int builtin_is_restricted(int pos) |
{ |
builtin_t *cmd = builtins; |
cmd += pos; |
if (cli_interactive && cmd->restricted <= 0) |
return 0; |
if (!cli_interactive && cmd->restricted >= 0) |
return 0; |
return 1; |
} |
int is_builtin(const char *command) |
{ |
builtin_t *cmd; |
/branches/network/uspace/app/bdsh/config.h |
---|
1,15 → 1,18 |
/* Various things that are used in many files |
* Various temporary port work-arounds are addressed in __HELENOS__ , this |
* serves as a convenience and later as a guide to make "phony.h" for future |
* ports */ |
/* Various things that are used in many places including a few |
* tidbits left over from autoconf prior to the HelenOS port */ |
/* Specific port work-arounds : */ |
#ifndef PATH_MAX |
#define PATH_MAX 255 |
#endif |
#ifndef EXIT_SUCCESS |
#define EXIT_SUCCESS 0 |
#define EXIT_FAILURE 0 |
#define EXIT_FAILURE 1 |
#endif |
/* Work around for getenv() */ |
#define PATH "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" |
#define PATH "/srv:/app" |
#define PATH_DELIM ":" |
/* Used in many places */ |
26,7 → 29,7 |
#define PACKAGE_BUGREPORT "echo@echoreply.us" |
#define PACKAGE_NAME "bdsh" |
#define PACKAGE_STRING "The brain dead shell" |
#define PACKAGE_TARNAME "scli" |
#define PACKAGE_TARNAME "bdsh" |
#define PACKAGE_VERSION "0.0.1" |
/branches/network/uspace/app/bdsh/README |
---|
57,12 → 57,12 |
They are typed as such (from cmds.h): |
/* Types for module command entry and help */ |
typedef int * (* mod_entry_t)(char **); |
typedef void * (* mod_help_t)(unsigned int); |
typedef int (* mod_entry_t)(char **); |
typedef void (* mod_help_t)(unsigned int); |
/* Built-in commands need to be able to modify cliuser_t */ |
typedef int * (* builtin_entry_t)(char **, cliuser_t *); |
typedef void * (* builtin_help_t)(unsigned int); |
typedef int (* builtin_entry_t)(char **, cliuser_t *); |
typedef void (* builtin_help_t)(unsigned int); |
As you can see, both modular and builtin commands expect an array of |
arguments, however bulitins also expect to be pointed to cliuser_t. |
153,9 → 153,7 |
2: Change your "usage()" command as shown: |
-- void usage(...) |
++ void * help_cmd_foo(unsigned int level) |
-- return; |
++ retrn CMD_VOID; |
++ void help_cmd_foo(unsigned int level) |
'level' is either 0 or 1, indicating the level of help requested. |
If the help / usage function currently exits based on how it is |
163,33 → 161,19 |
3: Change the programs "main()" as shown: |
-- int main(int argc, char **argv) |
++ int * cmd_foo(char **argv) |
++ int cmd_foo(char **argv) |
-- return 1; |
++ return CMD_FAILURE; |
-- return 0; |
++ return CMD_SUCCESS; |
If main() returns an int that is not 1 or 0 (e.g. 127), cast it as |
such: |
-- return 127; |
++ return (int *) 127; |
NOTE: _ONLY_ the main and help entry points need to return int * or |
void *, respectively. Also take note that argc has changed. The type |
for entry points may soon change. |
NOTE: If main is void, you'll need to change it and ensure that its |
expecting an array of arguments, even if they'll never be read or |
used. I.e.: |
-- void main(void) |
++ int * cmd_foo(char **argv) |
++ int cmd_foo(char **argv) |
Similararly, do not try to return CMD_VOID within the modules main |
entry point. If somehow you escape the compiler yelling at you, you |
will surely see pretty blue and yellow fireworks once its reached. |
4: Don't expose more than the entry and help points: |
-- void my_function(int n) |
++ static void my_function(int n) |
/branches/network/uspace/app/bdsh/util.c |
---|
1,7 → 1,4 |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> |
* Copyright (C) 1998 by Wes Peters <wes@softweyr.com> |
* Copyright (c) 1988, 1993 The Regents of the University of California. |
* All rights reserved by all copyright holders. |
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> - All rights reserved |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
30,18 → 27,6 |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* NOTES: |
* 1 - Various functions were adapted from FreeBSD (copyright holders noted above) |
* these functions are identified with comments. |
* |
* 2 - Some of these have since appeared in libc. They remain here for various |
* reasons, such as the eventual integration of garbage collection for things |
* that allocate memory and don't automatically free it. |
* |
* 3 - Things that expect a pointer to an allocated string do _no_ sanity checking |
* if developing on a simulator with no debugger, take care :) |
*/ |
#include <stdio.h> |
#include <string.h> |
#include <stdarg.h> |
54,190 → 39,6 |
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) |
{ |
size_t len = strlen(s1) + 1; |
void *ret = malloc(len); |
if (ret == NULL) { |
cli_errno = CL_ENOMEM; |
return (char *) NULL; |
} |
cli_errno = CL_EOK; |
return (char *) memcpy(ret, s1, len); |
} |
/* |
* Take a previously allocated string (s1), re-size it to accept s2 and copy |
* the contents of s2 into s1. |
* Return -1 on failure, or the length of the copied string on success. |
*/ |
int cli_redup(char **s1, const char *s2) |
{ |
size_t len = strlen(s2) + 1; |
if (! len) |
return -1; |
*s1 = realloc(*s1, len); |
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 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: Length of the new string on success, 0 if the string was handed |
* back unmodified, -1 on failure. On failure, cli_errno is set. |
* |
* 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); |
/* Don't even touch s1, not enough memory */ |
if (NULL == tmp) { |
cli_errno = CL_ENOMEM; |
return -1; |
} |
/* 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 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; |
} |
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */ |
char * cli_strtok_r(char *s, const char *delim, char **last) |
{ |
char *spanp, *tok; |
int c, sc; |
if (s == NULL && (s = *last) == NULL) { |
cli_errno = CL_EFAIL; |
return (NULL); |
} |
cont: |
c = *s++; |
for (spanp = (char *)delim; (sc = *spanp++) != 0;) { |
if (c == sc) |
goto cont; |
} |
if (c == 0) { /* no non-delimiter characters */ |
*last = NULL; |
return (NULL); |
} |
tok = s - 1; |
for (;;) { |
c = *s++; |
spanp = (char *)delim; |
do { |
if ((sc = *spanp++) == c) { |
if (c == 0) |
s = NULL; |
else |
s[-1] = '\0'; |
*last = s; |
return (tok); |
} |
} while (sc != 0); |
} |
} |
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */ |
char * cli_strtok(char *s, const char *delim) |
{ |
static char *last; |
return (cli_strtok_r(s, delim, &last)); |
} |
/* Count and return the # of elements in an array */ |
unsigned int cli_count_args(char **args) |
{ |
273,10 → 74,7 |
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; |
} |
asprintf(&usr->prompt, "%s # ", usr->cwd); |
return 0; |
} |
/branches/network/uspace/app/bdsh/util.h |
---|
3,13 → 3,6 |
#include "scli.h" |
/* Internal string handlers */ |
extern char * cli_strdup(const char *); |
extern int cli_redup(char **, const char *); |
extern int cli_psprintf(char **, const char *, ...); |
extern char * cli_strtok_r(char *, const char *, char **); |
extern char * cli_strtok(char *, const char *); |
/* Utility functions */ |
extern unsigned int cli_count_args(char **); |
extern unsigned int cli_set_prompt(cliuser_t *usr); |
/branches/network/uspace/app/bdsh/exec.c |
---|
46,13 → 46,13 |
#include "errors.h" |
/* FIXME: Just have find_command() return an allocated string */ |
char *found; |
static char *found; |
static char *find_command(char *); |
static unsigned int try_access(const char *); |
static int try_access(const char *); |
/* work-around for access() */ |
static unsigned int try_access(const char *f) |
static int try_access(const char *f) |
{ |
int fd; |
80,10 → 80,10 |
return (char *) cmd; |
} |
path_tok = cli_strdup(PATH); |
path_tok = strdup(PATH); |
/* Extract the PATH env to a path[] array */ |
path[n] = cli_strtok(path_tok, PATH_DELIM); |
path[n] = strtok(path_tok, PATH_DELIM); |
while (NULL != path[n]) { |
if ((strlen(path[n]) + x ) > PATH_MAX) { |
cli_error(CL_ENOTSUP, |
91,7 → 91,7 |
n, n-1); |
break; |
} |
path[++n] = cli_strtok(NULL, PATH_DELIM); |
path[++n] = strtok(NULL, PATH_DELIM); |
} |
/* We now have n places to look for the command */ |
114,14 → 114,14 |
task_id_t tid; |
char *tmp; |
tmp = cli_strdup(find_command(cmd)); |
tmp = strdup(find_command(cmd)); |
free(found); |
tid = task_spawn((const char *)tmp, (const char **)argv); |
tid = task_spawn((const char *)tmp, argv); |
free(tmp); |
if (tid == 0) { |
cli_error(CL_EEXEC, "Can not spawn %s", cmd); |
cli_error(CL_EEXEC, "Cannot spawn `%s'.", cmd); |
return 1; |
} else { |
return 0; |
/branches/network/uspace/app/bdsh/scli.c |
---|
45,7 → 45,6 |
/* 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; |
/* The official name of this program |
53,8 → 52,8 |
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); |
static int cli_init(cliuser_t *); |
static void cli_finit(cliuser_t *); |
/* Constructor */ |
static int cli_init(cliuser_t *usr) |
94,6 → 93,7 |
get_input(&usr); |
if (NULL != usr.line) { |
ret = tok_input(&usr); |
cli_set_prompt(&usr); |
usr.lasterr = ret; |
} |
} |
/branches/network/uspace/app/bdsh/Makefile |
---|
30,25 → 30,17 |
# POSSIBILITY OF SUCH DAMAGE. |
include ../../../version |
include ../../Makefile.config |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
CFLAGS += -I../../srv/kbd/include |
LIBS = $(LIBC_PREFIX)/libc.a |
DEFS += -DRELEASE=\"$(RELEASE)\" |
DEFS += -DRELEASE=$(RELEASE) |
ifdef REVISION |
DEFS += "-DREVISION=\"$(TIMESTAMP)\"" |
endif |
ifdef TIMESTAMP |
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\"" |
endif |
PROGRAM = bdsh |
# Any directory that cleaning targets should know about |
57,7 → 49,6 |
cmds/ \ |
cmds/modules/ \ |
cmds/modules/help/ \ |
cmds/modules/quit/ \ |
cmds/modules/mkdir/ \ |
cmds/modules/rm/ \ |
cmds/modules/cat/ \ |
64,12 → 55,14 |
cmds/modules/touch/ \ |
cmds/modules/ls/ \ |
cmds/modules/pwd/ \ |
cmds/modules/sleep/ \ |
cmds/modules/cp/ \ |
cmds/builtins/ \ |
cmds/builtins/exit/\ |
cmds/builtins/cd/ |
SOURCES = \ |
cmds/modules/help/help.c \ |
cmds/modules/quit/quit.c \ |
cmds/modules/mkdir/mkdir.c \ |
cmds/modules/rm/rm.c \ |
cmds/modules/cat/cat.c \ |
76,6 → 69,9 |
cmds/modules/touch/touch.c \ |
cmds/modules/ls/ls.c \ |
cmds/modules/pwd/pwd.c \ |
cmds/modules/sleep/sleep.c \ |
cmds/modules/cp/cp.c \ |
cmds/builtins/exit/exit.c \ |
cmds/builtins/cd/cd.c \ |
cmds/mod_cmds.c \ |
cmds/builtin_cmds.c \ |
108,7 → 104,7 |
@$(CC) -M $(CFLAGS) $(INC) $*.c > $*.d |
$(PROGRAM): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(PROGRAM).map |
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(PROGRAM).map |
# Everything else is a phony target |
.PHONY: all clean distclean depend disasm |