File: asktty.c

package info (click to toggle)
debfoster 2.7-2.1
  • links: PTS
  • area: main
  • in suites: bullseye, buster, sid, stretch
  • size: 1,188 kB
  • sloc: sh: 4,243; ansic: 2,397; perl: 39; makefile: 26; sed: 16
file content (92 lines) | stat: -rw-r--r-- 1,600 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>

#include "config.h"
#include "intl.h"
#include "asktty.h"

#define READBUF 4096

static struct termios *tty = NULL;
static void (*old_sighandler)(int) = NULL;

void tty_restore(void) {
	if(tty)
		tcsetattr(STDIN_FILENO, TCSANOW, tty);
}

static void sighandler(int sig) {
	tty_restore();
	printf(_("Interrupted\n"));
	if(old_sighandler)
		old_sighandler(sig);
	exit(128+sig);
}

void tty_init(void) {
	static struct termios t;
	void (*old_sig)(int);

	if(!tcgetattr(STDIN_FILENO, &t)) {
		tty = &t;
		old_sig = signal(SIGINT, sighandler);
		if(old_sig != SIG_ERR)
			old_sighandler = old_sig;
	}
}

int tty_ask(char *choices, char *fmt, ...) {
	va_list ap;
	struct termios tmp;
	int r;
	unsigned char c[READBUF];
        char *choice;

	for(;;) {
		va_start(ap, fmt);
		vfprintf(stdout, fmt, ap);
		va_end(ap);
		fflush(stdout);

		if(tty) {
			tmp = *tty;
			tmp.c_lflag &= ~ICANON;
			tmp.c_iflag &= ~ICRNL;
			tmp.c_lflag &= ~ECHO;
			tmp.c_cc[VTIME] = 0;
			tmp.c_cc[VMIN] = 1;
			tcsetattr(STDIN_FILENO, TCSANOW, &tmp);
		}

		r = read(STDIN_FILENO, c, READBUF);

		tty_restore();

		if(r < 0) {
			printf(_("Interrupted\n"));
			return -1;
		}

		if(!r || strchr(" \r", *c))
			*c = choices[0];
		else
			*c = tolower(*c);

		if((choice = strchr(choices, *c))) {
			printf("%c\n", toupper(*c));
			fflush(stdout);
			return choice - choices;
		}

		printf("\a\r\033[K");
	}
	return -1;
}