// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-FileCopyrightText: 2020-2021 Alyssa Ross #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "log.h" #include "num.h" #include "vsock.h" noreturn static void ex_usage(void) { if (verbosity) fprintf(stderr, "Usage: %s cid port prog...\n", program_invocation_short_name); exit(EX_USAGE); } int main(int argc, char *argv[]) { int opt, fd; uint32_t cid, port; // A skeleton of an option parser to reject any options that // are given, so we can add options in the future without // worrying about breaking backwards compatibility because // they were previously interpreted as a first argument. while ((opt = getopt(argc, argv, "+")) != -1) { switch (opt) { default: ex_usage(); } } // Check there are enough positional arguments (two for the // address and at least one to exec into). if (optind > argc - 3) ex_usage(); // Parse the `cid' argument. if (!strcmp(argv[optind], "-1")) cid = VMADDR_CID_ANY; else if (getu32(argv[optind], 0, UINT32_MAX, &cid)) ex_usage(); optind++; // Parse the `port' argument. if (!strcmp(argv[optind], "-1")) port = VMADDR_PORT_ANY; else if (getu32(argv[optind], 0, UINT32_MAX, &port)) ex_usage(); optind++; // Set up the socket. fd = socket(AF_VSOCK, SOCK_STREAM, 0); if (fd == -1) diee(EX_OSERR, "socket"); if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) diee(EX_OSERR, "fcntl"); if (vsock_bind(fd, cid, port) == -1) diee(EX_OSERR, "bind"); if (listen(fd ,40) == -1) diee(EX_OSERR, "listen"); // Place the socket at stdout. if (dup2(fd, STDIN_FILENO) == -1) diee(EX_OSERR, "dup2"); if (fd != STDIN_FILENO) close(fd); // Finally, exec into `prog'. execvp(argv[optind], &argv[optind]); diee(EX_OSERR, "execvp"); }