Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 3396 → Rev 3397

/branches/sparc/uspace/app/cli/cli.c
File deleted
/branches/sparc/uspace/app/cli/Makefile
File deleted
/branches/sparc/uspace/app/bdsh/scli.c
0,0 → 1,106
/* 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 <string.h>
#include <unistd.h>
#include "config.h"
#include "scli.h"
#include "input.h"
#include "util.h"
#include "errors.h"
#include "cmds/cmds.h"
 
/* 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;
volatile unsigned int cli_interactive = 1;
volatile unsigned int cli_verbocity = 1;
 
/* The official name of this program
* (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);
 
/* Constructor */
static int cli_init(cliuser_t *usr)
{
usr->line = (char *) NULL;
usr->name = "root";
usr->home = "/";
usr->cwd = (char *) NULL;
usr->prompt = (char *) NULL;
chdir(usr->home);
usr->lasterr = 0;
return (int) cli_set_prompt(usr);
}
 
/* Destructor */
static void cli_finit(cliuser_t *usr)
{
if (NULL != usr->line)
free(usr->line);
if (NULL != usr->prompt)
free(usr->prompt);
if (NULL != usr->cwd)
free(usr->cwd);
}
 
int main(int argc, char *argv[])
{
int ret = 0;
 
if (cli_init(&usr))
exit(EXIT_FAILURE);
 
printf("Welcome to %s - %s\nType `help' at any time for usage information.\n",
progname, PACKAGE_STRING);
 
while (!cli_quit) {
get_input(&usr);
if (NULL != usr.line) {
ret = tok_input(&usr);
cli_set_prompt(&usr);
usr.lasterr = ret;
}
}
goto finit;
 
finit:
cli_finit(&usr);
return ret;
}
/branches/sparc/uspace/app/bdsh/scli.h
0,0 → 1,16
#ifndef SCLI_H
#define SCLI_H
 
#include "config.h"
#include <stdint.h>
 
typedef struct {
char *name;
char *home;
char *line;
char *cwd;
char *prompt;
int lasterr;
} cliuser_t;
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/builtins/cd/cd.c
0,0 → 1,106
/* 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 <string.h>
#include <errno.h>
 
#include "util.h"
#include "errors.h"
#include "entry.h"
#include "cmds.h"
#include "cd.h"
 
static char * cmdname = "cd";
 
void * help_cmd_cd(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' changes the current working directory.\n", cmdname);
} else {
printf(
" %s <directory>\n"
" Change directory to <directory>, e.g `%s /sbin'\n",
cmdname, cmdname);
}
 
return CMD_VOID;
}
 
/* This is a very rudamentary 'cd' command. It is not 'link smart' (yet) */
 
int * cmd_cd(char **argv, cliuser_t *usr)
{
int argc, rc = 0;
 
argc = cli_count_args(argv);
 
/* We don't yet play nice with whitespace, a getopt implementation should
* protect "quoted\ destination" as a single argument. Its not our job to
* look for && || or redirection as the tokenizer should have done that
* (currently, it does not) */
 
if (argc > 2) {
cli_error(CL_EFAIL, "Too many arguments to `%s'", cmdname);
return CMD_FAILURE;
}
 
if (argc < 2) {
printf("%s - no directory specified. Try `help %s extended'\n",
cmdname, cmdname);
return CMD_FAILURE;
}
 
/* We have the correct # of arguments
* TODO: handle tidle (~) expansion? */
 
rc = chdir(argv[1]);
 
if (rc == 0) {
cli_set_prompt(usr);
return CMD_SUCCESS;
} else {
switch (rc) {
case ENOMEM:
cli_error(CL_EFAIL, "Destination path too long");
break;
case ENOENT:
cli_error(CL_ENOENT, "Invalid directory `%s'", argv[1]);
break;
default:
cli_error(CL_EFAIL, "Unable to change to `%s'", argv[1]);
break;
}
}
 
return CMD_FAILURE;
}
/branches/sparc/uspace/app/bdsh/cmds/builtins/cd/cd_def.h
0,0 → 1,14
{
"cd",
"Change the current working directory",
&cmd_cd,
&help_cmd_cd,
-1
},
{
"chdir",
NULL,
&cmd_cd,
&help_cmd_cd,
-1
},
/branches/sparc/uspace/app/bdsh/cmds/builtins/cd/entry.h
0,0 → 1,12
#ifndef CD_ENTRY_H_
#define CD_ENTRY_H_
 
#include "scli.h"
 
/* Entry points for the cd command */
extern void * help_cmd_cd(unsigned int);
extern int * cmd_cd(char **, cliuser_t *);
 
#endif
 
 
/branches/sparc/uspace/app/bdsh/cmds/builtins/cd/cd.h
0,0 → 1,7
#ifndef CD_H
#define CD_H
 
/* Prototypes for the cd command (excluding entry points) */
 
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/builtins/builtins.h
0,0 → 1,13
#ifndef BUILTINS_H
#define BUILTINS_H
 
#include "config.h"
 
#include "cd/entry.h"
 
builtin_t builtins[] = {
#include "cd/cd_def.h"
{NULL, NULL, NULL, NULL}
};
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/builtins/README
0,0 → 1,21
Commands that need to modify the running user structure defined in scli.h
should reside here. They (will) have a slightly different prototype that
allows passing the user structure to them for ease of modifications.
 
Examples of what should be a built-in and not a module would be:
 
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 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.
 
 
 
/branches/sparc/uspace/app/bdsh/cmds/builtins/builtin_aliases.h
0,0 → 1,11
#ifndef BUILTIN_ALIASES_H
#define BUILTIN_ALIASES_H
 
/* See modules/module_aliases.h for an explanation of this file */
 
char *builtin_aliases[] = {
"chdir", "cd",
NULL, NULL
};
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/modules/touch/touch.c
0,0 → 1,107
/* 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.
*/
 
/* TODO: Options that people would expect, such as not creating the file if
* it doesn't exist, specifying the access time, etc */
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/types.h>
 
#include "config.h"
#include "errors.h"
#include "util.h"
#include "entry.h"
#include "touch.h"
#include "cmds.h"
 
static char *cmdname = "touch";
 
/* Dispays help for touch in various levels */
void * help_cmd_touch(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' updates access times for files\n", cmdname);
} else {
help_cmd_touch(HELP_SHORT);
printf(" `%s' <file>, if the file does not exist it will be "
"created\n", cmdname);
}
 
return CMD_VOID;
}
 
/* Main entry point for touch, accepts an array of arguments */
int * cmd_touch(char **argv)
{
unsigned int argc, i = 0, ret = 0;
int fd;
char *buff = NULL;
 
DIR *dirp;
 
argc = cli_count_args(argv);
 
if (argc == 1) {
printf("%s - incorrect number of arguments. Try `help %s extended'\n",
cmdname, cmdname);
return CMD_FAILURE;
}
 
for (i = 1; i < argc; i ++) {
buff = cli_strdup(argv[i]);
dirp = opendir(buff);
if (dirp) {
cli_error(CL_ENOTSUP, "%s is a directory", buff);
closedir(dirp);
ret ++;
continue;
}
 
fd = open(buff, O_RDWR | O_CREAT);
if (fd < 0) {
cli_error(CL_EFAIL, "Could not update / create %s ", buff);
ret ++;
continue;
} else
close(fd);
 
free(buff);
}
 
if (ret)
return CMD_FAILURE;
else
return CMD_SUCCESS;
}
 
/branches/sparc/uspace/app/bdsh/cmds/modules/touch/touch_def.h
0,0 → 1,8
{
"touch",
"Create files or update access times",
&cmd_touch,
&help_cmd_touch,
0
},
 
/branches/sparc/uspace/app/bdsh/cmds/modules/touch/entry.h
0,0 → 1,9
#ifndef TOUCH_ENTRY_H
#define TOUCH_ENTRY_H
 
/* Entry points for the touch command */
extern int * cmd_touch(char **);
extern void * help_cmd_touch(unsigned int);
 
#endif /* TOUCH_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/touch/touch.h
0,0 → 1,8
#ifndef TOUCH_H
#define TOUCH_H
 
/* Prototypes for the touch command, excluding entry points */
 
 
#endif /* TOUCH_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c
0,0 → 1,251
/* 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 <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>
#include <stdarg.h>
 
#include "config.h"
#include "errors.h"
#include "util.h"
#include "entry.h"
#include "mkdir.h"
#include "cmds.h"
 
#define MKDIR_VERSION "0.0.1"
 
static char *cmdname = "mkdir";
 
static struct option const long_options[] = {
{"parents", no_argument, 0, 'p'},
{"verbose", no_argument, 0, 'v'},
{"mode", required_argument, 0, 'm'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"follow", no_argument, 0, 'f'},
{0, 0, 0, 0}
};
 
 
void * help_cmd_mkdir(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' creates a new directory\n", cmdname);
} else {
help_cmd_mkdir(HELP_SHORT);
printf(
"Usage: %s [options] <path>\n"
"Options:\n"
" -h, --help A short option summary\n"
" -V, --version Print version information and exit\n"
" -p, --parents Create needed parents for <path>\n"
" -m, --mode Set permissions to [mode] (UNUSED)\n"
" -v, --verbose Be extremely noisy about what is happening\n"
" -f, --follow Go to the new directory once created\n"
"Currently, %s is under development, some options don't work.\n",
cmdname, cmdname);
}
 
return CMD_VOID;
}
 
/* This is kind of clunky, but effective for now */
static unsigned int
create_directory(const char *path, unsigned int p)
{
DIR *dirp;
char *tmp = NULL, *buff = NULL, *wdp = NULL;
char *dirs[255];
unsigned int absolute = 0, i = 0, ret = 0;
 
/* 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))) {
cli_error(CL_ENOMEM, "%s: path too big?", cmdname);
return 1;
}
 
if (NULL == (wdp = (char *) malloc(PATH_MAX))) {
cli_error(CL_ENOMEM, "%s: could not alloc cwd", cmdname);
free(tmp);
return 1;
}
 
/* The only reason for wdp is to be (optionally) verbose */
getcwd(wdp, PATH_MAX);
 
/* Typical use without specifying the creation of parents */
if (p == 0) {
dirp = opendir(tmp);
if (dirp) {
cli_error(CL_EEXISTS, "%s: can not create %s, try -p", cmdname, path);
closedir(dirp);
goto finit;
}
if (-1 == (mkdir(tmp, 0))) {
cli_error(CL_EFAIL, "%s: could not create %s", cmdname, path);
goto finit;
}
}
 
/* Parents need to be created, path has to be broken up */
 
/* See if path[0] is a slash, if so we have to remember to append it */
if (tmp[0] == '/')
absolute = 1;
 
/* TODO: Canonify the path prior to tokenizing it, see below */
dirs[i] = cli_strtok(tmp, "/");
while (dirs[i] && i < 255)
dirs[++i] = cli_strtok(NULL, "/");
 
if (NULL == dirs[0])
return 1;
 
if (absolute == 1) {
asprintf(&buff, "/%s", dirs[0]);
mkdir(buff, 0);
chdir(buff);
free(buff);
getcwd(wdp, PATH_MAX);
i = 1;
} else {
i = 0;
}
 
while (dirs[i] != NULL) {
/* Sometimes make or scripts conjoin odd paths. Account for something
* like this: ../../foo/bar/../foo/foofoo/./bar */
if (!strcmp(dirs[i], "..") || !strcmp(dirs[i], ".")) {
if (0 != (chdir(dirs[i]))) {
cli_error(CL_EFAIL, "%s: impossible path: %s",
cmdname, path);
ret ++;
goto finit;
}
getcwd(wdp, PATH_MAX);
} else {
if (-1 == (mkdir(dirs[i], 0))) {
cli_error(CL_EFAIL,
"%s: failed at %s/%s", wdp, dirs[i]);
ret ++;
goto finit;
}
if (0 != (chdir(dirs[i]))) {
cli_error(CL_EFAIL, "%s: failed creating %s\n",
cmdname, dirs[i]);
ret ++;
break;
}
}
i++;
}
goto finit;
 
finit:
free(wdp);
free(tmp);
return ret;
}
 
