Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 4054 → Rev 4055

/branches/dd/uspace/app/bdsh/cmds/modules/ls/ls.c
0,0 → 1,214
/* 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 inline off_t flen(const char *f)
{
int fd;
off_t size;
 
fd = open(f, O_RDONLY);
if (fd == -1)
return 0;
 
size = lseek(fd, 0, SEEK_END);
close(fd);
 
if (size < 0)
size = 0;
 
return size;
}
 
static unsigned int ls_scope(const char *path)
{
int fd;
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, buff);
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 *name, const char *pathname)
{
printf("%-40s\t%llu\n", name, (long long) flen(pathname));
 
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;
}
 
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, 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/dd/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 *, const char *);
 
#endif /* LS_H */
 
/branches/dd/uspace/app/bdsh/cmds/modules/ls/ls_def.h
0,0 → 1,6
{
"ls",
"List files and directories",
&cmd_ls,
&help_cmd_ls,
},
/branches/dd/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/dd/uspace/app/bdsh/cmds/modules/cp/cp.c
0,0 → 1,231
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <fcntl.h>
#include "config.h"
#include "util.h"
#include "errors.h"
#include "entry.h"
#include "cp.h"
#include "cmds.h"
 
#define CP_VERSION "0.0.1"
#define CP_DEFAULT_BUFLEN 1024
 
static const char *cmdname = "cp";
 
static struct option const long_options[] = {
{ "buffer", required_argument, 0, 'b' },
{ "force", no_argument, 0, 'f' },
{ "recursive", no_argument, 0, 'r' },
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'v' },
{ "verbose", no_argument, 0, 'V' },
{ 0, 0, 0, 0 }
};
 
static int strtoint(const char *s1)
{
long t1;
 
if (-1 == (t1 = strtol(s1, (char **) NULL, 10)))
return -1;
 
if (t1 <= 0)
return -1;
 
return (int) t1;
}
 
static int64_t copy_file(const char *src, const char *dest,
size_t blen, int vb)
{
int fd1, fd2, bytes = 0;
off_t total = 0;
int64_t copied = 0;
char *buff = NULL;
 
if (vb)
printf("Copying %s to %s\n", src, dest);
 
if (-1 == (fd1 = open(src, O_RDONLY))) {
printf("Unable to open source file %s\n", src);
return -1;
}
 
if (-1 == (fd2 = open(dest, O_CREAT))) {
printf("Unable to open destination file %s\n", dest);
close(fd1);
return -1;
}
 
total = lseek(fd1, 0, SEEK_END);
 
if (vb)
printf("%d bytes to copy\n", total);
 
lseek(fd1, 0, SEEK_SET);
 
if (NULL == (buff = (char *) malloc(blen))) {
printf("Unable to allocate enough memory to read %s\n",
src);
copied = -1;
goto out;
}
 
for (;;) {
ssize_t res;
 
bytes = read(fd1, buff, blen);
if (bytes <= 0)
break;
copied += bytes;
res = bytes;
do {
/*
* Theoretically, it may not be enough to call write()
* only once. Also the previous read() may have
* returned less data than requested.
*/
bytes = write(fd2, buff, res);
if (bytes < 0)
goto err;
res -= bytes;
} while (res > 0);
 
/* TODO: re-insert assert() once this is stand alone,
* removed as abort() exits the entire shell
*/
if (res != 0) {
printf("\n%d more bytes than actually exist were copied\n", res);
goto err;
}
}
 
if (bytes < 0) {
err:
printf("\nError copying %s, (%d)\n", src, bytes);
copied = bytes;
}
 
out:
close(fd1);
close(fd2);
if (buff)
free(buff);
return copied;
}
 
