[Libsysio-commit] namespace_assembly: libsysio/src command.c parser.c module.mk
Brought to you by:
lward
|
From: Sonja T. <so...@us...> - 2003-12-18 18:44:06
|
Update of /cvsroot/libsysio/libsysio/src
In directory sc8-pr-cvs1:/tmp/cvs-serv11335/src
Modified Files:
Tag: namespace_assembly
module.mk
Added Files:
Tag: namespace_assembly
command.c parser.c
Log Message:
Added boottime namespace assembly code
--- NEW FILE ---
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "sysio.h"
#define MAXDRIVERSIZE 100 /* Maximum size for a driver name */
/*
* REVISIT:
* There should probably be some form of #define around this..
*/
#include "../drivers/native/fs_native.h"
#include "../drivers/incore/fs_incore.h"
#define SYSIO_MKDEV(major, minor) \
((((major) & 0xff) << 8) | ((minor) & 0xff))
struct arg_list;
struct arg_list {
char* arg; /* Arguments can be of arbitray length */
struct arg_list *next;
};
/* Command structure (well, duh... */
struct command_t {
char command[6];
struct arg_list *args;
};
struct command_function_t {
char *cmd;
int (*func)(struct arg_list *args);
};
static char *get_arg(char *arg, char** prefix, int *num)
{
int i, start;
for (i=0; prefix[i] != NULL; i++) {
if (prefix[i][2] != '\0')
start = 3;
else
start = 2;
if ((arg[0] == prefix[i][0]) && (arg[1] == prefix[i][1])
&& (arg[start-1] == prefix[i][start-1]) && (arg[start] == '=')) {
if (num != NULL)
*num = i;
return &arg[start+1];
}
}
*num = i;
return NULL;
}
struct init_function_t {
char *driverName;
int (*initFunc)();
};
struct init_function_t init_funcs[] = {
{"native", _sysio_native_init},
{"incore", _sysio_incore_init},
#ifdef CPLANT_YOD
{"yod", _sysio_yod_init},
#endif
{NULL, NULL}
};
int do_init(struct arg_list *args)
{
int i;
char *prefix[] = {"dn", NULL};
char *driverName;
/* Must be exactly one argument */
if ((args == NULL) || (args->next != NULL)) {
return EINVAL;
}
/* Extract the driver from the argument */
driverName = get_arg(args->arg, prefix, NULL);
for (i=0; init_funcs[i].driverName != NULL; i++) {
if (strcmp(init_funcs[i].driverName, driverName) == 0)
return (init_funcs[i].initFunc)();
}
return EINVAL;
}
static int get_perms(char *perms)
{
int total, i, j, digit;
char c[2];
int len = strlen(perms);
total = 0;
for (i=0; i < len; i++) {
c[0] = perms[i];
c[1] = '\0';
digit = atoi(c);
if (digit > 7) {
return 0;
}
for (j=len-i-1; j >0; j--)
digit *= 8;
total += digit;
}
return total;
}
int do_creat(struct arg_list *args)
{
struct arg_list *curr_arg = args;
char *tmp_str, *type=NULL;
char *prefixs[] = {"ft", "nm", "pm", "ow", "gr", "mm", NULL };
int argnum, perms=-1;
char *path=NULL, *own=NULL, *group=NULL;
int maj_num=-1, min_num=-1;
int i=0, j=0, ret=0;
char *maj_num_str;
char *min_num_str;
/* Needs to be at least one argument */
if (args == NULL){
return EINVAL;
}
while (curr_arg != NULL) {
tmp_str = get_arg(curr_arg->arg, prefixs, &argnum);
if (tmp_str == NULL) {
return EINVAL;
}
switch (argnum) {
case 0:
type = tmp_str;
break;
case 1:
path = tmp_str;
break;
case 2:
perms = get_perms(tmp_str);
break;
case 3:
own = tmp_str;
break;
case 4:
group = tmp_str;
break;
case 5:
maj_num_str = (char *) malloc(strlen(tmp_str));
min_num_str = (char *) malloc(strlen(tmp_str));
i=j=0;
while(tmp_str[i] != '\0' && tmp_str[i] != '+') {
maj_num_str[i] = tmp_str[i];
i++;
}
/* Don't let the first char for the minor num be a '+' */
maj_num_str[i++] = '\0';
while(tmp_str[i+j] != '\0' && tmp_str[i+j] != '+') {
min_num_str[j] = tmp_str[i+j];
j++;
}
min_num_str[j] = '\0';
maj_num = atoi(maj_num_str);
min_num = atoi(min_num_str);
free(maj_num_str);
free(min_num_str);
break;
}
curr_arg = curr_arg->next;
}
if ((type == NULL) || (perms == -1) || (path == NULL)) {
return EINVAL;
}
ret = 0;
if (strcmp(type, "dir") == 0) {
if (mkdir(path, perms) != 0) {
ret = errno;
}
} else if ((strcmp(type, "chr") == 0) || (strcmp(type, "blk") == 0)) {
int mode;
int devnum = SYSIO_MKDEV(maj_num, min_num);
if (strcmp(type, "chr") == 0)
mode = perms | S_IFCHR;
else
mode = perms | S_IFBLK;
if ((maj_num == -1) || (min_num == -1)) {
return EINVAL;
}
ret = mknod(path, mode, devnum);
} else if (strcmp(type, "file") == 0) {
ret = creat(path, perms);
} else {
errno = EINVAL;
return EINVAL;
}
return ret;
}
int do_mnt(struct arg_list *args)
{
int i,j,argnum,len;
int flags = 0;
int is_root =0; /* Are we mounting the root dir? */
char *src=NULL, *to=NULL;
char *tmp_str, *data=NULL;
char fstype[MAXDRIVERSIZE];
char *prefixs[] = { "dev", "dir", "fl", "da", NULL};
struct arg_list *curr_arg = args;
/* Needs to be at least one argument */
if (args == NULL){
errno = EINVAL;
return EINVAL;
}
while (curr_arg != NULL) {
tmp_str = get_arg(curr_arg->arg, prefixs, &argnum);
if (tmp_str == NULL) {
errno = EINVAL;
return EINVAL;
}
switch (argnum) {
case 0 :
len = strlen(tmp_str);
/*
* Technically, this is allocating too much--the source
* argument also includes the fstype, but since the fstype
* isn't that large, it is OK
*/
src = (char *) malloc(len+1);
for (i=0; i < len; i++) {
if (tmp_str[i] == ':')
break;
fstype[i] = tmp_str[i];
}
fstype[i] = '\0';
if (i == len) {
errno = EINVAL;
return EINVAL;
}
i++;
if (tmp_str[i] == '"')
i++;
for (j=0; (j+i) < len; j++) {
if (tmp_str[j+i] != '"')
src[j] = tmp_str[j+i];
}
src[j] = '\0';
break;
case 1:
to = tmp_str;
if (strcmp(to,"/") == 0)
is_root = 1;
break;
case 2:
flags = atoi(tmp_str);
break;
case 3:
data = tmp_str;
break;
}
curr_arg = curr_arg->next;
}
if ((src == NULL) || (to == NULL)) {
errno = EINVAL;
return EINVAL;
}
if (is_root) {
_sysio_mount_root(src, fstype, flags, data);
free(src);
return errno;
} else {
mount(src, to, fstype, flags, data);
free(src);
return errno;
}
return 0;
}
int do_cd(struct arg_list *args)
{
char *prefix[] = {"dir", NULL};
char *path;
/* Must be exactly one argument */
if ((args == NULL) || (args->next != NULL)) {
errno = EINVAL;
return EINVAL;
}
path = get_arg(args->arg, prefix, NULL);
if (path == NULL) {
errno = EINVAL;
return EINVAL;
}
return chdir(path);
}
/*
* Put the given string into the given file
* Puts it at the beginning of the file
*/
int do_put(struct arg_list *args)
{
char *prefixs[] = {"str", "src", NULL};
struct arg_list *curr_arg = args;
char *filename, *val;
char *tmp_str = NULL;
int argnum = -1;
int fd, ret, size;
/* Need both the filename and the value to populate it with */
if ((args == NULL) || (args->next == NULL)) {
errno = EINVAL;
return EINVAL;
}
while (curr_arg != NULL) {
tmp_str = get_arg(curr_arg->arg, prefixs, &argnum);
if (tmp_str == NULL) {
errno = EINVAL;
return EINVAL;
}
switch (argnum) {
case 0 :
val = tmp_str;
break;
case 1:
filename = tmp_str;
break;
case 2:
errno = EINVAL;
return EINVAL;
break;
}
curr_arg = curr_arg->next;
}
if ((fd = open(filename, O_WRONLY)) < 0 )
return fd;
size = strlen(val)+1;
if ((ret = write(fd, val, size)) != size)
return ret;
return (close(fd));
}
/* Does a chmod */
int do_chmod(struct arg_list *args) {
char *prefixs[] = {"src", "pm", NULL};
struct arg_list *curr_arg = args;
char *src;
char *tmp_str = NULL;
int argnum, perms;
/* Need both the filename and the permissions */
if ((args == NULL) || (args->next == NULL)) {
errno = EINVAL;
return EINVAL;
}
while (curr_arg != NULL) {
tmp_str = get_arg(curr_arg->arg, prefixs, &argnum);
if (tmp_str == NULL) {
errno = EINVAL;
return EINVAL;
}
switch (argnum) {
case 0 :
src = tmp_str;
break;
case 1:
perms = get_perms(tmp_str);
break;
case 2:
errno = EINVAL;
return EINVAL;
break;
}
curr_arg = curr_arg->next;
}
return chmod(src, perms);
}
struct command_function_t cmd_funcs[] = {
{"init", do_init},
{"creat", do_creat},
{"mnt", do_mnt},
{"cd", do_cd},
{"put", do_put},
{"chmd", do_chmod},
{NULL, NULL}
};
/* Execute the given cmd. Return exit status code */
int do_command(struct command_t *cmd)
{
int i;
for (i=0; cmd_funcs[i].cmd != NULL; i++) {
if (strcmp(cmd_funcs[i].cmd, cmd->command) == 0)
return (cmd_funcs[i].func)(cmd->args);
}
errno = EINVAL;
return EINVAL;
}
--- NEW FILE ---
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "sysio.h"
#define MAXBUFSIZE 4096 /* Maximum command sequence size */
struct arg_list {
char* arg; /* Arguments can be of arbitray length */
struct arg_list *next;
};
/* Command structure (well, duh... */
struct command_t {
char command[6];
struct arg_list *args;
};
extern int do_command(struct command_t *cmd);
static int is_valid(char ch)
{
if ( ch != '\0' && ch != '{' && ch != '}')
return 1;
return 0;
}
/*
* Given a string of command bits, returns a valid ASCII string
* This could be a command name or an argument, but it will not need
* any further parsing
*/
static char *get_valid_name(char *buf, int* name_size)
{
int i=0;
char *new_buf;
int in_quotes=0;
if ( (buf == NULL) || (name_size == NULL)) {
return NULL;
}
*name_size=0;
/* Chop off any initial chars */
if (!is_valid(buf[0]) || buf[0] == ',') {
buf++;
*name_size = *name_size+1;
}
/*
* If the first char is a ", then we just look for an ending "
* Otherwise, look for the first control char
*/
new_buf = buf;
while ( (in_quotes == 1) ||
(is_valid(buf[i]) && buf[i] != ',') )
{
*name_size = *name_size+1;
if (buf[i] == '"') {
if (in_quotes)
in_quotes = 0;
else
in_quotes = 1;
}
i++;
}
new_buf[i] = buf[i] = '\0';
return new_buf;
}
/*
* Create an argument list for use in a command_t structure
*/
static struct arg_list *get_args(char *args, int *size)
{
struct arg_list *new_list, *start_list;
struct arg_list *prev_list = NULL;
char *tmp_str;
int i,j=1;
if ( (args == NULL) || (size == NULL) ) {
return NULL;
}
for (i=0; is_valid(args[i]); i += j+1) {
tmp_str = get_valid_name(&args[i], &j);
if (tmp_str == NULL) {
/*
* Don't print out a msg here since it will be printed
* in get_valid_name.
*/
return NULL;
}
if (j > 2) {
new_list = (struct arg_list *)malloc(sizeof(struct arg_list));
if (prev_list)
prev_list->next = new_list;
else
start_list = new_list;
new_list->next = NULL;
new_list->arg = (char *)malloc(j);
memcpy(new_list->arg, tmp_str, j+1);
*size = *size -j -1;
prev_list = new_list;
} else
break;
}
return start_list;
}
static int is_ws(char ch)
{
if (ch == ' ' || ch == '\n' || ch == '\0')
return 1;
return 0;
}
/*
* Fill in the passed-in command structure with the command at the
* beginning of the string. The command is assumed to be "fresh"
* in that it does not contain any old, sterile data. Returns the
* remainder of the string. If it reaches the end of the string (or
* file), it frees the string and returns NULL
*/
static char *get_command(char *commands_str, struct command_t *cmd, int *size)
{
char *cmd_str;
int i=0, orig_size = *size;
if ((commands_str == NULL) || (cmd == NULL) || (size == NULL)) {
return NULL;
}
/*
* Check the first char. If it is not '{', either the
* command sequence is invalid or we have reached the end of the
* file. Either way, just advance the string by 1 and return
*/
if (commands_str[0] != '{') {
commands_str++;
*size = *size-1;
return commands_str;
}
/* Get the command name */
cmd_str = get_valid_name(&commands_str[1], &i);
if (cmd_str == NULL)
return NULL;
/*
* Take out any quotes on command name. This is not
* done for arguments since some args can have the quotes
* just passed in
*/
if (cmd_str[0] == '"') {
cmd_str++;
memcpy(cmd->command, cmd_str, i-2);
cmd->command[i-2] = '\0';
*size = *size-1;
i--;
} else
memcpy(cmd->command, cmd_str, i+1);
*size = *size-i-1;
/* Get all the arguments */
cmd->args = get_args(&cmd_str[i+1], size);
if (cmd->args == NULL)
return NULL;
commands_str += (orig_size - *size);
/*
* Clean up any trailing ws. This catches any ws at end
* of command sequences
*/
while (is_ws(*commands_str)){
cmd_str++;
commands_str++;
*size = *size-1;
}
if (*size <= 1)
return NULL;
return commands_str;
}
static void free_cmd(struct command_t *cmd)
{
struct arg_list *curr_arg, *next_arg;
curr_arg = cmd->args;
while (curr_arg != NULL) {
next_arg = curr_arg->next;
free(curr_arg->arg);
free(curr_arg);
curr_arg = next_arg;
}
free(cmd);
}
/*
* Given a command sequence buffer, parse it and run the given
* commands
*/
int run_cmds(char *buf)
{
int size = strlen(buf);
struct command_t *cmd;
char *cmdStr = buf;
int err;
/* Initilize sysio first */
_sysio_init();
while (1) {
cmd = (struct command_t *)malloc(sizeof(struct command_t));
cmd->args = NULL;
cmdStr = get_command(cmdStr, cmd, &size);
if (cmd == NULL)
return EINVAL;
if ((err = do_command(cmd)) == -1) {
free_cmd(cmd);
/* Something screwed up, bail */
return errno;
}
free_cmd(cmd);
if ((cmdStr == NULL) || (size == 0))
break;
}
return 0;
}
Index: module.mk
===================================================================
RCS file: /cvsroot/libsysio/libsysio/src/module.mk,v
retrieving revision 1.1
retrieving revision 1.1.2.1
diff -u -w -b -B -p -r1.1 -r1.1.2.1
--- module.mk 16 Dec 2003 15:43:14 -0000 1.1
+++ module.mk 18 Dec 2003 18:44:02 -0000 1.1.2.1
@@ -9,5 +9,5 @@ SRCDIR_SRCS = src/access.c src/chdir.c s
src/rmdir.c src/stat64.c src/stat.c \
src/statvfs64.c src/statvfs.c src/symlink.c \
src/truncate.c src/unlink.c src/utime.c \
- src/write.c
+ src/write.c src/parser.c src/command.c
SRCDIR_EXTRA = src/module.mk
|