int * cmd_mkdir(char **argv)
{
unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
unsigned int verbose = 0;
int c, opt_ind;
char *cwd;
 
argc = cli_count_args(argv);
 
for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
switch (c) {
case 'p':
create_parents = 1;
break;
case 'v':
verbose = 1;
break;
case 'h':
help_cmd_mkdir(HELP_LONG);
return CMD_SUCCESS;
case 'V':
printf("%s\n", MKDIR_VERSION);
return CMD_SUCCESS;
case 'f':
follow = 1;
break;
case 'm':
printf("%s: [W] Ignoring mode %s\n", cmdname, optarg);
break;
}
}
 
argc -= optind;
 
if (argc < 1) {
printf("%s - incorrect number of arguments. Try `%s --help'\n",
cmdname, cmdname);
return CMD_FAILURE;
}
 
if (NULL == (cwd = (char *) malloc(PATH_MAX))) {
cli_error(CL_ENOMEM, "%s: could not allocate cwd", cmdname);
return CMD_FAILURE;
}
 
memset(cwd, 0, sizeof(cwd));
getcwd(cwd, PATH_MAX);
 
for (i = optind; argv[i] != NULL; i++) {
if (verbose == 1)
printf("%s: creating %s%s\n",
cmdname, argv[i],
create_parents ? " (and all parents)" : "");
ret += create_directory(argv[i], create_parents);
}
 
if (follow == 0)
chdir(cwd);
 
free(cwd);
 
if (ret)
return CMD_FAILURE;
else
return CMD_SUCCESS;
}
 
/branches/sparc/uspace/app/bdsh/cmds/modules/mkdir/mkdir_def.h
0,0 → 1,16
{
"mkdir",
"Create new directories",
&cmd_mkdir,
&help_cmd_mkdir,
0
},
 
{
"md",
NULL,
&cmd_mkdir,
&help_cmd_mkdir,
0
},
 
/branches/sparc/uspace/app/bdsh/cmds/modules/mkdir/mkdir.h
0,0 → 1,8
#ifndef MKDIR_H
#define MKDIR_H
 
/* Prototypes for the mkdir command, excluding entry points */
 
static unsigned int create_directory(const char *, unsigned int);
#endif /* MKDIR_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/mkdir/entry.h
0,0 → 1,9
#ifndef MKDIR_ENTRY_H
#define MKDIR_ENTRY_H
 
/* Entry points for the mkdir command */
extern int * cmd_mkdir(char **);
extern void * help_cmd_mkdir(unsigned int);
 
#endif /* MKDIR_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/cat/cat.c
0,0 → 1,186
/* 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 "cat.h"
#include "cmds.h"
 
static char *cmdname = "cat";
#define CAT_VERSION "0.0.1"
#define CAT_DEFAULT_BUFLEN 1024
 
static char *cat_oops = "That option is not yet supported\n";
 
static struct option const long_options[] = {
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'v' },
{ "head", required_argument, 0, 'H' },
{ "tail", required_argument, 0, 't' },
{ "buffer", required_argument, 0, 'b' },
{ "more", no_argument, 0, 'm' },
{ 0, 0, 0, 0 }
};
 
/* Dispays help for cat in various levels */
void * help_cmd_cat(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' shows the contents of files\n", cmdname);
} else {
help_cmd_cat(HELP_SHORT);
printf(
"Usage: %s [options] <file1> [file2] [...]\n"
"Options:\n"
" -h, --help A short option summary\n"
" -v, --version Print version information and exit\n"
" -H, --head ## Print only the first ## bytes\n"
" -t, --tail ## Print only the last ## bytes\n"
" -b, --buffer ## Set the read buffer size to ##\n"
" -m, --more Pause after each screen full\n"
"Currently, %s is under development, some options don't work.\n",
cmdname, cmdname);
}
 
return CMD_VOID;
}
 
static unsigned int cat_file(const char *fname, size_t blen)
{
int fd, bytes = 0, count = 0, reads = 0;
off_t total = 0;
char *buff = NULL;
 
if (-1 == (fd = open(fname, O_RDONLY))) {
printf("Unable to open %s\n", fname);
return 1;
}
 
total = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
 
if (NULL == (buff = (char *) malloc(blen + 1))) {
close(fd);
printf("Unable to allocate enough memory to read %s\n",
fname);
return 1;
}
 
do {
memset(buff, 0, sizeof(buff));
bytes = read(fd, buff, blen);
if (bytes > 0) {
count += bytes;
if (bytes < blen)
buff[bytes] = '\0';
printf(buff);
reads++;
}
} while (bytes > 0);
 
close(fd);
if (bytes == -1) {
printf("Error reading %s\n", fname);
free(buff);
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;
}
 
/* Main entry point for cat, accepts an array of arguments */
int * cmd_cat(char **argv)
{
unsigned int argc, i, ret = 0, buffer = 0;
int c, opt_ind;
 
argc = cli_count_args(argv);
 
for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
c = getopt_long(argc, argv, "hvmH:t:b:", long_options, &opt_ind);
switch (c) {
case 'h':
help_cmd_cat(HELP_LONG);
return CMD_SUCCESS;
case 'v':
printf("%s\n", CAT_VERSION);
return CMD_SUCCESS;
case 'H':
printf(cat_oops);
return CMD_FAILURE;
case 't':
printf(cat_oops);
return CMD_FAILURE;
case 'b':
printf(cat_oops);
break;
case 'm':
printf(cat_oops);
return CMD_FAILURE;
}
}
 
argc -= optind;
 
if (argc < 1) {
printf("%s - incorrect number of arguments. Try `%s --help'\n",
cmdname, cmdname);
return CMD_FAILURE;
}
 
if (buffer <= 0)
buffer = CAT_DEFAULT_BUFLEN;
 
for (i = optind; argv[i] != NULL; i++)
ret += cat_file(argv[i], buffer);
 
if (ret)
return CMD_FAILURE;
else
return CMD_SUCCESS;
}
 
/branches/sparc/uspace/app/bdsh/cmds/modules/cat/cat_def.h
0,0 → 1,8
{
"cat",
"Show the contents of a file",
&cmd_cat,
&help_cmd_cat,
0
},
 
/branches/sparc/uspace/app/bdsh/cmds/modules/cat/cat.h
0,0 → 1,9
#ifndef CAT_H
#define CAT_H
 
/* Prototypes for the cat command, excluding entry points */
 
static unsigned int cat_file(const char *, size_t);
 
#endif /* CAT_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/cat/entry.h
0,0 → 1,9
#ifndef CAT_ENTRY_H
#define CAT_ENTRY_H
 
/* Entry points for the cat command */
extern int * cmd_cat(char **);
extern void * help_cmd_cat(unsigned int);
 
#endif /* CAT_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/help/help.c
0,0 → 1,162
/* 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 <string.h>
 
#include "config.h"
#include "entry.h"
#include "help.h"
#include "cmds.h"
#include "modules.h"
#include "builtins.h"
#include "errors.h"
#include "util.h"
 
static char *cmdname = "help";
extern const char *progname;
 
#define HELP_IS_MODULE 1
#define HELP_IS_BUILTIN 0
#define HELP_IS_RUBBISH -1
 
volatile int mod_switch = -1;
 
/* Just use a pointer here, no need for mod_switch */
static int is_mod_or_builtin(char *cmd)
{
int rc = HELP_IS_RUBBISH;
 
rc = is_builtin(cmd);
if (rc > -1) {
mod_switch = rc;
return HELP_IS_BUILTIN;
}
rc = is_module(cmd);
if (rc > -1) {
mod_switch = rc;
return HELP_IS_MODULE;
}
 
return HELP_IS_RUBBISH;
}
 
void *help_cmd_help(unsigned int level)
{
if (level == HELP_SHORT) {
printf(
"\n %s [command] <extended>\n"
" Use help [command] extended for detailed help on [command] "
", even `help'\n\n", cmdname);
} else {
printf(
"\n `%s' - shows help for commands\n"
" Examples:\n"
" %s [command] Show help for [command]\n"
" %s [command] extended Show extended help for [command]\n"
"\n If no argument is given to %s, a list of commands are shown\n\n",
cmdname, cmdname, cmdname, cmdname);
}
 
return CMD_VOID;
}
 
int *cmd_help(char *argv[])
{
module_t *mod;
builtin_t *cmd;
unsigned int i = 0;
int rc = 0;
int argc;
int level = HELP_SHORT;
 
argc = cli_count_args(argv);
 
if (argc > 3) {
printf("\nToo many arguments to `%s', try:\n", cmdname);
help_cmd_help(HELP_SHORT);
return CMD_FAILURE;
}
 
if (argc == 3) {
if (!strcmp("extended", argv[2]))
level = HELP_LONG;
else
level = HELP_SHORT;
}
 
if (argc > 1) {
rc = is_mod_or_builtin(argv[1]);
switch (rc) {
case HELP_IS_RUBBISH:
printf("Invalid command %s\n", argv[1]);
return CMD_FAILURE;
case HELP_IS_MODULE:
help_module(mod_switch, level);
return CMD_SUCCESS;
case HELP_IS_BUILTIN:
help_builtin(mod_switch, level);
return CMD_SUCCESS;
}
}
 
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++) {
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;
 
/* 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",
cmdname, cmdname, cmdname);
 
return CMD_SUCCESS;
}
/branches/sparc/uspace/app/bdsh/cmds/modules/help/help_def.h
0,0 → 1,7
{
"help",
"Show help for commands",
&cmd_help,
&help_cmd_help,
0
},
/branches/sparc/uspace/app/bdsh/cmds/modules/help/help.h
0,0 → 1,7
#ifndef HELP_H
#define HELP_H
 
/* Prototypes for the help command (excluding entry points) */
static int is_mod_or_builtin(char *);
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/modules/help/entry.h
0,0 → 1,8
#ifndef HELP_ENTRY_H_
#define HELP_ENTRY_H_
 
/* Entry points for the help command */
extern void * help_cmd_help(unsigned int);
extern int * cmd_help(char *[]);
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/modules/ls/ls.c
0,0 → 1,196
/* 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.
*/
 
/* NOTE:
* This is a bit of an ugly hack, working around the absence of fstat / etc.
* As more stuff is completed and exposed in libc, this will improve */
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
 
#include "errors.h"
#include "config.h"
#include "util.h"
#include "entry.h"
#include "ls.h"
#include "cmds.h"
 
static char *cmdname = "ls";
 
static unsigned int ls_scope(const char *path)
{
int fd;
DIR *dirp;
 
dirp = opendir(path);
if (dirp) {
closedir(dirp);
return LS_DIR;
}
 
fd = open(path, O_RDONLY);
if (fd > 0) {
close(fd);
return LS_FILE;
}
 
return LS_BOGUS;
}
 
static void ls_scan_dir(const char *d, DIR *dirp)
{
struct dirent *dp;
unsigned int scope;
char *buff;
 
if (! dirp)
return;
 
buff = (char *)malloc(PATH_MAX);
if (NULL == buff) {
cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
return;
}
 
while ((dp = readdir(dirp))) {
memset(buff, 0, sizeof(buff));
/* Don't worry if inserting a double slash, this will be fixed by
* absolutize() later with subsequent calls to open() or readdir() */
snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name);
scope = ls_scope(buff);
switch (scope) {
case LS_DIR:
ls_print_dir(dp->d_name);
break;
case LS_FILE:
ls_print_file(dp->d_name);
break;
case LS_BOGUS:
/* Odd chance it was deleted from the time readdir() found
* it and the time that it was scoped */
printf("ls: skipping bogus node %s\n", dp->d_name);
break;
}
}
 
free(buff);
 
return;
}
 
