systemSetup

system setup, configuration and dotfiles
git clone https://noulin.net/git/systemSetup.git
Log | Files | Refs | README | LICENSE

tty.c (3762B)


      1 #include <stdio.h>
      2 #include <unistd.h>
      3 #include <fcntl.h>
      4 #include <stdlib.h>
      5 #include <stdarg.h>
      6 #include <termios.h>
      7 #include <sys/ioctl.h>
      8 #include <sys/select.h>
      9 #include <signal.h>
     10 #include <errno.h>
     11 
     12 #include "tty.h"
     13 
     14 #include "config.h"
     15 
     16 void tty_reset(tty_t *tty) {
     17 	tcsetattr(tty->fdin, TCSANOW, &tty->original_termios);
     18 }
     19 
     20 void tty_close(tty_t *tty) {
     21 	tty_reset(tty);
     22 	fclose(tty->fout);
     23 	close(tty->fdin);
     24 }
     25 
     26 static void handle_sigwinch(int sig){
     27 	(void)sig;
     28 }
     29 
     30 void tty_init(tty_t *tty, const char *tty_filename) {
     31 	tty->fdin = open(tty_filename, O_RDONLY);
     32 	if (tty->fdin < 0) {
     33 		perror("Failed to open tty");
     34 		exit(EXIT_FAILURE);
     35 	}
     36 
     37 	tty->fout = fopen(tty_filename, "w");
     38 	if (!tty->fout) {
     39 		perror("Failed to open tty");
     40 		exit(EXIT_FAILURE);
     41 	}
     42 
     43 	if (setvbuf(tty->fout, NULL, _IOFBF, 4096)) {
     44 		perror("setvbuf");
     45 		exit(EXIT_FAILURE);
     46 	}
     47 
     48 	if (tcgetattr(tty->fdin, &tty->original_termios)) {
     49 		perror("tcgetattr");
     50 		exit(EXIT_FAILURE);
     51 	}
     52 
     53 	struct termios new_termios = tty->original_termios;
     54 
     55 	/*
     56 	 * Disable all of
     57 	 * ICANON  Canonical input (erase and kill processing).
     58 	 * ECHO    Echo.
     59 	 * ISIG    Signals from control characters
     60 	 * ICRNL   Conversion of CR characters into NL
     61 	 */
     62 	new_termios.c_iflag &= ~(ICRNL);
     63 	new_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
     64 
     65 	if (tcsetattr(tty->fdin, TCSANOW, &new_termios))
     66 		perror("tcsetattr");
     67 
     68 	tty_getwinsz(tty);
     69 
     70 	tty_setnormal(tty);
     71 
     72 	signal(SIGWINCH, handle_sigwinch);
     73 }
     74 
     75 void tty_getwinsz(tty_t *tty) {
     76 	struct winsize ws;
     77 	if (ioctl(fileno(tty->fout), TIOCGWINSZ, &ws) == -1) {
     78 		tty->maxwidth = 80;
     79 		tty->maxheight = 25;
     80 	} else {
     81 		tty->maxwidth = ws.ws_col;
     82 		tty->maxheight = ws.ws_row;
     83 	}
     84 }
     85 
     86 char tty_getchar(tty_t *tty) {
     87 	char ch;
     88 	int size = read(tty->fdin, &ch, 1);
     89 	if (size < 0) {
     90 		perror("error reading from tty");
     91 		exit(EXIT_FAILURE);
     92 	} else if (size == 0) {
     93 		/* EOF */
     94 		exit(EXIT_FAILURE);
     95 	} else {
     96 		return ch;
     97 	}
     98 }
     99 
    100 int tty_input_ready(tty_t *tty, long int timeout, int return_on_signal) {
    101 	fd_set readfs;
    102 	FD_ZERO(&readfs);
    103 	FD_SET(tty->fdin, &readfs);
    104 
    105 	struct timespec ts = {timeout / 1000, (timeout % 1000) * 1000000};
    106 
    107 	sigset_t mask;
    108 	sigemptyset(&mask);
    109 	if (!return_on_signal)
    110 		sigaddset(&mask, SIGWINCH);
    111 
    112 	int err = pselect(
    113 			tty->fdin + 1,
    114 			&readfs,
    115 			NULL,
    116 			NULL,
    117 			timeout < 0 ? NULL : &ts,
    118 			return_on_signal ? NULL : &mask);
    119 
    120 	if (err < 0) {
    121 		if (errno == EINTR) {
    122 			return 0;
    123 		} else {
    124 			perror("select");
    125 			exit(EXIT_FAILURE);
    126 		}
    127 	} else {
    128 		return FD_ISSET(tty->fdin, &readfs);
    129 	}
    130 }
    131 
    132 static void tty_sgr(tty_t *tty, int code) {
    133 	tty_printf(tty, "%c%c%im", 0x1b, '[', code);
    134 }
    135 
    136 void tty_setfg(tty_t *tty, int fg) {
    137 	if (tty->fgcolor != fg) {
    138 		tty_sgr(tty, 30 + fg);
    139 		tty->fgcolor = fg;
    140 	}
    141 }
    142 
    143 void tty_setinvert(tty_t *tty) {
    144 	tty_sgr(tty, 7);
    145 }
    146 
    147 void tty_setunderline(tty_t *tty) {
    148 	tty_sgr(tty, 4);
    149 }
    150 
    151 void tty_setnormal(tty_t *tty) {
    152 	tty_sgr(tty, 0);
    153 	tty->fgcolor = 9;
    154 }
    155 
    156 void tty_setnowrap(tty_t *tty) {
    157 	tty_printf(tty, "%c%c?7l", 0x1b, '[');
    158 }
    159 
    160 void tty_setwrap(tty_t *tty) {
    161 	tty_printf(tty, "%c%c?7h", 0x1b, '[');
    162 }
    163 
    164 void tty_newline(tty_t *tty) {
    165 	tty_printf(tty, "%c%cK\n", 0x1b, '[');
    166 }
    167 
    168 void tty_clearline(tty_t *tty) {
    169 	tty_printf(tty, "%c%cK", 0x1b, '[');
    170 }
    171 
    172 void tty_setcol(tty_t *tty, int col) {
    173 	tty_printf(tty, "%c%c%iG", 0x1b, '[', col + 1);
    174 }
    175 
    176 void tty_moveup(tty_t *tty, int i) {
    177 	tty_printf(tty, "%c%c%iA", 0x1b, '[', i);
    178 }
    179 
    180 void tty_printf(tty_t *tty, const char *fmt, ...) {
    181 	va_list args;
    182 	va_start(args, fmt);
    183 	vfprintf(tty->fout, fmt, args);
    184 	va_end(args);
    185 }
    186 
    187 void tty_putc(tty_t *tty, char c) {
    188 	fputc(c, tty->fout);
    189 }
    190 
    191 void tty_flush(tty_t *tty) {
    192 	fflush(tty->fout);
    193 }
    194 
    195 size_t tty_getwidth(tty_t *tty) {
    196 	return tty->maxwidth;
    197 }
    198 
    199 size_t tty_getheight(tty_t *tty) {
    200 	return tty->maxheight;
    201 }