summaryrefslogtreecommitdiff
path: root/usr/src/cmd/eeprom/i386/benv.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/eeprom/i386/benv.c')
-rw-r--r--usr/src/cmd/eeprom/i386/benv.c375
1 files changed, 2 insertions, 373 deletions
diff --git a/usr/src/cmd/eeprom/i386/benv.c b/usr/src/cmd/eeprom/i386/benv.c
index f032a3e064..11613cc5ce 100644
--- a/usr/src/cmd/eeprom/i386/benv.c
+++ b/usr/src/cmd/eeprom/i386/benv.c
@@ -20,11 +20,11 @@
*/
/*
+ * Copyright 2016 Toomas Soome <tsoome@me.com>
* Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include "benv.h"
-#include "message.h"
#include <ctype.h>
#include <stdarg.h>
#include <sys/mman.h>
@@ -186,280 +186,15 @@ get_var(char *name, eplist_t *list)
return (NULL);
}
-/*PRINTFLIKE1*/
-static void
-eeprom_error(const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- (void) fprintf(stderr, "eeprom: ");
- (void) vfprintf(stderr, format, ap);
- va_end(ap);
-}
-
-static int
-exec_cmd(char *cmdline, char *output, int64_t osize)
-{
- char buf[BUFSIZ];
- int ret;
- size_t len;
- FILE *ptr;
- sigset_t set;
- void (*disp)(int);
-
- if (output)
- output[0] = '\0';
-
- /*
- * For security
- * - only absolute paths are allowed
- * - set IFS to space and tab
- */
- if (*cmdline != '/') {
- eeprom_error(ABS_PATH_REQ, cmdline);
- return (-1);
- }
- (void) putenv("IFS= \t");
-
- /*
- * We may have been exec'ed with SIGCHLD blocked
- * unblock it here
- */
- (void) sigemptyset(&set);
- (void) sigaddset(&set, SIGCHLD);
- if (sigprocmask(SIG_UNBLOCK, &set, NULL) != 0) {
- eeprom_error(FAILED_SIG, strerror(errno));
- return (-1);
- }
-
- /*
- * Set SIGCHLD disposition to SIG_DFL for popen/pclose
- */
- disp = sigset(SIGCHLD, SIG_DFL);
- if (disp == SIG_ERR) {
- eeprom_error(FAILED_SIG, strerror(errno));
- return (-1);
- }
- if (disp == SIG_HOLD) {
- eeprom_error(BLOCKED_SIG, cmdline);
- return (-1);
- }
-
- ptr = popen(cmdline, "r");
- if (ptr == NULL) {
- eeprom_error(POPEN_FAIL, cmdline, strerror(errno));
- return (-1);
- }
-
- /*
- * If we simply do a pclose() following a popen(), pclose()
- * will close the reader end of the pipe immediately even
- * if the child process has not started/exited. pclose()
- * does wait for cmd to terminate before returning though.
- * When the executed command writes its output to the pipe
- * there is no reader process and the command dies with
- * SIGPIPE. To avoid this we read repeatedly until read
- * terminates with EOF. This indicates that the command
- * (writer) has closed the pipe and we can safely do a
- * pclose().
- *
- * Since pclose() does wait for the command to exit,
- * we can safely reap the exit status of the command
- * from the value returned by pclose()
- */
- while (fgets(buf, sizeof (buf), ptr) != NULL) {
- if (output && osize > 0) {
- (void) snprintf(output, osize, "%s", buf);
- len = strlen(buf);
- output += len;
- osize -= len;
- }
- }
-
- /*
- * If there's a "\n" at the end, we want to chop it off
- */
- if (output) {
- len = strlen(output) - 1;
- if (output[len] == '\n')
- output[len] = '\0';
- }
-
- ret = pclose(ptr);
- if (ret == -1) {
- eeprom_error(PCLOSE_FAIL, cmdline, strerror(errno));
- return (-1);
- }
-
- if (WIFEXITED(ret)) {
- return (WEXITSTATUS(ret));
- } else {
- eeprom_error(EXEC_FAIL, cmdline, ret);
- return (-1);
- }
-}
-
-#define BOOTADM_STR "bootadm: "
-
-/*
- * bootadm starts all error messages with "bootadm: ".
- * Add a note so users don't get confused on how they ran bootadm.
- */
-static void
-output_error_msg(const char *msg)
-{
- size_t len = sizeof (BOOTADM_STR) - 1;
-
- if (strncmp(msg, BOOTADM_STR, len) == 0) {
- eeprom_error("error returned from %s\n", msg);
- } else if (msg[0] != '\0') {
- eeprom_error("%s\n", msg);
- }
-}
-
-static char *
-get_bootadm_value(char *name, const int quiet)
-{
- char *ptr, *ret_str, *end_ptr, *orig_ptr;
- char output[BUFSIZ];
- int is_console, is_kernel = 0;
- size_t len;
-
- is_console = (strcmp(name, "console") == 0);
-
- if (strcmp(name, "boot-file") == 0) {
- is_kernel = 1;
- ptr = "/sbin/bootadm set-menu kernel 2>&1";
- } else if (is_console || (strcmp(name, "boot-args") == 0)) {
- ptr = "/sbin/bootadm set-menu args 2>&1";
- } else {
- eeprom_error("Unknown value in get_bootadm_value: %s\n", name);
- return (NULL);
- }
-
- if (exec_cmd(ptr, output, BUFSIZ) != 0) {
- if (quiet == 0) {
- output_error_msg(output);
- }
- return (NULL);
- }
-
- if (is_console) {
- if ((ptr = strstr(output, "console=")) == NULL) {
- return (NULL);
- }
- ptr += strlen("console=");
-
- /*
- * -B may have comma-separated values. It may also be
- * followed by other flags.
- */
- len = strcspn(ptr, " \t,");
- ret_str = calloc(len + 1, 1);
- if (ret_str == NULL) {
- eeprom_error(NO_MEM, len + 1);
- return (NULL);
- }
- (void) strncpy(ret_str, ptr, len);
- return (ret_str);
- } else if (is_kernel) {
- ret_str = strdup(output);
- if (ret_str == NULL)
- eeprom_error(NO_MEM, strlen(output) + 1);
- return (ret_str);
- } else {
- /* If there's no console setting, we can return */
- if ((orig_ptr = strstr(output, "console=")) == NULL) {
- return (strdup(output));
- }
- len = strcspn(orig_ptr, " \t,");
- ptr = orig_ptr;
- end_ptr = orig_ptr + len + 1;
-
- /* Eat up any white space */
- while ((*end_ptr == ' ') || (*end_ptr == '\t'))
- end_ptr++;
-
- /*
- * If there's data following the console string, copy it.
- * If not, cut off the new string.
- */
- if (*end_ptr == '\0')
- *ptr = '\0';
-
- while (*end_ptr != '\0') {
- *ptr = *end_ptr;
- ptr++;
- end_ptr++;
- }
- *ptr = '\0';
- if ((strchr(output, '=') == NULL) &&
- (strncmp(output, "-B ", 3) == 0)) {
- /*
- * Since we removed the console setting, we no
- * longer need the initial "-B "
- */
- orig_ptr = output + 3;
- } else {
- orig_ptr = output;
- }
-
- ret_str = strdup(orig_ptr);
- if (ret_str == NULL)
- eeprom_error(NO_MEM, strlen(orig_ptr) + 1);
- return (ret_str);
- }
-}
-
-/*
- * If quiet is 1, print nothing if there is no value. If quiet is 0, print
- * a message. Return 1 if the value is printed, 0 otherwise.
- */
-static int
-print_bootadm_value(char *name, const int quiet)
-{
- int rv = 0;
- char *value = get_bootadm_value(name, quiet);
-
- if ((value != NULL) && (value[0] != '\0')) {
- (void) printf("%s=%s\n", name, value);
- rv = 1;
- } else if (quiet == 0) {
- (void) printf("%s: data not available.\n", name);
- }
-
- if (value != NULL)
- free(value);
- return (rv);
-}
-
static void
print_var(char *name, eplist_t *list)
{
benv_ent_t *p;
char *bootcmd;
- /*
- * The console property is kept in both menu.lst and bootenv.rc. The
- * menu.lst value takes precedence.
- */
- if (strcmp(name, "console") == 0) {
- if (print_bootadm_value(name, 1) == 0) {
- if ((p = get_var(name, list)) != NULL) {
- (void) printf("%s=%s\n", name, p->val ?
- p->val : "");
- } else {
- (void) printf("%s: data not available.\n",
- name);
- }
- }
- } else if (strcmp(name, "bootcmd") == 0) {
+ if (strcmp(name, "bootcmd") == 0) {
bootcmd = getbootcmd();
(void) printf("%s=%s\n", name, bootcmd ? bootcmd : "");
- } else if ((strcmp(name, "boot-file") == 0) ||
- (strcmp(name, "boot-args") == 0)) {
- (void) print_bootadm_value(name, 0);
} else if ((p = get_var(name, list)) == NULL) {
(void) printf("%s: data not available.\n", name);
} else {
@@ -472,30 +207,13 @@ print_vars(eplist_t *list)
{
eplist_t *e;
benv_ent_t *p;
- int console_printed = 0;
-
- /*
- * The console property is kept both in menu.lst and bootenv.rc.
- * The menu.lst value takes precedence, so try printing that one
- * first.
- */
- console_printed = print_bootadm_value("console", 1);
for (e = list->next; e != list; e = e->next) {
p = (benv_ent_t *)e->item;
if (p->name != NULL) {
- if (((strcmp(p->name, "console") == 0) &&
- (console_printed == 1)) ||
- ((strcmp(p->name, "boot-file") == 0) ||
- (strcmp(p->name, "boot-args") == 0))) {
- /* handle these separately */
- continue;
- }
(void) printf("%s=%s\n", p->name, p->val ? p->val : "");
}
}
- (void) print_bootadm_value("boot-file", 1);
- (void) print_bootadm_value("boot-args", 1);
}
/*
@@ -522,77 +240,6 @@ put_quoted(FILE *fp, char *val)
(void) putc('\'', fp);
}
-static void
-set_bootadm_var(char *name, char *value)
-{
- char buf[BUFSIZ];
- char output[BUFSIZ] = "";
- char *console, *args;
- int is_console;
-
- if (verbose) {
- (void) printf("old:");
- (void) print_bootadm_value(name, 0);
- }
-
- /*
- * For security, we single-quote whatever we run on the command line,
- * and we don't allow single quotes in the string.
- */
- if (strchr(value, '\'') != NULL) {
- eeprom_error("Single quotes are not allowed "
- "in the %s property.\n", name);
- return;
- }
-
- is_console = (strcmp(name, "console") == 0);
- if (strcmp(name, "boot-file") == 0) {
- (void) snprintf(buf, BUFSIZ, "/sbin/bootadm set-menu "
- "kernel='%s' 2>&1", value);
- } else if (is_console || (strcmp(name, "boot-args") == 0)) {
- if (is_console) {
- args = get_bootadm_value("boot-args", 1);
- console = value;
- } else {
- args = value;
- console = get_bootadm_value("console", 1);
- }
- if (((args == NULL) || (args[0] == '\0')) &&
- ((console == NULL) || (console[0] == '\0'))) {
- (void) snprintf(buf, BUFSIZ, "/sbin/bootadm set-menu "
- "args= 2>&1");
- } else if ((args == NULL) || (args[0] == '\0')) {
- (void) snprintf(buf, BUFSIZ, "/sbin/bootadm "
- "set-menu args='-B console=%s' 2>&1",
- console);
- } else if ((console == NULL) || (console[0] == '\0')) {
- (void) snprintf(buf, BUFSIZ, "/sbin/bootadm "
- "set-menu args='%s' 2>&1", args);
- } else if (strncmp(args, "-B ", 3) != 0) {
- (void) snprintf(buf, BUFSIZ, "/sbin/bootadm "
- "set-menu args='-B console=%s %s' 2>&1",
- console, args);
- } else {
- (void) snprintf(buf, BUFSIZ, "/sbin/bootadm "
- "set-menu args='-B console=%s,%s' 2>&1",
- console, args + 3);
- }
- } else {
- eeprom_error("Unknown value in set_bootadm_value: %s\n", name);
- return;
- }
-
- if (exec_cmd(buf, output, BUFSIZ) != 0) {
- output_error_msg(output);
- return;
- }
-
- if (verbose) {
- (void) printf("new:");
- (void) print_bootadm_value(name, 0);
- }
-}
-
/*
* Returns 1 if bootenv.rc was modified, 0 otherwise.
*/
@@ -600,28 +247,10 @@ static int
set_var(char *name, char *val, eplist_t *list)
{
benv_ent_t *p;
- int old_verbose;
if (strcmp(name, "bootcmd") == 0)
return (0);
- if ((strcmp(name, "boot-file") == 0) ||
- (strcmp(name, "boot-args") == 0)) {
- set_bootadm_var(name, val);
- return (0);
- }
-
- /*
- * The console property is kept in two places: menu.lst and bootenv.rc.
- * Update them both. We clear verbose to prevent duplicate messages.
- */
- if (strcmp(name, "console") == 0) {
- old_verbose = verbose;
- verbose = 0;
- set_bootadm_var(name, val);
- verbose = old_verbose;
- }
-
if (verbose) {
(void) printf("old:");
print_var(name, list);