/* ls_print_* currently does nothing more than print the entry.
* in the future, we will likely pass the absolute path, and
* some sort of ls_options structure that controls how each
* entry is printed and what is printed about it.
*
* Now we just print basic DOS style lists */
 
static void ls_print_dir(const char *d)
{
printf("%-40s\t<DIR>\n", d);
 
return;
}
 
static void ls_print_file(const char *f)
{
printf("%-40s\n", f);
 
return;
}
 
void * help_cmd_ls(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' lists files and directories.\n", cmdname);
} else {
help_cmd_ls(HELP_SHORT);
printf(" `%s' [path], if no path is given the current "
"working directory is used.\n", cmdname);
}
 
return CMD_VOID;
}
 
int * cmd_ls(char **argv)
{
unsigned int argc;
unsigned int scope;
char *buff;
DIR *dirp;
 
argc = cli_count_args(argv);
 
buff = (char *) malloc(PATH_MAX);
if (NULL == buff) {
cli_error(CL_ENOMEM, "%s: ", cmdname);
return CMD_FAILURE;
}
memset(buff, 0, sizeof(buff));
 
if (argc == 1)
getcwd(buff, PATH_MAX);
else
strncpy(buff, argv[1], PATH_MAX);
 
scope = ls_scope(buff);
 
switch (scope) {
case LS_BOGUS:
cli_error(CL_ENOENT, buff);
free(buff);
return CMD_FAILURE;
case LS_FILE:
ls_print_file(buff);
break;
case LS_DIR:
dirp = opendir(buff);
if (! dirp) {
/* May have been deleted between scoping it and opening it */
cli_error(CL_EFAIL, "Could not stat %s", buff);
free(buff);
return CMD_FAILURE;
}
ls_scan_dir(buff, dirp);
closedir(dirp);
break;
}
 
free(buff);
 
return CMD_SUCCESS;
}
 
/branches/sparc/uspace/app/bdsh/cmds/modules/ls/ls_def.h
0,0 → 1,16
{
"ls",
"List files and directories",
&cmd_ls,
&help_cmd_ls,
0
},
 
{
"dir",
NULL,
&cmd_ls,
&help_cmd_ls,
0
},
 
/branches/sparc/uspace/app/bdsh/cmds/modules/ls/ls.h
0,0 → 1,16
#ifndef LS_H
#define LS_H
 
/* Various values that can be returned by ls_scope() */
#define LS_BOGUS 0
#define LS_FILE 1
#define LS_DIR 2
 
 
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 *);
 
#endif /* LS_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/ls/entry.h
0,0 → 1,9
#ifndef LS_ENTRY_H
#define LS_ENTRY_H
 
/* Entry points for the ls command */
extern int * cmd_ls(char **);
extern void * help_cmd_ls(unsigned int);
 
#endif /* LS_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/rm/rm.c
0,0 → 1,254
/* 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 <fcntl.h>
#include <dirent.h>
#include <assert.h>
#include <getopt.h>
 
#include "config.h"
#include "errors.h"
#include "util.h"
#include "entry.h"
#include "rm.h"
#include "cmds.h"
 
static char *cmdname = "rm";
#define RM_VERSION "0.0.1"
 
static rm_job_t rm;
 
static struct option const long_options[] = {
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'v' },
{ "recursive", no_argument, 0, 'r' },
{ "force", no_argument, 0, 'f' },
{ "safe", no_argument, 0, 's' },
{ 0, 0, 0, 0 }
};
 
static unsigned int rm_start(rm_job_t *rm)
{
rm->recursive = 0;
rm->force = 0;
rm->safe = 0;
 
/* Make sure we can allocate enough memory to store
* what is needed in the job structure */
if (NULL == (rm->nwd = (char *) malloc(PATH_MAX)))
return 0;
memset(rm->nwd, 0, sizeof(rm->nwd));
 
if (NULL == (rm->owd = (char *) malloc(PATH_MAX)))
return 0;
memset(rm->owd, 0, sizeof(rm->owd));
 
if (NULL == (rm->cwd = (char *) malloc(PATH_MAX)))
return 0;
memset(rm->cwd, 0, sizeof(rm->cwd));
 
chdir(".");
 
if (NULL == (getcwd(rm->owd, PATH_MAX)))
return 0;
 
return 1;
}
 
static void rm_end(rm_job_t *rm)
{
if (NULL != rm->nwd)
free(rm->nwd);
 
if (NULL != rm->owd)
free(rm->owd);
 
if (NULL != rm->cwd)
free(rm->cwd);
 
return;
}
 
static unsigned int rm_recursive(const char *path)
{
int rc;
 
/* First see if it will just go away */
rc = rmdir(path);
if (rc == 0)
return 0;
 
/* Its not empty, recursively scan it */
cli_error(CL_ENOTSUP,
"Can not remove %s, directory not empty", path);
return 1;
}
 
static unsigned int rm_single(const char *path)
{
if (unlink(path)) {
cli_error(CL_EFAIL, "rm: could not remove file %s", path);
return 1;
}
return 0;
}
 
static unsigned int rm_scope(const char *path)
{
int fd;
DIR *dirp;
 
dirp = opendir(path);
if (dirp) {
closedir(dirp);
return RM_DIR;
}
 
fd = open(path, O_RDONLY);
if (fd > 0) {
close(fd);
return RM_FILE;
}
 
return RM_BOGUS;
}
 
/* Dispays help for rm in various levels */
void * help_cmd_rm(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' removes files and directories.\n", cmdname);
} else {
help_cmd_rm(HELP_SHORT);
printf(
"Usage: %s [options] <path>\n"
"Options:\n"
" -h, --help A short option summary\n"
" -v, --version Print version information and exit\n"
" -r, --recursive Recursively remove sub directories\n"
" -f, --force Do not prompt prior to removing files\n"
" -s, --safe Stop if directories change during removal\n\n"
"Currently, %s is under development, some options don't work.\n",
cmdname, cmdname);
}
return CMD_VOID;
}
 
/* Main entry point for rm, accepts an array of arguments */
int * cmd_rm(char **argv)
{
unsigned int argc;
unsigned int i, scope, ret = 0;
int c, opt_ind;
size_t len;
char *buff = NULL;
 
argc = cli_count_args(argv);
 
if (argc < 2) {
cli_error(CL_EFAIL,
"%s: insufficient arguments. Try %s --help", cmdname, cmdname);
return CMD_FAILURE;
}
 
if (!rm_start(&rm)) {
cli_error(CL_ENOMEM, "%s: could not initialize", cmdname);
rm_end(&rm);
return CMD_FAILURE;
}
 
for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
c = getopt_long(argc, argv, "hvrfs", long_options, &opt_ind);
switch (c) {
case 'h':
help_cmd_rm(HELP_LONG);
return CMD_SUCCESS;
case 'v':
printf("%s\n", RM_VERSION);
return CMD_SUCCESS;
case 'r':
rm.recursive = 1;
break;
case 'f':
rm.force = 1;
break;
case 's':
rm.safe = 1;
break;
}
}
 
if (optind == argc) {
cli_error(CL_EFAIL,
"%s: insufficient arguments. Try %s --help", cmdname, cmdname);
rm_end(&rm);
return CMD_FAILURE;
}
 
i = optind;
while (NULL != argv[i]) {
len = strlen(argv[i]) + 2;
buff = (char *) realloc(buff, len);
assert(buff != NULL);
memset(buff, 0, sizeof(buff));
snprintf(buff, len, argv[i]);
 
scope = rm_scope(buff);
switch (scope) {
case RM_BOGUS: /* FIXME */
case RM_FILE:
ret += rm_single(buff);
break;
case RM_DIR:
if (! rm.recursive) {
printf("%s is a directory, use -r to remove it.\n", buff);
ret ++;
} else {
ret += rm_recursive(buff);
}
break;
}
i++;
}
 
if (NULL != buff)
free(buff);
 
rm_end(&rm);
 
if (ret)
return CMD_FAILURE;
else
return CMD_SUCCESS;
}
 
/branches/sparc/uspace/app/bdsh/cmds/modules/rm/rm_def.h
0,0 → 1,16
{
"rm",
"Remove files and directories",
&cmd_rm,
&help_cmd_rm,
0
},
 
{
"del",
NULL,
&cmd_rm,
&help_cmd_rm,
0
},
 
/branches/sparc/uspace/app/bdsh/cmds/modules/rm/rm.h
0,0 → 1,43
#ifndef RM_H
#define RM_H
 
/* Return values for rm_scope() */
#define RM_BOGUS 0
#define RM_FILE 1
#define RM_DIR 2
 
/* Flags for rm_update() */
#define _RM_ENTRY 0
#define _RM_ADVANCE 1
#define _RM_REWIND 2
#define _RM_EXIT 3
 
/* A simple job structure */
typedef struct {
/* Options set at run time */
unsigned int force; /* -f option */
unsigned int recursive; /* -r option */
unsigned int safe; /* -s option */
 
/* Keeps track of the job in progress */
int advance; /* How far deep we've gone since entering */
DIR *entry; /* Entry point to the tree being removed */
char *owd; /* Where we were when we invoked rm */
char *cwd; /* Current directory being transversed */
char *nwd; /* Next directory to be transversed */
 
/* Counters */
int f_removed; /* Number of files unlinked */
int d_removed; /* Number of directories unlinked */
} rm_job_t;
 
 
/* Prototypes for the rm command, excluding entry points */
static unsigned int rm_start(rm_job_t *);
static void rm_end(rm_job_t *rm);
static unsigned int rm_recursive(const char *);
static unsigned int rm_single(const char *);
static unsigned int rm_scope(const char *);
 
#endif /* RM_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/rm/entry.h
0,0 → 1,9
#ifndef RM_ENTRY_H
#define RM_ENTRY_H
 
/* Entry points for the rm command */
extern int * cmd_rm(char **);
extern void * help_cmd_rm(unsigned int);
 
#endif /* RM_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/quit/quit_def.h
0,0 → 1,14
{
"quit",
"Exit the console",
&cmd_quit,
&help_cmd_quit,
-1
},
{
"exit",
NULL,
&cmd_quit,
&help_cmd_quit,
-1
},
/branches/sparc/uspace/app/bdsh/cmds/modules/quit/quit.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 "quit.h"
#include "cmds.h"
 
static char *cmdname = "quit";
 
extern volatile unsigned int cli_quit;
extern const char *progname;
 
void * help_cmd_quit(unsigned int level)
{
printf("Type `%s' to exit %s\n", cmdname, progname);
return CMD_VOID;
}
 
/* Quits the program and returns the status of whatever command
* came before invoking 'quit' */
int * cmd_quit(char *argv[])
{
/* Inform that we're outta here */
cli_quit = 1;
return CMD_SUCCESS;
}
/branches/sparc/uspace/app/bdsh/cmds/modules/quit/entry.h
0,0 → 1,10
#ifndef QUIT_ENTRY_H_
#define QUIT_ENTRY_H_
 
/* Entry points for the quit command */
extern void * help_cmd_quit(unsigned int);
extern int * cmd_quit(char *[]);
 
