/* * Copyright (c) 2023 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF7 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * getty.c * Initialize a terminal session. */ #include #include #include #include #include #include #include #include #include #include #include int main(int argc, char* argv[]) { bool logo = true; struct winsize ws; ws.ws_row = 24; ws.ws_col = 80; int opt; while ( (opt = getopt(argc, argv, "h:lw:")) != -1 ) { switch ( opt ) { case 'l': logo = true; break; case 'h': ws.ws_row = atoi(optarg); break; case 'w': ws.ws_col = atoi(optarg); break; default: return 1; } } if ( argc - optind < 1 ) errx(1, "Expected terminal path"); if ( argc - optind < 2 ) errx(1, "Expected program"); const char* path = argv[optind + 0]; int tty = open(path, O_RDWR); if ( tty < 0 ) err(1, "%s", path); if ( !isatty(tty) ) err(1, "%s", path); struct termios tio; if ( tcgetattr(tty, &tio) < 0 ) err(1, "tcgetattr: %s", path); pid_t child_pid = fork(); if ( child_pid < 0 ) err(1, "fork"); if ( child_pid ) { int status; waitpid(child_pid, &status, 0); return WEXITSTATUS(status); } if ( setsid() < 0 ) err(1, "setsid"); if ( ioctl(tty, TIOCSCTTY) < 0 ) err(1, "ioctl: TIOCSCTTY"); if ( close(0) < 0 || close(1) < 0 || close(2) < 0 ) err(1, "close"); if ( dup2(tty, 0) != 0 || dup2(tty, 1) != 1 || dup2(tty, 2) != 2 ) err(1, "dup"); if ( closefrom(3) < 0 ) err(1, "closefrom"); tty = 0; if ( ioctl(tty, TIOCSWINSZ, &ws) < 0 ) err(1, "TIOCSWINSZ"); tio.c_cflag |= CREAD; if ( tcsetattr(tty, TCSANOW, &tio) < 0 ) err(1, "tcsetattr: %s", path); if ( logo ) { printf("\e[37;41m\e[J"); const char* string = BRAND_LOGO; while ( *string ) { size_t string_width = strcspn(string, "\n"); size_t leading = string_width <= ws.ws_col ? (ws.ws_col - string_width) / 2 : 0; for ( size_t i = 0; i < leading; i++ ) putchar(' '); fwrite(string, string_width, 1, stdout); string += string_width; if ( *string == '\n' ) { string++; if ( !*string ) printf("\e[m"); putchar('\n'); } } } execvp(argv[optind + 1], argv + optind + 1); err(1, "%s", argv[optind + 1]); }