usage() {
cat <<EOM
-usage: rumprun STACK [ -ipd ] [ -D PORT ] [ -N NAME ] [ -M MEM ] [ -b BLKSPEC ] [ -n NETSPEC ] [ -- ] APP [ args ]
+usage: rumprun STACK [ -ipd ] [ -D PORT ] [ -N NAME ] [ -M MEM ] [ -b BLKSPEC ] [ -n NETSPEC ] [ -e VAR[=VALUE] ] [ -- ] APP [ args ]
STACK is the rumprun stack to use. Only "xen" is currently supported
APP is the rumprun application to start
args will be passed to the application command line
-n NETSPEC configures a network interface, using one of:
inet,dhcp - IPv4 with DHCP
inet,static,ADDR/MASK[,GATEWAY] - IPv4 with static IP
+ -e set guest environment VAR to VALUE
-i attaches to domain console on startup
-p creates the domain but leaves it paused
-d destroys the domain on poweroff
opt_name=
opt_debug=
sudo=''
- while getopts "n:b:pidD:N:M:" opt; do
+ while getopts "n:b:e:pidD:N:M:" opt; do
case "$opt" in
# -n: NETSPEC
n)
>>${xenstore}
bindex=$(expr $bindex + 1)
;;
+ # -e: Set guest environment variable.
+ e)
+ case "${OPTARG}" in
+ *=*)
+ key=${OPTARG%%=*}
+ value=${OPTARG#*=}
+ ;;
+ *)
+ key=${OPTARG}
+ value=
+ ;;
+ esac
+ [ -n "$key" ] || usage
+ echo environ/${key} "${value}" >>${xenstore}
+ ;;
# -p: Leave the domain paused after creation.
p)
opt_pause=1
domid=$(${sudo} xl domid ${name})
# Write provisioning information for domain to xenstore.
prefix=/local/domain/${domid}/rumprun
- cat ${xenstore} | while read line; do
- xenstore-write ${prefix}/${line}
+ cat ${xenstore} | while read key value; do
+ xenstore-write "${prefix}/${key}" "${value}"
done
rm ${xenstore}
# Attach debugger if requested.
free(blk_fstype);
}
+static int
+xs_read_environ(const char *name, char **value_out)
+{
+ char *value = NULL;
+ char buf[128];
+ char *xberr = NULL;
+ xenbus_transaction_t txn;
+ int xbretry = 0;
+
+ xberr = xenbus_transaction_start(&txn);
+ if (xberr) {
+ warnx("rumprun_config: xenbus_transaction_start() failed: %s",
+ xberr);
+ return 1;
+ }
+ snprintf(buf, sizeof buf, "rumprun/environ/%s", name);
+ xberr = xenbus_read(txn, buf, &value);
+ if (xberr) {
+ warnx("rumprun_config: environ: read %s failed: %s",
+ buf, xberr);
+ xenbus_transaction_end(txn, 0, &xbretry);
+ return 1;
+ }
+ xberr = xenbus_transaction_end(txn, 0, &xbretry);
+ if (xberr) {
+ warnx("rumprun_config: xenbus_transaction_end() failed: %s",
+ xberr);
+ free(value);
+ return 1;
+ }
+ *value_out = value;
+ return 0;
+}
+
+static void
+rumprun_config_environ(const char *name)
+{
+ char *value = NULL;
+ int rv;
+
+ rv = xs_read_environ(name, &value);
+ if (rv != 0)
+ return;
+ if (setenv(name, value, 1) != 0) {
+ warnx("rumprun_config: setenv(%s) failed: %d", errno);
+ goto out;
+ }
+
+out:
+ free(value);
+}
+
void
_rumprun_config(void)
{
char *err = NULL;
xenbus_transaction_t txn;
char **netdevices = NULL,
- **blkdevices = NULL;
+ **blkdevices = NULL,
+ **environ = NULL;
int retry = 0,
i;
xenbus_transaction_end(txn, 0, &retry);
goto out_err;
}
+ err = xenbus_ls(txn, "rumprun/environ", &environ);
+ if (err && strcmp(err, "ENOENT") != 0) {
+ warnx("rumprun_config: xenbus_ls(rumprun/environ) failed: %s",
+ err);
+ xenbus_transaction_end(txn, 0, &retry);
+ goto out_err;
+ }
err = xenbus_transaction_end(txn, 0, &retry);
if (err) {
warnx("rumprun_config: xenbus_transaction_end() failed: %s",
}
free(blkdevices);
}
+ if (environ) {
+ for(i = 0; environ[i]; i++) {
+ rumprun_config_environ(environ[i]);
+ free(environ[i]);
+ }
+ free(environ);
+ }
return;
out_err:
free(blkdevices[i]);
free(blkdevices);
}
+ if (environ) {
+ for(i = 0; environ[i]; i++)
+ free(environ[i]);
+ free(environ);
+ }
}
void
#include <stdio.h>
+#include <stdlib.h>
int main (int argc, char *argv[])
{
- printf ("Hello, world!\n");
+ char *world = getenv ("WORLD");
+ if (world)
+ printf ("Hello, %s!\n", world);
+ else
+ printf ("Hello, world!\n");
printf ("Sleeping 5s...\n");
sleep (5);
printf ("Goodbye, world!\n");