#endif
 
 
/branches/sparc/uspace/app/bdsh/cmds/modules/quit/quit.h
0,0 → 1,6
#ifndef QUIT_H
#define QUIT_H
 
/* Prototypes for the quit command (excluding entry points) */
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/modules/pwd/pwd_def.h
0,0 → 1,7
{
"pwd",
"Prints the current working directory",
&cmd_pwd,
&help_cmd_pwd,
-1
},
/branches/sparc/uspace/app/bdsh/cmds/modules/pwd/pwd.h
0,0 → 1,6
#ifndef PWD_H_
#define PWD_H_
 
/* Prototypes for the pwd command (excluding entry points) */
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/modules/pwd/entry.h
0,0 → 1,12
#ifndef PWD_ENTRY_H
#define PWD_ENTRY_H
 
#include "scli.h"
 
/* Entry points for the pwd command */
extern void * help_cmd_pwd(unsigned int);
extern int * cmd_pwd(char **);
 
#endif
 
 
/branches/sparc/uspace/app/bdsh/cmds/modules/pwd/pwd.c
0,0 → 1,71
/* 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 "errors.h"
#include "entry.h"
#include "cmds.h"
#include "pwd.h"
 
static char * cmdname = "pwd";
 
void * help_cmd_pwd(unsigned int level)
{
printf("`%s' prints your current working directory.\n", cmdname);
return CMD_VOID;
}
 
int * cmd_pwd(char *argv[])
{
char *buff;
 
buff = (char *) malloc(PATH_MAX);
if (NULL == buff) {
cli_error(CL_ENOMEM, "%s:", cmdname);
return CMD_FAILURE;
}
 
memset(buff, 0, sizeof(buff));
getcwd(buff, PATH_MAX);
 
if (! buff) {
cli_error(CL_EFAIL,
"Unable to determine the current working directory");
free(buff);
return CMD_FAILURE;
} else {
printf("%s\n", buff);
free(buff);
return CMD_SUCCESS;
}
}
/branches/sparc/uspace/app/bdsh/cmds/modules/modules.h
0,0 → 1,45
#ifndef MODULES_H
#define MODULES_H
 
/* Each built in function has two files, one being an entry.h file which
* prototypes the run/help entry functions, the other being a .def file
* which fills the modules[] array according to the cmd_t structure
* defined in cmds.h.
*
* To add or remove a module, just make a new directory in cmds/modules
* for it and copy the 'show' example for basics, then include it here.
* (or reverse the process to remove one)
*
* NOTE: See module_ aliases.h as well, this is where aliases (commands that
* share an entry point with others) are indexed */
 
#include "config.h"
 
/* 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"
#include "touch/entry.h"
#include "ls/entry.h"
#include "pwd/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
* are loaded based on what libraries exist on the system. */
 
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"
#include "touch/touch_def.h"
#include "ls/ls_def.h"
#include "pwd/pwd_def.h"
{NULL, NULL, NULL, NULL}
};
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/modules/README
0,0 → 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 (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, 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.
 
 
 
 
/branches/sparc/uspace/app/bdsh/cmds/modules/module_aliases.h
0,0 → 1,22
#ifndef MODULE_ALIASES_H
#define MODULE_ALIASES_H
 
/* Modules that declare multiple names for themselves but use the
* same entry functions are aliases. This array helps to determine if
* a module is an alias, as such it can be invoked differently.
* format is alias , real_name */
 
/* So far, this is only used in the help display but could be used to
* handle a module differently even prior to reaching its entry code.
* For instance, 'exit' could behave differently than 'quit', prior to
* the entry point being reached. */
 
char *mod_aliases[] = {
"exit", "quit",
"md", "mkdir",
"del", "rm",
"dir", "ls",
NULL, NULL
};
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/mknewcmd
0,0 → 1,347
#!/bin/sh
# Copyright (C) 2008 Tim Post - 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.
 
# Script to generate skeletal files for a new command
# Uses `getopt', not quite a bash-ism but might be
# lacking on some legacy systems.
 
# If your shell does not support eval, shift (x) or
# here-now documents, sorry :)
 
usage()
{
def="$DEFAULT_COMMAND"
cat << EOF
\`$PROGNAME' generates skeletal command files to simplify adding commands
Usage: $PROGNAME [options] <location>
Options:
-n, --name Name of the command (default: ${def})
-d, --desc Short (20 30 chars) description of the command
(def: "The $def command")
-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
 
Notes:
You must supply at least the name of the command.
 
If you do not specify a location (i.e. modules/foo), the command will be
created in modules/command_name or builtins/command_name depending on your
selection.
 
This script will only create skeletal files and inform you what headers
need to be modified to incorporate the command. You will also have to
manually update the main Makefile.
 
This script is intended only to be a convenience for developers. Example use:
$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.
 
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.
 
Report bugs to $PROGMAINT
 
EOF
}
 
# Convert a string to all uppercase
toupper()
{
local str="$1"
 
echo "${str}" | tr 'a-z' 'A-Z'
}
 
# Template stored `here-now' style, this generates all files needed
# for a new command according to arguments passed.
generate_code()
{
echo "Creating ${OUTDIR}/${CMDNAME}_def.h ..."
cat << EOF > ${OUTDIR}/${CMDNAME}_def.h
{
"${CMDNAME}",
"${CMDDESC}",
&${CMDENTRY},
&${HELPENTRY},
${CMDRESTRICT}
},
 
EOF
[ -n "${CMDALIAS}" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}_def.h
{
"${CMDALIAS}",
NULL,
&${CMDENTRY},
&${HELPENTRY},
${CMDRESTRICT}
},
 
EOF
local defname=$(toupper "${CMDNAME}")
echo "Creating ${OUTDIR}/entry.h ..."
cat << EOF > ${OUTDIR}/entry.h
#ifndef ${defname}_ENTRY_H
#define ${defname}_ENTRY_H
 
EOF
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/entry.h
/* Entry points for the ${CMDNAME} command */
extern int * ${CMDENTRY}(char **);
extern void * ${HELPENTRY}(unsigned int);
 
#endif /* ${defname}_ENTRY_H */
 
EOF
[ "${CMDTYPE}" = "builtin" ] && cat << EOF >> ${OUTDIR}/entry.h
/* Pick up cliuser_t */
#include "scli.h"
 
/* Entry points for the ${CMDNAME} command */
extern int * ${CMDENTRY}(char **, cliuser_t *);
extern void * ${HELPENTRY}(unsigned int);
 
#endif /* ${defname}_ENTRY_H */
 
EOF
echo "Creating ${OUTDIR}/${CMDNAME}.h ..."
cat << EOF > ${OUTDIR}/${CMDNAME}.h
#ifndef ${defname}_H
#define ${defname}_H
 
/* Prototypes for the ${CMDNAME} command, excluding entry points */
 
 
#endif /* ${defname}_H */
 
EOF
echo "Creating ${OUTDIR}/${CMDNAME}.c ..."
cat << EOF > ${OUTDIR}/${CMDNAME}.c
/* Automatically generated by ${PROGNAME} on ${TIMESTAMP}
* This is machine generated output. The author of ${PROGNAME} claims no
* copyright over the contents of this file. Where legally permitted, the
* contents herein are donated to the public domain.
*
* You should apply any license and copyright that you wish to this file,
* replacing this header in its entirety. */
 
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "util.h"
#include "errors.h"
#include "entry.h"
#include "${CMDNAME}.h"
#include "cmds.h"
 
static char *cmdname = "${CMDNAME}";
 
/* Dispays help for ${CMDNAME} in various levels */
void * ${HELPENTRY}(unsigned int level)
{
printf("This is the %s help for '%s'.\n",
level ? EXT_HELP : SHORT_HELP, cmdname);
return CMD_VOID;
}
 
EOF
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c
/* Main entry point for ${CMDNAME}, accepts an array of arguments */
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)
EOF
cat << EOF >> ${OUTDIR}/${CMDNAME}.c
{
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;
}
 
EOF
printf "Done.\n\nYou should now modify %ss/%ss.h and ../Makefile" \
"${CMDTYPE}" "${CMDTYPE}"
printf " to include your new command.\n"
[ -n "$CMDALIAS" ] && {
printf "\nYou should also modify %ss/%s_aliases.h and " \
"${CMDTYPE}" "${CMDTYPE}"
printf "add %s as an alias for %s\n" \
"${CMDALIAS}" "${CMDNAME}"
}
printf "\nOnce completed, re-run make\n\n"
}
 
# Main program
 
TIMESTAMP="$(date)"
PROGNAME=$(basename $0)
PROGVER="0.0.1"
PROGMAINT="Tim Post <echo@echoreply.us>"
DEFAULT_COMMAND="cmdname"
 
# 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 \
-- "$@") || {
echo "Try $PROGNAME --help for help"
}
 
eval set -- "$TEMP"
 
while true; do
case "$1" in
-n | --name)
CMDNAME="$2"
shift 2
continue
;;
-d | --desc)
CMDDESC="$2"
shift 2
continue
;;
-e | --entry)
CMDENTRY="$2"
shift 2
continue
;;
-h | --help-entry)
HELPENTRY="$2"
shift 2
continue
;;
-a | --alias)
CMDALIAS="$2"
shift 2
continue
;;
-r | --restrict)
CMDRESTRICT="$2"
shift 2
continue
;;
-t | --type)
CMDTYPE="$2"
shift 2
continue
;;
-H | --help)
usage
exit 0
;;
-V | --version)
echo "$PROGVER"
exit 0
;;
--)
break
;;
esac
done
 
# Pick up a location if one was specified
eval set -- "$*"
[ -n "$2" ] && OUTDIR="$2"
 
# Fill in defaults for whatever was not specified
[ -n "$CMDNAME" ] || CMDNAME="$DEFAULT_COMMAND"
[ -n "$CMDDESC" ] || CMDDESC="The $CMDNAME command"
[ -n "$CMDENTRY" ] || CMDENTRY="cmd_${CMDNAME}"
[ -n "$HELPENTRY" ] || HELPENTRY="help_cmd_${CMDNAME}"
[ -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."
exit 1
}
 
mkdir -p ${OUTDIR} >/dev/null 2>&1 || {
echo "Could not create ${OUTDIR}, aborting!"
exit 1
}
 
# Generate the files and inform on how to include them based on options
generate_code
 
exit 0
 
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/sparc/uspace/app/bdsh/cmds/mod_cmds.c
0,0 → 1,156
/* 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.
*/
 
/* NOTES:
* module_* functions are pretty much identical to builtin_* functions at this
* point. On the surface, it would appear that making each function dual purpose
* would be economical.
*
* These are kept separate because the structures (module_t and builtin_t) may
* grow apart and become rather different, even though they're identical at this
* point.
*
* To keep things easy to hack, everything is separated. In reality this only adds
* 6 - 8 extra functions, but keeps each function very easy to read and modify. */
 
/* TODO:
* Many of these could be unsigned, provided the modules and builtins themselves
* can follow suit. Long term goal. */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "errors.h"
#include "cmds.h"
#include "module_aliases.h"
 
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)
{
module_t *mod;
unsigned int i = 0;
 
if (NULL == command)
return -2;
 
for (mod = modules; mod->name != NULL; mod++, i++) {
if (!strcmp(mod->name, command))
return i;
}
 
return -1;
}
 
/* Checks if a module is an alias (sharing an entry point with another
* module). Returns 1 if so */
int is_module_alias(const char *command)
{
unsigned int i = 0;
 
if (NULL == command)
return -1;
 
for(i=0; mod_aliases[i] != NULL; i+=2) {
if (!strcmp(mod_aliases[i], command))
return 1;
}
 
return 0;
}
 
