// 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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[FDIO_MAX_HANDLES]; zx_handle_t handles[FDIO_MAX_HANDLES]; uint32_t dcount, hcount; if (zx_channel_read(h0, 0, types, handles, sizeof(types), FDIO_MAX_HANDLES, &dcount, &hcount) < 0) { return -1; } if (dcount / sizeof(uint32_t) != hcount) { 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[1 + FDIO_MAX_HANDLES] = { {.action = FDIO_SPAWN_ACTION_SET_NAME, .name = {.data = pname}}, }; for (uint32_t i = 0; i < hcount; i++) { actions[1 + i].action = FDIO_SPAWN_ACTION_ADD_HANDLE; actions[1 + i].h.id = types[i]; actions[1 + i].h.handle = handles[i]; }; char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH]; zx_status_t status = fdio_spawn_etc(ZX_HANDLE_INVALID, flags, argv[0], argv, NULL, 1 + hcount, 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; }