1
4
5# include "luametatex.h"
6
7# if defined (_WIN32)
8# define MKDIR(a,b) mkdir(a)
9# else
10# define MKDIR(a,b) mkdir(a,b)
11# endif
12
13
21
22# ifdef _WIN32
23# define OSLIB_PLATTYPE "windows"
24# define OSLIB_PLATNAME "windows"
25# else
26# include <sys/param.h>
27# include <sys/utsname.h>
28# if defined(__linux__) || defined (__gnu_linux__)
29# define OSLIB_PLATNAME "linux"
30# elif defined(__MACH__) && defined(__APPLE__)
31# define OSLIB_PLATNAME "macosx"
32# elif defined(__FreeBSD__)
33# define OSLIB_PLATNAME "freebsd"
34# elif defined(__OpenBSD__)
35# define OSLIB_PLATNAME "openbsd"
36# elif defined(__BSD__)
37# define OSLIB_PLATNAME "bsd"
38# elif defined(__GNU__)
39# define OSLIB_PLATNAME "gnu"
40# else
41# define OSLIB_PLATNAME "generic"
42# endif
43# define OSLIB_PLATTYPE "unix"
44# endif
45
46
52
53# ifndef _WIN32
54# include <sys/time.h>
55# include <sys/times.h>
56# include <sys/wait.h>
57# endif
58
59static int oslib_sleep(lua_State *L)
60{
61 lua_Number interval = luaL_checknumber(L, 1);
62 lua_Number units = luaL_optnumber(L, 2, 1);
63# ifdef _WIN32
64 Sleep((DWORD) (1e3 * interval / units));
65# else
66 usleep((unsigned) (1e6 * interval / units));
67# endif
68 return 0;
69}
70
71# ifdef _WIN32
72
73 # define _UTSNAME_LENGTH 65
74
75
76
77 typedef struct utsname {
78 char sysname [_UTSNAME_LENGTH];
79 char nodename[_UTSNAME_LENGTH];
80 char release [_UTSNAME_LENGTH];
81 char version [_UTSNAME_LENGTH];
82 char machine [_UTSNAME_LENGTH];
83 } utsname;
84
85
86
87
108
109 static int uname(struct utsname *uts)
110 {
111 OSVERSIONINFO osver;
112 SYSTEM_INFO sysinfo;
113 DWORD sLength;
114 memset(uts, 0, sizeof(*uts));
115 osver.dwOSVersionInfoSize = sizeof(osver);
116 GetSystemInfo(&sysinfo);
117 strcpy(uts->sysname, "Windows");
118
119
120
121
122
123
124
125
126
127
128
129 strcpy(uts->version, "");
130 strcpy(uts->release, "");
131
132
133 switch (sysinfo.wProcessorArchitecture) {
134 case PROCESSOR_ARCHITECTURE_AMD64:
135 strcpy(uts->machine, "x86_64");
136 break;
137# ifdef PROCESSOR_ARCHITECTURE_ARM64
138 case PROCESSOR_ARCHITECTURE_ARM64:
139 strcpy(uts->machine, "arm64");
140 break;
141# endif
142 case PROCESSOR_ARCHITECTURE_INTEL:
143 strcpy(uts->machine, "i386");
144 break;
145 default:
146 strcpy(uts->machine, "unknown");
147 break;
148 }
149 sLength = sizeof(uts->nodename) - 1;
150 GetComputerName(uts->nodename, &sLength);
151 return 0;
152 }
153
154# endif
155
156static int oslib_uname(lua_State *L)
157{
158 struct utsname uts;
159 if (uname(&uts) >= 0) {
160 lua_createtable(L,0,5);
161 lua_pushstring(L, uts.sysname);
162 lua_setfield(L, -2, "sysname");
163 lua_pushstring(L, uts.machine);
164 lua_setfield(L, -2, "machine");
165 lua_pushstring(L, uts.release);
166 lua_setfield(L, -2, "release");
167 lua_pushstring(L, uts.version);
168 lua_setfield(L, -2, "version");
169 lua_pushstring(L, uts.nodename);
170 lua_setfield(L, -2, "nodename");
171 } else {
172 lua_pushnil(L);
173 }
174 return 1;
175}
176
177# if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
178 # define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
179# else
180 # define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
181# endif
182
183# ifdef _WIN32
184
185 # ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
186 # define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x04
187 # endif
188
189 static int oslib_gettimeofday(lua_State *L)
190 {
191 FILETIME ft;
192 __int64 tmpres = 0;
193 GetSystemTimeAsFileTime(&ft);
194 tmpres |= ft.dwHighDateTime;
195 tmpres <<= 32;
196 tmpres |= ft.dwLowDateTime;
197 tmpres /= 10;
198
199 tmpres -= DELTA_EPOCH_IN_MICROSECS;
200
201 lua_pushnumber(L, (double) tmpres / 1000000.0);
202 return 1;
203 }
204
205 static int oslib_enableansi(lua_State *L)
206 {
207 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
208 DWORD mode = 0;
209 int done = 0;
210 if (GetConsoleMode(handle, &mode)) {
211 mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
212 if (SetConsoleMode(handle, mode)) {
213 done = 1;
214 } else {
215
216 }
217 }
218 lua_pushboolean(L, done);
219 return 1;
220 }
221
222# else
223
224 static int oslib_gettimeofday(lua_State *L)
225 {
226 double v;
227 struct timeval tv;
228 gettimeofday(&tv, NULL);
229 v = (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
230
231 lua_pushnumber(L, v);
232 return 1;
233 }
234
235 static int oslib_enableansi(lua_State *L)
236 {
237 lua_pushboolean(L, 1);
238 return 1;
239 }
240
241# endif
242
243
244
245static int oslib_execute(lua_State *L)
246{
247 const char *cmd = luaL_optstring(L, 1, NULL);
248 if (cmd) {
249 lua_pushinteger(L, aux_utf8_system(cmd) || lmt_error_state.default_exit_code);
250 } else {
251 lua_pushinteger(L, 0);
252 }
253 return 1;
254}
255
256# ifdef _WIN32
257
258 static int oslib_remove (lua_State *L)
259 {
260 const char *filename = luaL_checkstring(L, 1);
261 return luaL_fileresult(L, aux_utf8_remove(filename) == 0, filename);
262 }
263
264 static int oslib_rename (lua_State *L)
265 {
266 const char *fromname = luaL_checkstring(L, 1);
267 const char *toname = luaL_checkstring(L, 2);
268 return luaL_fileresult(L, aux_utf8_rename(fromname, toname) == 0, NULL);
269 }
270
271 static int oslib_getcodepage(lua_State *L)
272 {
273 lua_pushinteger(L, (int) GetOEMCP());
274 lua_pushinteger(L, (int) GetACP());
275 return 2;
276 }
277
278
288
289 static int oslib_getenv(lua_State *L)
290 {
291 const char *key = luaL_checkstring(L, 1);
292 char *val = NULL;
293 if (key) {
294 size_t wlen = 0;
295 LPWSTR wkey = aux_utf8_to_wide(key);
296 _wgetenv_s(&wlen, NULL, 0, wkey);
297 if (wlen) {
298 LPWSTR wval = (LPWSTR) lmt_memory_malloc(wlen * sizeof(WCHAR));
299 if (! _wgetenv_s(&wlen, wval, wlen, wkey)) {
300 val = aux_utf8_from_wide(wval);
301 }
302 }
303 }
304 if (val) {
305 lua_pushstring(L, val);
306 } else {
307 lua_pushnil(L);
308 }
309 return 1;
310 }
311
312 static int oslib_setenv(lua_State *L)
313 {
314 const char *key = luaL_optstring(L, 1, NULL);
315 if (key) {
316 const char *val = luaL_optstring(L, 2, NULL);
317 LPWSTR wkey = aux_utf8_to_wide(key);
318 LPWSTR wval = aux_utf8_to_wide(val ? val : "");
319 int bad = _wputenv_s(wkey, wval);
320 lmt_memory_free(wval);
321 lmt_memory_free(wkey);
322 if (bad) {
323 return luaL_error(L, "unable to change environment");
324 }
325 }
326 lua_pushboolean(L, 1);
327 return 1;
328 }
329
330# else
331
332 static int oslib_getcodepage(lua_State *L)
333 {
334 lua_pushboolean(L,0);
335 lua_pushboolean(L,0);
336 return 2;
337 }
338
339 static int oslib_setenv(lua_State *L)
340 {
341 const char *key = luaL_optstring(L, 1, NULL);
342 if (key) {
343 const char *val = luaL_optstring(L, 2, NULL);
344 if (val) {
345 char *value = lmt_memory_malloc((unsigned) (strlen(key) + strlen(val) + 2));
346 sprintf(value, "%s=%s", key, val);
347 if (putenv(value)) {
348
349 return luaL_error(L, "unable to change environment");
350 } else {
351
352 }
353 } else {
354 (void) unsetenv(key);
355 }
356 }
357 lua_pushboolean(L, 1);
358 return 1;
359 }
360
361# endif
362
363static const luaL_Reg oslib_function_list[] = {
364 { "sleep", oslib_sleep },
365 { "uname", oslib_uname },
366 { "gettimeofday", oslib_gettimeofday },
367 { "setenv", oslib_setenv },
368 { "execute", oslib_execute },
369# ifdef _WIN32
370 { "rename", oslib_rename },
371 { "remove", oslib_remove },
372 { "getenv", oslib_getenv },
373# endif
374 { "enableansi", oslib_enableansi },
375 { "getcodepage", oslib_getcodepage },
376 { NULL, NULL },
377};
378
379
380
384
385# ifndef _WIN32
386 extern char **environ;
387# else
388 # define environ _environ
389# endif
390
391int luaextend_os(lua_State *L)
392{
393
394 lua_getglobal(L, "os");
395
396 lua_pushliteral(L, OSLIB_PLATTYPE);
397 lua_setfield(L, -2, "type");
398 lua_pushliteral(L, OSLIB_PLATNAME);
399 lua_setfield(L, -2, "name");
400
401 for (const luaL_Reg *lib = oslib_function_list; lib->name; lib++) {
402 lua_pushcfunction(L, lib->func);
403 lua_setfield(L, -2, lib->name);
404 }
405
406 if (0) {
407 char **envpointer = environ;
408 if (envpointer) {
409 lua_pushstring(L, "env");
410 lua_newtable(L);
411 while (*envpointer) {
412
413 char *envitem = lmt_memory_strdup(*envpointer);
414 char *envitem_orig = envitem;
415 char *envkey = envitem;
416 while (*envitem != '=') {
417 envitem++;
418 }
419 *envitem = 0;
420 envitem++;
421 lua_pushstring(L, envkey);
422 lua_pushstring(L, envitem);
423 lua_rawset(L, -3);
424 envpointer++;
425 lmt_memory_free(envitem_orig);
426 }
427 lua_rawset(L, -3);
428 }
429 }
430
431 lua_pop(L, 1);
432 return 1;
433}
434 |