1// Copyright 2016 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <fcntl.h> 6#include <lib/fdio/io.h> 7#include <lib/fdio/spawn.h> 8#include <lib/fdio/util.h> 9#include <lib/fdio/watcher.h> 10#include <limits.h> 11#include <stdbool.h> 12#include <stdio.h> 13#include <stdlib.h> 14#include <string.h> 15#include <unistd.h> 16#include <zircon/device/dmctl.h> 17#include <zircon/process.h> 18#include <zircon/processargs.h> 19#include <zircon/status.h> 20#include <zircon/syscalls.h> 21#include <zircon/types.h> 22 23int main(int argc, const char** argv) { 24 int fd; 25 int retry = 30; 26 27 while ((fd = open("/dev/misc/dmctl", O_RDWR)) < 0) { 28 if (--retry == 0) { 29 fprintf(stderr, "run-vc: could not connect to virtual console\n"); 30 return -1; 31 } 32 } 33 34 zx_handle_t h0, h1; 35 if (zx_channel_create(0, &h0, &h1) < 0) { 36 return -1; 37 } 38 if (ioctl_dmctl_open_virtcon(fd, &h1) < 0) { 39 return -1; 40 } 41 close(fd); 42 43 zx_object_wait_one(h0, ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, 44 ZX_TIME_INFINITE, NULL); 45 46 uint32_t types[FDIO_MAX_HANDLES]; 47 zx_handle_t handles[FDIO_MAX_HANDLES]; 48 uint32_t dcount, hcount; 49 if (zx_channel_read(h0, 0, types, handles, 50 sizeof(types), FDIO_MAX_HANDLES, &dcount, &hcount) < 0) { 51 return -1; 52 } 53 if (dcount / sizeof(uint32_t) != hcount) { 54 return -1; 55 } 56 zx_handle_close(h0); 57 58 // start shell if no arguments 59 if (argc == 1) { 60 argv[0] = "/boot/bin/sh"; 61 } else { 62 argv++; 63 } 64 65 const char* pname = strrchr(argv[0], '/'); 66 if (pname == NULL) { 67 pname = argv[0]; 68 } else { 69 pname++; 70 } 71 72 uint32_t flags = FDIO_SPAWN_CLONE_ALL & ~FDIO_SPAWN_CLONE_STDIO; 73 74 fdio_spawn_action_t actions[1 + FDIO_MAX_HANDLES] = { 75 {.action = FDIO_SPAWN_ACTION_SET_NAME, .name = {.data = pname}}, 76 }; 77 for (uint32_t i = 0; i < hcount; i++) { 78 actions[1 + i].action = FDIO_SPAWN_ACTION_ADD_HANDLE; 79 actions[1 + i].h.id = types[i]; 80 actions[1 + i].h.handle = handles[i]; 81 }; 82 83 char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH]; 84 zx_status_t status = fdio_spawn_etc(ZX_HANDLE_INVALID, flags, argv[0], argv, 85 NULL, 1 + hcount, actions, NULL, err_msg); 86 if (status != ZX_OK) { 87 fprintf(stderr, "error %d (%s) launching: %s\n", status, 88 zx_status_get_string(status), err_msg); 89 return -1; 90 } 91 92 return 0; 93} 94