void help_cmd_cp(unsigned int level)
{
static char helpfmt[] =
"Usage: %s [options] <source> <dest>\n"
"Options: (* indicates not yet implemented)\n"
" -h, --help A short option summary\n"
" -v, --version Print version information and exit\n"
"* -V, --verbose Be annoyingly noisy about what's being done\n"
"* -f, --force Do not complain when <dest> exists\n"
"* -r, --recursive Copy entire directories\n"
" -b, --buffer ## Set the read buffer size to ##\n"
"Currently, %s is under development, some options may not work.\n";
if (level == HELP_SHORT) {
printf("`%s' copies files and directories\n", cmdname);
} else {
help_cmd_cp(HELP_SHORT);
printf(helpfmt, cmdname, cmdname);
}
 
return;
}
 
int cmd_cp(char **argv)
{
unsigned int argc, buffer = 0, verbose = 0;
int c, opt_ind;
int64_t ret;
 
argc = cli_count_args(argv);
 
for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
c = getopt_long(argc, argv, "hvVfrb:", long_options, &opt_ind);
switch (c) {
case 'h':
help_cmd_cp(1);
return CMD_SUCCESS;
case 'v':
printf("%d\n", CP_VERSION);
return CMD_SUCCESS;
case 'V':
verbose = 1;
break;
case 'f':
break;
case 'r':
break;
case 'b':
if (-1 == (buffer = strtoint(optarg))) {
printf("%s: Invalid buffer specification, "
"(should be a number greater than zero)\n",
cmdname);
return CMD_FAILURE;
}
if (verbose)
printf("Buffer = %d\n", buffer);
break;
}
}
 
if (buffer == 0)
buffer = CP_DEFAULT_BUFLEN;
 
argc -= optind;
 
if (argc != 2) {
printf("%s: invalid number of arguments. Try %s --help\n",
cmdname, cmdname);
return CMD_FAILURE;
}
 
ret = copy_file(argv[optind], argv[optind + 1], buffer, verbose);
 
if (verbose)
printf("%d bytes copied\n", ret);
 
if (ret >= 0)
return CMD_SUCCESS;
else
return CMD_FAILURE;
}
 
/branches/dd/uspace/app/bdsh/cmds/modules/cp/cp_def.h
0,0 → 1,7
{
"cp",
"Copy files and directories",
&cmd_cp,
&help_cmd_cp,
},
 
/branches/dd/uspace/app/bdsh/cmds/modules/cp/entry.h
0,0 → 1,9
#ifndef CP_ENTRY_H
#define CP_ENTRY_H
 
/* Entry points for the cp command */
extern int cmd_cp(char **);
extern void help_cmd_cp(unsigned int);
 
#endif /* CP_ENTRY_H */
 
/branches/dd/uspace/app/bdsh/cmds/modules/cp/cp.h
0,0 → 1,8
#ifndef CP_H
#define CP_H
 
/* Prototypes for the cp command, excluding entry points */
 
 
#endif /* CP_H */
 
/branches/dd/uspace/app/bdsh/cmds/modules/rm/rm.c
0,0 → 1,257
/* 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 <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;
}
 
/* 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);
if (buff == NULL) {
printf("rm: out of memory\n");
ret = 1;
break;
}
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/dd/uspace/app/bdsh/cmds/modules/rm/rm_def.h
0,0 → 1,7
{
"rm",
"Remove files and directories",
&cmd_rm,
&help_cmd_rm,
},
 
/branches/dd/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/dd/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/dd/uspace/app/bdsh/cmds/modules/touch/touch.c
0,0 → 1,108
/* 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 <string.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;
}
 
/* 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 = 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/dd/uspace/app/bdsh/cmds/modules/touch/touch_def.h
0,0 → 1,7
{
"touch",
"Create files or update access times",
&cmd_touch,
&help_cmd_touch,
},
 
/branches/dd/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/dd/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/dd/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;
}
 
/* 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 = 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] = strtok(tmp, "/");
while (dirs[i] && i < 255)
dirs[++i] = 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/dd/uspace/app/bdsh/cmds/modules/mkdir/mkdir_def.h
0,0 → 1,8
{
"mkdir",
"Create new directories",
&cmd_mkdir,
&help_cmd_mkdir,
},
 
 
/branches/dd/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/dd/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/dd/uspace/app/bdsh/cmds/modules/modules.h
0,0 → 1,47
#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 "mkdir/entry.h"
#include "rm/entry.h"
#include "cat/entry.h"
#include "touch/entry.h"
#include "ls/entry.h"
#include "pwd/entry.h"
#include "sleep/entry.h"
#include "cp/entry.h"
 
/* Each .def function fills the module_t struct with the individual name, entry
* point, help entry point, etc. You can use config.h to control what modules
* are loaded based on what libraries exist on the system. */
 
