-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtty.c
More file actions
136 lines (106 loc) · 2.37 KB
/
tty.c
File metadata and controls
136 lines (106 loc) · 2.37 KB
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <lauxlib.h>
#include <stdio.h>
#ifndef LUA_FILEHANDLE
#define LUA_FILEHANDLE "FILE*"
#endif
#ifdef _WIN32
#include <io.h>
#include <windows.h>
#else
#include <sys/ioctl.h>
#include <unistd.h>
#endif
static int fd_from_file(FILE *fp) {
#ifdef _WIN32
return _fileno(fp);
#else
return fileno(fp);
#endif
}
static int fd_isatty(int fd) {
#ifdef _WIN32
return _isatty(fd);
#else
return isatty(fd);
#endif
}
static int filehandle_to_fd(lua_State *L, int index) {
FILE **fp = (FILE **)luaL_checkudata(L, index, LUA_FILEHANDLE);
if (*fp == NULL) {
luaL_argerror(L, index, "closed file");
}
return fd_from_file(*fp);
}
static int get_fd(lua_State *L, int index) {
if (lua_isnoneornil(L, index)) {
return 1;
}
if (lua_type(L, index) == LUA_TNUMBER) {
return (int)luaL_checkinteger(L, index);
}
return filehandle_to_fd(L, index);
}
#ifdef _WIN32
static HANDLE get_handle_for_fd(int fd) {
if (fd == 0) {
return GetStdHandle(STD_INPUT_HANDLE);
}
if (fd == 1) {
return GetStdHandle(STD_OUTPUT_HANDLE);
}
if (fd == 2) {
return GetStdHandle(STD_ERROR_HANDLE);
}
return (HANDLE)_get_osfhandle(fd);
}
#endif
static int get_terminal_size(int fd, int *rows, int *cols) {
#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO info;
HANDLE handle = get_handle_for_fd(fd);
if (handle == INVALID_HANDLE_VALUE || handle == NULL) {
return -1;
}
if (!GetConsoleScreenBufferInfo(handle, &info)) {
return -1;
}
*rows = (int)(info.srWindow.Bottom - info.srWindow.Top + 1);
*cols = (int)(info.srWindow.Right - info.srWindow.Left + 1);
return 0;
#else
struct winsize ws;
if (ioctl(fd, TIOCGWINSZ, &ws) != 0) {
return -1;
}
if (ws.ws_row == 0 || ws.ws_col == 0) {
return -1;
}
*rows = (int)ws.ws_row;
*cols = (int)ws.ws_col;
return 0;
#endif
}
static int l_isatty(lua_State *L) {
int fd = get_fd(L, 1);
lua_pushboolean(L, fd_isatty(fd));
return 1;
}
static int l_size(lua_State *L) {
int cols;
int fd = get_fd(L, 1);
int rows;
if (get_terminal_size(fd, &rows, &cols) != 0) {
return luaL_error(L, "unable to get terminal size");
}
lua_pushinteger(L, rows);
lua_pushinteger(L, cols);
return 2;
}
int luaopen_tty(lua_State *L) {
lua_createtable(L, 0, 2);
lua_pushcfunction(L, l_isatty);
lua_setfield(L, -2, "isatty");
lua_pushcfunction(L, l_size);
lua_setfield(L, -2, "size");
return 1;
}