rewrite command processing.
authormickey <mickey@openbsd.org>
Mon, 21 Apr 1997 20:03:30 +0000 (20:03 +0000)
committermickey <mickey@openbsd.org>
Mon, 21 Apr 1997 20:03:30 +0000 (20:03 +0000)
two levels of commands from now (set has it's own {device,image,addr,howto})
all the combinations of {device,path,image,options} is now possible on boot.
move cmd_state init into .data again, no more memory limits

sys/arch/i386/stand/boot/boot.c
sys/arch/i386/stand/boot/cmd.c
sys/arch/i386/stand/boot/cmd.h
sys/stand/boot/boot.c
sys/stand/boot/cmd.c
sys/stand/boot/cmd.h

index 38293eb..bad0678 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: boot.c,v 1.6 1997/04/14 10:48:04 deraadt Exp $        */
+/*     $OpenBSD: boot.c,v 1.7 1997/04/21 20:03:30 mickey Exp $ */
 
 /*
  * Copyright (c) 1997 Michael Shalayeff
@@ -48,13 +48,15 @@ char *kernels[] = {
 extern const char version[];
 int    boothowto;
 u_int  cnvmem, extmem;
+struct cmd_state cmd = {
+       "", "", "/", (void *)0x100000, 50, ""
+};
 
 void
 boot(bootdev)
        dev_t   bootdev;
 {
        register char *bootfile = kernels[0];
-       register struct cmd_state *cmd;
        register int i = 0;
 
 #ifdef DEBUG
@@ -72,34 +74,23 @@ boot(bootdev)
 
        printf(">> OpenBSD BOOT: %u/%u k [%s]\n", cnvmem, extmem, version);
 
-       /* XXX init cmd here to cut on .data !!! */
-       cmd = (struct cmd_state *)alloc(sizeof(*cmd));
-       devboot(bootdev, cmd->bootdev);
-       cmd->image[0] = '\0';
-       cmd->cwd[0] = '/';
-       cmd->cwd[1] = '\0';
-       cmd->addr = (void *)0x100000;
-       cmd->timeout = 50;
-
+       devboot(bootdev, cmd.bootdev);
        while (1) {
-               strncpy(cmd->image, bootfile, sizeof(cmd->image));
+               strncpy(cmd.image, bootfile, sizeof(cmd.image));
 
                do {
                        printf("boot> ");
-               } while(!getcmd(cmd) && !execmd(cmd));
-
-               if (cmd->rc < 0)
-                       break;
+               } while(!getcmd(&cmd));
 
-               printf("booting %s: ", cmd->path);
-               exec(cmd->path, cmd->addr, boothowto);
+               printf("booting %s: ", cmd.path);
+               exec(cmd.path, cmd.addr, boothowto);
 
                if (kernels[++i] == NULL)
                        bootfile = kernels[i=0];
                else
                        bootfile = kernels[i];
 
-               cmd->timeout += 20;
+               cmd.timeout += 20;
                printf(" failed(%d). will try %s\n", errno, bootfile);
        }
 }
index 92cab8d..c423016 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cmd.c,v 1.9 1997/04/17 21:47:37 deraadt Exp $ */
+/*     $OpenBSD: cmd.c,v 1.10 1997/04/21 20:03:30 mickey Exp $ */
 
 /*
  * Copyright (c) 1997 Michael Shalayeff
@@ -46,24 +46,50 @@ extern int debug;
 
 #define CTRL(c)        ((c)&0x1f)
 
-const struct cmd_table {
+static int Xaddr __P((struct cmd_state *));
+static int Xboot __P((struct cmd_state *));
+static int Xcd __P((struct cmd_state *));
+static int Xcp __P((struct cmd_state *));
+static int Xdevice __P((struct cmd_state *));
+#ifdef DEBUG
+static int Xdebug __P((struct cmd_state *));
+#endif
+static int Xhelp __P((struct cmd_state *));
+static int Ximage __P((struct cmd_state *));
+static int Xls __P((struct cmd_state *));
+static int Xnope __P((struct cmd_state *));
+static int Xreboot __P((struct cmd_state *));
+static int Xregs __P((struct cmd_state *));
+static int Xset __P((struct cmd_state *));
+static int Xhowto __P((struct cmd_state *));
+
+struct cmd_table {
        char *cmd_name;
-       int cmd_id;
-} cmd_table[] = {
-       {"addr",   CMD_ADDR},
-       {"boot",   CMD_BOOT},
-       {"cd",     CMD_CD},
-       {"device", CMD_DEVICE},
+       int (*cmd_exec)(struct cmd_state *);
+       const struct cmd_table *cmd_table;
+};
+
+const struct cmd_table cmd_set[] = {
+       {"addr",      Xaddr},
+       {"boothowto", Xhowto},
 #ifdef DEBUG   
-       {"debug",  CMD_DEBUG},
+       {"debug",     Xdebug},
 #endif
-       {"help",   CMD_HELP},
-       {"image",  CMD_IMAGE},
-       {"ls",     CMD_LS},
-       {"nope",   CMD_NOPE},
-       {"reboot", CMD_REBOOT},
-       {"regs",   CMD_REGS},
-       {"set",    CMD_SET},
+       {"device",    Xdevice},
+       {"image",     Ximage},
+       {NULL,0}
+};
+
+const struct cmd_table cmd_table[] = {
+       {"boot",   Xboot}, /* XXX must be first */
+       {"cd",     Xcd},
+       {"cp",     Xcp},
+       {"help",   Xhelp},
+       {"ls",     Xls},
+       {"nope",   Xnope},
+       {"reboot", Xreboot},
+       {"regs",   Xregs},
+       {"set",    Xset, cmd_set},
        {NULL, 0},
 };
 
@@ -71,61 +97,76 @@ extern const char version[];
 static void ls __P((char *, register struct stat *));
 static int readline __P((register char *, int));
 char *nextword __P((register char *));