module_t modules[] = {
#include "help/help_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"
#include "sleep/sleep_def.h"
#include "cp/cp_def.h"
{NULL, NULL, NULL, NULL}
};
 
#endif
/branches/dd/uspace/app/bdsh/cmds/modules/cat/cat_def.h
0,0 → 1,7
{
"cat",
"Show the contents of a file",
&cmd_cat,
&help_cmd_cat,
},
 
/branches/dd/uspace/app/bdsh/cmds/modules/cat/cat.c
0,0 → 1,178
/* 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;
}
 
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 {
bytes = read(fd, buff, blen);
if (bytes > 0) {
count += bytes;
buff[bytes] = '\0';
printf("%s", buff);
reads++;
}
} while (bytes > 0);
 
close(fd);
if (bytes == -1) {
printf("Error reading %s\n", fname);
free(buff);
return 1;
}
 
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/dd/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/dd/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/dd/uspace/app/bdsh/cmds/modules/help/help.c
0,0 → 1,158
/* 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;
}
 
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 (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 (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/dd/uspace/app/bdsh/cmds/modules/help/help_def.h
0,0 → 1,6
{
"help",
"Show help for commands",
&cmd_help,
&help_cmd_help,
},
/branches/dd/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/dd/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/dd/uspace/app/bdsh/cmds/modules/sleep/sleep_def.h
0,0 → 1,7
{
"sleep",
"Pause for given time interval (in seconds)",
&cmd_sleep,
&help_cmd_sleep,
},
 
/branches/dd/uspace/app/bdsh/cmds/modules/sleep/entry.h
0,0 → 1,9
#ifndef SLEEP_ENTRY_H
#define SLEEP_ENTRY_H
 
/* Entry points for the sleep command */
extern int cmd_sleep(char **);
extern void help_cmd_sleep(unsigned int);
 
#endif /* SLEEP_ENTRY_H */
 
/branches/dd/uspace/app/bdsh/cmds/modules/sleep/sleep.c
0,0 → 1,73
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "util.h"
#include "errors.h"
#include "entry.h"
#include "sleep.h"
#include "cmds.h"
 
static char *cmdname = "sleep";
 
/* Dispays help for sleep in various levels */
void help_cmd_sleep(unsigned int level)
{
printf("This is the %s help for '%s'.\n",
level ? EXT_HELP : SHORT_HELP, cmdname);
return;
}
 
/* Main entry point for sleep, accepts an array of arguments */
int cmd_sleep(char **argv)
{
unsigned int argc;
unsigned int i;
 
/* Count the arguments */
for (argc = 0; argv[argc] != NULL; argc ++);
 
printf("%s %s\n", TEST_ANNOUNCE, cmdname);
printf("%d arguments passed to %s", argc - 1, cmdname);
 
if (argc < 2) {
printf("\n");
return CMD_SUCCESS;
}
 
printf(":\n");
for (i = 1; i < argc; i++)
printf("[%d] -> %s\n", i, argv[i]);
 
return CMD_SUCCESS;
}
 
/branches/dd/uspace/app/bdsh/cmds/modules/sleep/sleep.h
0,0 → 1,8
#ifndef SLEEP_H
#define SLEEP_H
 
/* Prototypes for the sleep command, excluding entry points */
 
 
#endif /* SLEEP_H */
 