/* Returns the name of the module that an alias points to */
char *alias_for_module(const char *command)
{
unsigned int i = 0;
 
if (NULL == command)
return (char *)NULL;
 
for(i=0; mod_aliases[i] != NULL; i++) {
if (!strcmp(mod_aliases[i], command))
return (char *)mod_aliases[++i];
i++;
}
 
return (char *)NULL;
}
 
 
/* Invokes the 'help' entry function for the module at position (int) module,
* which wants an unsigned int to determine brief or extended display. */
int help_module(int module, unsigned int extended)
{
module_t *mod = modules;
 
mod += module;
 
if (NULL != mod->help) {
mod->help(extended);
return CL_EOK;
} else
return CL_ENOENT;
}
 
/* Invokes the module entry point modules[module], passing argv[] as an argument
* stack. */
int run_module(int module, char *argv[])
{
module_t *mod = modules;
 
mod += module;
 
if (NULL != mod->entry)
return ((int)mod->entry(argv));
 
return CL_ENOENT;
}
/branches/sparc/uspace/app/bdsh/cmds/cmds.h
0,0 → 1,73
#ifndef CMDS_H
#define CMDS_H
 
#include "config.h"
#include "scli.h"
 
/* Temporary to store strings */
#define EXT_HELP "extended"
#define SHORT_HELP "short"
#define TEST_ANNOUNCE "Hello, this is :"
 
/* Simple levels of help displays */
#define HELP_SHORT 0
#define HELP_LONG 1
 
/* Acceptable buffer sizes (for strn functions) */
/* TODO: Move me, other files duplicate these needlessly */
#define BUFF_LARGE 1024
#define BUFF_SMALL 255
 
/* Return macros for int type entry points */
#define CMD_FAILURE (int*)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);
 
/* 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);
 
/* Module structure */
typedef struct {
char *name; /* Name of the command */
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 */
typedef struct {
char *name;
char *desc;
builtin_entry_t entry;
builtin_help_t help;
int restricted;
} builtin_t;
 
/* Declared in cmds/modules/modules.h and cmds/builtins/builtins.h
* respectively */
extern module_t modules[];
extern builtin_t builtins[];
 
/* Prototypes for module launchers */
extern int module_is_restricted(int);
extern int is_module(const char *);
extern int is_module_alias(const char *);
extern char * alias_for_module(const char *);
extern int help_module(int, unsigned int);
extern int run_module(int, char *[]);
 
/* Prototypes for builtin launchers */
extern int builtin_is_restricted(int);
extern int is_builtin(const char *);
extern int is_builtin_alias(const char *);
extern char * alias_for_builtin(const char *);
extern int help_builtin(int, unsigned int);
extern int run_builtin(int, char *[], cliuser_t *);
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/builtin_cmds.c
0,0 → 1,126
/* 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.
*/
 
/* Almost identical (for now) to mod_cmds.c , however this will not be the case
* soon as builtin_t is going to grow way beyond module_t */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "errors.h"
#include "cmds.h"
#include "builtin_aliases.h"
 
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;
unsigned int i = 0;
 
if (NULL == command)
return -2;
 
for (cmd = builtins; cmd->name != NULL; cmd++, i++) {
if (!strcmp(cmd->name, command))
return i;
}
 
return -1;
}
 
int is_builtin_alias(const char *command)
{
unsigned int i = 0;
 
if (NULL == command)
return -1;
 
for(i=0; builtin_aliases[i] != NULL; i+=2) {
if (!strcmp(builtin_aliases[i], command))
return 1;
}
 
return 0;
}
 
char *alias_for_builtin(const char *command)
{
unsigned int i = 0;
 
if (NULL == command)
return (char *)NULL;
 
for(i=0; builtin_aliases[i] != NULL; i++) {
if (!strcmp(builtin_aliases[i], command))
return (char *)builtin_aliases[++i];
i++;
}
 
return (char *)NULL;
}
 
int help_builtin(int builtin, unsigned int extended)
{
builtin_t *cmd = builtins;
 
cmd += builtin;
 
if (NULL != cmd->help) {
cmd->help(extended);
return CL_EOK;
} else
return CL_ENOENT;
}
 
int run_builtin(int builtin, char *argv[], cliuser_t *usr)
{
builtin_t *cmd = builtins;
 
cmd += builtin;
 
if (NULL != cmd->entry)
return((int)cmd->entry(argv, usr));
 
return CL_ENOENT;
}
/branches/sparc/uspace/app/bdsh/util.c
0,0 → 1,284
/* 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.
*
* 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.
*/
 
/* 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>
#include <stdlib.h>
#include <stdarg.h>
 
#include "config.h"
#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)
{
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)
{
unsigned int i;
 
for (i=0; args[i] != NULL; i++);
return i;
}
 
/* (re)allocates memory to store the current working directory, gets
* 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);
if (NULL == usr->prompt) {
cli_error(CL_ENOMEM, "Can not allocate prompt");
cli_errno = CL_ENOMEM;
return 1;
}
memset(usr->prompt, 0, sizeof(usr->prompt));
 
usr->cwd = (char *) realloc(usr->cwd, PATH_MAX);
if (NULL == usr->cwd) {
cli_error(CL_ENOMEM, "Can not allocate cwd");
cli_errno = CL_ENOMEM;
return 1;
}
memset(usr->cwd, 0, sizeof(usr->cwd));
 
usr->cwd = getcwd(usr->cwd, PATH_MAX - 1);
 
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;
}
 
return 0;
}
 
 
/branches/sparc/uspace/app/bdsh/util.h
0,0 → 1,17
#ifndef UTIL_H
#define UTIL_H
 
#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);
 
#endif
/branches/sparc/uspace/app/bdsh/Makefile
0,0 → 1,134
# Copyright (c) 2005, Martin Decky
# All rights reserved.
# 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 ../../../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)\"
 
ifdef REVISION
DEFS += "-DREVISION=\"$(TIMESTAMP)\""
endif
 
ifdef TIMESTAMP
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\""
endif
 
PROGRAM = bdsh
 
# Any directory that cleaning targets should know about
SUBDIRS = \
./ \
cmds/ \
cmds/modules/ \
cmds/modules/help/ \
cmds/modules/quit/ \
cmds/modules/mkdir/ \
cmds/modules/rm/ \
cmds/modules/cat/ \
cmds/modules/touch/ \
cmds/modules/ls/ \
cmds/modules/pwd/ \
cmds/builtins/ \
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 \
cmds/modules/touch/touch.c \
cmds/modules/ls/ls.c \
cmds/modules/pwd/pwd.c \
cmds/builtins/cd/cd.c \
cmds/mod_cmds.c \
cmds/builtin_cmds.c \
errors.c \
input.c \
util.c \
exec.c \
scli.c
 
CFLAGS += -I. -Icmds/ -Icmds/builtins -Icmds/modules
 
OBJECTS = $(SOURCES:.c=.o)
 
# For easy cleaning, *.o is already handled
CLEANDIRS := $(addsuffix *~,$(SUBDIRS))
CLEANDIRS += $(addsuffix *.bak,$(SUBDIRS))
CLEANDIRS += $(addsuffix *.tmp,$(SUBDIRS))
CLEANDIRS += $(addsuffix *.out,$(SUBDIRS))
CLEANDIRS += $(addsuffix *.d,$(SUBDIRS))
CLEANDIRS += $(addsuffix *.gch,$(SUBDIRS) )
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(CFLAGS) $(INC) -c $< -o $@
@$(CC) -M $(CFLAGS) $(INC) $*.c > $*.d
 
$(PROGRAM): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(PROGRAM).map
 
# Everything else is a phony target
.PHONY: all clean distclean depend disasm
 
all: $(PROGRAM) disasm
 
clean:
@-rm -f $(OBJECTS)
@-rm -f $(PROGRAM)
@-rm -f $(PROGRAM).map
@-rm -f $(PROGRAM).disasm
@-rm -f $(CLEANDIRS)
 
depend:
@echo ''
 
disasm:
$(OBJDUMP) -d $(PROGRAM) >$(PROGRAM).disasm
 
distclean: clean
 
# Do not delete - dependencies
-include $(OBJECTS:.o=.d)
/branches/sparc/uspace/app/bdsh/input.c
0,0 → 1,177
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
* Copyright (c) 2008, Jiri Svoboda - 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 <string.h>
#include <io/stream.h>
 
#include "config.h"
#include "util.h"
#include "scli.h"
#include "input.h"
#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 */
int tok_input(cliuser_t *usr)
{
char *cmd[WORD_MAX];
int n = 0, i = 0;
int rc = 0;
char *tmp;
 
if (NULL == usr->line)
return CL_EFAIL;
 
tmp = cli_strdup(usr->line);
 
/* Break up what the user typed, space delimited */
 
/* TODO: Protect things in quotes / ticks, expand wildcards */
cmd[n] = cli_strtok(tmp, " ");
while (cmd[n] && n < WORD_MAX) {
cmd[++n] = cli_strtok(NULL, " ");
}
 
/* We have rubbish */
if (NULL == cmd[0]) {
rc = CL_ENOENT;
goto finit;
}
 
/* 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 */
} 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;
}
 
finit:
if (NULL != usr->line) {
free(usr->line);
usr->line = (char *) NULL;
}
if (NULL != tmp)
free(tmp);
 
return rc;
}
 
/* Borrowed from Jiri Svoboda's 'cli' uspace app */
static void read_line(char *buffer, int n)
{
char c;
int chars;
 
chars = 0;
while (chars < n - 1) {
c = getchar();
if (c < 0)
return;
if (c == '\n')
break;
if (c == '\b') {
if (chars > 0) {
putchar('\b');
--chars;
}
continue;
}
putchar(c);
buffer[chars++] = c;
}
putchar('\n');
buffer[chars] = '\0';
}
 
/* TODO:
* Implement something like editline() / readline(), if even
* just for command history and making arrows work. */
void get_input(cliuser_t *usr)
{
char line[INPUT_MAX];
size_t len = 0;
 
printf("%s", usr->prompt);
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);
 
return;
}
 
/branches/sparc/uspace/app/bdsh/input.h
0,0 → 1,11
#ifndef INPUT_H
#define INPUT_H
 
#include "cmds/cmds.h"
 
/* prototypes */
 
extern void get_input(cliuser_t *);
extern int tok_input(cliuser_t *);
 
#endif
/branches/sparc/uspace/app/bdsh/exec.c
0,0 → 1,129
/* 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.
*/
 
/* The VERY basics of execute in place support. These are buggy, leaky
* and not nearly done. Only here for beta testing!! You were warned!!
* TODO:
* Hash command lookups to save time
* Create a running pointer to **path and advance/rewind it as we go */
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
 
#include "config.h"
#include "util.h"
#include "exec.h"
#include "errors.h"
 
/* FIXME: Just have find_command() return an allocated string */
char *found;
 
static char *find_command(char *);
static unsigned int try_access(const char *);
 
/* work-around for access() */
static unsigned int try_access(const char *f)
{
int fd;
 
fd = open(f, O_RDONLY);
if (fd > -1) {
close(fd);
return 0;
} else
return -1;
}
 
/* Returns the full path of "cmd" if cmd is found, else just hand back
* cmd as it was presented */
static char *find_command(char *cmd)
{
char *path_tok;
char *path[PATH_MAX];
int n = 0, i = 0;
size_t x = strlen(cmd) + 2;
 
found = (char *)malloc(PATH_MAX);
 
/* The user has specified a full or relative path, just give it back. */
if (-1 != try_access(cmd)) {
return (char *) cmd;
}
 
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]) {
if ((strlen(path[n]) + x ) > PATH_MAX) {
cli_error(CL_ENOTSUP,
"Segment %d of path is too large, search ends at segment %d",
n, n-1);
break;
}
path[++n] = cli_strtok(NULL, PATH_DELIM);
}
 
