Add getty(8).

This commit is contained in:
Jonas 'Sortie' Termansen 2023-07-05 22:53:25 +02:00
parent deff2b660e
commit 8a89ca543c
3 changed files with 116 additions and 0 deletions

1
utils/.gitignore vendored
View File

@ -21,6 +21,7 @@ expr
false
find
getaddrinfo
getty
halt
head
help

View File

@ -93,6 +93,7 @@ uname.1 \
SBINS=\
chroot \
getty \
unmount \
MANPAGES8=\

114
utils/getty.c Normal file
View File

@ -0,0 +1,114 @@
/*
* 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 <sys/ioctl.h>
#include <sys/wait.h>
#include <brand.h>
#include <err.h>
#include <fcntl.h>
#include <termios.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
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]);
}