-int bootparse __P((struct cmd_state *));
-
-char *cmd_buf = NULL;
+static int bootparse __P((struct cmd_state *, int));
+static char *whatcmd
+       __P((register const struct cmd_table **, register char *));
+char cmd_buf[133];
 
 int
 getcmd(cmd)
        struct cmd_state *cmd;
 {
-       register const struct cmd_table *ct = cmd_table;
-       register char *p, *q;
-       int l;
-
-       if (cmd_buf == NULL)
-               cmd_buf = alloc(133);
+       const struct cmd_table *ct;
+       register char *p;
 
-       cmd->rc = 0;
        cmd->argc = 1;
 
        if (!readline(cmd_buf, cmd->timeout)) {
-               printf("\n");
-               cmd->cmd = CMD_BOOT;
-               cmd->argv[0] = cmd_table[CMD_BOOT].cmd_name;
-               cmd->argv[1] = NULL;
-               cmd->rc = 1;
-               return 0;
-       }
-
-       /* command */
-       for (q = cmd_buf; *q && (*q == ' ' || *q == '\t'); q++)
-               ;
-       p = nextword(q);
+               cmd->cmd = cmd_table;
+               p = NULL;
+       } else {
 
-       for (l = 0; q[l]; l++)
-               ;
-       while (ct->cmd_name != NULL && strncmp(q, ct->cmd_name, l))
-               ct++;
-
-       if (ct->cmd_name == NULL) {
-               cmd->cmd = CMD_BOOT;
-               cmd->argv[0] = cmd_table[CMD_BOOT].cmd_name;
-               if (q && *q) {
-                       if (*q == '-')
-                               cmd->argv[cmd->argc++] = NULL;  /* XXX */
-                       cmd->argv[cmd->argc++] = q;
+               /* command */
+               for (p = cmd_buf; *p && (*p == ' ' || *p == '\t'); p++)
+                       ;
+               ct = cmd_table;
+               cmd->argv[cmd->argc] = p; /* in case it's shortcut boot */
+               p = whatcmd(&ct, p);
+               if (ct == NULL) {
+                       cmd->argc++;
+                       ct = cmd_table;
+               } else if (ct->cmd_table != NULL && p != NULL) {
+                       const struct cmd_table *cs = ct->cmd_table;
+                       p = whatcmd(&cs, p);
+                       if (cs == NULL) {
+                               printf("%s: syntax error\n", ct->cmd_name);
+                               return 0;
+                       }
+                       ct = cs;
                }
-       } else {
-               cmd->cmd = ct->cmd_id;
-               cmd->argv[0] = ct->cmd_name;
+               cmd->cmd = ct;
        }
+
+       cmd->argv[0] = ct->cmd_name;
        while (p && cmd->argc+1 < sizeof(cmd->argv) / sizeof(cmd->argv[0])) {
                cmd->argv[cmd->argc++] = p;
                p = nextword(p);
        }
        cmd->argv[cmd->argc] = NULL;
-       return bootparse(cmd);
+
+       return (*cmd->cmd->cmd_exec)(cmd);
+}
+
+static char *
+whatcmd(ct, p)
+       register const struct cmd_table **ct;
+       register char *p;
+{
+       register char *q;
+       register int l;
+
+       q = nextword(p);
+
+       for (l = 0; p[l]; l++)
+               ;
+
+       while ((*ct)->cmd_name != NULL && strncmp(p, (*ct)->cmd_name, l))
+               (*ct)++;
+
+       if ((*ct)->cmd_name == NULL)
+               *ct = NULL;
+
+       return q;
 }
 
 static int
@@ -201,204 +242,137 @@ nextword(p)
        return p;
 }
 
