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
46static int oslib_gettypevalues(lua_State *L)
47{
48 lua_createtable(L, 2, 0);
49 lua_set_string_by_index(L, 1, "windows");
50 lua_set_string_by_index(L, 2, "unix");
51 return 1;
52}
53
54static int oslib_getnamevalues(lua_State *L)
55{
56 lua_createtable(L, 7, 0);
57 lua_set_string_by_index(L, 1, "windows");
58 lua_set_string_by_index(L, 2, "linux");
59 lua_set_string_by_index(L, 3, "macosx");
60 lua_set_string_by_index(L, 4, "freebsd");
61 lua_set_string_by_index(L, 5, "bsd");
62 lua_set_string_by_index(L, 6, "gnu");
63 lua_set_string_by_index(L, 7, "generic");
64 return 1;
65}
66
67
73
74# ifndef _WIN32
75# include <sys/time.h>
76# include <sys/times.h>
77# include <sys/wait.h>
78# endif
79
80static int oslib_sleep(lua_State *L)
81{
82 lua_Number interval = luaL_checknumber(L, 1);
83 lua_Number units = luaL_optnumber(L, 2, 1);
84# ifdef _WIN32
85 Sleep((DWORD) (1e3 * interval / units));
86# else
87 usleep((unsigned) (1e6 * interval / units));
88# endif
89 return 0;
90}
91
92# ifdef _WIN32
93
94 # define _UTSNAME_LENGTH 65
95
96
97
98 typedef struct utsname {
99 char sysname [_UTSNAME_LENGTH];
100 char nodename[_UTSNAME_LENGTH];
101 char release [_UTSNAME_LENGTH];
102 char version [_UTSNAME_LENGTH];
103 char machine [_UTSNAME_LENGTH];
104 } utsname;
105
106
107
108
129
130 static int uname(struct utsname *uts)
131 {
132 OSVERSIONINFO osver;
133 SYSTEM_INFO sysinfo;
134 DWORD sLength;
135 memset(uts, 0, sizeof(*uts));
136 osver.dwOSVersionInfoSize = sizeof(osver);
137 GetSystemInfo(&sysinfo);
138 strcpy(uts->sysname, "Windows");
139
140
141
142
143
144
145
146
147
148
149
150 strcpy(uts->version, "");
151 strcpy(uts->release, "");
152
153
154 switch (sysinfo.wProcessorArchitecture) {
155 case PROCESSOR_ARCHITECTURE_AMD64:
156 strcpy(uts->machine, "x86_64");
157 break;
158# ifdef PROCESSOR_ARCHITECTURE_ARM64
159 case PROCESSOR_ARCHITECTURE_ARM64:
160 strcpy(uts->machine, "arm64");
161 break;
162# endif
163 case PROCESSOR_ARCHITECTURE_INTEL:
164 strcpy(uts->machine, "i386");
165 break;
166 default:
167 strcpy(uts->machine, "unknown");
168 break;
169 }
170 sLength = sizeof(uts->nodename) - 1;
171 GetComputerName(uts->nodename, &sLength);
172 return 0;
173 }
174
175# endif
176
177static int oslib_getunamefields(lua_State *L)
178{
179 lua_createtable(L, 5, 0);
180 lua_set_string_by_index(L, 1, "sysname");
181 lua_set_string_by_index(L, 2, "machine");
182 lua_set_string_by_index(L, 3, "release");
183 lua_set_string_by_index(L, 4, "version");
184 lua_set_string_by_index(L, 5, "nodename");
185 return 1;
186}
187
188static int oslib_uname(lua_State *L)
189{
190 struct utsname uts;
191 if (uname(&uts) >= 0) {
192 lua_createtable(L,0,5);
193 lua_pushstring(L, uts.sysname);
194 lua_setfield(L, -2, "sysname");
195 lua_pushstring(L, uts.machine);
196 lua_setfield(L, -2, "machine");
197 lua_pushstring(L, uts.release);
198 lua_setfield(L, -2, "release");
199 lua_pushstring(L, uts.version);
200 lua_setfield(L, -2, "version");
201 lua_pushstring(L, uts.nodename);
202 lua_setfield(L, -2, "nodename");
203 } else {
204 lua_pushnil(L);
205 }
206 return 1;
207}
208
209# if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
210 # define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
211# else
212 # define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
213# endif
214
215# ifdef _WIN32
216
217 # ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
218 # define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x04
219 # endif
220
221 static int oslib_gettimeofday(lua_State *L)
222 {
223 FILETIME ft;
224 __int64 tmpres = 0;
225 GetSystemTimeAsFileTime(&ft);
226 tmpres |= ft.dwHighDateTime;
227 tmpres <<= 32;
228 tmpres |= ft.dwLowDateTime;
229 tmpres /= 10;
230
231 tmpres -= DELTA_EPOCH_IN_MICROSECS;
232
233 lua_pushnumber(L, (double) tmpres / 1000000.0);
234 return 1;
235 }
236
237 static int oslib_enableansi(lua_State *L)
238 {
239 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
240 DWORD mode = 0;
241 int done = 0;
242 if (GetConsoleMode(handle, &mode)) {
243 mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
244 if (SetConsoleMode(handle, mode)) {
245 done = 1;
246 } else {
247
248 }
249 }
250 lua_pushboolean(L, done);
251 return 1;
252 }
253
254# else
255
256 static int oslib_gettimeofday(lua_State *L)
257 {
258 double v;
259 struct timeval tv;
260 gettimeofday(&tv, NULL);
261 v = (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
262
263 lua_pushnumber(L, v);
264 return 1;
265 }
266
267 static int oslib_enableansi(lua_State *L)
268 {
269 lua_pushboolean(L, 1);
270 return 1;
271 }
272
273# endif
274
275
276
277static int oslib_execute(lua_State *L)
278{
279 const char *cmd = luaL_optstring(L, 1, NULL);
280 if (cmd) {
281 lua_pushinteger(L, aux_utf8_system(cmd) || lmt_error_state.default_exit_code);
282 } else {
283 lua_pushinteger(L, 0);
284 }
285 return 1;
286}
287
288# ifdef _WIN32
289
290 static int oslib_remove (lua_State *L)
291 {
292 const char *filename = luaL_checkstring(L, 1);
293 return luaL_fileresult(L, aux_utf8_remove(filename) == 0, filename);
294 }
295
296 static int oslib_rename (lua_State *L)
297 {
298 const char *fromname = luaL_checkstring(L, 1);
299 const char *toname = luaL_checkstring(L, 2);
300 return luaL_fileresult(L, aux_utf8_rename(fromname, toname) == 0, NULL);
301 }
302
303 static int oslib_getcodepage(lua_State *L)
304 {
305 lua_pushinteger(L, (int) GetOEMCP());
306 lua_pushinteger(L, (int) GetACP());
307 return 2;
308 }
309
310
320
321 static int oslib_getenv(lua_State *L)
322 {
323 const char *key = luaL_checkstring(L, 1);
324 char *val = NULL;
325 if (key) {
326 size_t wlen = 0;
327 LPWSTR wkey = aux_utf8_to_wide(key);
328 _wgetenv_s(&wlen, NULL, 0, wkey);
329 if (wlen) {
330 LPWSTR wval = (LPWSTR) lmt_memory_malloc(wlen * sizeof(WCHAR));
331 if (! _wgetenv_s(&wlen, wval, wlen, wkey)) {
332 val = aux_utf8_from_wide(wval);
333 }
334 }
335 }
336 if (val) {
337 lua_pushstring(L, val);
338 } else {
339 lua_pushnil(L);
340 }
341 return 1;
342 }
343
344 static int oslib_setenv(lua_State *L)
345 {
346 const char *key = luaL_optstring(L, 1, NULL);
347 if (key) {
348 const char *val = luaL_optstring(L, 2, NULL);
349 LPWSTR wkey = aux_utf8_to_wide(key);
350 LPWSTR wval = aux_utf8_to_wide(val ? val : "");
351 int bad = _wputenv_s(wkey, wval);
352 lmt_memory_free(wval);
353 lmt_memory_free(wkey);
354 if (bad) {
355 return luaL_error(L, "unable to change environment");
356 }
357 }
358 lua_pushboolean(L, 1);
359 return 1;
360 }
361
362# else
363
364 static int oslib_getcodepage(lua_State *L)
365 {
366 lua_pushboolean(L,0);
367 lua_pushboolean(L,0);
368 return 2;
369 }
370
371 static int oslib_setenv(lua_State *L)
372 {
373 const char *key = luaL_optstring(L, 1, NULL);
374 if (key) {
375 const char *val = luaL_optstring(L, 2, NULL);
376 if (val) {
377 char *value = lmt_memory_malloc((unsigned) (strlen(key) + strlen(val) + 2));
378 sprintf(value, "%s=%s", key, val);
379 if (putenv(value)) {
380
381 return luaL_error(L, "unable to change environment");
382 } else {
383
384 }
385 } else {
386 (void) unsetenv(key);
387 }
388 }
389 lua_pushboolean(L, 1);
390 return 1;
391 }
392
393# endif
394
395static const luaL_Reg oslib_function_list[] = {
396 { "sleep", oslib_sleep },
397 { "uname", oslib_uname },
398 { "gettimeofday", oslib_gettimeofday },
399 { "setenv", oslib_setenv },
400 { "execute", oslib_execute },
401# ifdef _WIN32
402 { "rename", oslib_rename },
403 { "remove", oslib_remove },
404 { "getenv", oslib_getenv },
405# endif
406 { "enableansi", oslib_enableansi },
407 { "getcodepage", oslib_getcodepage },
408 { "getnamevalues", oslib_getnamevalues },
409 { "gettypevalues", oslib_gettypevalues },
410 { "getunamefields", oslib_getunamefields },
411 { NULL, NULL },
412};
413
414
418
419# ifndef _WIN32
420 extern char **environ;
421# else
422 # define environ _environ
423# endif
424
425int luaextend_os(lua_State *L)
426{
427
428 lua_getglobal(L, "os");
429
430 lua_pushliteral(L, OSLIB_PLATTYPE);
431 lua_setfield(L, -2, "type");
432 lua_pushliteral(L, OSLIB_PLATNAME);
433 lua_setfield(L, -2, "name");
434
435 for (const luaL_Reg *lib = oslib_function_list; lib->name; lib++) {
436 lua_pushcfunction(L, lib->func);
437 lua_setfield(L, -2, lib->name);
438 }
439
440 if (0) {
441 char **envpointer = environ;
442 if (envpointer) {
443 lua_pushstring(L, "env");
444 lua_newtable(L);
445 while (*envpointer) {
446
447 char *envitem = lmt_memory_strdup(*envpointer);
448 char *envitem_orig = envitem;
449 char *envkey = envitem;
450 while (*envitem != '=') {
451 envitem++;
452 }
453 *envitem = 0;
454 envitem++;
455 lua_pushstring(L, envkey);
456 lua_pushstring(L, envitem);
457 lua_rawset(L, -3);
458 envpointer++;
459 lmt_memory_free(envitem_orig);
460 }
461 lua_rawset(L, -3);
462 }
463 }
464
465 lua_pop(L, 1);
466 return 1;
467}
468 |