diff --git a/sys/boot/common/boot.c b/sys/boot/common/boot.c index e0ea678c299..d54201c2b6d 100644 --- a/sys/boot/common/boot.c +++ b/sys/boot/common/boot.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: boot.c,v 1.3 1998/09/28 22:03:01 peter Exp $ + * $Id: boot.c,v 1.4 1998/10/02 16:22:26 msmith Exp $ */ /* @@ -40,6 +40,8 @@ static char *getbootfile(int try); /* List of kernel names to try (may be overwritten by boot.config) XXX should move from here? */ static char *default_bootfiles = "kernel,kernel.old"; +static int autoboot_tried; + /* * The user wants us to boot. */ @@ -119,9 +121,6 @@ command_boot(int argc, char *argv[]) COMMAND_SET(autoboot, "autoboot", "boot automatically after a delay", command_autoboot); -/* - * XXX note the 'prompt' argument is not really useful until quoting is implemented - */ static int command_autoboot(int argc, char *argv[]) { @@ -149,15 +148,39 @@ command_autoboot(int argc, char *argv[]) return(CMD_ERROR); } +/* + * Called before we go interactive. If we think we can autoboot, and + * we haven't tried already, try now. + */ +void +autoboot_maybe() +{ + char *cp; + + cp = getenv("autoboot_delay"); + if ((autoboot_tried == 0) && ((cp == NULL) || strcasecmp(cp, "NO"))) + autoboot(-1, NULL); /* try to boot automatically */ +} + int autoboot(int delay, char *prompt) { time_t when, otime, ntime; int c, yes; - char *argv[2]; + char *argv[2], *cp, *ep; - if (delay == -1) - delay = 5; /* env var? compile-time define? */ + autoboot_tried = 1; + + if (delay == -1) { + /* try to get a delay from the environment */ + if ((cp = getenv("autoboot_delay"))) { + delay = strtol(cp, &ep, 0); + if (cp == ep) + delay = -1; + } + } + if (delay == -1) /* all else fails */ + delay = 10; otime = time(NULL); when = otime + delay; /* when to boot */ @@ -183,7 +206,6 @@ autoboot(int delay, char *prompt) otime = ntime; } } - printf("\n"); if (yes) { argv[0] = "boot"; argv[1] = NULL; diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h index 1c4d00f8d8a..bf3874b292b 100644 --- a/sys/boot/common/bootstrap.h +++ b/sys/boot/common/bootstrap.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bootstrap.h,v 1.9 1998/09/30 19:25:26 peter Exp $ + * $Id: bootstrap.h,v 1.10 1998/10/02 08:04:56 peter Exp $ */ #include @@ -62,6 +62,7 @@ extern int parse(int *argc, char ***argv, char *str); /* boot.c */ extern int autoboot(int delay, char *prompt); +extern void autoboot_maybe(void); /* misc.c */ extern char *unargv(int argc, char *argv[]); diff --git a/sys/boot/common/commands.c b/sys/boot/common/commands.c index e7b67251c85..b0d05181079 100644 --- a/sys/boot/common/commands.c +++ b/sys/boot/common/commands.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: commands.c,v 1.2 1998/09/03 02:10:07 msmith Exp $ + * $Id: commands.c,v 1.3 1998/09/18 02:01:38 msmith Exp $ */ #include @@ -43,7 +43,7 @@ command_help(int argc, char *argv[]) char helppath[80]; /* XXX buffer size? */ /* page the help text from our load path */ - sprintf(helppath, "%s/boot.help", getenv("loaddev")); + sprintf(helppath, "%s/boot/boot.help", getenv("loaddev")); printf("%s\n", helppath); if (pager_file(helppath) == -1) printf("Verbose help not available, use '?' to list commands\n"); @@ -177,3 +177,62 @@ command_echo(int argc, char *argv[]) return(CMD_OK); } +/* + * A passable emulation of the sh(1) command of the same name. + */ + +COMMAND_SET(read, "read", NULL, command_read); + +static int +command_read(int argc, char *argv[]) +{ + char *prompt; + int timeout; + time_t when; + char *cp; + char *name; + char buf[256]; /* XXX size? */ + int c; + + timeout = -1; + prompt = NULL; + optind = 1; + while ((c = getopt(argc, argv, "p:t:")) != -1) { + switch(c) { + + case 'p': + prompt = optarg; + break; + case 't': + timeout = strtol(optarg, &cp, 0); + if (cp == optarg) { + sprintf(command_errbuf, "bad timeout '%s'", optarg); + return(CMD_ERROR); + } + break; + default: + return(CMD_OK); + } + } + + argv += (optind); + argc -= (optind); + name = (argc > 0) ? argv[0]: NULL; + + if (prompt != NULL) + printf(prompt); + if (timeout >= 0) { + when = time(NULL) + timeout; + while (!ischar()) + if (time(NULL) >= when) + return(CMD_OK); /* is timeout an error? */ + } + + ngets(buf, sizeof(buf)); + + printf("read name '%s' value '%s'\n", name, buf); + + if (name != NULL) + setenv(name, buf, 1); + return(CMD_OK); +} diff --git a/sys/boot/common/interp.c b/sys/boot/common/interp.c index 69a2fc36593..5c4aa515eda 100644 --- a/sys/boot/common/interp.c +++ b/sys/boot/common/interp.c @@ -23,12 +23,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: interp.c,v 1.3 1998/09/03 02:10:07 msmith Exp $ + * $Id: interp.c,v 1.4 1998/09/14 18:27:04 msmith Exp $ */ /* * Simple commandline interpreter, toplevel and misc. * - * XXX may be obsoleted by BootFORTH + * XXX may be obsoleted by BootFORTH or some other, better, interpreter. */ #include @@ -87,11 +87,10 @@ interact(void) source("/boot/boot.conf"); printf("\n"); /* - * Before interacting, we might want to autoboot + * Before interacting, we might want to autoboot. */ - if (getenv("no_autoboot") == NULL) - autoboot(10, NULL); /* try to boot automatically */ - + autoboot_maybe(); + /* * Not autobooting, go manual */ @@ -114,7 +113,13 @@ interact(void) } /* - * Read command from a file + * Read commands from a file, then execute them. + * + * We store the commands in memory and close the source file so that the media + * holding it can safely go away while we are executing. + * + * Commands may be prefixed with '@' (so they aren't displayed) or '-' (so + * that the script won't stop if they fail). */ COMMAND_SET(source, "source", "read commands from a file", command_source); @@ -128,39 +133,103 @@ command_source(int argc, char *argv[]) return(CMD_OK); } +struct sourceline +{ + char *text; + int flags; + int line; +#define SL_QUIET (1<<0) +#define SL_IGNOREERR (1<<1) + struct sourceline *next; +}; + void source(char *filename) { - char input[256]; /* big enough? */ - int argc; - char **argv, *cp; - int fd; + struct sourceline *script, *se, *sp; + char input[256]; /* big enough? */ + int argc; + char **argv, *cp; + int fd, flags, line; if (((fd = open(filename, O_RDONLY)) == -1)) { printf("can't open '%s': %s\n", filename, strerror(errno)); - } else { - while (fgetstr(input, sizeof(input), fd) > 0) { + return; + } - /* Discard comments */ - if (input[0] == '#') - continue; - cp = input; - /* Echo? */ - if (input[0] == '@') { - cp++; - } else { - prompt(); - printf("%s\n", input); - } - - if (!parse(&argc, &argv, cp)) { - if ((argc > 0) && - (perform(argc, argv) != 0)) - printf("%s: %s\n", argv[0], command_errmsg); - free(argv); - } + /* + * Read the script into memory. + */ + script = se = NULL; + line = 0; + + while (fgetstr(input, sizeof(input), fd) > 0) { + line++; + flags = 0; + /* Discard comments */ + if (input[0] == '#') + continue; + cp = input; + /* Echo? */ + if (input[0] == '@') { + cp++; + flags |= SL_QUIET; } - close(fd); + /* Error OK? */ + if (input[0] == '-') { + cp++; + flags |= SL_IGNOREERR; + } + /* Allocate script line structure and copy line, flags */ + sp = malloc(sizeof(struct sourceline) + strlen(input) + 1); + sp->text = (char *)sp + sizeof(struct sourceline); + strcpy(sp->text, input); + sp->flags = flags; + sp->line = line; + sp->next = NULL; + + if (script == NULL) { + script = sp; + } else { + se->next = sp; + } + se = sp; + } + close(fd); + + /* + * Execute the script + */ + argv = NULL; + for (sp = script; sp != NULL; sp = sp->next) { + + /* print if not being quiet */ + if (!(sp->flags & SL_QUIET)) { + prompt(); + printf("%s\n", sp->text); + } + + /* Parse the command */ + if (!parse(&argc, &argv, sp->text)) { + if ((argc > 1) && (perform(argc, argv) != 0)) { + /* normal command */ + printf("%s: %s\n", argv[0], command_errmsg); + if (!(sp->flags & SL_IGNOREERR)) + break; + } + free(argv); + argv = NULL; + } else { + printf("%s line %d: parse error\n", filename, sp->line); + break; + } + } + if (argv != NULL) + free(argv); + while(script != NULL) { + se = script; + script = script->next; + free(se); } } diff --git a/sys/boot/common/ls.c b/sys/boot/common/ls.c index 1596a3abce7..2cce8adc387 100644 --- a/sys/boot/common/ls.c +++ b/sys/boot/common/ls.c @@ -1,5 +1,5 @@ /* - * $Id: ls.c,v 1.2 1998/09/03 02:10:07 msmith Exp $ + * $Id: ls.c,v 1.3 1998/09/26 01:29:13 msmith Exp $ * From: $NetBSD: ls.c,v 1.3 1997/06/13 13:48:47 drochner Exp $ */ @@ -61,7 +61,6 @@ command_ls(int argc, char *argv[]) static char buf[128]; /* must be long enough for full pathname */ char *path; int result, ch; -#ifdef VERBOSE_LS int verbose; verbose = 0; @@ -79,7 +78,6 @@ command_ls(int argc, char *argv[]) } argv += (optind - 1); argc -= (optind - 1); -#endif if (argc < 2) { path = "/"; @@ -107,11 +105,9 @@ command_ls(int argc, char *argv[]) result = CMD_ERROR; goto out; } -#ifdef VERBOSE_LS /* fixup path for stat()ing files */ if (!strcmp(path, "/")) path = ""; -#endif while ((size = read(fd, dirbuf, DIRBLKSIZ)) == DIRBLKSIZ) { struct direct *dp, *edp; @@ -139,18 +135,14 @@ command_ls(int argc, char *argv[]) } if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) { -#ifdef VERBOSE_LS /* too much UFS activity blows the heap out */ if (verbose) { /* stat the file, if possible */ sb.st_size = 0; sprintf(buf, "%s/%s", path, dp->d_name); - /* ignore return */ - if (stat(buf, &sb)) { - printf("stat(%s) failed: %s\n", buf, strerror(errno)); - sb.st_size = -1; - } + /* ignore return, could be symlink, etc. */ + if (stat(buf, &sb)) + sb.st_size = 0; sprintf(buf, " %c %8d %s\n", typestr[dp->d_type], (int)sb.st_size, dp->d_name); -#endif } else sprintf(buf, " %c %s\n", typestr[dp->d_type], dp->d_name); if (pager_output(buf))