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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#include <errno.h>
#include <poll.h>
#include <signal.h>
#include <stddef.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
static struct termios saved;
static int active = 0;
static volatile sig_atomic_t stopped = 0;
static void on_signal(int sig)
{
(void)sig;
stopped = 1;
}
int zm_enter(void)
{
struct termios t;
if (tcgetattr(STDIN_FILENO, &saved) != 0)
return -1;
t = saved;
t.c_lflag &= ~(tcflag_t)(ISIG | ICANON | ECHO);
t.c_cc[VMIN] = 0;
t.c_cc[VTIME] = 0;
if (tcsetattr(STDIN_FILENO, TCSANOW, &t) != 0)
return -1;
active = 1;
return 0;
}
void zm_leave(void)
{
if (active) {
tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved);
active = 0;
}
}
void zm_install(int lock)
{
struct sigaction handle;
struct sigaction ignore;
memset(&handle, 0, sizeof handle);
memset(&ignore, 0, sizeof ignore);
handle.sa_handler = on_signal;
ignore.sa_handler = SIG_IGN;
sigemptyset(&handle.sa_mask);
sigemptyset(&ignore.sa_mask);
sigaction(SIGTERM, &handle, NULL);
sigaction(SIGHUP, &handle, NULL);
sigaction(SIGINT, lock ? &ignore : &handle, NULL);
}
int zm_stopped(void)
{
return stopped ? 1 : 0;
}
int zm_size(int *rows, int *cols)
{
struct winsize ws;
memset(&ws, 0, sizeof ws);
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != 0 || ws.ws_row == 0 || ws.ws_col == 0) {
memset(&ws, 0, sizeof ws);
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) != 0 || ws.ws_row == 0 || ws.ws_col == 0)
return -1;
}
*rows = (int)ws.ws_row;
*cols = (int)ws.ws_col;
return 0;
}
int zm_wait(int ms)
{
struct pollfd p;
int r;
p.fd = STDIN_FILENO;
p.events = POLLIN;
p.revents = 0;
r = poll(&p, 1, ms);
return (r > 0 && (p.revents & POLLIN)) ? 1 : 0;
}
ssize_t zm_read(unsigned char *buf, size_t n)
{
return read(STDIN_FILENO, buf, n);
}
void zm_write(int fd, const unsigned char *buf, size_t n)
{
size_t off = 0;
while (off < n) {
ssize_t r = write(fd, buf + off, n - off);
if (r < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
return;
}
off += (size_t)r;
}
}
unsigned long long zm_seed(void)
{
struct timespec ts;
unsigned long long a;
unsigned long long b;
unsigned long long p;
clock_gettime(CLOCK_REALTIME, &ts);
a = (unsigned long long)ts.tv_sec;
b = (unsigned long long)ts.tv_nsec;
p = (unsigned long long)getpid();
return (a * 1000000007ULL) ^ b ^ (p << 32);
}
|