diff --git a/sbin/reboot/reboot.8 b/sbin/reboot/reboot.8 --- a/sbin/reboot/reboot.8 +++ b/sbin/reboot/reboot.8 @@ -37,15 +37,19 @@ .Sh SYNOPSIS .Nm halt .Op Fl DflNnpq +.Op Fl e Ar variable=value .Op Fl k Ar kernel .Nm .Op Fl cDdflNnpqr +.Op Fl e Ar variable=value .Op Fl k Ar kernel .Nm fasthalt .Op Fl DflNnpq +.Op Fl e Ar variable=value .Op Fl k Ar kernel .Nm fastboot .Op Fl dDflNnpq +.Op Fl e Ar variable=value .Op Fl k Ar kernel .Sh DESCRIPTION The diff --git a/sbin/reboot/reboot.c b/sbin/reboot/reboot.c --- a/sbin/reboot/reboot.c +++ b/sbin/reboot/reboot.c @@ -88,7 +88,7 @@ } static void -write_nextboot(const char *fn, const char *kernel, bool force) +write_nextboot(const char *fn, const char *kernel, const char *env, bool force) { FILE *fp; struct statfs sfs; @@ -114,8 +114,9 @@ if (fp == NULL) E("Can't create %s to boot %s", fn, kernel); - if (fprintf(fp,"%skernel=\"%s\"\n", + if (fprintf(fp,"%s%skernel=\"%s\"\n", supported ? "nextboot_enable=\"YES\"\n" : "", + env ? env : "", kernel) < 0) { int e; @@ -129,6 +130,49 @@ fclose(fp); } +static char * +quoted(char *str) +{ + char *src, *dst, *rv; + int len = 0, slen; + + src = str; + slen = strlen(str); + if (slen == 0) + return (NULL); + while ((src = strchr(src, '"')) != NULL) { + len++; + src++; + } + if (len == 2 && str[0] == '"' && str[slen - 1] == '"') + /* quoted string, no extra quotes, just strdup */ + return (strdup(str)); + dst = rv = malloc(len + slen + 1); + if (rv == NULL) + errx(1, "Can't allocate memory for string"); + *dst++ = '"'; + for (src = str; *src; src++) { + if (*src == '"') + *dst++ = '\\'; + *dst++ = *src++; + } + *dst++ = '"'; + *dst++ = '\0'; + return (rv); +} + + +static char * +build_kv(char *raw) +{ + char *eq; + + eq = strchr(raw, '='); + if (eq == NULL) + return (NULL); + *eq++ = '\0'; + return (quoted(eq)); +} int main(int argc, char *argv[]) @@ -139,6 +183,8 @@ bool Dflag, fflag, lflag, Nflag, nflag, qflag; uint64_t pageins; const char *user, *kernel = NULL; + char *env = NULL, *oldenv, *v; + if (strstr(getprogname(), "halt") != NULL) { dohalt = true; @@ -146,7 +192,7 @@ } else howto = 0; Dflag = fflag = lflag = Nflag = nflag = qflag = false; - while ((ch = getopt(argc, argv, "cDdk:lNnpqr")) != -1) + while ((ch = getopt(argc, argv, "cDdek:lNnpqr")) != -1) switch(ch) { case 'c': howto |= RB_POWERCYCLE; @@ -157,6 +203,17 @@ case 'd': howto |= RB_DUMP; break; + case 'e': + oldenv = env; + v = build_kv(optarg); + if (v == NULL) + errx(1, "Malformed env arg: '%s'", optarg); + asprintf(&env, "%s%s=%s\n", oldenv ? oldenv : "", optarg, v); + if (env == NULL) + errx(1, "No memory to build env array"); + free(v); + free(oldenv); + break; case 'f': fflag = true; break; @@ -234,7 +291,7 @@ errx(1, "%s is not a file", k); free(k); } - write_nextboot(PATH_NEXTBOOT, kernel, fflag); + write_nextboot(PATH_NEXTBOOT, env, kernel, fflag); } /* Log the reboot. */