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 @@ -87,6 +91,21 @@ supported only when rebooting, and it has no effect unless a dump device has previously been specified with .Xr dumpon 8 . +.It Fl e Ar variable=value +Sets +.Va variable +to +.Va value +in the loader's and kernel's environment. +If +.Va value +is not already enclosed in double quotes, they will be added before writing to the +.Nm nextboot +configuration. +Care should be taken if +.Va value +contains any characters that are special to the shell or loader's configuration +parsing code. .It Fl k Ar kname Boot the specified kernel .Ar kname 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 *env, const char *kernel, 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,28 @@ fclose(fp); } +static char * +split_kv(char *raw) +{ + char *eq; + int len; + + eq = strchr(raw, '='); + if (eq == NULL) + errx(1, "No = in environment string %s", raw); + *eq++ = '\0'; + len = strlen(eq); + if (len == 0) + errx(1, "Invalid null value %s=", raw); + if (eq[0] == '"') { + if (len < 2 || eq[len - 1] != '"') + errx(1, "Invalid string '%s'", eq); + eq[len - 1] = '\0'; + return (eq + 1); + } + return (eq); +} + int main(int argc, char *argv[]) { @@ -138,6 +161,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; @@ -145,7 +170,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; @@ -156,6 +181,14 @@ case 'd': howto |= RB_DUMP; break; + case 'e': + oldenv = env; + v = split_kv(optarg); + asprintf(&env, "%s%s=\"%s\"\n", oldenv ? oldenv : "", optarg, v); + if (env == NULL) + errx(1, "No memory to build env array"); + free(oldenv); + break; case 'f': fflag = true; break; @@ -233,7 +266,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. */