-int
-execmd(cmd)
+#ifdef DEBUG
+static int
+Xdebug(cmd)
        struct cmd_state *cmd;
 {
-       struct stat sb;
-       int fd;
-       register char *p, *q;
-       register const struct cmd_table *ct;
-
-       cmd->rc = 0;
-       switch (cmd->cmd) {
-
-#ifdef DEBUG
-       case CMD_DEBUG:
-               debug = !debug;
-               printf("debug is %s\n", debug? "on": "off");
-               break;
+       if (cmd->argc !=2)
+               printf("debug=%s\n", (debug? "on": "off"));
+       else
+               debug = (cmd->argv[1][0] == '0' ||
+                        (cmd->argv[1][0] == 'o' && cmd->argv[1][1] == 'f'))?
+                        0: 1;
+       return 0;
+}
 #endif
 
-       case CMD_HELP:
-               printf("commands: ");
-               for (ct = cmd_table; ct->cmd_name != NULL; ct++)
-                       printf(" %s", ct->cmd_name);
-               putchar('\n');
-               break;
-
-       case CMD_DEVICE:
-               if (cmd->argc != 2)
-                       printf("device: device name required\n");
-               else {
-                       strncpy(cmd->bootdev, cmd->argv[1],
-                               sizeof(cmd->bootdev));
-               }
-               break;
-
-       case CMD_IMAGE:
-               if (cmd->argc != 2)
-                       printf("image: pathname required\n");
-               else {
-                       strncpy(cmd->image, cmd->argv[1],
-                               sizeof(cmd->image));
-               }
-               break;
-
-       case CMD_ADDR:
-               if (cmd->argc != 2)
-                       printf("addr: address required\n");
-               else {
-                       register u_long a;
-
-                       p = cmd->argv[1];
-                       if (p[0] == '0' && p[1] == 'x')
-                               p += 2;
-                       for (a = 0; *p != '\0'; p++) {
-                               a <<= 4;
-                               a |= (isdigit(*p)? *p - '0':
-                                     10 + tolower(*p) - 'a') & 0xf;
-                       }
+static int
+Xhelp(cmd)
+       struct cmd_state *cmd;
+{
+       register const struct cmd_table *ct;
 
-                       cmd->addr = (void *)a;
-               }
-               break;
+       printf("commands: ");
+       for (ct = cmd_table; ct->cmd_name != NULL; ct++)
+               printf(" %s", ct->cmd_name);
+       putchar('\n');
 
-       case CMD_LS:
-               {
-                       if (cmd->argv[1] != NULL)
-                               strncpy (cmd->path, cmd->argv[1],
-                                        sizeof(cmd->path));
-                       else
-                               sprintf(cmd->path, "%s:%s/.",
-                                       cmd->bootdev, cmd->cwd);
+       return 0;
+}
 
-                       if (stat(cmd->path, &sb) < 0) {
-                               printf("stat(%s): %d\n", cmd->path, errno);
-                               break;
-                       }
+/* called only w/ no arguments */
+static int
+Xset(cmd)
+       struct cmd_state *cmd;
+{
+       register const struct cmd_table *ct;
 
-                       if ((sb.st_mode & S_IFMT) != S_IFDIR)
-                               ls(cmd->path, &sb);
-                       else {
-                               if ((fd = opendir(cmd->path)) < 0) {
-                                       printf ("opendir(%s): %d\n",
-                                               cmd->path, errno);
-                                       break;
-                               }
+       printf("OpenBSD boot[%s]\n", version);
+       printf("cwd=%s\n", cmd->cwd);
+       for (ct = cmd_set; ct->cmd_name != NULL; ct++)
+               (*ct->cmd_exec)(cmd);
+       return 0;
+}
 
-                               /* no strlen in lib !!! */
-                               for (p = cmd->path; *p; p++);
-                               *p++ = '/';
-                               *p = '\0';
+static int
+Xdevice(cmd)
+       struct cmd_state *cmd;
+{
+       if (cmd->argc != 2)
+               printf("device=%s\n", cmd->bootdev);
+       else
+               strncpy(cmd->bootdev, cmd->argv[1], sizeof(cmd->bootdev));
+       return 0;
+}
 
-                               while(readdir(fd, p) >= 0) {
+static int
+Ximage(cmd)
+       struct cmd_state *cmd;
+{
+       if (cmd->argc != 2)
+               printf("image=%s\n", cmd->image);
+       else
+               strncpy(cmd->image, cmd->argv[1], sizeof(cmd->image));
+       return 0;
+}
 
-                                       if (stat(cmd->path, &sb) < 0)
-                                               printf("stat(%s): %d\n",
-                                                      cmd->path, errno);
-                                       else
-                                               ls(p, &sb);
-                               }
+static int
+Xaddr(cmd)
+       struct cmd_state *cmd;
+{
+       register char *p;
 
-                               closedir (fd);
-                       }
+       if (cmd->argc != 2)
+               printf("addr=%p\n", cmd->addr);
+       else {
+               register u_long a;
+
+               p = cmd->argv[1];
+               if (p[0] == '0' && p[1] == 'x')
+                       p += 2;
+               for (a = 0; *p != '\0'; p++) {
+                       a <<= 4;
+                       a |= (isdigit(*p)? *p - '0':
+                             10 + tolower(*p) - 'a') & 0xf;
                }
-               break;
+               cmd->addr = (void *)a;
+       }
+       return 0;
+}
 
-       case CMD_CD:
-               if (cmd->argc == 1) {
-                       cmd->cwd[0] = '/';
-                       cmd->cwd[1] = '\0';
-                       break;
-               }
+static int
+Xls(cmd)
+       struct cmd_state *cmd;
+{
+       struct stat sb;
+       register char *p;
+       int fd;
 
-               if (cmd->argv[1][0] == '.' && cmd->argv[1][1] == '\0')
-                       break;
+       if (cmd->argv[1] != NULL)
+               strncpy (cmd->path, cmd->argv[1], sizeof(cmd->path));
+       else
+               sprintf(cmd->path, "%s:%s/.", cmd->bootdev, cmd->cwd);
 
-               if (cmd->argv[1][0] == '.' && cmd->argv[1][1] == '.'
-                   && cmd->argv[1][2] == '\0') {
-                       /* strrchr(cmd->cwd, '/'); */
-                       for (p = cmd->cwd; *++p;);
-                       for (p--; *--p != '/';);
-                       p[1] = '\0';
-                       break;
-               }
+       if (stat(cmd->path, &sb) < 0) {
+               printf("stat(%s): %s\n", cmd->path, strerror(errno));
+               return 0;
+       }
 
-               sprintf(cmd->path, "%s:%s%s",
-                       cmd->bootdev, cmd->cwd, cmd->argv[1]);
-               if (stat(cmd->path, &sb) < 0) {
-                       printf("stat(%s): %d\n", cmd->argv[1], errno);
-                       break;
+       if ((sb.st_mode & S_IFMT) != S_IFDIR)
+               ls(cmd->path, &sb);
+       else {
+               if ((fd = opendir(cmd->path)) < 0) {
+                       printf ("opendir(%s): %s\n", cmd->path,
+                               strerror(errno));
+                       return 0;
                }
 
-               if (!S_ISDIR(sb.st_mode)) {
-                       printf("boot: %s: not a dir\n", cmd->argv[1]);
-                       break;
-               }
+               /* no strlen in lib !!! */
+               for (p = cmd->path; *p; p++);
+               *p++ = '/';
+               *p = '\0';
 
-               /* change dir */
-               for (p = cmd->cwd; *p; p++);
-               for (q = cmd->argv[1]; (*p++ = *q++) != '\0';);
-               if (p[-2] != '/') {
-                       p[-1] = '/';
-                       p[0] = '\0';
+               while(readdir(fd, p) >= 0) {
+                       if (stat(cmd->path, &sb) < 0)
+                               printf("stat(%s): %s\n", cmd->path,
+                                       strerror(errno));
+                       else
+                               ls(p, &sb);
                }
-               break;
-
-       case CMD_SET:
-               printf("OpenBSD/i386 boot version %s(debug is %s)\n"
-                      "device:\t%s\n"
-                      "cwd:\t%s\n"
-                      "image:\t%s\n"
-                      "load at:\t%p\n"
-                      "timeout:\t%d\n",
-                      version,
-#ifdef DEBUG
-                      (debug? "on": "off"),
-#else
-                               "not present",
-#endif
-                      cmd->bootdev, cmd->cwd, cmd->image,
-                      cmd->addr, cmd->timeout);
-               break;
-
-       case CMD_REBOOT:
-               printf("Rebooting...\n");
-               cmd->rc = -1;
-               break;
-
-       case CMD_REGS:
-               DUMP_REGS;
-               break;
-
-       case CMD_BOOT:
-               /* XXX "boot -s" will not work as this is written */
-               if (cmd->argc > 1 && cmd->argv[1]) {
-                       char *p;
-
-                       for (p = cmd->argv[1]; *p; p++)
-                               if (*p == ':')
-                                       break;
-                       if (*p == ':')
-                               sprintf(cmd->path, "%s", cmd->argv[1]);
-                       else 
-                               sprintf(cmd->path, "%s:%s", cmd->bootdev,
-                                   cmd->argv[1]);
-               } else
-                       sprintf(cmd->path, "%s:%s%s", cmd->bootdev,
-                               cmd->cwd, cmd->image);
-               cmd->rc = !bootparse(cmd);
-               break;
-
-       case CMD_ERROR:
-       default:
-               printf ("%s: invalid command\n", cmd->argv[0]);
-       case CMD_NOPE:
-               break;
+               closedir (fd);
        }
-
-       return cmd->rc;
+       return 0;
 }
 
 #define lsrwx(mode,s) \
@@ -419,34 +393,95 @@ ls(name, sb)
        printf (" %u,%u\t%lu\t%s\n", sb->st_uid, sb->st_gid,
                (u_long)sb->st_size, name);
 }
+#undef lsrwx
 
-int
-bootparse(cmd)
+static int
+Xhowto(cmd)
        struct cmd_state *cmd;
 {
-       char *cp;
+       if (cmd->argc < 2) {
+               printf("boothowto=");
+               if (boothowto) {
+                       putchar('-');
+                       if (boothowto & RB_ASKNAME)
+                               putchar('a');
+                       if (boothowto & RB_HALT)
+                               putchar('b');
+                       if (boothowto & RB_CONFIG)
+                               putchar('c');
+                       if (boothowto & RB_SINGLE)
+                               putchar('s');
+                       if (boothowto & RB_KDB)
+                               putchar('d');
+               }
+               putchar('\n');
+       } else
+               bootparse(cmd, 1);
+       return 0;
+}
+
+static int
+Xboot(cmd)
+       struct cmd_state *cmd;
+{
+       if (cmd->argc > 1 && cmd->argv[1][0] != '-') {
+               register char *p;
+
+               for (p = cmd->argv[1]; *p; p++)
+                       if (*p == ':')
+                               break;
+               if (*p == ':')
+                       sprintf(cmd->path, "%s", cmd->argv[1]);
+               else if (cmd->argv[1][0] == '/')
+                       sprintf(cmd->path, "%s:%s", cmd->bootdev,
+                               cmd->argv[1]);
+               else
+                       sprintf(cmd->path, "%s:%s%s", cmd->bootdev,
+                               cmd->cwd, cmd->argv[1]);
+
+               if (bootparse(cmd, 2))
+                       return 0;
+       } else {
+               if (bootparse(cmd, 1))
+                       return 0;
+               sprintf(cmd->path, "%s:%s%s", cmd->bootdev,
+                       cmd->cwd, cmd->image);
+       }
+
+       return 1;
+}
+
+static int
+bootparse(cmd, i)
+       struct cmd_state *cmd;
        int i;
+{
+       register char *cp;
+       int howto = boothowto;
 
-       for (i = 2; i < cmd->argc; i++) {
+       for (; i < cmd->argc; i++) {
                cp = cmd->argv[i];
                if (*cp == '-') {
                        while (*++cp) {
                                switch (*cp) {
                                case 'a':
-                                       boothowto |= RB_ASKNAME;
+                                       howto |= RB_ASKNAME;
                                        break;
                                case 'b':
-                                       boothowto |= RB_HALT;
+                                       howto |= RB_HALT;
                                        break;
                                case 'c':
-                                       boothowto |= RB_CONFIG;
+                                       howto |= RB_CONFIG;
                                        break;
                                case 's':
-                                       boothowto |= RB_SINGLE;
+                                       howto |= RB_SINGLE;
                                        break;
                                case 'd':
-                                       boothowto |= RB_KDB;
+                                       howto |= RB_KDB;
                                        break;
+                               default:
+                                       printf("howto: bad option: %c\n", *cp);
+                                       return 1;
                                }
                        }
                } else {
@@ -454,5 +489,92 @@ bootparse(cmd)
                        return 1;
                }
        }
+       boothowto = howto;
        return 0;
 }
+
+static int
+Xcd(cmd)
+       struct cmd_state *cmd;
+{
+       register char *p, *q;
+       struct stat sb;
+
+       /* cd home */
+       if (cmd->argc == 1) {
+               cmd->cwd[0] = '/';
+               cmd->cwd[1] = '\0';
+               return 0;
+       }
+
+       /* cd '.' */
+       if (cmd->argv[1][0] == '.' && cmd->argv[1][1] == '\0')
+               return 0;
+
+       /* cd '..' */
+       if (cmd->argv[1][0] == '.' && cmd->argv[1][1] == '.'
+           && cmd->argv[1][2] == '\0') {
+               /* strrchr(cmd->cwd, '/'); */
+               for (p = cmd->cwd; *++p;);
+               for (p--; *--p != '/';);
+               p[1] = '\0';
+               return 0;
+       }
+
+       /* cd dir */
+       sprintf(cmd->path, "%s:%s%s",
+               cmd->bootdev, cmd->cwd, cmd->argv[1]);
+
+       if (stat(cmd->path, &sb) < 0) {
+               printf("stat(%s): %s\n", cmd->argv[1], strerror(errno));
+               return 0;
+       }
+
+       if (!S_ISDIR(sb.st_mode)) {
+               printf("boot: %s: not a dir\n", cmd->argv[1]);
+               return 0;
+       }
+
+       /* change dir */
+       for (p = cmd->cwd; *p; p++);
+       for (q = cmd->argv[1]; (*p++ = *q++) != '\0';);
+       if (p[-2] != '/') {
+               p[-1] = '/';
+               p[0] = '\0';
+       }
+
+       return 0;
+}
+
+static int
+Xreboot(cmd)
+       struct cmd_state *cmd;
+{
+       printf("Rebooting...\n");
+       exit();
+       return 0; /* just in case */
+}
+
+static int
+Xregs(cmd)
+       struct cmd_state *cmd;
+{
+       DUMP_REGS;
+       return 0;
+}
+
+static int
+Xnope(cmd)
+       struct cmd_state *cmd;
+{
+       return 0;
+}
+
+static int
+Xcp(cmd)
+       struct cmd_state *cmd;
+{
+       printf("cp: no writable filesystems\n");
+       return 0;
+}
+
index 3a5d168..a806e1c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cmd.h,v 1.3 1997/04/01 04:50:33 mickey Exp $  */
+/*     $OpenBSD: cmd.h,v 1.4 1997/04/21 20:03:31 mickey Exp $  */
 
 /*
  * Copyright (c) 1997 Michael Shalayeff
@@ -32,6 +32,7 @@
  *
  */
 
+struct cmd_table;
 struct cmd_state {
        char bootdev[16]; /* device */
        char image[32]; /* image */
@@ -40,15 +41,9 @@ struct cmd_state {
        int timeout;
        char path[MAXPATHLEN]; /* buffer for pathname compose */
 
-       enum { CMD_ADDR, CMD_BOOT, CMD_CD, CMD_DEVICE, CMD_DEBUG, CMD_HELP,
-              CMD_IMAGE, CMD_LS, CMD_NOPE, CMD_REBOOT, CMD_SET,
-              CMD_REGS,
-              CMD_ERROR /* last !!! */
-       }       cmd;
+       const struct cmd_table *cmd;
        int argc;
        char *argv[8];  /* XXX i hope this is enough */
-       int rc;
 };
 
 int getcmd __P((register struct cmd_state *));
-int execmd __P((register struct cmd_state *));
index 38293eb..bad0678 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: boot.c,v 1.6 1997/04/14 10:48:04 deraadt Exp $        */
+/*     $OpenBSD: boot.c,v 1.7 1997/04/21 20:03:30 mickey Exp $ */
 
 /*
  * Copyright (c) 1997 Michael Shalayeff
@@ -48,13 +48,15 @@ char *kernels[] = {
 extern const char version[];
 int    boothowto;
 u_int  cnvmem, extmem;
+struct cmd_state cmd = {
+       "", "", "/", (void *)0x100000, 50, ""
+};
 
 void
 boot(bootdev)
        dev_t   bootdev;
 {
        register char *bootfile = kernels[0];
-       register struct cmd_state *cmd;
        register int i = 0;
 
 #ifdef DEBUG
@@ -72,34 +74,23 @@ boot(bootdev)
 
        printf(">> OpenBSD BOOT: %u/%u k [%s]\n", cnvmem, extmem, version);
 
-       /* XXX init cmd here to cut on .data !!! */
-       cmd = (struct cmd_state *)alloc(sizeof(*cmd));
-       devboot(bootdev, cmd->bootdev);
-       cmd->image[0] = '\0';
-       cmd->cwd[0] = '/';
-       cmd->cwd[1] = '\0';
-       cmd->addr = (void *)0x100000;
-       cmd->timeout = 50;
-
+       devboot(bootdev, cmd.bootdev);
        while (1) {
-               strncpy(cmd->image, bootfile, sizeof(cmd->image));
+               strncpy(cmd.image, bootfile, sizeof(cmd.image));
 
                do {
                        printf("boot> ");
-               } while(!getcmd(cmd) && !execmd(cmd));
-
-               if (cmd->rc < 0)
-                       break;
+               } while(!getcmd(&cmd));
 
-               printf("booting %s: ", cmd->path);
-               exec(cmd->path, cmd->addr, boothowto);
+               printf("booting %s: ", cmd.path);
+               exec(cmd.path, cmd.addr, boothowto);
 
                if (kernels[++i] == NULL)
                        bootfile = kernels[i=0];
                else
                        bootfile = kernels[i];
 
-               cmd->timeout += 20;
+               cmd.timeout += 20;
                printf(" failed(%d). will try %s\n", errno, bootfile);
        }
 }
index 92cab8d..c423016 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cmd.c,v 1.9 1997/04/17 21:47:37 deraadt Exp $ */
+/*     $OpenBSD: cmd.c,v 1.10 1997/04/21 20:03:30 mickey Exp $ */
 
 /*
  * Copyright (c) 1997 Michael Shalayeff
@@ -46,24 +46,50 @@ extern int debug;
 
 #define CTRL(c)        ((c)&0x1f)
 
-const struct cmd_table {
+static int Xaddr __P((struct cmd_state *));
+static int Xboot __P((struct cmd_state *));
+static int Xcd __P((struct cmd_state *));
+static int Xcp __P((struct cmd_state *));
+static int Xdevice __P((struct cmd_state *));
+#ifdef DEBUG
+static int Xdebug __P((struct cmd_state *));
+#endif
+static int Xhelp __P((struct cmd_state *));
+static int Ximage __P((struct cmd_state *));
+static int Xls __P((struct cmd_state *));
+static int Xnope __P((struct cmd_state *));
+static int Xreboot __P((struct cmd_state *));
+static int Xregs __P((struct cmd_state *));
+static int Xset __P((struct cmd_state *));
+static int Xhowto __P((struct cmd_state *));
+
+struct cmd_table {
        char *cmd_name;
-       int cmd_id;
-} cmd_table[] = {
-       {"addr",   CMD_ADDR},
-       {"boot",   CMD_BOOT},
-       {"cd",     CMD_CD},
-       {"device", CMD_DEVICE},
+       int (*cmd_exec)(struct cmd_state *);
+       const struct cmd_table *cmd_table;
+};
+
+const struct cmd_table cmd_set[] = {
+       {"addr",      Xaddr},
+       {"boothowto", Xhowto},
 #ifdef DEBUG   
-       {"debug",  CMD_DEBUG},
+       {"debug",     Xdebug},
 #endif
-       {"help",   CMD_HELP},
-       {"image",  CMD_IMAGE},
-       {"ls",     CMD_LS},
-       {"nope",   CMD_NOPE},
-       {"reboot", CMD_REBOOT},
-       {"regs",   CMD_REGS},
-       {"set",    CMD_SET},
+       {"device",    Xdevice},
+       {"image",     Ximage},
+       {NULL,0}
+};
+
+const struct cmd_table cmd_table[] = {
+       {"boot",   Xboot}, /* XXX must be first */
+       {"cd",     Xcd},
+       {"cp",     Xcp},
+       {"help",   Xhelp},
+       {"ls",     Xls},
+       {"nope",   Xnope},
+       {"reboot", Xreboot},
+       {"regs",   Xregs},
+       {"set",    Xset, cmd_set},
        {NULL, 0},
 };
 
@@ -71,61 +97,76 @@ extern const char version[];
 static void ls __P((char *, register struct stat *));
 static int readline __P((register char *, int));
 char *nextword __P((register char *));
-int bootparse __P((struct cmd_state *));
-
-char *cmd_buf = NULL;
+static int bootparse __P((struct cmd_state *, int));
+static char *whatcmd
+       __P((register const struct cmd_table **, register char *));
+char cmd_buf[133];
 
 int
 getcmd(cmd)
        struct cmd_state *cmd;
 {
-       register const struct cmd_table *ct = cmd_table;
-       register char *p, *q;
-       int l;
-
-       if (cmd_buf == NULL)
-               cmd_buf = alloc(133);
+       const struct cmd_table *ct;
+       register char *p;
 
-       cmd->rc = 0;
        cmd->argc = 1;
 
        if (!readline(cmd_buf, cmd->timeout)) {
-               printf("\n");
-               cmd->cmd = CMD_BOOT;
-               cmd->argv[0] = cmd_table[CMD_BOOT].cmd_name;
-               cmd->argv[1] = NULL;
-               cmd->rc = 1;
-               return 0;
-       }
-
-       /* command */
-       for (q = cmd_buf; *q && (*q == ' ' || *q == '\t'); q++)
-               ;
-       p = nextword(q);
+               cmd->cmd = cmd_table;
+               p = NULL;
+       } else {
 
-       for (l = 0; q[l]; l++)
-               ;
-       while (ct->cmd_name != NULL && strncmp(q, ct->cmd_name, l))
-               ct++;
-
-       if (ct->cmd_name == NULL) {
-               cmd->cmd = CMD_BOOT;
-               cmd->argv[0] = cmd_table[CMD_BOOT].cmd_name;
-               if (q && *q) {
-                       if (*q == '-')
-                               cmd->argv[cmd->argc++] = NULL;  /* XXX */
-                       cmd->argv[cmd->argc++] = q;
+               /* command */
+               for (p = cmd_buf; *p && (*p == ' ' || *p == '\t'); p++)
+                       ;
+               ct = cmd_table;
+               cmd->argv[cmd->argc] = p; /* in case it's shortcut boot */
+               p = whatcmd(&ct, p);
+               if (ct == NULL) {
+                       cmd->argc++;
+                       ct = cmd_table;
+               } else if (ct->cmd_table != NULL && p != NULL) {
+                       const struct cmd_table *cs = ct->cmd_table;
+                       p = whatcmd(&cs, p);
+                       if (cs == NULL) {
+                               printf("%s: syntax error\n", ct->cmd_name);
+                               return 0;
+                       }
+                       ct = cs;
                }
-       } else {
-               cmd->cmd = ct->cmd_id;
-               cmd->argv[0] = ct->cmd_name;
+               cmd->cmd = ct;
        }
+
+       cmd->argv[0] = ct->cmd_name;
        while (p && cmd->argc+1 < sizeof(cmd->argv) / sizeof(cmd->argv[0])) {
                cmd->argv[cmd->argc++] = p;
                p = nextword(p);
        }
        cmd->argv[cmd->argc] = NULL;
-       return bootparse(cmd);
+
+       return (*cmd->cmd->cmd_exec)(cmd);
+}
+
+static char *
+whatcmd(ct, p)
+       register const struct cmd_table **ct;
+       register char *p;
+{
+       register char *q;
+       register int l;
+
+       q = nextword(p);
+
+       for (l = 0; p[l]; l++)
+               ;
+
+       while ((*ct)->cmd_name != NULL && strncmp(p, (*ct)->cmd_name, l))
+               (*ct)++;
+
+       if ((*ct)->cmd_name == NULL)
+               *ct = NULL;
+
+       return q;
 }
 
 static int
@@ -201,204 +242,137 @@ nextword(p)
        return p;
 }
 
-int
-execmd(cmd)
+#ifdef DEBUG
+static int
+Xdebug(cmd)
        struct cmd_state *cmd;
 {
-       struct stat sb;
-       int fd;
-       register char *p, *q;
-       register const struct cmd_table *ct;
-
-       cmd->rc = 0;
-       switch (cmd->cmd) {
-
-#ifdef DEBUG
-       case CMD_DEBUG:
-               debug = !debug;
-               printf("debug is %s\n", debug? "on": "off");
-               break;
+       if (cmd->argc !=2)
+               printf("debug=%s\n", (debug? "on": "off"));
+       else
+               debug = (cmd->argv[1][0] == '0' ||
+                        (cmd->argv[1][0] == 'o' && cmd->argv[1][1] == 'f'))?
+                        0: 1;
+       return 0;
+}
 #endif
 
-       case CMD_HELP:
-               printf("commands: ");
-               for (ct = cmd_table; ct->cmd_name != NULL; ct++)
-                       printf(" %s", ct->cmd_name);
-               putchar('\n');
-               break;
-
-       case CMD_DEVICE:
-               if (cmd->argc != 2)
-                       printf("device: device name required\n");
-               else {
-                       strncpy(cmd->bootdev, cmd->argv[1],
-                               sizeof(cmd->bootdev));
-               }
-               break;
-
-       case CMD_IMAGE:
-               if (cmd->argc != 2)
-                       printf("image: pathname required\n");
-               else {
-                       strncpy(cmd->image, cmd->argv[1],
-                               sizeof(cmd->image));
-               }
-               break;
-
-       case CMD_ADDR:
-               if (cmd->argc != 2)
-                       printf("addr: address required\n");
-               else {
-                       register u_long a;
-
-                       p = cmd->argv[1];
-                       if (p[0] == '0' && p[1] == 'x')
-                               p += 2;
-                       for (a = 0; *p != '\0'; p++) {
-                               a <<= 4;
-                               a |= (isdigit(*p)? *p - '0':
-                                     10 + tolower(*p) - 'a') & 0xf;
-                       }
+static int
+Xhelp(cmd)
+       struct cmd_state *cmd;
+{
+       register const struct cmd_table *ct;
 
-                       cmd->addr = (void *)a;
-               }
-               break;
+       printf("commands: ");
+       for (ct = cmd_table; ct->cmd_name != NULL; ct++)
+               printf(" %s", ct->cmd_name);
+       putchar('\n');
 
-       case CMD_LS:
-               {
-                       if (cmd->argv[1] != NULL)
-                               strncpy (cmd->path, cmd->argv[1],
-                                        sizeof(cmd->path));
-                       else
-                               sprintf(cmd->path, "%s:%s/.",
-                                       cmd->bootdev, cmd->cwd);
+       return 0;
+}
 
-                       if (stat(cmd->path, &sb) < 0) {
-                               printf("stat(%s): %d\n", cmd->path, errno);
-                               break;
-                       }
+/* called only w/ no arguments */
+static int
+Xset(cmd)
+       struct cmd_state *cmd;
+{
+       register const struct cmd_table *ct;
 
-                       if ((sb.st_mode & S_IFMT) != S_IFDIR)
-                               ls(cmd->path, &sb);
-                       else {
-                               if ((fd = opendir(cmd->path)) < 0) {
-                                       printf ("opendir(%s): %d\n",
-                                               cmd->path, errno);
-                                       break;
-                               }
+       printf("OpenBSD boot[%s]\n", version);
+       printf("cwd=%s\n", cmd->cwd);
+       for (ct = cmd_set; ct->cmd_name != NULL; ct++)
+               (*ct->cmd_exec)(cmd);
+       return 0;
+}
 
-                               /* no strlen in lib !!! */
-                               for (p = cmd->path; *p; p++);
-                               *p++ = '/';
-                               *p = '\0';
+static int
+Xdevice(cmd)
+       struct cmd_state *cmd;
+{
+       if (cmd->argc != 2)
+               printf("device=%s\n", cmd->bootdev);
+       else
+               strncpy(cmd->bootdev, cmd->argv[1], sizeof(cmd->bootdev));
+       return 0;
+}
 
-                               while(readdir(fd, p) >= 0) {
+static int
+Ximage(cmd)
+       struct cmd_state *cmd;
+{
+       if (cmd->argc != 2)
+               printf("image=%s\n", cmd->image);
+       else
+               strncpy(cmd->image, cmd->argv[1], sizeof(cmd->image));
+       return 0;
+}
 
-                                       if (stat(cmd->path, &sb) < 0)
-                                               printf("stat(%s): %d\n",
-                                                      cmd->path, errno);
-                                       else
-                                               ls(p, &sb);
-                               }
+static int
+Xaddr(cmd)
+       struct cmd_state *cmd;
+{
+       register char *p;
 
-                               closedir (fd);
-                       }
+       if (cmd->argc != 2)
+               printf("addr=%p\n", cmd->addr);
+       else {
+               register u_long a;
+
+               p = cmd->argv[1];
+               if (p[0] == '0' && p[1] == 'x')
+                       p += 2;
+               for (a = 0; *p != '\0'; p++) {
+                       a <<= 4;
+                       a |= (isdigit(*p)? *p - '0':
+                             10 + tolower(*p) - 'a') & 0xf;
                }
-               break;
+               cmd->addr = (void *)a;
+       }
+       return 0;
+}
 
-       case CMD_CD:
-               if (cmd->argc == 1) {
-                       cmd->cwd[0] = '/';
-                       cmd->cwd[1] = '\0';
-                       break;
-               }
+static int
+Xls(cmd)
+       struct cmd_state *cmd;
+{
+       struct stat sb;
+       register char *p;
+       int fd;
 
-               if (cmd->argv[1][0] == '.' && cmd->argv[1][1] == '\0')
-                       break;
+       if (cmd->argv[1] != NULL)
+               strncpy (cmd->path, cmd->argv[1], sizeof(cmd->path));
+       else
+               sprintf(cmd->path, "%s:%s/.", cmd->bootdev, cmd->cwd);
 
-               if (cmd->argv[1][0] == '.' && cmd->argv[1][1] == '.'
-                   && cmd->argv[1][2] == '\0') {
-                       /* strrchr(cmd->cwd, '/'); */
-                       for (p = cmd->cwd; *++p;);
-                       for (p--; *--p != '/';);
-                       p[1] = '\0';
-                       break;
-               }
+       if (stat(cmd->path, &sb) < 0) {
+               printf("stat(%s): %s\n", cmd->path, strerror(errno));
+               return 0;
+       }
 
-               sprintf(cmd->path, "%s:%s%s",
-                       cmd->bootdev, cmd->cwd, cmd->argv[1]);
-               if (stat(cmd->path, &sb) < 0) {
-                       printf("stat(%s): %d\n", cmd->argv[1], errno);
-                       break;
+       if ((sb.st_mode & S_IFMT) != S_IFDIR)
+               ls(cmd->path, &sb);
+       else {
+               if ((fd = opendir(cmd->path)) < 0) {
+                       printf ("opendir(%s): %s\n", cmd->path,
+                               strerror(errno));
+                       return 0;
                }
 
-               if (!S_ISDIR(sb.st_mode)) {
-                       printf("boot: %s: not a dir\n", cmd->argv[1]);
-                       break;
-               }
+               /* no strlen in lib !!! */
+               for (p = cmd->path; *p; p++);
+               *p++ = '/';
+               *p = '\0';
 
-               /* change dir */
-               for (p = cmd->cwd; *p; p++);
-               for (q = cmd->argv[1]; (*p++ = *q++) != '\0';);
-               if (p[-2] != '/') {
-                       p[-1] = '/';
-                       p[0] = '\0';
+               while(readdir(fd, p) >= 0) {
+                       if (stat(cmd->path, &sb) < 0)
+                               printf("stat(%s): %s\n", cmd->path,
+                                       strerror(errno));
+                       else
+                               ls(p, &sb);
                }
-               break;
-
-       case CMD_SET:
-               printf("OpenBSD/i386 boot version %s(debug is %s)\n"
-                      "device:\t%s\n"
-                      "cwd:\t%s\n"
-                      "image:\t%s\n"
-                      "load at:\t%p\n"
-                      "timeout:\t%d\n",
-                      version,
-#ifdef DEBUG
-                      (debug? "on": "off"),
-#else
-                               "not present",
-#endif
-                      cmd->bootdev, cmd->cwd, cmd->image,
-                      cmd->addr, cmd->timeout);
-               break;
-
-       case CMD_REBOOT:
-               printf("Rebooting...\n");
-               cmd->rc = -1;
-               break;
-
-       case CMD_REGS:
-               DUMP_REGS;
-               break;
-
-       case CMD_BOOT:
-               /* XXX "boot -s" will not work as this is written */
-               if (cmd->argc > 1 && cmd->argv[1]) {
-                       char *p;
-
-                       for (p = cmd->argv[1]; *p; p++)
-                               if (*p == ':')
-                                       break;
-                       if (*p == ':')
-                               sprintf(cmd->path, "%s", cmd->argv[1]);
-                       else 
-                               sprintf(cmd->path, "%s:%s", cmd->bootdev,
-                                   cmd->argv[1]);
-               } else
-                       sprintf(cmd->path, "%s:%s%s", cmd->bootdev,
-                               cmd->cwd, cmd->image);
-               cmd->rc = !bootparse(cmd);
-               break;
-
-       case CMD_ERROR:
-       default:
-               printf ("%s: invalid command\n", cmd->argv[0]);
-       case CMD_NOPE:
-               break;
+               closedir (fd);
        }
-
-       return cmd->rc;
+       return 0;
 }
 
 #define lsrwx(mode,s) \
@@ -419,34 +393,95 @@ ls(name, sb)
        printf (" %u,%u\t%lu\t%s\n", sb->st_uid, sb->st_gid,
                (u_long)sb->st_size, name);
 }
+#undef lsrwx
 
-int
-bootparse(cmd)
+static int
+Xhowto(cmd)
        struct cmd_state *cmd;
 {
-       char *cp;
+       if (cmd->argc < 2) {
+               printf("boothowto=");
+               if (boothowto) {
+                       putchar('-');
+                       if (boothowto & RB_ASKNAME)
+                               putchar('a');
+                       if (boothowto & RB_HALT)
+                               putchar('b');
+                       if (boothowto & RB_CONFIG)
+                               putchar('c');
+                       if (boothowto & RB_SINGLE)
+                               putchar('s');
+                       if (boothowto & RB_KDB)
+                               putchar('d');
+               }
+               putchar('\n');
+       } else
+               bootparse(cmd, 1);
+       return 0;
+}
+
+static int
+Xboot(cmd)
+       struct cmd_state *cmd;
+{
+       if (cmd->argc > 1 && cmd->argv[1][0] != '-') {
+               register char *p;
+
+               for (p = cmd->argv[1]; *p; p++)
+                       if (*p == ':')
+                               break;
+               if (*p == ':')
+                       sprintf(cmd->path, "%s", cmd->argv[1]);
+               else if (cmd->argv[1][0] == '/')
+                       sprintf(cmd->path, "%s:%s", cmd->bootdev,
+                               cmd->argv[1]);
+               else
+                       sprintf(cmd->path, "%s:%s%s", cmd->bootdev,
+                               cmd->cwd, cmd->argv[1]);
+
+               if (bootparse(cmd, 2))
+                       return 0;
+       } else {
+               if (bootparse(cmd, 1))
+                       return 0;
+               sprintf(cmd->path, "%s:%s%s", cmd->bootdev,
+                       cmd->cwd, cmd->image);
+       }
+
+       return 1;
+}
+
+static int
+bootparse(cmd, i)
+       struct cmd_state *cmd;
        int i;
+{
+       register char *cp;
+       int howto = boothowto;
 
-       for (i = 2; i < cmd->argc; i++) {
+       for (; i < cmd->argc; i++) {
                cp = cmd->argv[i];
                if (*cp == '-') {
                        while (*++cp) {
                                switch (*cp) {
                                case 'a':
-                                       boothowto |= RB_ASKNAME;
+                                       howto |= RB_ASKNAME;
                                        break;
                                case 'b':
-                                       boothowto |= RB_HALT;
+                                       howto |= RB_HALT;
                                        break;
                                case 'c':
-                                       boothowto |= RB_CONFIG;
+                                       howto |= RB_CONFIG;
                                        break;
                                case 's':
-                                       boothowto |= RB_SINGLE;
+                                       howto |= RB_SINGLE;
                                        break;
                                case 'd':
-                                       boothowto |= RB_KDB;
+                                       howto |= RB_KDB;
                                        break;
+                               default:
+                                       printf("howto: bad option: %c\n", *cp);
+                                       return 1;
                                }
                        }
                } else {
@@ -454,5 +489,92 @@ bootparse(cmd)
                        return 1;
                }
        }
+       boothowto = howto;
        return 0;
 }
+
+static int
+Xcd(cmd)
+       struct cmd_state *cmd;
+{
+       register char *p, *q;
+       struct stat sb;
+
+       /* cd home */
+       if (cmd->argc == 1) {
+               cmd->cwd[0] = '/';
+               cmd->cwd[1] = '\0';
+               return 0;
+       }
+
+       /* cd '.' */
+       if (cmd->argv[1][0] == '.' && cmd->argv[1][1] == '\0')
+               return 0;
+
+       /* cd '..' */
+       if (cmd->argv[1][0] == '.' && cmd->argv[1][1] == '.'
+           && cmd->argv[1][2] == '\0') {
+               /* strrchr(cmd->cwd, '/'); */
+               for (p = cmd->cwd; *++p;);
+               for (p--; *--p != '/';);
+               p[1] = '\0';
+               return 0;
+       }
+
+       /* cd dir */
+       sprintf(cmd->path, "%s:%s%s",
+               cmd->bootdev, cmd->cwd, cmd->argv[1]);
+
+       if (stat(cmd->path, &sb) < 0) {
+               printf("stat(%s): %s\n", cmd->argv[1], strerror(errno));
+               return 0;
+       }
+
+       if (!S_ISDIR(sb.st_mode)) {
+               printf("boot: %s: not a dir\n", cmd->argv[1]);
+               return 0;
+       }
+
+       /* change dir */
+       for (p = cmd->cwd; *p; p++);
+       for (q = cmd->argv[1]; (*p++ = *q++) != '\0';);
+       if (p[-2] != '/') {
+               p[-1] = '/';
+               p[0] = '\0';
+       }
+
+       return 0;
+}
+
+static int
+Xreboot(cmd)
+       struct cmd_state *cmd;
+{
+       printf("Rebooting...\n");
+       exit();
+       return 0; /* just in case */
+}
+
+static int
+Xregs(cmd)
+       struct cmd_state *cmd;
+{
+       DUMP_REGS;
+       return 0;
+}
+
+static int
+Xnope(cmd)
+       struct cmd_state *cmd;
+{
+       return 0;
+}
+
+static int
+Xcp(cmd)
+       struct cmd_state *cmd;
+{
+       printf("cp: no writable filesystems\n");
+       return 0;
+}
+
index 3a5d168..a806e1c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cmd.h,v 1.3 1997/04/01 04:50:33 mickey Exp $  */
+/*     $OpenBSD: cmd.h,v 1.4 1997/04/21 20:03:31 mickey Exp $  */
 
 /*
  * Copyright (c) 1997 Michael Shalayeff
@@ -32,6 +32,7 @@
  *
  */
 
+struct cmd_table;
 struct cmd_state {
        char bootdev[16]; /* device */
        char image[32]; /* image */
@@ -40,15 +41,9 @@ struct cmd_state {
        int timeout;
        char path[MAXPATHLEN]; /* buffer for pathname compose */
 
-       enum { CMD_ADDR, CMD_BOOT, CMD_CD, CMD_DEVICE, CMD_DEBUG, CMD_HELP,
-              CMD_IMAGE, CMD_LS, CMD_NOPE, CMD_REBOOT, CMD_SET,
-              CMD_REGS,
-              CMD_ERROR /* last !!! */
-       }       cmd;
+       const struct cmd_table *cmd;
        int argc;
        char *argv[8];  /* XXX i hope this is enough */
-       int rc;
 };
 
 int getcmd __P((register struct cmd_state *));
-int execmd __P((register struct cmd_state *));