| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <fcntl.h> |
| #include <lib/fdio/io.h> |
| #include <lib/fdio/spawn.h> |
| #include <lib/fdio/util.h> |
| #include <lib/fdio/watcher.h> |
| #include <limits.h> |
| #include <stdbool.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <zircon/device/dmctl.h> |
| #include <zircon/process.h> |
| #include <zircon/processargs.h> |
| #include <zircon/status.h> |
| #include <zircon/syscalls.h> |
| #include <zircon/types.h> |
| |
| int main(int argc, const char** argv) { |
| int fd; |
| int retry = 30; |
| |
| while ((fd = open("/dev/misc/dmctl", O_RDWR)) < 0) { |
| if (--retry == 0) { |
| fprintf(stderr, "run-vc: could not connect to virtual console\n"); |
| return -1; |
| } |
| } |
| |
| zx_handle_t h0, h1; |
| if (zx_channel_create(0, &h0, &h1) < 0) { |
| return -1; |
| } |
| if (ioctl_dmctl_open_virtcon(fd, &h1) < 0) { |
| return -1; |
| } |
| close(fd); |
| |
| zx_object_wait_one(h0, ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, |
| ZX_TIME_INFINITE, NULL); |
| |
| uint32_t types[2]; |
| zx_handle_t handles[2]; |
| uint32_t dcount, hcount; |
| if (zx_channel_read(h0, 0, types, handles, sizeof(types), 2, &dcount, &hcount) < 0) { |
| return -1; |
| } |
| if ((dcount != sizeof(types)) || (hcount != 2)) { |
| return -1; |
| } |
| zx_handle_close(h0); |
| |
| // start shell if no arguments |
| if (argc == 1) { |
| argv[0] = "/boot/bin/sh"; |
| } else { |
| argv++; |
| } |
| |
| const char* pname = strrchr(argv[0], '/'); |
| if (pname == NULL) { |
| pname = argv[0]; |
| } else { |
| pname++; |
| } |
| |
| uint32_t flags = FDIO_SPAWN_CLONE_ALL & ~FDIO_SPAWN_CLONE_STDIO; |
| |
| fdio_spawn_action_t actions[] = { |
| {.action = FDIO_SPAWN_ACTION_SET_NAME, .name = {.data = pname}}, |
| {.action = FDIO_SPAWN_ACTION_ADD_HANDLE, |
| .h = {.id = types[0], .handle = handles[0]}}, |
| {.action = FDIO_SPAWN_ACTION_ADD_HANDLE, |
| .h = {.id = types[1], .handle = handles[1]}}, |
| }; |
| |
| char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH]; |
| zx_status_t status = fdio_spawn_etc(ZX_HANDLE_INVALID, flags, argv[0], argv, |
| NULL, countof(actions), actions, NULL, err_msg); |
| if (status != ZX_OK) { |
| fprintf(stderr, "error %d (%s) launching: %s\n", status, |
| zx_status_get_string(status), err_msg); |
| return -1; |
| } |
| |
| return 0; |
| } |