/* We now have n places to look for the command */
for (i=0; path[i]; i++) {
memset(found, 0, sizeof(found));
snprintf(found, PATH_MAX, "%s/%s", path[i], cmd);
if (-1 != try_access(found)) {
free(path_tok);
return (char *) found;
}
}
 
/* We didn't find it, just give it back as-is. */
free(path_tok);
return (char *) cmd;
}
 
unsigned int try_exec(char *cmd, char **argv)
{
task_id_t tid;
char *tmp;
 
tmp = cli_strdup(find_command(cmd));
free(found);
 
tid = task_spawn((const char *)tmp, (const char **)argv);
free(tmp);
 
if (tid == 0) {
cli_error(CL_EEXEC, "Can not spawn %s", cmd);
return 1;
} else {
return 0;
}
}
/branches/sparc/uspace/app/bdsh/exec.h
0,0 → 1,7
#ifndef EXEC_H
#define EXEC_H
 
#include <task.h>
 
extern unsigned int try_exec(char *, char **);
#endif
/branches/sparc/uspace/app/bdsh/README
0,0 → 1,268
BDSH - The Brain Dead Shell | Design Documentation
--------------------------------------------------
 
Overview:
=========
 
BDSH was written as a drop in command line interface for HelenOS to permit
interactive access to persistent file systems in development. BDSH was
written from scratch with a very limited userspace standard C library in
mind. Much like the popular Busybox program, BDSH provides a very limited
shell with limited common UNIX creature comforts built in.
 
Porting Busybox (and by extension ASH) would have taken much longer to
complete, much less make stable due to stark differences between Linux and
Spartan with regards to IPC, term I/O and process creation. BDSH was written
and made stable within the space of less than 30 days.
 
BDSH will eventually evolve and be refined into the HelenOS equivalent
of Busybox. While BDSH is now very intrinsic to HelenOS, its structure and
use of strictly lower level functions makes it extremely easy to port.
 
Design:
=======
 
BDSH is made up of three basic components:
 
1. Main i/o, error handling and task management
2. The builtin sub system
3. The module sub system
 
The main part handles user input, reports errors, spawns external tasks and
provides a convenient entry point for built-in and modular commands. A simple
structure, cliuser_t keeps track of the user's vitals, such as their current
working directory (and eventually uid, home directory, etc if they apply).
 
This part defines and exposes all functions that are not intrinsic to a
certain built in or modular command. For instance: string handlers,
module/builtin search and launch functions, error handlers and other things
can be found here.
 
Builtin commands are commands that must have access to cliuser_t, which is
not exposed to modular commands. For instance, the 'cd' command must update
the current working directory, which is stored in cliuser_t. As such, the
entry types for builtin commands are slightly different.
 
Modular commands do not need anything more than the basic functions that are
exposed by default. They do not need to modify cliuser_t, they are just self
contained. A modular command could very easily be made into a stand alone
program, likewise any stand alone program could easily become a modular
command.
 
Both modular and builtin commands share two things in common. Both must have
two entry points, one to invoke the command and one to invoke a help display
for the command. Exec (main()) entry points are int * and are expected to
return a value. Help entry points are void *, no return value is expected.
 
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);
 
/* 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);
 
As you can see, both modular and builtin commands expect an array of
arguments, however bulitins also expect to be pointed to cliuser_t.
 
Both are defined with the same simple structure:
 
/* Module structure */
typedef struct {
char *name; /* Name of the command */
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;
 
NOTE: Builtin commands may grow in this respect, that is why they are
defined separately.
 
Builtins, of course, would use the builtin_entry_t type. The name of the
command is used to associate user input to a possible entry point. The
description is a short (40 - 60 chars) summary of what the command does. Both
entry points are then defined, and the restrict value is used to determine a
commands availability.
 
Restriction levels are easy, a command is either available exclusively within
interactive mode, exclusively within non-interactive mode or both. If you are
looking at a prompt, you are in interactive mode. If you issue a command like
this:
 
/sbin/bdsh command [arg1] [arg2]
 
... you are in non interactive mode. This is done when you need to force the
parent shell to be the one who actually handles the command, or ensure that
/sbin/ls was used in lieu of the built in 'ls' when in non-interactive mode.
 
The values are:
0 : Unrestricted
-1 : Interactive only
1 : Non-interactive only
 
A script to generate skeletal files for a new command is included, it can be
found in cmds/mknewcmd. To generate a new modular command named 'foo', which
should also be reachable by typing 'f00', you would issue this command:
 
./mknewcmd -n foo -a f00 -t module
 
This generates all needed files and instructs you on how to include your new
command in the build and make it accessible. By default, the command will be
unrestricted. Builtin commands can be created by changing 'module' to
'builtin'
 
There are more options to mknewcmd, which allow you to specify the
description, entry point, help entry point, or restriction. By default, names
just follow the command such as cmd_foo(), help_cmd_foo(), 'The foo command',
etc. If you want to see the options and explanations in detail, use
./mknewcmd --help.
 
When working with commands, keep in mind that only the main and help entry
points need to be exposed. If commands share the same functions, put them
where they are exposed to all commands, without the potential oops of those
functions going away if the command is eliminated in favor of a stand alone
external program.
 
The util.c file is a great place to put those types of functions.
 
Also, be careful with globals, option structures, etc. The compiler will
generally tell you if you've made a mistake, however declaring:
 
volatile int foo
 
... in a command will allow for anything else to pick it up. Sometimes
this could be desirable .. other times not. When communicating between
builtins and the main system, try to use cliuser_t. The one exception
for this is the cli_quit global, since everything may at some point
need to check it. Modules should only communicate their return value.
 
Symbolic constants that everything needs should go in the config.h file,
however this is not the place to define shared macros.
 
Making a program into a module
==============================
 
If you have some neat program that would be useful as a modular command,
converting it is not very hard. The following steps should get you through
the process easily (assuming your program is named 'foo'):
 
1: Use mknewcmd to generate the skeletal files.
 
2: Change your "usage()" command as shown:
-- void usage(...)
++ void * help_cmd_foo(unsigned int level)
-- return;
++ retrn CMD_VOID;
 
'level' is either 0 or 1, indicating the level of help requested.
If the help / usage function currently exits based on how it is
called, you'll need to change it.
 
3: Change the programs "main()" as shown:
-- int main(int argc, 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)
 
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)
 
5: Copy/paste to the stub generated by mknewcmd then add your files to the
Makefile. Be sure to add any directories that you made to the SUBDIRS so
that a 'make clean' will clean them.
 
Provided that all functions that your calling are available in the
userspace C library, your program should compile just fine and appear
as a modular command.
 
Overcoming userspace libc obstacles
===================================
 
A quick glance through the util.c file will reveal functions like
cli_strdup(), cli_strtok(), cli_strtok_r() and more. Those are functions
that were missing from userspace libc when BDSH was born. Later, after
porting what was needed from FBSD/NBSD, the real functions appeared in
the userspace libc after being tested in their cli_* implementations.
 
Those functions remain because they guarantee that bdsh will work even
on systems that lack them. Additionally, more BDSH specific stuff can
go into them, such as error handling and reporting when malloc() fails.
 
You will also notice that FILE, fopen() (and all friends), ato*() and
other common things might be missing. The HelenOS userspace C library is
still very young, you are sure to run into something that you want/need
which is missing.
 
When that happens, you have three options:
 
1 - Implement it internally in util.c , when its tested and stable send a
patch to HelenOS asking for your function to be included in libc. This is
the best option, as you not only improve BDSH .. but HelenOS as a whole.
 
2 - Work around it. Not everyone can implement / port fopen() and all of
its friends. Make open(), read(), write() (etc) work if at all possible.
 
3 - Send an e-mail to the HelenOS development mailing list. Explain why you
need the function and what its absence is holding up.
 
If what you need is part of a library that is typically a shared object, try
to implement a 'mini' version of it. Currently, all userspace applications
are statically linked. Giving up creature comforts for size while avoiding
temporary 'band aids' is never frowned upon.
 
Most of all, don't get discouraged .. ask for some help prior to giving up
if you just can't accomplish something with the limited means provided.
 
Contributing
============
 
I will take any well written patch that sanely improves or expands BDSH. Send
me a patch against the trunk revision, or, if you like a Mercurial repository
is also maintained at http://echoreply.us/hg/bdsh.hg and kept in sync with
the trunk.
 
Please be sure to follow the simple coding standards outlined at
http://www.helenos.eu/cstyle (mostly just regarding formatting), test your
changes and make sure your patch applies cleanly against the latest revision.
 
All patches submitted must be your original code, or a derivative work of
something licensed under the same 3 clause BSD license as BDSH. See LICENSE
for more information.
 
When sending patches, you agree that your work will be published under the
same 3 clause BSD license as BDSH itself. Failure to ensure that anything
you used is not under the same or less restrictive license could cause major
issues for BDSH in the future .. please be sure. Also, please don't forget
to add yourself in the AUTHORS file, as I am horrible about keeping such
things up to date.
 
 
 
 
/branches/sparc/uspace/app/bdsh/errors.c
0,0 → 1,87
/* 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 <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
 
#include "config.h"
#include "errors.h"
#include "errstr.h"
 
volatile int cli_errno = CL_EOK;
extern volatile unsigned int cli_quit;
 
/* Error printing, translation and handling functions */
 
 
/* Look up errno in cl_errors and return the corresponding string.
* Return NULL if not found */
static char *err2str(int err)
{
 
if (NULL != cl_errors[err])
return cl_errors[err];
 
return (char *)NULL;
}
 
/* Print an error report signifying errno, which is translated to
* 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, ...)
{
va_list vargs;
va_start(vargs, fmt);
vprintf(fmt, vargs);
va_end(vargs);
 
if (NULL != err2str(err))
printf(" (%s)\n", err2str(err));
else
printf(" (Unknown Error %d)\n", err);
 
/* 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;
 
}
 
 
 
 
 
/branches/sparc/uspace/app/bdsh/errors.h
0,0 → 1,22
#ifndef ERRORS_H
#define ERRORS_H
 
/* Various error levels */
#define CL_EFATAL -1
#define CL_EOK 0
#define CL_EFAIL 1
#define CL_EBUSY 2
#define CL_ENOENT 3
#define CL_ENOMEM 4
#define CL_EPERM 5
#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 void cli_error(int, const char *, ...);
 
#endif
/branches/sparc/uspace/app/bdsh/errstr.h
0,0 → 1,23
#ifndef ERRSTR_H
#define ERRSTR_H
 
/* Simple array to translate error codes to meaningful strings */
 
static char *cl_errors[] = {
"Success",
"Failure",
"Busy",
"No Such Entry",
"Not Enough Memory",
"Permission Denied",
"Method Not Supported",
"Bad command or file name",
"Entry already exists",
"Object too large",
NULL
};
 
static char *err2str(int);
 
#endif
 
/branches/sparc/uspace/app/bdsh/TODO
0,0 → 1,57
This is a very brain dead shell. It needs some love, coffee or perhaps beer.
Currently, you can't even really call it a shell, its more of a CLI that
offers some shell like creature comforts.
 
This was written in a hurry to provide some means of testing persistent file
systems in HelenOS. It does its job, its nowhere near complete but it is
actively developed. If your reading this, its likely that you're looking for
some functionality that is not yet present. Prior to filing a bug report,
please make sure that what you want is not on the list below.
 
A list of things to do:
-----------------------
 
