summaryrefslogtreecommitdiff
path: root/boot-proxy-exc/boot_script.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot-proxy-exc/boot_script.c')
-rw-r--r--boot-proxy-exc/boot_script.c791
1 files changed, 0 insertions, 791 deletions
diff --git a/boot-proxy-exc/boot_script.c b/boot-proxy-exc/boot_script.c
deleted file mode 100644
index f95cc5c4..00000000
--- a/boot-proxy-exc/boot_script.c
+++ /dev/null
@@ -1,791 +0,0 @@
-/* Boot script parser for Mach. */
-
-/* Written by Shantanu Goel (goel@cs.columbia.edu). */
-
-#include <mach/mach_types.h>
-#if !KERNEL || OSKIT_MACH
-#include <string.h>
-#endif
-#include "boot_script.h"
-
-
-/* This structure describes a symbol. */
-struct sym
-{
- /* Symbol name. */
- const char *name;
-
- /* Type of value returned by function. */
- int type;
-
- /* Symbol value. */
- integer_t val;
-
- /* For function symbols; type of value returned by function. */
- int ret_type;
-
- /* For function symbols; if set, execute function at the time
- of command execution, not during parsing. A function with
- this field set must also have `no_arg' set. Also, the function's
- `val' argument will always be NULL. */
- int run_on_exec;
-};
-
-/* Additional values symbols can take.
- These are only used internally. */
-#define VAL_SYM 10 /* symbol table entry */
-#define VAL_FUNC 11 /* function pointer */
-
-/* This structure describes an argument. */
-struct arg
-{
- /* Argument text copied verbatim. 0 if none. */
- char *text;
-
- /* Type of value assigned. 0 if none. */
- int type;
-
- /* Argument value. */
- integer_t val;
-};
-
-/* List of commands. */
-static struct cmd **cmds = 0;
-
-/* Amount allocated for `cmds'. */
-static int cmds_alloc = 0;
-
-/* Next available slot in `cmds'. */
-static int cmds_index = 0;
-
-/* Symbol table. */
-static struct sym **symtab = 0;
-
-/* Amount allocated for `symtab'. */
-static int symtab_alloc = 0;
-
-/* Next available slot in `symtab'. */
-static int symtab_index = 0;
-
-/* Create a task and suspend it. */
-static int
-create_task (struct cmd *cmd, int *val)
-{
- int err = boot_script_task_create (cmd);
- *val = (int) cmd->task;
- return err;
-}
-
-/* Resume a task. */
-static int
-resume_task (struct cmd *cmd, int *val)
-{
- return boot_script_task_resume (cmd);
-}
-
-/* Resume a task when the user hits return. */
-static int
-prompt_resume_task (struct cmd *cmd, int *val)
-{
- return boot_script_prompt_task_resume (cmd);
-}
-
-/* List of builtin symbols. */
-static struct sym builtin_symbols[] =
-{
- { "task-create", VAL_FUNC, (integer_t) create_task, VAL_TASK, 0 },
- { "task-resume", VAL_FUNC, (integer_t) resume_task, VAL_NONE, 1 },
- { "prompt-task-resume",
- VAL_FUNC, (integer_t) prompt_resume_task, VAL_NONE, 1 },
-};
-#define NUM_BUILTIN (sizeof (builtin_symbols) / sizeof (builtin_symbols[0]))
-
-/* Free CMD and all storage associated with it.
- If ABORTING is set, terminate the task associated with CMD,
- otherwise just deallocate the send right. */
-static void
-free_cmd (struct cmd *cmd, int aborting)
-{
- if (cmd->task)
- boot_script_free_task (cmd->task, aborting);
- if (cmd->args)
- {
- int i;
- for (i = 0; i < cmd->args_index; i++)
- boot_script_free (cmd->args[i], sizeof *cmd->args[i]);
- boot_script_free (cmd->args, sizeof cmd->args[0] * cmd->args_alloc);
- }
- if (cmd->exec_funcs)
- boot_script_free (cmd->exec_funcs,
- sizeof cmd->exec_funcs[0] * cmd->exec_funcs_alloc);
- boot_script_free (cmd, sizeof *cmd);
-}
-
-/* Free all storage allocated by the parser.
- If ABORTING is set, terminate all tasks. */
-static void
-cleanup (int aborting)
-{
- int i;
-
- for (i = 0; i < cmds_index; i++)
- free_cmd (cmds[i], aborting);
- boot_script_free (cmds, sizeof cmds[0] * cmds_alloc);
- cmds = 0;
- cmds_index = cmds_alloc = 0;
-
- for (i = 0; i < symtab_index; i++)
- boot_script_free (symtab[i], sizeof *symtab[i]);
- boot_script_free (symtab, sizeof symtab[0] * symtab_alloc);
- symtab = 0;
- symtab_index = symtab_alloc = 0;
-}
-
-/* Add PTR to the list of pointers PTR_LIST, which
- currently has ALLOC amount of space allocated to it, and
- whose next available slot is INDEX. If more space
- needs to to allocated, INCR is the amount by which
- to increase it. Return 0 on success, non-zero otherwise. */
-static int
-add_list (void *ptr, void ***ptr_list, int *alloc, int *index, int incr)
-{
- if (*index == *alloc)
- {
- void **p;
-
- *alloc += incr;
- p = boot_script_malloc (*alloc * sizeof (void *));
- if (! p)
- {
- *alloc -= incr;
- return 1;
- }
- if (*ptr_list)
- {
- memcpy (p, *ptr_list, *index * sizeof (void *));
- boot_script_free (*ptr_list, (*alloc - incr) * sizeof (void *));
- }
- *ptr_list = p;
- }
- *(*ptr_list + *index) = ptr;
- *index += 1;
- return 0;
-}
-
-/* Create an argument with TEXT, value type TYPE, and value VAL.
- Add the argument to the argument list of CMD. */
-static struct arg *
-add_arg (struct cmd *cmd, const char *text, int textlen, int type, int val)
-{
- struct arg *arg;
-
- arg = boot_script_malloc (sizeof (struct arg) + textlen);
- if (arg)
- {
- arg->text = text == 0 ? 0 : memcpy (arg + 1, text, textlen);
- arg->type = type;
- arg->val = val;
- if (add_list (arg, (void ***) (void *)&cmd->args,
- &cmd->args_alloc, &cmd->args_index, 5))
- {
- boot_script_free (arg, sizeof *arg);
- return 0;
- }
- }
- return arg;
-}
-
-/* Search for the symbol NAME in the symbol table. */
-static struct sym *
-sym_lookup (const char *name)
-{
- int i;
-
- for (i = 0; i < symtab_index; i++)
- if (! strcmp (name, symtab[i]->name))
- return symtab[i];
- return 0;
-}
-
-/* Create an entry for symbol NAME in the symbol table. */
-static struct sym *
-sym_enter (const char *name)
-{
- struct sym *sym;
-
- sym = boot_script_malloc (sizeof (struct sym));
- if (sym)
- {
- memset (sym, 0, sizeof (struct sym));
- sym->name = name;
- if (add_list (sym, (void ***) (void *)&symtab, &symtab_alloc, &symtab_index, 20))
- {
- boot_script_free (sym, sizeof *sym);
- return 0;
- }
- }
- return sym;
-}
-
-/* Parse the command line CMDLINE. */
-int
-boot_script_parse_line (void *hook, char *cmdline)
-{
- char *p, *q;
- int error;
- struct cmd *cmd;
- struct arg *arg;
-
- /* Extract command name. Ignore line if it lacks a command. */
- for (p = cmdline; *p == ' ' || *p == '\t'; p++)
- ;
- if (*p == '#')
- /* Ignore comment line. */
- return 0;
-
-#if 0
- if (*p && *p != ' ' && *p != '\t' && *p != '\n')
- {
- printf ("(bootstrap): %s\n", cmdline);
- }
-#endif
-
- for (q = p; *q && *q != ' ' && *q != '\t' && *q != '\n'; q++)
- ;
- if (p == q)
- return 0;
-
- *q++ = '\0';
-
- /* Allocate a command structure. */
- cmd = boot_script_malloc (sizeof (struct cmd) + (q - p));
- if (! cmd)
- return BOOT_SCRIPT_NOMEM;
- memset (cmd, 0, sizeof (struct cmd));
- cmd->hook = hook;
- cmd->path = memcpy (cmd + 1, p, q - p);
- p = q;
-
- for (arg = 0;;)
- {
- if (! arg)
- {
- /* Skip whitespace. */
- while (*p == ' ' || *p == '\t')
- p++;
-
- /* End of command line. */
- if (! *p || *p == '\n')
- {
- /* Add command to list. */
- if (add_list (cmd, (void ***) (void *) &cmds,
- &cmds_alloc, &cmds_index, 10))
- {
- error = BOOT_SCRIPT_NOMEM;
- goto bad;
- }
- return 0;
- }
- }
-
- /* Look for a symbol. */
- if (arg || (*p == '$' && (*(p + 1) == '{' || *(p + 1) == '(')))
- {
- char end_char = (*(p + 1) == '{') ? '}' : ')';
- struct sym *sym = 0;
-
- for (p += 2;;)
- {
- char c;
- int i, type;
- integer_t val;
- struct sym *s;
-
- /* Parse symbol name. */
- for (q = p; *q && *q != '\n' && *q != end_char && *q != '='; q++)
- ;
- if (p == q || ! *q || *q == '\n'
- || (end_char == '}' && *q != '}'))
- {
- error = BOOT_SCRIPT_SYNTAX_ERROR;
- goto bad;
- }
- c = *q;
- *q = '\0';
-
- /* See if this is a builtin symbol. */
- for (i = 0; i < NUM_BUILTIN; i++)
- if (! strcmp (p, builtin_symbols[i].name))
- break;
-
- if (i < NUM_BUILTIN)
- s = &builtin_symbols[i];
- else
- {
- /* Look up symbol in symbol table.
- If no entry exists, create one. */
- s = sym_lookup (p);
- if (! s)
- {
- s = sym_enter (p);
- if (! s)
- {
- error = BOOT_SCRIPT_NOMEM;
- goto bad;
- }
- }
- }
-
- /* Only values are allowed in ${...} constructs. */
- if (end_char == '}' && s->type == VAL_FUNC)
- return BOOT_SCRIPT_INVALID_SYM;
-
- /* Check that assignment is valid. */
- if (c == '=' && s->type == VAL_FUNC)
- {
- error = BOOT_SCRIPT_INVALID_ASG;
- goto bad;
- }
-
- /* For function symbols, execute the function. */
- if (s->type == VAL_FUNC)
- {
- if (! s->run_on_exec)
- {
- (error
- = ((*((int (*) (struct cmd *, integer_t *)) s->val))
- (cmd, &val)));
- if (error)
- goto bad;
- type = s->ret_type;
- }
- else
- {
- if (add_list (s, (void ***) (void *) &cmd->exec_funcs,
- &cmd->exec_funcs_alloc,
- &cmd->exec_funcs_index, 5))
- {
- error = BOOT_SCRIPT_NOMEM;
- goto bad;
- }
- type = VAL_NONE;
- goto out;
- }
- }
- else if (s->type == VAL_NONE)
- {
- type = VAL_SYM;
- val = (integer_t) s;
- }
- else
- {
- type = s->type;
- val = s->val;
- }
-
- if (sym)
- {
- sym->type = type;
- sym->val = val;
- }
- else if (arg)
- {
- arg->type = type;
- arg->val = val;
- }
-
- out:
- p = q + 1;
- if (c == end_char)
- {
- /* Create an argument if necessary.
- We create an argument if the symbol appears
- in the expression by itself.
-
- NOTE: This is temporary till the boot filesystem
- servers support arguments. When that happens,
- symbol values will only be printed if they're
- associated with an argument. */
- if (! arg && end_char == '}')
- {
- if (! add_arg (cmd, 0, 0, type, val))
- {
- error = BOOT_SCRIPT_NOMEM;
- goto bad;
- }
- }
- arg = 0;
- break;
- }
- if (s->type != VAL_FUNC)
- sym = s;
- }
- }
- else
- {
- char c;
-
- /* Command argument; just copy the text. */
- for (q = p;; q++)
- {
- if (! *q || *q == ' ' || *q == '\t' || *q == '\n')
- break;
- if (*q == '$' && *(q + 1) == '{')
- break;
- }
- c = *q;
- *q = '\0';
-
- /* Add argument to list. */
- arg = add_arg (cmd, p, q + 1 - p, VAL_NONE, 0);
- if (! arg)
- {
- error = BOOT_SCRIPT_NOMEM;
- goto bad;
- }
- if (c == '$')
- p = q;
- else
- {
- if (c)
- p = q + 1;
- else
- p = q;
- arg = 0;
- }
- }
- }
-
-
- bad:
- free_cmd (cmd, 1);
- cleanup (1);
- return error;
-}
-
-/* Ensure that the command line buffer can accommodate LEN bytes of space. */
-#define CHECK_CMDLINE_LEN(len) \
-{ \
- if (cmdline_alloc - cmdline_index < len) \
- { \
- char *ptr; \
- int alloc, i; \
- alloc = cmdline_alloc + len - (cmdline_alloc - cmdline_index) + 100; \
- ptr = boot_script_malloc (alloc); \
- if (! ptr) \
- { \
- error = BOOT_SCRIPT_NOMEM; \
- goto done; \
- } \
- memcpy (ptr, cmdline, cmdline_index); \
- for (i = 0; i < argc; ++i) \
- argv[i] = ptr + (argv[i] - cmdline); \
- boot_script_free (cmdline, cmdline_alloc); \
- cmdline = ptr; \
- cmdline_alloc = alloc; \
- } \
-}
-
-/* Execute commands previously parsed. */
-int
-boot_script_exec ()
-{
- int cmd_index;
-
- for (cmd_index = 0; cmd_index < cmds_index; cmd_index++)
- {
- char **argv, *cmdline;
- int i, argc, cmdline_alloc;
- int cmdline_index, error, arg_index;
- struct cmd *cmd = cmds[cmd_index];
-
- /* Skip command if it doesn't have an associated task. */
- if (cmd->task == 0)
- continue;
-
- /* Allocate a command line and copy command name. */
- cmdline_index = strlen (cmd->path) + 1;
- cmdline_alloc = cmdline_index + 100;
- cmdline = boot_script_malloc (cmdline_alloc);
- if (! cmdline)
- {
- cleanup (1);
- return BOOT_SCRIPT_NOMEM;
- }
- memcpy (cmdline, cmd->path, cmdline_index);
-
- /* Allocate argument vector. */
- argv = boot_script_malloc (sizeof (char *) * (cmd->args_index + 2));
- if (! argv)
- {
- boot_script_free (cmdline, cmdline_alloc);
- cleanup (1);
- return BOOT_SCRIPT_NOMEM;
- }
- argv[0] = cmdline;
- argc = 1;
-
- /* Build arguments. */
- for (arg_index = 0; arg_index < cmd->args_index; arg_index++)
- {
- struct arg *arg = cmd->args[arg_index];
-
- /* Copy argument text. */
- if (arg->text)
- {
- int len = strlen (arg->text);
-
- if (arg->type == VAL_NONE)
- len++;
- CHECK_CMDLINE_LEN (len);
- memcpy (cmdline + cmdline_index, arg->text, len);
- argv[argc++] = &cmdline[cmdline_index];
- cmdline_index += len;
- }
-
- /* Add value of any symbol associated with this argument. */
- if (arg->type != VAL_NONE)
- {
- char *p, buf[50];
- int len;
- mach_port_t name;
-
- if (arg->type == VAL_SYM)
- {
- struct sym *sym = (struct sym *) arg->val;
-
- /* Resolve symbol value. */
- while (sym->type == VAL_SYM)
- sym = (struct sym *) sym->val;
- if (sym->type == VAL_NONE)
- {
- error = BOOT_SCRIPT_UNDEF_SYM;
- goto done;
- }
- arg->type = sym->type;
- arg->val = sym->val;
- }
-
- /* Print argument value. */
- switch (arg->type)
- {
- case VAL_STR:
- p = (char *) arg->val;
- len = strlen (p);
- break;
-
- case VAL_TASK:
- case VAL_PORT:
- if (arg->type == VAL_TASK)
- /* Insert send right to task port. */
- error = boot_script_insert_task_port
- (cmd, (task_t) arg->val, &name);
- else
- /* Insert send right. */
- error = boot_script_insert_right (cmd,
- (mach_port_t) arg->val,
- &name);
- if (error)
- goto done;
-
- i = name;
- p = buf + sizeof (buf);
- len = 0;
- do
- {
- *--p = i % 10 + '0';
- len++;
- }
- while (i /= 10);
- break;
-
- default:
- error = BOOT_SCRIPT_BAD_TYPE;
- goto done;
- }
- len++;
- CHECK_CMDLINE_LEN (len);
- memcpy (cmdline + cmdline_index, p, len - 1);
- *(cmdline + cmdline_index + len - 1) = '\0';
- if (! arg->text)
- argv[argc++] = &cmdline[cmdline_index];
- cmdline_index += len;
- }
- }
-
- /* Terminate argument vector. */
- argv[argc] = 0;
-
- /* Execute the command. */
- if (boot_script_exec_cmd (cmd->hook, cmd->task, cmd->path,
- argc, argv, cmdline, cmdline_index))
- {
- error = BOOT_SCRIPT_EXEC_ERROR;
- goto done;
- }
-
- error = 0;
-
- done:
- boot_script_free (cmdline, cmdline_alloc);
- boot_script_free (argv, sizeof (char *) * (cmd->args_index + 2));
- if (error)
- {
- cleanup (1);
- return error;
- }
- }
-
- for (cmd_index = 0; cmd_index < cmds_index; cmd_index++)
- {
- int i;
- struct cmd *cmd = cmds[cmd_index];
-
- /* Execute functions that want to be run on exec. */
- for (i = 0; i < cmd->exec_funcs_index; i++)
- {
- struct sym *sym = cmd->exec_funcs[i];
- int error = ((*((int (*) (struct cmd *, integer_t *)) sym->val))
- (cmd, 0));
- if (error)
- {
- cleanup (1);
- return error;
- }
- }
- }
-
- cleanup (0);
- return 0;
-}
-
-/* Create an entry for the variable NAME with TYPE and value VAL,
- in the symbol table. */
-int
-boot_script_set_variable (const char *name, int type, integer_t val)
-{
- struct sym *sym = sym_enter (name);
-
- if (sym)
- {
- sym->type = type;
- sym->val = val;
- }
- return sym ? 0 : 1;
-}
-
-
-/* Define the function NAME, which will return type RET_TYPE. */
-int
-boot_script_define_function (const char *name, int ret_type,
- int (*func) (const struct cmd *cmd,
- integer_t *val))
-{
- struct sym *sym = sym_enter (name);
-
- if (sym)
- {
- sym->type = VAL_FUNC;
- sym->val = (integer_t) func;
- sym->ret_type = ret_type;
- sym->run_on_exec = ret_type == VAL_NONE;
- }
- return sym ? 0 : 1;
-}
-
-
-/* Return a string describing ERR. */
-char *
-boot_script_error_string (int err)
-{
- switch (err)
- {
- case BOOT_SCRIPT_NOMEM:
- return "no memory";
-
- case BOOT_SCRIPT_SYNTAX_ERROR:
- return "syntax error";
-
- case BOOT_SCRIPT_INVALID_ASG:
- return "invalid variable in assignment";
-
- case BOOT_SCRIPT_MACH_ERROR:
- return "mach error";
-
- case BOOT_SCRIPT_UNDEF_SYM:
- return "undefined symbol";
-
- case BOOT_SCRIPT_EXEC_ERROR:
- return "exec error";
-
- case BOOT_SCRIPT_INVALID_SYM:
- return "invalid variable in expression";
-
- case BOOT_SCRIPT_BAD_TYPE:
- return "invalid value type";
- }
- return 0;
-}
-
-#ifdef BOOT_SCRIPT_TEST
-#include <stdio.h>
-
-int
-boot_script_exec_cmd (void *hook,
- mach_port_t task, char *path, int argc,
- char **argv, char *strings, int stringlen)
-{
- int i;
-
- printf ("port = %d: ", (int) task);
- for (i = 0; i < argc; i++)
- printf ("%s ", argv[i]);
- printf ("\n");
- return 0;
-}
-
-void
-main (int argc, char **argv)
-{
- char buf[500], *p;
- int len;
- FILE *fp;
- mach_port_t host_port, device_port;
-
- if (argc < 2)
- {
- fprintf (stderr, "Usage: %s <script>\n", argv[0]);
- exit (1);
- }
- fp = fopen (argv[1], "r");
- if (! fp)
- {
- fprintf (stderr, "Can't open %s\n", argv[1]);
- exit (1);
- }
- host_port = 1;
- device_port = 2;
- boot_script_set_variable ("host-port", VAL_PORT, (int) host_port);
- boot_script_set_variable ("device-port", VAL_PORT, (int) device_port);
- boot_script_set_variable ("root-device", VAL_STR, (int) "hd0a");
- boot_script_set_variable ("boot-args", VAL_STR, (int) "-ad");
- p = buf;
- len = sizeof (buf);
- while (fgets (p, len, fp))
- {
- int i, err;
-
- i = strlen (p) + 1;
- err = boot_script_parse_line (0, p);
- if (err)
- {
- fprintf (stderr, "error %s\n", boot_script_error_string (err));
- exit (1);
- }
- p += i;
- len -= i;
- }
- boot_script_exec ();
- exit (0);
-}
-#endif /* BOOT_SCRIPT_TEST */