diff options
author | Uwe Stuehler <uwe@cvs.openbsd.org> | 2005-04-16 17:23:35 +0000 |
---|---|---|
committer | Uwe Stuehler <uwe@cvs.openbsd.org> | 2005-04-16 17:23:35 +0000 |
commit | 1ed58a61cce6c5fa16d00401df96d8e2d76bb3ca (patch) | |
tree | 865a4098bad98aec192b0718c28b8316e2d0fea2 | |
parent | 0f02079dc07378828ff00d7d06ddc7b26db0ecfc (diff) |
support a "clear" command to clear the broken Linux console. grmpf.
-rw-r--r-- | sys/arch/zaurus/stand/zboot/cmd.c | 537 |
1 files changed, 537 insertions, 0 deletions
diff --git a/sys/arch/zaurus/stand/zboot/cmd.c b/sys/arch/zaurus/stand/zboot/cmd.c new file mode 100644 index 00000000000..18205f361c4 --- /dev/null +++ b/sys/arch/zaurus/stand/zboot/cmd.c @@ -0,0 +1,537 @@ +/* $OpenBSD: cmd.c,v 1.1 2005/04/16 17:23:34 uwe Exp $ */ + +/* + * Copyright (c) 1997-1999 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 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 <sys/param.h> +#include <sys/reboot.h> + +#ifdef REGRESS +#include <sys/stat.h> +#include <errno.h> +#else +#include <libsa.h> +#include <lib/libkern/funcs.h> +#endif + +#include <stand/boot/cmd.h> + +#define CTRL(c) ((c)&0x1f) + +static int Xboot(void); +static int Xclear(void); +static int Xecho(void); +static int Xhelp(void); +static int Xls(void); +static int Xnop(void); +static int Xreboot(void); +static int Xstty(void); +static int Xtime(void); +#ifdef MACHINE_CMD +static int Xmachine(void); +extern const struct cmd_table MACHINE_CMD[]; +#endif +extern int Xset(void); +extern int Xenv(void); + +extern const struct cmd_table cmd_set[]; +const struct cmd_table cmd_table[] = { + {"#", CMDT_CMD, Xnop}, /* XXX must be first */ + {"boot", CMDT_CMD, Xboot}, + {"clear", CMDT_CMD, Xclear}, + {"echo", CMDT_CMD, Xecho}, + {"env", CMDT_CMD, Xenv}, + {"help", CMDT_CMD, Xhelp}, + {"ls", CMDT_CMD, Xls}, +#ifdef MACHINE_CMD + {"machine",CMDT_MDC, Xmachine}, +#endif + {"reboot", CMDT_CMD, Xreboot}, + {"set", CMDT_SET, Xset}, + {"stty", CMDT_CMD, Xstty}, + {"time", CMDT_CMD, Xtime}, + {NULL, 0}, +}; + +static void ls(char *, struct stat *); +static int readline(char *, size_t, int); +char *nextword(char *); +static char *whatcmd(const struct cmd_table **ct, char *); +static char *qualify(char *); + +char cmd_buf[CMD_BUFF_SIZE]; + +int +getcmd(void) +{ + cmd.cmd = NULL; + + if (!readline(cmd_buf, sizeof(cmd_buf), cmd.timeout)) + cmd.cmd = cmd_table; + + return docmd(); +} + +int +read_conf(void) +{ +#ifndef INSECURE + struct stat sb; +#endif + int fd, rc = 0; + + if ((fd = open(qualify(cmd.conf), 0)) < 0) { + if (errno != ENOENT && errno != ENXIO) { + printf("open(%s): %s\n", cmd.path, strerror(errno)); + return 0; + } + return -1; + } + +#ifndef INSECURE + (void) fstat(fd, &sb); + if (sb.st_uid || (sb.st_mode & 2)) { + printf("non-secure %s, will not proceed\n", cmd.path); + close(fd); + return -1; + } +#endif + + do { + char *p = cmd_buf; + + cmd.cmd = NULL; + + do { + rc = read(fd, p, 1); + } while (rc > 0 && *p++ != '\n' && + (p-cmd_buf) < sizeof(cmd_buf)); + + if (rc < 0) { /* Error from read() */ + printf("%s: %s\n", cmd.path, strerror(errno)); + break; + } + + if (rc == 0) { /* eof from read() */ + if (p != cmd_buf) { /* Line w/o trailing \n */ + *p = '\0'; + rc = docmd(); + break; + } + } else { /* rc > 0, read a char */ + p--; /* Get back to last character */ + + if (*p != '\n') { /* Line was too long */ + printf("%s: line too long\n", cmd.path); + + /* Don't want to run the truncated command */ + rc = -1; + } + + *p = '\0'; + } + + } while (rc > 0 && !(rc = docmd())); + + close(fd); + return rc; +} + +int +docmd(void) +{ + char *p = NULL; + const struct cmd_table *ct = cmd_table, *cs; + + cmd.argc = 1; + if (cmd.cmd == NULL) { + + /* command */ + for (p = cmd_buf; *p == ' ' || *p == '\t'; p++) + ; + if (*p == '#' || *p == '\0') { /* comment or empty string */ +#ifdef DEBUG + printf("rem\n"); +#endif + return 0; + } + ct = cmd_table; + cs = NULL; + 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_type == CMDT_SET && p != NULL) { + cs = cmd_set; +#ifdef MACHINE_CMD + } else if (ct->cmd_type == CMDT_MDC && p != NULL) { + cs = MACHINE_CMD; +#endif + } + + if (cs != NULL) { + p = whatcmd(&cs, p); + if (cs == NULL) { + printf("%s: syntax error\n", ct->cmd_name); + return 0; + } + ct = cs; + } + 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; + +#ifdef REGRESS + printf("%s %s\n", cmd.argv[0], + (cmd.argv[1] == NULL) ? "(null)" : cmd.argv[1]); +#else + return (*cmd.cmd->cmd_exec)(); +#endif +} + +static char * +whatcmd(const struct cmd_table **ct, char *p) +{ + char *q; + 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 +readline(char *buf, size_t n, int to) +{ +#ifdef DEBUG + extern int debug; +#endif + char *p = buf, ch; + + /* Only do timeout if greater than 0 */ + if (to > 0) { + u_long i = 0; + time_t tt = getsecs() + to; +#ifdef DEBUG + if (debug > 2) + printf ("readline: timeout(%d) at %u\n", to, tt); +#endif + /* check for timeout expiration less often + (for some very constrained archs) */ + while (!cnischar()) + if (!(i++ % 1000) && (getsecs() >= tt)) + break; + + if (!cnischar()) { + strlcpy(buf, "boot", 5); + putchar('\n'); + return strlen(buf); + } + } else + while (!cnischar()) + ; + + /* User has typed something. Turn off timeouts. */ + cmd.timeout = 0; + + while (1) { + switch ((ch = getchar())) { + case CTRL('u'): + while (p > buf) { + putchar('\177'); + p--; + } + continue; + case '\n': + case '\r': + p[1] = *p = '\0'; + break; + case '\b': + case '\177': + if (p > buf) { + putchar('\177'); + p--; + } + continue; + default: + if (p - buf < n-1) + *p++ = ch; + else { + putchar('\007'); + putchar('\177'); + } + continue; + } + break; + } + + return p - buf; +} + +/* + * Search for spaces/tabs after the current word. If found, \0 the + * first one. Then pass a pointer to the first character of the + * next word, or NULL if there is no next word. + */ +char * +nextword(char *p) +{ + /* skip blanks */ + while (*p && *p != '\t' && *p != ' ') + p++; + if (*p) { + *p++ = '\0'; + while (*p == '\t' || *p == ' ') + p++; + } + if (*p == '\0') + p = NULL; + return p; +} + +static void +print_help(const struct cmd_table *ct) +{ + for (; ct->cmd_name != NULL; ct++) + printf(" %s", ct->cmd_name); + putchar('\n'); +} + +static int +Xhelp(void) +{ + printf("commands:"); + print_help(cmd_table); +#ifdef MACHINE_CMD + return Xmachine(); +#else + return 0; +#endif +} + +#ifdef MACHINE_CMD +static int +Xmachine(void) +{ + printf("machine:"); + print_help(MACHINE_CMD); + return 0; +} +#endif + +static int +Xclear(void) +{ + int i; + + printf("\033[H\033[J"); + return 0; +} + +static int +Xecho(void) +{ + int i; + + for (i = 1; i < cmd.argc; i++) + printf("%s ", cmd.argv[i]); + putchar('\n'); + return 0; +} + +static int +Xstty(void) +{ + int sp; + char *cp; + dev_t dev; + + if (cmd.argc == 1) + printf("%s speed is %d\n", ttyname(0), cnspeed(0, -1)); + else { + dev = ttydev(cmd.argv[1]); + if (dev == NODEV) + printf("%s not a console device\n", cmd.argv[1]); + else { + if (cmd.argc == 2) + printf("%s speed is %d\n", cmd.argv[1], + cnspeed(dev, -1)); + else { + sp = 0; + for (cp = cmd.argv[2]; *cp && isdigit(*cp); cp++) + sp = sp * 10 + (*cp - '0'); + cnspeed(dev, sp); + } + } + } + + return 0; +} + +static int +Xtime(void) +{ + time_t tt = getsecs(); + + if (cmd.argc == 1) + printf(ctime(&tt)); + else { + } + + return 0; +} + +static int +Xls(void) +{ + struct stat sb; + char *p; + int fd; + + if (stat(qualify((cmd.argv[1]? cmd.argv[1]: "/.")), &sb) < 0) { + printf("stat(%s): %s\n", cmd.path, strerror(errno)); + return 0; + } + + 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; + } + + /* no strlen in lib !!! */ + for (p = cmd.path; *p; p++) + ; + *p++ = '/'; + *p = '\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); + } + closedir (fd); + } + return 0; +} + +#define lsrwx(mode,s) \ + putchar ((mode) & S_IROTH? 'r' : '-'); \ + putchar ((mode) & S_IWOTH? 'w' : '-'); \ + putchar ((mode) & S_IXOTH? *(s): (s)[1]); + +static void +ls(char *name, struct stat *sb) +{ + putchar("-fc-d-b---l-s-w-"[(sb->st_mode & S_IFMT) >> 12]); + lsrwx(sb->st_mode >> 6, (sb->st_mode & S_ISUID? "sS" : "x-")); + lsrwx(sb->st_mode >> 3, (sb->st_mode & S_ISGID? "sS" : "x-")); + lsrwx(sb->st_mode , (sb->st_mode & S_ISTXT? "tT" : "x-")); + + printf (" %u,%u\t%lu\t%s\n", sb->st_uid, sb->st_gid, + (u_long)sb->st_size, name); +} +#undef lsrwx + +int doboot = 1; + +static int +Xnop(void) +{ + if (doboot) { + doboot = 0; + return (Xboot()); + } + + return 0; +} + +static int +Xboot(void) +{ + if (cmd.argc > 1 && cmd.argv[1][0] != '-') { + qualify((cmd.argv[1]? cmd.argv[1]: cmd.image)); + if (bootparse(2)) + return 0; + } else { + if (bootparse(1)) + return 0; + snprintf(cmd.path, sizeof cmd.path, "%s:%s", + cmd.bootdev, cmd.image); + } + + return 1; +} + +/* + * Qualifies the path adding necessary dev + */ + +static char * +qualify(char *name) +{ + char *p; + + for (p = name; *p; p++) + if (*p == ':') + break; + if (*p == ':') + strlcpy(cmd.path, name, sizeof(cmd.path)); + else + snprintf(cmd.path, sizeof cmd.path, "%s:%s", + cmd.bootdev, name); + return cmd.path; +} + +static int +Xreboot(void) +{ + printf("Rebooting...\n"); + exit(); + return 0; /* just in case */ +} + |