+ if (argc < 1) {
+ reply_with_error ("sh: expecting a command to run");
+ return NULL;
+ }
+
+ char *cmd;
+ int len, i, j;
+
+ /* guestfish splits the parameter(s) into a list of strings,
+ * and we have to reassemble them here. Not ideal. XXX
+ */
+ for (i = len = 0; i < argc; ++i)
+ len += strlen (argv[i]) + 1;
+ cmd = malloc (len);
+ if (!cmd) {
+ reply_with_perror ("malloc");
+ return NULL;
+ }
+ for (i = j = 0; i < argc; ++i) {
+ len = strlen (argv[i]);
+ memcpy (&cmd[j], argv[i], len);
+ j += len;
+ cmd[j] = ' ';
+ j++;
+ }
+ cmd[j-1] = '\0';
+
+ /* Set up some environment variables. */
+ setenv ("root", sysroot, 1);
+ if (access ("/sys/block/sda", F_OK) == 0)
+ setenv ("sd", "sd", 1);
+ else if (access ("/sys/block/hda", F_OK) == 0)
+ setenv ("sd", "hd", 1);
+ else if (access ("/sys/block/vda", F_OK) == 0)
+ setenv ("sd", "vd", 1);
+
+ char *err;
+ int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
+ "/bin/sh", "-c", cmd, NULL);
+ free (cmd);
+
+ if (r == -1) {
+ reply_with_error ("%s", err);
+ free (err);
+ return NULL;
+ }
+
+ return err;
+}
+
+/* Print the environment that commands get (by running external printenv). */
+static char *
+debug_env (const char *subcmd, int argc, char *const *const argv)
+{