From d66a72cfe0bf6d9ab9725f0d0cb1f38dbcc0ac49 Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Sat, 16 Jun 2018 15:28:06 +0300 Subject: [PATCH] =?utf8?q?9615=20loader:=20cstyle=20fixes=20for=20some=20c?= =?utf8?q?ommon=20files=20Reviewed=20by:=20Yuri=20Pankov=20=20Reviewed=20by:=20Ken=20Mays=20=20Rev?= =?utf8?q?iewed=20by:=20Gerg=C5=91=20Mih=C3=A1ly=20Doma=20=20Approved=20by:=20Robert=20Mustacchi=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- usr/src/boot/sys/boot/common/boot.c | 819 ++++++++++++------------ usr/src/boot/sys/boot/common/interp_backslash.c | 338 +++++----- usr/src/boot/sys/boot/common/interp_parse.c | 270 ++++---- 3 files changed, 722 insertions(+), 705 deletions(-) rewrite usr/src/boot/sys/boot/common/boot.c (70%) rewrite usr/src/boot/sys/boot/common/interp_backslash.c (72%) diff --git a/usr/src/boot/sys/boot/common/boot.c b/usr/src/boot/sys/boot/common/boot.c dissimilarity index 70% index 349fa5f9e8..db5aae9b92 100644 --- a/usr/src/boot/sys/boot/common/boot.c +++ b/usr/src/boot/sys/boot/common/boot.c @@ -1,402 +1,417 @@ -/* - * Copyright (c) 1998 Michael Smith - * 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 AND CONTRIBUTORS ``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 AUTHOR 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 - -/* - * Loading modules, booting the system - */ - -#include -#include - -#include "bootstrap.h" - -static char *getbootfile(int try); -static int loadakernel(int try, int argc, char* argv[]); - -/* List of kernel names to try (may be overwritten by boot.config) XXX should move from here? */ -static const char *default_bootfiles = "kernel"; - -static int autoboot_tried; - -/* - * The user wants us to boot. - */ -COMMAND_SET(boot, "boot", "boot a file or loaded kernel", command_boot); - -static int -command_boot(int argc, char *argv[]) -{ - struct preloaded_file *fp; - - /* - * See if the user has specified an explicit kernel to boot. - */ - if ((argc > 1) && (argv[1][0] == '/')) { - - /* XXX maybe we should discard everything and start again? */ - if (file_findfile(NULL, NULL) != NULL) { - snprintf(command_errbuf, sizeof (command_errbuf), - "can't boot '%s', kernel module already loaded", argv[1]); - return(CMD_ERROR); - } - - /* find/load the kernel module */ - if (mod_loadkld(argv[1], argc - 2, argv + 2) != 0) - return(CMD_ERROR); - /* we have consumed all arguments */ - argc = 1; - } - - /* - * See if there is a kernel module already loaded - */ - if (file_findfile(NULL, NULL) == NULL) - if (loadakernel(0, argc - 1, argv + 1)) - /* we have consumed all arguments */ - argc = 1; - - /* - * Loaded anything yet? - */ - if ((fp = file_findfile(NULL, NULL)) == NULL) { - command_errmsg = "no bootable kernel"; - return(CMD_ERROR); - } - - /* - * If we were given arguments, discard any previous. - * XXX should we merge arguments? Hard to DWIM. - */ - if (argc > 1) { - if (fp->f_args != NULL) - free(fp->f_args); - fp->f_args = unargv(argc - 1, argv + 1); - } - - /* Hook for platform-specific autoloading of modules */ - if (archsw.arch_autoload() != 0) - return(CMD_ERROR); - - /* Call the exec handler from the loader matching the kernel */ - file_formats[fp->f_loader]->l_exec(fp); - return(CMD_ERROR); -} - - -/* - * Autoboot after a delay - */ - -COMMAND_SET(autoboot, "autoboot", "boot automatically after a delay", command_autoboot); - -static int -command_autoboot(int argc, char *argv[]) -{ - int howlong; - char *cp, *prompt; - - prompt = NULL; - howlong = -1; - switch(argc) { - case 3: - prompt = argv[2]; - /* FALLTHROUGH */ - case 2: - howlong = strtol(argv[1], &cp, 0); - if (*cp != 0) { - snprintf(command_errbuf, sizeof (command_errbuf), - "bad delay '%s'", argv[1]); - return(CMD_ERROR); - } - /* FALLTHROUGH */ - case 1: - return(autoboot(howlong, prompt)); - } - - command_errmsg = "too many arguments"; - 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(void) -{ - char *cp; - - /* compatibility with sparc prom, check for autoboot? */ - cp = getenv("autoboot?"); - if (cp != NULL && strcasecmp(cp, "true") != 0) - return; - cp = getenv("autoboot_delay"); - if ((autoboot_tried == 0) && ((cp == NULL) || strcasecmp(cp, "NO"))) - autoboot(-1, NULL); /* try to boot automatically */ -} - -int -autoboot(int timeout, char *prompt) -{ - time_t when, otime, ntime; - int c, yes; - char *argv[2], *cp, *ep; - char *kernelname; - struct preloaded_file *fp; - - autoboot_tried = 1; - - if (timeout == -1) { - timeout = 10; - /* try to get a delay from the environment */ - if ((cp = getenv("autoboot_delay"))) { - timeout = strtol(cp, &ep, 0); - if (cp == ep) - timeout = 10; /* Unparseable? Set default! */ - } - } - - fp = file_findfile(NULL, NULL); - if (fp == NULL) { /* no preloaded files, run command start to load all */ - bf_run("start"); - fp = file_findfile(NULL, NULL); - if (fp == NULL) { /* still nothing? can't boot */ - command_errmsg = "no valid kernel found"; - return(CMD_ERROR); - } - } - - kernelname = fp->f_name; - - if (timeout >= 0) { - otime = time(NULL); - when = otime + timeout; /* when to boot */ - - yes = 0; - - printf("%s\n", (prompt == NULL) ? "Hit [Enter] to boot immediately, or any other key for command prompt." : prompt); - - for (;;) { - if (ischar()) { - c = getchar(); - if ((c == '\r') || (c == '\n')) - yes = 1; - break; - } - ntime = time(NULL); - if (ntime >= when) { - yes = 1; - break; - } - - if (ntime != otime) { - printf("\rBooting [%s] in %d second%s... ", - kernelname, (int)(when - ntime), - (when-ntime)==1?"":"s"); - otime = ntime; - } - } - } else { - yes = 1; - } - - if (yes) - printf("\rBooting [%s]... ", kernelname); - putchar('\n'); - if (yes) { - argv[0] = "boot"; - argv[1] = NULL; - return(command_boot(1, argv)); - } - return(CMD_OK); -} - -/* - * Scrounge for the name of the (try)'th file we will try to boot. - */ -static char * -getbootfile(int try) -{ - static char *name = NULL; - const char *spec, *ep; - size_t len; - - /* we use dynamic storage */ - if (name != NULL) { - free(name); - name = NULL; - } - - /* - * Try $bootfile, then try our builtin default - */ - if ((spec = getenv("bootfile")) == NULL) - spec = default_bootfiles; - - while ((try > 0) && (spec != NULL)) { - spec = strchr(spec, ';'); - if (spec) - spec++; /* skip over the leading ';' */ - try--; - } - if (spec != NULL) { - if ((ep = strchr(spec, ';')) != NULL) { - len = ep - spec; - } else { - len = strlen(spec); - } - name = malloc(len + 1); - strncpy(name, spec, len); - name[len] = 0; - } - if (name && name[0] == 0) { - free(name); - name = NULL; - } - return(name); -} - -/* - * Try to find the /etc/fstab file on the filesystem (rootdev), - * which should be be the root filesystem, and parse it to find - * out what the kernel ought to think the root filesystem is. - * - * If we're successful, set vfs.root.mountfrom to : - * so that the kernel can tell both which VFS and which node to use - * to mount the device. If this variable's already set, don't - * overwrite it. - */ -int -getrootmount(char *rootdev) -{ - char lbuf[128], *cp, *ep, *dev, *fstyp, *options; - int fd, error; - - if (getenv("vfs.root.mountfrom") != NULL) - return(0); - - error = 1; - sprintf(lbuf, "%s/etc/fstab", rootdev); - if ((fd = open(lbuf, O_RDONLY)) < 0) - goto notfound; - - /* loop reading lines from /etc/fstab What was that about sscanf again? */ - fstyp = NULL; - dev = NULL; - while (fgetstr(lbuf, sizeof(lbuf), fd) >= 0) { - if ((lbuf[0] == 0) || (lbuf[0] == '#')) - continue; - - /* skip device name */ - for (cp = lbuf; (*cp != 0) && !isspace(*cp); cp++) - ; - if (*cp == 0) /* misformatted */ - continue; - /* delimit and save */ - *cp++ = 0; - free(dev); - dev = strdup(lbuf); - - /* skip whitespace up to mountpoint */ - while ((*cp != 0) && isspace(*cp)) - cp++; - /* must have / to be root */ - if ((*cp == 0) || (*cp != '/') || !isspace(*(cp + 1))) - continue; - /* skip whitespace up to fstype */ - cp += 2; - while ((*cp != 0) && isspace(*cp)) - cp++; - if (*cp == 0) /* misformatted */ - continue; - /* skip text to end of fstype and delimit */ - ep = cp; - while ((*cp != 0) && !isspace(*cp)) - cp++; - *cp = 0; - free(fstyp); - fstyp = strdup(ep); - - /* skip whitespace up to mount options */ - cp += 1; - while ((*cp != 0) && isspace(*cp)) - cp++; - if (*cp == 0) /* misformatted */ - continue; - /* skip text to end of mount options and delimit */ - ep = cp; - while ((*cp != 0) && !isspace(*cp)) - cp++; - *cp = 0; - options = strdup(ep); - /* Build the : and save it in vfs.root.mountfrom */ - sprintf(lbuf, "%s:%s", fstyp, dev); - setenv("vfs.root.mountfrom", lbuf, 0); - - /* Don't override vfs.root.mountfrom.options if it is already set */ - if (getenv("vfs.root.mountfrom.options") == NULL) { - /* save mount options */ - setenv("vfs.root.mountfrom.options", options, 0); - } - free(options); - error = 0; - break; - } - close(fd); - free(dev); - free(fstyp); - -notfound: - if (error) { - const char *currdev; - - currdev = getenv("currdev"); - if (currdev != NULL && strncmp("zfs:", currdev, 4) == 0) { - cp = strdup(currdev); - cp[strlen(cp) - 1] = '\0'; - setenv("vfs.root.mountfrom", cp, 0); - error = 0; - free(cp); - } - } - - return(error); -} - -static int -loadakernel(int try, int argc, char* argv[]) -{ - char *cp; - - for (try = 0; (cp = getbootfile(try)) != NULL; try++) - if (mod_loadkld(cp, argc - 1, argv + 1) != 0) - printf("can't load '%s'\n", cp); - else - return 1; - return 0; -} +/* + * Copyright (c) 1998 Michael Smith + * 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 AND CONTRIBUTORS ``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 AUTHOR 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 + +/* + * Loading modules, booting the system + */ + +#include +#include + +#include "bootstrap.h" + +static char *getbootfile(int try); +static int loadakernel(int try, int argc, char *argv[]); + +/* + * List of kernel names to try (may be overwritten by boot.config) + * XXX should move from here? + */ +static const char *default_bootfiles = "kernel"; + +static int autoboot_tried; + +/* + * The user wants us to boot. + */ +COMMAND_SET(boot, "boot", "boot a file or loaded kernel", command_boot); + +static int +command_boot(int argc, char *argv[]) +{ + struct preloaded_file *fp; + + /* + * See if the user has specified an explicit kernel to boot. + */ + if ((argc > 1) && (argv[1][0] == '/')) { + + /* XXX maybe we should discard everything and start again? */ + if (file_findfile(NULL, NULL) != NULL) { + snprintf(command_errbuf, sizeof (command_errbuf), + "can't boot '%s', kernel module already loaded", + argv[1]); + return (CMD_ERROR); + } + + /* find/load the kernel module */ + if (mod_loadkld(argv[1], argc - 2, argv + 2) != 0) + return (CMD_ERROR); + /* we have consumed all arguments */ + argc = 1; + } + + /* + * See if there is a kernel module already loaded + */ + if (file_findfile(NULL, NULL) == NULL) + if (loadakernel(0, argc - 1, argv + 1)) { + /* we have consumed all arguments */ + argc = 1; + } + + /* + * Loaded anything yet? + */ + if ((fp = file_findfile(NULL, NULL)) == NULL) { + command_errmsg = "no bootable kernel"; + return (CMD_ERROR); + } + + /* + * If we were given arguments, discard any previous. + * XXX should we merge arguments? Hard to DWIM. + */ + if (argc > 1) { + free(fp->f_args); + fp->f_args = unargv(argc - 1, argv + 1); + } + + /* Hook for platform-specific autoloading of modules */ + if (archsw.arch_autoload() != 0) + return (CMD_ERROR); + + /* Call the exec handler from the loader matching the kernel */ + file_formats[fp->f_loader]->l_exec(fp); + return (CMD_ERROR); +} + + +/* + * Autoboot after a delay + */ + +COMMAND_SET(autoboot, "autoboot", "boot automatically after a delay", + command_autoboot); + +static int +command_autoboot(int argc, char *argv[]) +{ + int howlong; + char *cp, *prompt; + + prompt = NULL; + howlong = -1; + switch (argc) { + case 3: + prompt = argv[2]; + /* FALLTHROUGH */ + case 2: + howlong = strtol(argv[1], &cp, 0); + if (*cp != 0) { + snprintf(command_errbuf, sizeof (command_errbuf), + "bad delay '%s'", argv[1]); + return (CMD_ERROR); + } + /* FALLTHROUGH */ + case 1: + return (autoboot(howlong, prompt)); + } + + command_errmsg = "too many arguments"; + 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(void) +{ + char *cp; + + /* compatibility with sparc prom, check for autoboot? */ + cp = getenv("autoboot?"); + if (cp != NULL && strcasecmp(cp, "true") != 0) + return; + cp = getenv("autoboot_delay"); + if ((autoboot_tried == 0) && ((cp == NULL) || strcasecmp(cp, "NO"))) + autoboot(-1, NULL); /* try to boot automatically */ +} + +int +autoboot(int timeout, char *prompt) +{ + time_t when, otime, ntime; + int c, yes; + char *argv[2], *cp, *ep; + char *kernelname; + struct preloaded_file *fp; + + autoboot_tried = 1; + + if (timeout == -1) { + timeout = 10; + /* try to get a delay from the environment */ + if ((cp = getenv("autoboot_delay"))) { + timeout = strtol(cp, &ep, 0); + if (cp == ep) + timeout = 10; /* Unparseable? Set default! */ + } + } + + fp = file_findfile(NULL, NULL); + if (fp == NULL) { + /* no preloaded files, run command start to load all */ + bf_run("start"); + fp = file_findfile(NULL, NULL); + if (fp == NULL) { /* still nothing? can't boot */ + command_errmsg = "no valid kernel found"; + return (CMD_ERROR); + } + } + + kernelname = fp->f_name; + + if (timeout >= 0) { + otime = time(NULL); + when = otime + timeout; /* when to boot */ + + yes = 0; + + printf("%s\n", (prompt == NULL) ? + "Hit [Enter] to boot immediately, or any other key " + "for command prompt." : prompt); + + for (;;) { + if (ischar()) { + c = getchar(); + if ((c == '\r') || (c == '\n')) + yes = 1; + break; + } + ntime = time(NULL); + if (ntime >= when) { + yes = 1; + break; + } + + if (ntime != otime) { + printf("\rBooting [%s] in %d second%s... ", + kernelname, (int)(when - ntime), + (when - ntime) == 1? "":"s"); + otime = ntime; + } + } + } else { + yes = 1; + } + + if (yes) + printf("\rBooting [%s]... ", kernelname); + putchar('\n'); + if (yes) { + argv[0] = "boot"; + argv[1] = NULL; + return (command_boot(1, argv)); + } + return (CMD_OK); +} + +/* + * Scrounge for the name of the (try)'th file we will try to boot. + */ +static char * +getbootfile(int try) +{ + static char *name = NULL; + const char *spec, *ep; + size_t len; + + /* we use dynamic storage */ + free(name); + name = NULL; + + /* + * Try $bootfile, then try our builtin default + */ + if ((spec = getenv("bootfile")) == NULL) + spec = default_bootfiles; + + while ((try > 0) && (spec != NULL)) { + spec = strchr(spec, ';'); + if (spec) + spec++; /* skip over the leading ';' */ + try--; + } + if (spec != NULL) { + if ((ep = strchr(spec, ';')) != NULL) { + len = ep - spec; + } else { + len = strlen(spec); + } + name = malloc(len + 1); + strncpy(name, spec, len); + name[len] = 0; + } + if (name && name[0] == 0) { + free(name); + name = NULL; + } + return (name); +} + +/* + * Try to find the /etc/fstab file on the filesystem (rootdev), + * which should be be the root filesystem, and parse it to find + * out what the kernel ought to think the root filesystem is. + * + * If we're successful, set vfs.root.mountfrom to : + * so that the kernel can tell both which VFS and which node to use + * to mount the device. If this variable's already set, don't + * overwrite it. + */ +int +getrootmount(char *rootdev) +{ + char lbuf[128], *cp, *ep, *dev, *fstyp, *options; + int fd, error; + + if (getenv("vfs.root.mountfrom") != NULL) + return (0); + + error = 1; + sprintf(lbuf, "%s/etc/fstab", rootdev); + if ((fd = open(lbuf, O_RDONLY)) < 0) + goto notfound; + + /* + * loop reading lines from /etc/fstab + * What was that about sscanf again? + */ + fstyp = NULL; + dev = NULL; + while (fgetstr(lbuf, sizeof (lbuf), fd) >= 0) { + if ((lbuf[0] == 0) || (lbuf[0] == '#')) + continue; + + /* skip device name */ + for (cp = lbuf; (*cp != 0) && !isspace(*cp); cp++) + ; + if (*cp == 0) /* misformatted */ + continue; + /* delimit and save */ + *cp++ = 0; + free(dev); + dev = strdup(lbuf); + + /* skip whitespace up to mountpoint */ + while ((*cp != 0) && isspace(*cp)) + cp++; + /* must have / to be root */ + if ((*cp == 0) || (*cp != '/') || !isspace(*(cp + 1))) + continue; + /* skip whitespace up to fstype */ + cp += 2; + while ((*cp != 0) && isspace(*cp)) + cp++; + if (*cp == 0) /* misformatted */ + continue; + /* skip text to end of fstype and delimit */ + ep = cp; + while ((*cp != 0) && !isspace(*cp)) + cp++; + *cp = 0; + free(fstyp); + fstyp = strdup(ep); + + /* skip whitespace up to mount options */ + cp += 1; + while ((*cp != 0) && isspace(*cp)) + cp++; + if (*cp == 0) /* misformatted */ + continue; + /* skip text to end of mount options and delimit */ + ep = cp; + while ((*cp != 0) && !isspace(*cp)) + cp++; + *cp = 0; + options = strdup(ep); + /* + * Build the : and save it in + * vfs.root.mountfrom + */ + sprintf(lbuf, "%s:%s", fstyp, dev); + setenv("vfs.root.mountfrom", lbuf, 0); + + /* + * Don't override vfs.root.mountfrom.options if it is + * already set + */ + if (getenv("vfs.root.mountfrom.options") == NULL) { + /* save mount options */ + setenv("vfs.root.mountfrom.options", options, 0); + } + free(options); + error = 0; + break; + } + close(fd); + free(dev); + free(fstyp); + +notfound: + if (error) { + const char *currdev; + + currdev = getenv("currdev"); + if (currdev != NULL && strncmp("zfs:", currdev, 4) == 0) { + cp = strdup(currdev); + cp[strlen(cp) - 1] = '\0'; + setenv("vfs.root.mountfrom", cp, 0); + error = 0; + free(cp); + } + } + + return (error); +} + +static int +loadakernel(int try, int argc, char *argv[]) +{ + char *cp; + + for (try = 0; (cp = getbootfile(try)) != NULL; try++) + if (mod_loadkld(cp, argc - 1, argv + 1) != 0) + printf("can't load '%s'\n", cp); + else + return (1); + return (0); +} diff --git a/usr/src/boot/sys/boot/common/interp_backslash.c b/usr/src/boot/sys/boot/common/interp_backslash.c dissimilarity index 72% index 3cbdd5b105..c8d59fa070 100644 --- a/usr/src/boot/sys/boot/common/interp_backslash.c +++ b/usr/src/boot/sys/boot/common/interp_backslash.c @@ -1,167 +1,171 @@ -/*- - * 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. - * - * Jordan K. Hubbard - * 29 August 1998 - * - * Routine for doing backslash elimination. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include "bootstrap.h" - -#define DIGIT(x) (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A') - -/* - * backslash: Return malloc'd copy of str with all standard "backslash - * processing" done on it. Original can be free'd if desired. - */ -char * -backslash(char *str) -{ - /* - * Remove backslashes from the strings. Turn \040 etc. into a single - * character (we allow eight bit values). Currently NUL is not - * allowed. - * - * Turn "\n" and "\t" into '\n' and '\t' characters. Etc. - * - */ - char *new_str; - int seenbs = 0; - int i = 0; - - if ((new_str = strdup(str)) == NULL) - return NULL; - - while (*str) { - if (seenbs) { - seenbs = 0; - switch (*str) { - case '\\': - new_str[i++] = '\\'; - str++; - break; - - /* preserve backslashed quotes, dollar signs */ - case '\'': - case '"': - case '$': - new_str[i++] = '\\'; - new_str[i++] = *str++; - break; - - case 'b': - new_str[i++] = '\b'; - str++; - break; - - case 'f': - new_str[i++] = '\f'; - str++; - break; - - case 'r': - new_str[i++] = '\r'; - str++; - break; - - case 'n': - new_str[i++] = '\n'; - str++; - break; - - case 's': - new_str[i++] = ' '; - str++; - break; - - case 't': - new_str[i++] = '\t'; - str++; - break; - - case 'v': - new_str[i++] = '\13'; - str++; - break; - - case 'z': - str++; - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - char val; - - /* Three digit octal constant? */ - if (*str >= '0' && *str <= '3' && - *(str + 1) >= '0' && *(str + 1) <= '7' && - *(str + 2) >= '0' && *(str + 2) <= '7') { - - val = (DIGIT(*str) << 6) + (DIGIT(*(str + 1)) << 3) + - DIGIT(*(str + 2)); - - /* Allow null value if user really wants to shoot - at feet, but beware! */ - new_str[i++] = val; - str += 3; - break; - } - - /* One or two digit hex constant? - * If two are there they will both be taken. - * Use \z to split them up if this is not wanted. - */ - if (*str == '0' && - (*(str + 1) == 'x' || *(str + 1) == 'X') && - isxdigit(*(str + 2))) { - val = DIGIT(*(str + 2)); - if (isxdigit(*(str + 3))) { - val = (val << 4) + DIGIT(*(str + 3)); - str += 4; - } - else - str += 3; - /* Yep, allow null value here too */ - new_str[i++] = val; - break; - } - } - break; - - default: - new_str[i++] = *str++; - break; - } - } - else { - if (*str == '\\') { - seenbs = 1; - str++; - } - else - new_str[i++] = *str++; - } - } - - if (seenbs) { - /* - * The final character was a '\'. Put it in as a single backslash. - */ - new_str[i++] = '\\'; - } - new_str[i] = '\0'; - return new_str; -} +/* + * 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. + * + * Jordan K. Hubbard + * 29 August 1998 + * + * Routine for doing backslash elimination. + */ + +#include + +#include +#include +#include "bootstrap.h" + +#define DIGIT(x) \ + (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A') + +/* + * backslash: Return malloc'd copy of str with all standard "backslash + * processing" done on it. Original can be free'd if desired. + */ +char * +backslash(char *str) +{ + /* + * Remove backslashes from the strings. Turn \040 etc. into a single + * character (we allow eight bit values). Currently NUL is not + * allowed. + * + * Turn "\n" and "\t" into '\n' and '\t' characters. Etc. + * + */ + char *new_str; + int seenbs = 0; + int i = 0; + + if ((new_str = strdup(str)) == NULL) + return (NULL); + + while (*str) { + if (seenbs) { + seenbs = 0; + switch (*str) { + case '\\': + new_str[i++] = '\\'; + str++; + break; + + /* preserve backslashed quotes, dollar signs */ + case '\'': + case '"': + case '$': + new_str[i++] = '\\'; + new_str[i++] = *str++; + break; + + case 'b': + new_str[i++] = '\b'; + str++; + break; + + case 'f': + new_str[i++] = '\f'; + str++; + break; + + case 'r': + new_str[i++] = '\r'; + str++; + break; + + case 'n': + new_str[i++] = '\n'; + str++; + break; + + case 's': + new_str[i++] = ' '; + str++; + break; + + case 't': + new_str[i++] = '\t'; + str++; + break; + + case 'v': + new_str[i++] = '\13'; + str++; + break; + + case 'z': + str++; + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + char val; + + /* Three digit octal constant? */ + if (*str >= '0' && *str <= '3' && + *(str + 1) >= '0' && *(str + 1) <= '7' && + *(str + 2) >= '0' && *(str + 2) <= '7') { + + val = (DIGIT(*str) << 6) + + (DIGIT(*(str + 1)) << 3) + + DIGIT(*(str + 2)); + + /* + * Allow null value if user really + * wants to shoot at feet, but beware! + */ + new_str[i++] = val; + str += 3; + break; + } + + /* + * One or two digit hex constant? + * If two are there they will both be taken. + * Use \z to split them up if this is not + * wanted. + */ + if (*str == '0' && + (*(str + 1) == 'x' || *(str + 1) == 'X') && + isxdigit(*(str + 2))) { + val = DIGIT(*(str + 2)); + if (isxdigit(*(str + 3))) { + val = (val << 4) + + DIGIT(*(str + 3)); + str += 4; + } else + str += 3; + /* Yep, allow null value here too */ + new_str[i++] = val; + break; + } + } + break; + + default: + new_str[i++] = *str++; + break; + } + } else { + if (*str == '\\') { + seenbs = 1; + str++; + } else + new_str[i++] = *str++; + } + } + + if (seenbs) { + /* + * The final character was a '\'. + * Put it in as a single backslash. + */ + new_str[i++] = '\\'; + } + new_str[i] = '\0'; + return (new_str); +} diff --git a/usr/src/boot/sys/boot/common/interp_parse.c b/usr/src/boot/sys/boot/common/interp_parse.c index 64ddadea21..11cf11c057 100644 --- a/usr/src/boot/sys/boot/common/interp_parse.c +++ b/usr/src/boot/sys/boot/common/interp_parse.c @@ -1,4 +1,4 @@ -/*- +/* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -7,7 +7,7 @@ * 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. - * + * * Jordan K. Hubbard * 29 August 1998 * @@ -15,7 +15,6 @@ */ #include -__FBSDID("$FreeBSD$"); #include #include @@ -25,8 +24,8 @@ static void clean(void); static int insert(int *argcp, char *buf); static char *variable_lookup(char *name); -#define PARSE_BUFSIZE 1024 /* maximum size of one element */ -#define MAXARGS 20 /* maximum number of elements */ +#define PARSE_BUFSIZE 1024 /* maximum size of one element */ +#define MAXARGS 20 /* maximum number of elements */ static char *args[MAXARGS]; /* @@ -49,176 +48,175 @@ static char *args[MAXARGS]; * me. - jkh */ -#define PARSE_FAIL(expr) \ -if (expr) { \ - printf("fail at line %d\n", __LINE__); \ - clean(); \ - free(copy); \ - free(buf); \ - return 1; \ -} +#define PARSE_FAIL(expr) \ + if (expr) { \ + printf("fail at line %d\n", __LINE__); \ + clean(); \ + free(copy); \ + free(buf); \ + return (1); \ + } /* Accept the usual delimiters for a variable, returning counterpart */ static char isdelim(int ch) { - if (ch == '{') - return '}'; - else if (ch == '(') - return ')'; - return '\0'; + if (ch == '{') + return ('}'); + else if (ch == '(') + return (')'); + return ('\0'); } static int isquote(int ch) { - return (ch == '\''); + return (ch == '\''); } static int isdquote(int ch) { - return (ch == '"'); + return (ch == '"'); } int parse(int *argc, char ***argv, char *str) { - int ac; - char *val, *p, *q, *copy = NULL; - size_t i = 0; - char token, tmp, quote, dquote, *buf; - enum { STR, VAR, WHITE } state; - - ac = *argc = 0; - dquote = quote = 0; - if (!str || (p = copy = backslash(str)) == NULL) - return 1; - - /* Initialize vector and state */ - clean(); - state = STR; - buf = (char *)malloc(PARSE_BUFSIZE); - token = 0; - - /* And awaaaaaaaaay we go! */ - while (*p) { - switch (state) { - case STR: - if ((*p == '\\') && p[1]) { - p++; - PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); - buf[i++] = *p++; - } else if (isquote(*p)) { - quote = quote ? 0 : *p; - if (dquote) { /* keep quote */ - PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); - buf[i++] = *p++; - } else { - ++p; + int ac; + char *val, *p, *q, *copy = NULL; + size_t i = 0; + char token, tmp, quote, dquote, *buf; + enum { STR, VAR, WHITE } state; + + ac = *argc = 0; + dquote = quote = 0; + if (!str || (p = copy = backslash(str)) == NULL) + return (1); + + /* Initialize vector and state */ + clean(); + state = STR; + buf = malloc(PARSE_BUFSIZE); + token = 0; + + /* And awaaaaaaaaay we go! */ + while (*p) { + switch (state) { + case STR: + if ((*p == '\\') && p[1]) { + p++; + PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); + buf[i++] = *p++; + } else if (isquote(*p)) { + quote = quote ? 0 : *p; + if (dquote) { /* keep quote */ + PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); + buf[i++] = *p++; + } else { + ++p; + } + } else if (isdquote(*p)) { + dquote = dquote ? 0 : *p; + if (quote) { /* keep dquote */ + PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); + buf[i++] = *p++; + } else { + ++p; + } + } else if (isspace(*p) && !quote && !dquote) { + state = WHITE; + if (i) { + buf[i] = '\0'; + PARSE_FAIL(insert(&ac, buf)); + i = 0; + } + ++p; + } else if (*p == '$' && !quote) { + token = isdelim(*(p + 1)); + if (token) + p += 2; + else + ++p; + state = VAR; + } else { + PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); + buf[i++] = *p++; + } + break; + + case WHITE: + if (isspace(*p)) + ++p; + else + state = STR; + break; + + case VAR: + if (token) { + PARSE_FAIL((q = strchr(p, token)) == NULL); + } else { + q = p; + while (*q && !isspace(*q)) + ++q; + } + tmp = *q; + *q = '\0'; + if ((val = variable_lookup(p)) != NULL) { + size_t len = strlen(val); + + strncpy(buf + i, val, PARSE_BUFSIZE - (i + 1)); + i += min(len, PARSE_BUFSIZE - 1); + } + *q = tmp; /* restore value */ + p = q + (token ? 1 : 0); + state = STR; + break; } - } else if (isdquote(*p)) { - dquote = dquote ? 0 : *p; - if (quote) { /* keep dquote */ - PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); - buf[i++] = *p++; - } else { - ++p; - } - } else if (isspace(*p) && !quote && !dquote) { - state = WHITE; - if (i) { - buf[i] = '\0'; - PARSE_FAIL(insert(&ac, buf)); - i = 0; - } - ++p; - } else if (*p == '$' && !quote) { - token = isdelim(*(p + 1)); - if (token) - p += 2; - else - ++p; - state = VAR; - } else { - PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); - buf[i++] = *p++; - } - break; - - case WHITE: - if (isspace(*p)) - ++p; - else - state = STR; - break; - - case VAR: - if (token) { - PARSE_FAIL((q = strchr(p, token)) == NULL); - } else { - q = p; - while (*q && !isspace(*q)) - ++q; - } - tmp = *q; - *q = '\0'; - if ((val = variable_lookup(p)) != NULL) { - size_t len = strlen(val); - - strncpy(buf + i, val, PARSE_BUFSIZE - (i + 1)); - i += min(len, PARSE_BUFSIZE - 1); - } - *q = tmp; /* restore value */ - p = q + (token ? 1 : 0); - state = STR; - break; } - } - /* missing terminating ' or " */ - PARSE_FAIL(quote || dquote); - /* If at end of token, add it */ - if (i && state == STR) { - buf[i] = '\0'; - PARSE_FAIL(insert(&ac, buf)); - } - args[ac] = NULL; - *argc = ac; - *argv = (char **)malloc((sizeof(char *) * ac + 1)); - bcopy(args, *argv, sizeof(char *) * ac + 1); - free(buf); - free(copy); - return 0; + /* missing terminating ' or " */ + PARSE_FAIL(quote || dquote); + /* If at end of token, add it */ + if (i && state == STR) { + buf[i] = '\0'; + PARSE_FAIL(insert(&ac, buf)); + } + args[ac] = NULL; + *argc = ac; + *argv = malloc((sizeof (char *) * ac + 1)); + bcopy(args, *argv, sizeof (char *) * ac + 1); + free(buf); + free(copy); + return (0); } -#define MAXARGS 20 +#define MAXARGS 20 /* Clean vector space */ static void clean(void) { - int i; + int i; - for (i = 0; i < MAXARGS; i++) { - if (args[i] != NULL) { - free(args[i]); - args[i] = NULL; + for (i = 0; i < MAXARGS; i++) { + free(args[i]); + args[i] = NULL; } - } } static int insert(int *argcp, char *buf) { - if (*argcp >= MAXARGS) - return 1; - args[(*argcp)++] = strdup(buf); - return 0; + if (*argcp >= MAXARGS) + return (1); + args[(*argcp)++] = strdup(buf); + return (0); } static char * variable_lookup(char *name) { - /* XXX search "special variable" space first? */ - return (char *)getenv(name); + + /* XXX search "special variable" space first? */ + return (getenv(name)); } -- 2.11.4.GIT