* rm: add support for recursively removing directories and files therein
 
* Port an editor (vim?)
 
* Finish cat / cp
 
* Support basic redirection (i.e ls > foo.txt)
 
* Expand wildcards (i.e. *.txt), don't worry about variables for now
 
* Basic scripting
 
* Hash previously found commands
 
* Improve input, add history / etc (port libedit?)
 
* Add wrappers for signal, sigaction to make ports to modules easier
 
* Add 'echo' and 'printf' modules.
 
Regarding POSIX:
----------------
POSIX is a standard for Unix-like operating systems. HelenOS is (mostly) just
a kernel at this point with a few userspace programs that facilitate testing
of the kernel and file systems.
 
HelenOS is not a Unix-like operating system. HelenOS is its own thing, a modern
microkernel OS and many directions are not yet set.
 
Please do not e-mail me to point out that modular implementations that resemble
typical core utilities do not conform to some POSIX standard, these are temporary
and serve the useful purpose of testing persistent file systems.
 
Contributing:
-------------
If you feel like doing any of the above to-do items, I am echo@echoreply.us. Please
e-mail me and let me know your working on something so that I do not unwittingly
duplicate your efforts. You can also e-mail the HelenOS list directly:
 
HelenOS development mailing list <helenos-devel@lists.modry.cz>
Subscribe here if you like: http://lists.modry.cz/cgi-bin/listinfo/helenos-devel
 
Cheers and happy hacking!
--Tim
/branches/sparc/uspace/app/bdsh/config.h
0,0 → 1,33
/* 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 */
 
/* Specific port work-arounds : */
#define PATH_MAX 255
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 0
 
/* Work around for getenv() */
#define PATH "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
#define PATH_DELIM ":"
 
/* Used in many places */
#define SMALL_BUFLEN 256
#define LARGE_BUFLEN 1024
 
/* How many words (arguments) are permitted, how big can a whole
* sentence be? Similar to ARG_MAX */
#define WORD_MAX 255
#define INPUT_MAX 1024
 
/* Leftovers from Autoconf */
#define PACKAGE_MAINTAINER "Tim Post"
#define PACKAGE_BUGREPORT "echo@echoreply.us"
#define PACKAGE_NAME "bdsh"
#define PACKAGE_STRING "The brain dead shell"
#define PACKAGE_TARNAME "scli"
#define PACKAGE_VERSION "0.0.1"
 
 
 
/branches/sparc/uspace/app/bdsh/AUTHORS
0,0 → 1,17
 
Written by Tim Post <echo@echoreply.us> to serve as a primitive shell
for HelenOS, or as a template to make a command line interface that
offers shell like creature comforts.
 
This program was mostly written from scratch, some existing code was
used from other various free software projects:
 
* 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/sparc/uspace/app/bdsh/LICENSE
0,0 → 1,28
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.
/branches/sparc/uspace/app/init/init.c
98,10 → 98,8
{
info_print();
sleep(5); // FIXME
bool has_tmpfs = false;
bool has_fat = false;
if (!(has_tmpfs = mount_fs("tmpfs")) && !(has_fat = mount_fs("fat"))) {
if (!mount_fs("tmpfs") && !mount_fs("fat")) {
printf(NAME ": Exiting\n");
return -1;
}
114,18 → 112,7
console_wait();
version_print();
/*
* Spawn file system servers that were not loaded as init tasks.
*/
if (!has_fat)
spawn("/sbin/fat");
if (!has_tmpfs)
spawn("/sbin/tmpfs");
spawn("/sbin/tetris");
spawn("/sbin/cli");
// FIXME: spawn("/sbin/tester");
spawn("/sbin/klog");
spawn("/sbin/bdsh");
return 0;
}
/branches/sparc/uspace/lib/libc/include/getopt.h
0,0 → 1,71
/* $NetBSD: getopt.h,v 1.10.6.1 2008/05/18 12:30:09 yamt Exp $ */
 
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
 
/* Ported to HelenOS August 2008 by Tim Post <echo@echoreply.us> */
 
#ifndef _GETOPT_H_
#define _GETOPT_H_
 
#include <unistd.h>
 
/*
* Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions
*/
#define no_argument 0
#define required_argument 1
#define optional_argument 2
 
struct option {
/* name of long option */
const char *name;
/*
* one of no_argument, required_argument, and optional_argument:
* whether option takes an argument
*/
int has_arg;
/* if not NULL, set *flag to val when option found */
int *flag;
/* if flag not NULL, value to set *flag to; else return value */
int val;
};
 
/* HelenOS Port - These need to be exposed for legacy getopt() */
extern char *optarg;
extern int optind, opterr, optopt;
extern int optreset;
 
int getopt_long(int, char * const *, const char *,
const struct option *, int *);
 
/* HelenOS Port : Expose legacy getopt() */
int getopt(int, char * const [], const char *);
 
#endif /* !_GETOPT_H_ */
/branches/sparc/uspace/lib/libc/include/stdio.h
54,16 → 54,17
 
extern int getchar(void);
 
extern int puts(const char * str);
extern int putchar(int c);
extern int puts(const char *);
extern int putchar(int);
 
extern int printf(const char *fmt, ...);
extern int sprintf(char *str, const char *fmt, ...);
extern int snprintf(char *str, size_t size, const char *fmt, ...);
extern int printf(const char *, ...);
extern int asprintf(char **, const char *, ...);
extern int sprintf(char *, const char *fmt, ...);
extern int snprintf(char *, size_t , const char *, ...);
 
extern int vprintf(const char *fmt, va_list ap);
extern int vsprintf(char *str, const char *fmt, va_list ap);
extern int vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
extern int vprintf(const char *, va_list);
extern int vsprintf(char *, const char *, va_list);
extern int vsnprintf(char *, size_t, const char *, va_list);
 
#define fprintf(f, fmt, ...) printf(fmt, ##__VA_ARGS__)
 
/branches/sparc/uspace/lib/libc/generic/getopt.c
0,0 → 1,478
/* $NetBSD: getopt_long.c,v 1.21.4.1 2008/01/09 01:34:14 matt Exp $ */
 
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
 
/* Ported to HelenOS August 2008 by Tim Post <echo@echoreply.us> */
 
#include <assert.h>
#include <stdarg.h>
#include <err.h>
#include <errno.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
 
/* HelenOS Port : We're incorporating only the modern getopt_long with wrappers
* to keep legacy getopt() usage from breaking. All references to REPLACE_GETOPT
* are dropped, we just include the code */
 
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
 
 
#define IGNORE_FIRST (*options == '-' || *options == '+')
#define PRINT_ERROR ((opterr) && ((*options != ':') \
|| (IGNORE_FIRST && options[1] != ':')))
/*HelenOS Port - POSIXLY_CORRECT is always false */
#define IS_POSIXLY_CORRECT 0
#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
/* XXX: GNU ignores PC if *options == '-' */
#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
 
