#include #include #include #include #include #include #include #include #include #include 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); }