- static const char *dir_template = "/tmp/libguestfsXXXXXX";
- int r, i, len, pmore;
- int wfd[2], rfd[2];
- int tries;
- const char *kernel_name = "vmlinuz." REPO "." host_cpu;
- const char *initrd_name = "initramfs." REPO "." host_cpu ".img";
- char *path, *pelem, *pend;
- char *kernel = NULL, *initrd = NULL;
- char unixsock[256];
- struct sockaddr_un addr;
-
- /* Configured? */
- if (!g->cmdline) {
- error (g, "you must call guestfs_add_drive before guestfs_launch");
- return -1;
- }
-
- if (g->state != CONFIG) {
- error (g, "qemu has already been launched");
- return -1;
- }
-
- /* Search g->path for the kernel and initrd. */
- pelem = path = safe_strdup (g, g->path);
- do {
- pend = strchrnul (pelem, ':');
- pmore = *pend == ':';
- *pend = '\0';
- len = pend - pelem;
-
- /* Empty element or "." means cwd. */
- if (len == 0 || (len == 1 && *pelem == '.')) {
- if (g->verbose)
- fprintf (stderr,
- "looking for kernel and initrd in current directory\n");
- if (access (kernel_name, F_OK) == 0 && access (initrd_name, F_OK) == 0) {
- kernel = safe_strdup (g, kernel_name);
- initrd = safe_strdup (g, initrd_name);
- break;
- }
- }
- /* Look at <path>/kernel etc. */
- else {
- kernel = safe_malloc (g, len + strlen (kernel_name) + 2);
- initrd = safe_malloc (g, len + strlen (initrd_name) + 2);
- sprintf (kernel, "%s/%s", pelem, kernel_name);
- sprintf (initrd, "%s/%s", pelem, initrd_name);
-
- if (g->verbose)
- fprintf (stderr, "looking for %s and %s\n", kernel, initrd);
-
- if (access (kernel, F_OK) == 0 && access (initrd, F_OK) == 0)
- break;
- free (kernel);
- free (initrd);
- kernel = initrd = NULL;
- }
-
- pelem = pend + 1;
- } while (pmore);
-
- free (path);
-
- if (kernel == NULL || initrd == NULL) {
- error (g, "cannot find %s or %s on LIBGUESTFS_PATH (current path = %s)",
- kernel_name, initrd_name, g->path);
- goto cleanup0;
- }
-
- /* Make the temporary directory containing the socket. */
- if (!g->tmpdir) {
- g->tmpdir = safe_strdup (g, dir_template);
- if (mkdtemp (g->tmpdir) == NULL) {
- perrorf (g, "%s: cannot create temporary directory", dir_template);
- goto cleanup0;
- }
- }
-
- snprintf (unixsock, sizeof unixsock, "%s/sock", g->tmpdir);
- unlink (unixsock);
-
- if (pipe (wfd) == -1 || pipe (rfd) == -1) {
- perrorf (g, "pipe");
- goto cleanup0;
- }
-
- r = fork ();
- if (r == -1) {
- perrorf (g, "fork");
- close (wfd[0]);
- close (wfd[1]);
- close (rfd[0]);
- close (rfd[1]);
- goto cleanup0;
- }
-
- if (r == 0) { /* Child (qemu). */
- char vmchannel[256];
- char append[256];
-
- /* Set up the full command line. Do this in the subprocess so we
- * don't need to worry about cleaning up.
- */
- g->cmdline[0] = (char *) QEMU;
-
- /* Construct the -net channel parameter for qemu. */
- snprintf (vmchannel, sizeof vmchannel,
- "channel,%d:unix:%s,server,nowait",
- VMCHANNEL_PORT, unixsock);
-
- /* Linux kernel command line. */
- snprintf (append, sizeof append,
- "console=ttyS0 guestfs=%s:%d", VMCHANNEL_ADDR, VMCHANNEL_PORT);
-
- add_cmdline (g, "-m");
- add_cmdline (g, "384"); /* XXX Choose best size. */
- add_cmdline (g, "-no-kqemu"); /* Avoids a warning. */
- add_cmdline (g, "-kernel");
- add_cmdline (g, (char *) kernel);
- add_cmdline (g, "-initrd");
- add_cmdline (g, (char *) initrd);
- add_cmdline (g, "-append");
- add_cmdline (g, append);
- add_cmdline (g, "-nographic");
- add_cmdline (g, "-serial");
- add_cmdline (g, "stdio");
- add_cmdline (g, "-net");
- add_cmdline (g, vmchannel);
- add_cmdline (g, "-net");
- add_cmdline (g, "user,vlan=0");
- add_cmdline (g, "-net");
- add_cmdline (g, "nic,vlan=0");
- incr_cmdline_size (g);
- g->cmdline[g->cmdline_size-1] = NULL;
-
- if (g->verbose) {
- fprintf (stderr, "%s", QEMU);
- for (i = 0; g->cmdline[i]; ++i)
- fprintf (stderr, " %s", g->cmdline[i]);
- fprintf (stderr, "\n");
- }
-
- /* Set up stdin, stdout. */
- close (0);
- close (1);
- close (wfd[1]);
- close (rfd[0]);
- dup (wfd[0]);
- dup (rfd[1]);
- close (wfd[0]);
- close (rfd[1]);
-
-#if 0
- /* Set up a new process group, so we can signal this process
- * and all subprocesses (eg. if qemu is really a shell script).
- */
- setpgid (0, 0);
-#endif
-
- execv (QEMU, g->cmdline); /* Run qemu. */
- perror (QEMU);
- _exit (1);
- }