/* return values */
#define BADCH (int)'?'
#define BADARG ((IGNORE_FIRST && options[1] == ':') \
|| (*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
 
#define EMSG ""
 
static int getopt_internal(int, char **, const char *);
static int gcd(int, int);
static void permute_args(int, int, int, char **);
 
static const char *place = EMSG; /* option letter processing */
 
/* XXX: set optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */
 
/* Error messages */
 
/* HelenOS Port: Calls to warnx() were eliminated (as we have no stderr that
* may be redirected) and replaced with printf. As such, error messages now
* end in a newline */
 
static const char recargchar[] = "option requires an argument -- %c\n";
static const char recargstring[] = "option requires an argument -- %s\n";
static const char ambig[] = "ambiguous option -- %.*s\n";
static const char noarg[] = "option doesn't take an argument -- %.*s\n";
static const char illoptchar[] = "unknown option -- %c\n";
static const char illoptstring[] = "unknown option -- %s\n";
 
 
/*
* Compute the greatest common divisor of a and b.
*/
static int
gcd(a, b)
int a;
int b;
{
int c;
 
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
return b;
}
 
/*
* Exchange the block from nonopt_start to nonopt_end with the block
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void
permute_args(panonopt_start, panonopt_end, opt_end, nargv)
int panonopt_start;
int panonopt_end;
int opt_end;
char **nargv;
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
 
assert(nargv != NULL);
 
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
 
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
swap = nargv[pos];
nargv[pos] = nargv[cstart];
nargv[cstart] = swap;
}
}
}
 
/*
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
* Returns -2 if -- is found (can be long option or end of options marker).
*/
static int
getopt_internal(nargc, nargv, options)
int nargc;
char **nargv;
const char *options;
{
char *oli; /* option letter list index */
int optchar;
 
assert(nargv != NULL);
assert(options != NULL);
 
optarg = NULL;
 
/*
* XXX Some programs (like rsyncd) expect to be able to
* XXX re-initialize optind to 0 and have getopt_long(3)
* XXX properly function again. Work around this braindamage.
*/
if (optind == 0)
optind = 1;
 
if (optreset)
nonopt_start = nonopt_end = -1;
start:
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return -1;
}
if ((*(place = nargv[optind]) != '-')
|| (place[1] == '\0')) { /* found non-option */
place = EMSG;
if (IN_ORDER) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return INORDER;
}
if (!PERMUTE) {
/*
* if no permutation wanted, stop parsing
* at first non-option
*/
return -1;
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
(nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
if (place[1] && *++place == '-') { /* found "--" */
place++;
return -2;
}
}
if ((optchar = (int)*place++) == (int)':' ||
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
/* option letter unknown or ':' */
if (!*place)
++optind;
if (PRINT_ERROR)
printf(illoptchar, optchar);
optopt = optchar;
return BADCH;
}
if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
/* XXX: what if no long options provided (called by getopt)? */
if (*place)
return -2;
 
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
printf(recargchar, optchar);
optopt = optchar;
return BADARG;
} else /* white space */
place = nargv[optind];
/*
* Handle -W arg the same as --arg (which causes getopt to
* stop parsing).
*/
return -2;
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = *place;
/* XXX: disable test for :: if PC? (GNU doesn't) */
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
printf(recargchar, optchar);
optopt = optchar;
return BADARG;
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return optchar;
}
 
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(nargc, nargv, options)
int nargc;
char * const *nargv;
const char *options;
{
int retval;
 
assert(nargv != NULL);
assert(options != NULL);
 
retval = getopt_internal(nargc, (char **)nargv, options);
if (retval == -2) {
++optind;
/*
* We found an option (--), so if we skipped non-options,
* we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end, optind,
(char **)nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
retval = -1;
}
return retval;
}
 
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(nargc, nargv, options, long_options, idx)
int nargc;
char * const *nargv;
const char *options;
const struct option *long_options;
int *idx;
{
int retval;
 
#define IDENTICAL_INTERPRETATION(_x, _y) \
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
long_options[(_x)].flag == long_options[(_y)].flag && \
long_options[(_x)].val == long_options[(_y)].val)
 
assert(nargv != NULL);
assert(options != NULL);
assert(long_options != NULL);
/* idx may be NULL */
 
retval = getopt_internal(nargc, (char **)nargv, options);
if (retval == -2) {
char *current_argv, *has_equal;
size_t current_argv_len;
int i, ambiguous, match;
 
current_argv = (char *)place;
match = -1;
ambiguous = 0;
 
optind++;
place = EMSG;
 
if (*current_argv == '\0') { /* found "--" */
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, (char **)nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return -1;
}
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
continue;
 
if (strlen(long_options[i].name) ==
(unsigned)current_argv_len) {
/* exact match */
match = i;
ambiguous = 0;
break;
}
if (match == -1) /* partial match */
match = i;
else if (!IDENTICAL_INTERPRETATION(i, match))
ambiguous = 1;
}
if (ambiguous) {
/* ambiguous abbreviation */
if (PRINT_ERROR)
printf(ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return BADCH;
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
printf(noarg, (int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of
* flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
return BADARG;
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else if (long_options[match].has_arg ==
required_argument) {
/*
* optional argument doesn't use
* next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument; leading ':'
* indicates no error should be generated
*/
if (PRINT_ERROR)
printf(recargstring, current_argv);
/*
* XXX: GNU sets optopt to val regardless
* of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return BADARG;
}
} else { /* unknown option */
if (PRINT_ERROR)
printf(illoptstring, current_argv);
optopt = 0;
return BADCH;
}
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
retval = 0;
} else
retval = long_options[match].val;
if (idx)
*idx = match;
}
return retval;
#undef IDENTICAL_INTERPRETATION
}
 
/branches/sparc/uspace/lib/libc/generic/ipc.c
682,7 → 682,7
{
int res;
sysarg_t tmp_flags;
res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst,
res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst,
(ipcarg_t) size, arg, NULL, &tmp_flags);
if (flags)
*flags = tmp_flags;
742,7 → 742,7
*/
int ipc_share_out_start(int phoneid, void *src, int flags)
{
return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0,
return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0,
(ipcarg_t) flags);
}
 
/branches/sparc/uspace/lib/libc/generic/io/sprintf.c
48,7 → 48,6
va_start(args, fmt);
ret = vsprintf(str, fmt, args);
 
va_end(args);
 
return ret;
/branches/sparc/uspace/lib/libc/generic/io/asprintf.c
0,0 → 1,79
/*
* Copyright (c) 2006 Josef Cejka
* Copyright (c) 2008 Jakub Jermar
* 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.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <io/printf_core.h>
 
static int asprintf_prewrite(const char *str, size_t count, void *unused)
{
return count;
}
 
/** Allocate and print to string.
*
* @param strp Address of the pointer where to store the address of
* the newly allocated string.
* @fmt Format strin.
*
* @return Number of characters printed or a negative error code.
*/
int asprintf(char **strp, const char *fmt, ...)
{
struct printf_spec ps = {
asprintf_prewrite,
NULL
};
int ret;
va_list args;
 
va_start(args, fmt);
ret = printf_core(fmt, &ps, args);
va_end(args);
if (ret > 0) {
*strp = malloc(ret + 20);
if (!*strp)
return -1;
va_start(args, fmt);
vsprintf(*strp, fmt, args);
va_end(args);
}
 
return ret;
}
 
/** @}
*/
/branches/sparc/uspace/lib/libc/generic/io/vsnprintf.c
38,22 → 38,27
#include <io/printf_core.h>
 
struct vsnprintf_data {
size_t size; /* total space for string */
size_t len; /* count of currently used characters */
char *string; /* destination string */
size_t size; /* total space for string */
size_t len; /* count of currently used characters */
char *string; /* destination string */
};
 
/** Write string to given buffer.
* Write at most data->size characters including trailing zero. According to C99 has snprintf to return number
* of characters that would have been written if enough space had been available. Hence the return value is not
* number of really printed characters but size of input string. Number of really used characters
* is stored in data->len.
* @param str source string to print
* @param count size of source string
* @param data structure with destination string, counter of used space and total string size.
* @return number of characters to print (not characters really printed!)
* Write at most data->size characters including trailing zero. According to C99
* has snprintf to return number of characters that would have been written if
* enough space had been available. Hence the return value is not number of
* really printed characters but size of input string. Number of really used
* characters is stored in data->len.
*
* @param str Source string to print.
* @param count Size of the source string.
* @param data Structure with destination string, counter of used space
* and total string size.
* @return Number of characters to print (not characters really
* printed!)
*/
static int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data)
static int
vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data)
{
size_t i;
i = data->size - data->len;
63,7 → 68,10
}
if (i == 1) {
/* We have only one free byte left in buffer => write there trailing zero */
/*
* We have only one free byte left in buffer => write there
* trailing zero.
*/
data->string[data->size - 1] = 0;
data->len = data->size;
return count;
70,17 → 78,23
}
if (i <= count) {
/* We have not enought space for whole string with the trailing zero => print only a part of string */
memcpy((void *)(data->string + data->len), (void *)str, i - 1);
data->string[data->size - 1] = 0;
data->len = data->size;
return count;
/*
* We have not enought space for whole string with the trailing
* zero => print only a part of string.
*/
memcpy((void *)(data->string + data->len), (void *)str, i - 1);
data->string[data->size - 1] = 0;
data->len = data->size;
return count;
}
/* Buffer is big enought to print whole string */
memcpy((void *)(data->string + data->len), (void *)str, count);
data->len += count;
/* Put trailing zero at end, but not count it into data->len so it could be rewritten next time */
/*
* Put trailing zero at end, but not count it into data->len so it could
* be rewritten next time.
*/
data->string[data->len] = 0;
 
return count;
87,17 → 101,22
}
 
/** Print formatted to the given buffer with limited size.
* @param str buffer
* @param size buffer size
* @param fmt format string
* @param str Buffer.
* @param size Bffer size.
* @param fmt Format string.
* \see For more details about format string see printf_core.
*/
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
{
struct vsnprintf_data data = {size, 0, str};
struct printf_spec ps = {(int(*)(void *, size_t, void *)) vsnprintf_write, &data};
struct printf_spec ps = {
(int(*)(void *, size_t, void *)) vsnprintf_write,
&data
};
 
/* Print 0 at end of string - fix the case that nothing will be printed */
/*
* Print 0 at end of string - fix the case that nothing will be printed.
*/
if (size > 0)
str[0] = 0;
/branches/sparc/uspace/lib/libc/generic/io/printf_core.c
94,12 → 94,9
if (str == NULL)
return printf_putnchars("(NULL)", 6, ps);
 
for (count = 0; str[count] != 0; count++);
count = strlen(str);
 
if (ps->write((void *) str, count, ps->data) == count)
return 0;
return EOF;
return ps->write((void *) str, count, ps->data);
}
 
/** Print one character to output
/branches/sparc/uspace/lib/libc/Makefile
57,6 → 57,7
generic/tls.c \
generic/task.c \
generic/futex.c \
generic/io/asprintf.c \
generic/io/io.c \
generic/io/printf.c \
generic/io/stream.c \
70,6 → 71,7
generic/sysinfo.c \
generic/ipc.c \
generic/async.c \
generic/getopt.c \
generic/libadt/list.o \
generic/libadt/hash_table.o \
generic/time.c \
/branches/sparc/uspace/lib/libc/arch/sparc64/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = sparc64-linux-gnu
TOOLCHAIN_DIR = /usr/local/sparc64/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c
/branches/sparc/uspace/lib/libc/arch/ia64/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = ia64-pc-linux-gnu
TOOLCHAIN_DIR = /usr/local/ia64/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS +=
/branches/sparc/uspace/lib/libc/arch/arm32/Makefile.inc
30,8 → 30,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = arm-linux-gnu
TOOLCHAIN_DIR = /usr/local/arm/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin
CFLAGS += -ffixed-r9 -mtp=soft
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS +=
/branches/sparc/uspace/lib/libc/arch/mips32eb/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = mips-sgi-irix5
TOOLCHAIN_DIR = /usr/local/mips/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin
CFLAGS += -mips3
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \
/branches/sparc/uspace/lib/libc/arch/ppc32/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = ppc-linux-gnu
TOOLCHAIN_DIR = /usr/local/ppc/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \
arch/$(ARCH)/src/fibril.S \
/branches/sparc/uspace/lib/libc/arch/amd64/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = amd64-linux-gnu
TOOLCHAIN_DIR = /usr/local/amd64/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \
arch/$(ARCH)/src/fibril.S \
/branches/sparc/uspace/lib/libc/arch/ppc64/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = ppc64-linux-gnu
TOOLCHAIN_DIR = /usr/local/ppc64/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc64/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \
arch/$(ARCH)/src/fibril.S \
/branches/sparc/uspace/lib/libc/arch/mips32/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = mipsel-linux-gnu
TOOLCHAIN_DIR = /usr/local/mipsel/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin
CFLAGS += -mips3
 
-include ../../Makefile.config
/branches/sparc/uspace/lib/libc/arch/ia32/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = i686-pc-linux-gnu
TOOLCHAIN_DIR = /usr/local/i686/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \
arch/$(ARCH)/src/fibril.S \
/branches/sparc/uspace/srv/fs/tmpfs/tmpfs_ops.c
233,7 → 233,7
hash_table_destroy(&dentries);
return false;
}
root->lnkcnt = 1;
root->lnkcnt = 0; /* FS root is not linked */
return true;
}
 
405,11 → 405,12
 
if (dev_handle >= 0) {
if (tmpfs_restore(dev_handle))
ipc_answer_0(rid, EOK);
ipc_answer_3(rid, EOK, root->index, root->size,
root->lnkcnt);
else
ipc_answer_0(rid, ELIMIT);
} else {
ipc_answer_0(rid, EOK);
ipc_answer_3(rid, EOK, root->index, root->size, root->lnkcnt);
}
}
 
/branches/sparc/uspace/srv/fs/fat/fat_ops.c
737,6 → 737,7
rootp->type = FAT_DIRECTORY;
rootp->firstc = FAT_CLST_ROOT;
rootp->refcnt = 1;
rootp->lnkcnt = 0; /* FS root is not linked */
rootp->size = rde * sizeof(fat_dentry_t);
rootp->idx = ridxp;
ridxp->nodep = rootp;
743,7 → 744,7
futex_up(&ridxp->lock);
 
ipc_answer_0(rid, EOK);
ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
}
 
void fat_mount(ipc_callid_t rid, ipc_call_t *request)
/branches/sparc/uspace/srv/vfs/vfs_ops.c
205,6 → 205,12
} else {
/* We still don't have the root file system mounted. */
if ((size == 1) && (buf[0] == '/')) {
vfs_lookup_res_t mr_res;
vfs_node_t *mr_node;
ipcarg_t rindex;
ipcarg_t rsize;
ipcarg_t rlnkcnt;
/*
* For this simple, but important case,
* we are almost done.
213,16 → 219,30
/* Tell the mountee that it is being mounted. */
phone = vfs_grab_phone(fs_handle);
rc = async_req_1_0(phone, VFS_MOUNTED,
(ipcarg_t) dev_handle);
rc = async_req_1_3(phone, VFS_MOUNTED,
(ipcarg_t) dev_handle, &rindex, &rsize, &rlnkcnt);
vfs_release_phone(phone);
 
if (rc == EOK) {
rootfs.fs_handle = fs_handle;
rootfs.dev_handle = dev_handle;
if (rc != EOK) {
futex_up(&rootfs_futex);
ipc_answer_0(rid, rc);
return;
}
 
mr_res.triplet.fs_handle = fs_handle;
mr_res.triplet.dev_handle = dev_handle;
mr_res.triplet.index = (fs_index_t) rindex;
mr_res.size = (size_t) rsize;
mr_res.lnkcnt = (unsigned) rlnkcnt;
 
rootfs.fs_handle = fs_handle;
rootfs.dev_handle = dev_handle;
futex_up(&rootfs_futex);
 
/* Add reference to the mounted root. */
mr_node = vfs_node_get(&mr_res);
assert(mr_node);
 
ipc_answer_0(rid, rc);
return;
} else {
/branches/sparc/uspace/Makefile
48,9 → 48,9
srv/devmap \
app/tetris \
app/tester \
app/cli \
app/klog \
app/init
app/init \
app/bdsh
 
ifeq ($(ARCH), amd64)
DIRS += srv/pci