/branches/dd/uspace/app/bdsh/cmds/modules/pwd/pwd_def.h
0,0 → 1,6
{
"pwd",
"Prints the current working directory",
&cmd_pwd,
&help_cmd_pwd,
},
/branches/dd/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/dd/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;
}
 
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/dd/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/dd/uspace/app/bdsh/cmds/modules/module_aliases.h
0,0 → 1,18
#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[] = {
NULL, NULL
};
 
#endif
/branches/dd/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/dd/uspace/app/bdsh/cmds/builtins/builtins.h
0,0 → 1,15
#ifndef BUILTINS_H
#define BUILTINS_H
 
#include "config.h"
 
#include "cd/entry.h"
#include "exit/entry.h"
 
builtin_t builtins[] = {
#include "cd/cd_def.h"
#include "exit/exit_def.h"
{NULL, NULL, NULL, NULL}
};
 
#endif
/branches/dd/uspace/app/bdsh/cmds/builtins/exit/exit.h
0,0 → 1,6
#ifndef EXIT_H
#define EXIT_H
 
/* Prototypes for the quit command (excluding entry points) */
 
#endif
/branches/dd/uspace/app/bdsh/cmds/builtins/exit/entry.h
0,0 → 1,12
#ifndef EXIT_ENTRY_H_
#define EXIT_ENTRY_H_
 
#include "scli.h"
 
/* Entry points for the quit command */
extern void help_cmd_exit(unsigned int);
extern int cmd_exit(char *[], cliuser_t *);
 
#endif
 
 
/branches/dd/uspace/app/bdsh/cmds/builtins/exit/exit.c
0,0 → 1,55
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include "entry.h"
#include "exit.h"
#include "cmds.h"
 
static const char *cmdname = "exit";
 
extern volatile unsigned int cli_quit;
extern const char *progname;
 
void help_cmd_exit(unsigned int level)
{
printf("Type `%s' to exit %s\n", cmdname, progname);
return;
}
 
/* Quits the program and returns the status of whatever command
* came before invoking 'quit' */
int cmd_exit(char *argv[], cliuser_t *usr)
{
/* Inform that we're outta here */
cli_quit = 1;
return CMD_SUCCESS;
}
/branches/dd/uspace/app/bdsh/cmds/builtins/exit/exit_def.h
0,0 → 1,6
{
"exit",
"Exit the shell",
&cmd_exit,
&help_cmd_exit,
},
/branches/dd/uspace/app/bdsh/cmds/builtins/cd/cd_def.h
0,0 → 1,6
{
"cd",
"Change the current working directory",
&cmd_cd,
&help_cmd_cd,
},
/branches/dd/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;
}
 
/* 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/dd/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/dd/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/dd/uspace/app/bdsh/cmds/builtins/builtin_aliases.h
0,0 → 1,10
#ifndef BUILTIN_ALIASES_H
#define BUILTIN_ALIASES_H
 
/* See modules/module_aliases.h for an explanation of this file */
 
char *builtin_aliases[] = {
NULL, NULL
};
 
#endif
/branches/dd/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/dd/uspace/app/bdsh/cmds/mknewcmd
0,0 → 1,314
#!/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)
-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'.
 
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},
},
 
EOF
[ -n "${CMDALIAS}" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}_def.h
{
"${CMDALIAS}",
NULL,
&${CMDENTRY},
&${HELPENTRY},
},
 
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 const 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;
}
 
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:t:HV \
--long name:,desc:,entry:,help-entry:,alias:,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
;;
-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}"
 
 
# 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/dd/uspace/app/bdsh/cmds/mod_cmds.c
0,0 → 1,136
/* 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;
 
/* 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/dd/uspace/app/bdsh/cmds/cmds.h
0,0 → 1,71
#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 1
#define CMD_SUCCESS 0
 
/* 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 */
} 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/dd/uspace/app/bdsh/cmds/builtin_cmds.c
0,0 → 1,113
/* 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 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;
}