- VERBOSE_LS is obsolete, as the heap is much better behaved now.

- Don't whine about nodes we can't stat(); these are usually
   symlinks that lead out of the filesystem.
 - Autoboot is now controlled by $autoboot_delay, which is a value
   in seconds or NO to disable autoboot.
 - Don't autoboot at the end of boot.conf if we have already tried.
 - Add a 'read' command to complement 'echo'.  Both are still hidden.
 - Improve the 'source' command/function so that it is possible to
   source scripts off removable media.  The entire script is read and
   saved before beginning execution.  Script lines beginning with
   '@' will not be echoed when being executed.  Script execution will
   normally terminate at the first error, however if the script line
   begins with '-' this behaviour is overriden for that command.
This commit is contained in:
Mike Smith 1998-10-07 02:38:26 +00:00
parent 82bb1fb746
commit b820c8e626
5 changed files with 198 additions and 55 deletions

View File

@ -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;

View File

@ -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 <sys/types.h>
@ -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[]);

View File

@ -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 <stand.h>
@ -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);
}

View File

@ -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 <stand.h>
@ -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);
}
}

View File

@ -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))