1/*
2** OS library.
3** Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h
4**
5** Major portions taken verbatim or adapted from the Lua interpreter.
6** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
7*/
8
9#include <errno.h>
10#include <locale.h>
11#include <time.h>
12
13#define lib_os_c
14#define LUA_LIB
15
16#include "lua.h"
17#include "lauxlib.h"
18#include "lualib.h"
19
20#include "lj_obj.h"
21#include "lj_err.h"
22#include "lj_lib.h"
23
24#if LJ_TARGET_POSIX
25#include <unistd.h>
26#else
27#include <stdio.h>
28#endif
29
30/* ------------------------------------------------------------------------ */
31
32#define LJLIB_MODULE_os
33
34LJLIB_CF(os_execute)
35{
36#if LJ_TARGET_CONSOLE
37#if LJ_52
38 errno = ENOSYS;
39 return luaL_fileresult(L, 0, NULL);
40#else
41 lua_pushinteger(L, -1);
42 return 1;
43#endif
44#else
45 const char *cmd = luaL_optstring(L, 1, NULL);
46 int stat = system(cmd);
47#if LJ_52
48 if (cmd)
49 return luaL_execresult(L, stat);
50 setboolV(L->top++, 1);
51#else
52 setintV(L->top++, stat);
53#endif
54 return 1;
55#endif
56}
57
58LJLIB_CF(os_remove)
59{
60 const char *filename = luaL_checkstring(L, 1);
61 return luaL_fileresult(L, remove(filename) == 0, filename);
62}
63
64LJLIB_CF(os_rename)
65{
66 const char *fromname = luaL_checkstring(L, 1);
67 const char *toname = luaL_checkstring(L, 2);
68 return luaL_fileresult(L, rename(fromname, toname) == 0, fromname);
69}
70
71LJLIB_CF(os_tmpname)
72{
73#if LJ_TARGET_PS3 || LJ_TARGET_PS4
74 lj_err_caller(L, LJ_ERR_OSUNIQF);
75 return 0;
76#else
77#if LJ_TARGET_POSIX
78 char buf[15+1];
79 int fp;
80 strcpy(buf, "/tmp/lua_XXXXXX");
81 fp = mkstemp(buf);
82 if (fp != -1)
83 close(fp);
84 else
85 lj_err_caller(L, LJ_ERR_OSUNIQF);
86#else
87 char buf[L_tmpnam];
88 if (tmpnam(buf) == NULL)
89 lj_err_caller(L, LJ_ERR_OSUNIQF);
90#endif
91 lua_pushstring(L, buf);
92 return 1;
93#endif
94}
95
96LJLIB_CF(os_getenv)
97{
98#if LJ_TARGET_CONSOLE
99 lua_pushnil(L);
100#else
101 lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
102#endif
103 return 1;
104}
105
106LJLIB_CF(os_exit)
107{
108 int status;
109 if (L->base < L->top && tvisbool(L->base))
110 status = boolV(L->base) ? EXIT_SUCCESS : EXIT_FAILURE;
111 else
112 status = lj_lib_optint(L, 1, EXIT_SUCCESS);
113 if (L->base+1 < L->top && tvistruecond(L->base+1))
114 lua_close(L);
115 exit(status);
116 return 0; /* Unreachable. */
117}
118
119LJLIB_CF(os_clock)
120{
121 setnumV(L->top++, ((lua_Number)clock())*(1.0/(lua_Number)CLOCKS_PER_SEC));
122 return 1;
123}
124
125/* ------------------------------------------------------------------------ */
126
127static void setfield(lua_State *L, const char *key, int value)
128{
129 lua_pushinteger(L, value);
130 lua_setfield(L, -2, key);
131}
132
133static void setboolfield(lua_State *L, const char *key, int value)
134{
135 if (value < 0) /* undefined? */
136 return; /* does not set field */
137 lua_pushboolean(L, value);
138 lua_setfield(L, -2, key);
139}
140
141static int getboolfield(lua_State *L, const char *key)
142{
143 int res;
144 lua_getfield(L, -1, key);
145 res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
146 lua_pop(L, 1);
147 return res;
148}
149
150static int getfield(lua_State *L, const char *key, int d)
151{
152 int res;
153 lua_getfield(L, -1, key);
154 if (lua_isnumber(L, -1)) {
155 res = (int)lua_tointeger(L, -1);
156 } else {
157 if (d < 0)
158 lj_err_callerv(L, LJ_ERR_OSDATEF, key);
159 res = d;
160 }
161 lua_pop(L, 1);
162 return res;
163}
164
165LJLIB_CF(os_date)
166{
167 const char *s = luaL_optstring(L, 1, "%c");
168 time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
169 struct tm *stm;
170#if LJ_TARGET_POSIX
171 struct tm rtm;
172#endif
173 if (*s == '!') { /* UTC? */
174 s++; /* Skip '!' */
175#if LJ_TARGET_POSIX
176 stm = gmtime_r(&t, &rtm);
177#else
178 stm = gmtime(&t);
179#endif
180 } else {
181#if LJ_TARGET_POSIX
182 stm = localtime_r(&t, &rtm);
183#else
184 stm = localtime(&t);
185#endif
186 }
187 if (stm == NULL) { /* Invalid date? */
188 setnilV(L->top-1);
189 } else if (strcmp(s, "*t") == 0) {
190 lua_createtable(L, 0, 9); /* 9 = number of fields */
191 setfield(L, "sec", stm->tm_sec);
192 setfield(L, "min", stm->tm_min);
193 setfield(L, "hour", stm->tm_hour);
194 setfield(L, "day", stm->tm_mday);
195 setfield(L, "month", stm->tm_mon+1);
196 setfield(L, "year", stm->tm_year+1900);
197 setfield(L, "wday", stm->tm_wday+1);
198 setfield(L, "yday", stm->tm_yday+1);
199 setboolfield(L, "isdst", stm->tm_isdst);
200 } else {
201 char cc[3];
202 luaL_Buffer b;
203 cc[0] = '%'; cc[2] = '\0';
204 luaL_buffinit(L, &b);
205 for (; *s; s++) {
206 if (*s != '%' || *(s + 1) == '\0') { /* No conversion specifier? */
207 luaL_addchar(&b, *s);
208 } else {
209 size_t reslen;
210 char buff[200]; /* Should be big enough for any conversion result. */
211 cc[1] = *(++s);
212 reslen = strftime(buff, sizeof(buff), cc, stm);
213 luaL_addlstring(&b, buff, reslen);
214 }
215 }
216 luaL_pushresult(&b);
217 }
218 return 1;
219}
220
221LJLIB_CF(os_time)
222{
223 time_t t;
224 if (lua_isnoneornil(L, 1)) { /* called without args? */
225 t = time(NULL); /* get current time */
226 } else {
227 struct tm ts;
228 luaL_checktype(L, 1, LUA_TTABLE);
229 lua_settop(L, 1); /* make sure table is at the top */
230 ts.tm_sec = getfield(L, "sec", 0);
231 ts.tm_min = getfield(L, "min", 0);
232 ts.tm_hour = getfield(L, "hour", 12);
233 ts.tm_mday = getfield(L, "day", -1);
234 ts.tm_mon = getfield(L, "month", -1) - 1;
235 ts.tm_year = getfield(L, "year", -1) - 1900;
236 ts.tm_isdst = getboolfield(L, "isdst");
237 t = mktime(&ts);
238 }
239 if (t == (time_t)(-1))
240 lua_pushnil(L);
241 else
242 lua_pushnumber(L, (lua_Number)t);
243 return 1;
244}
245
246LJLIB_CF(os_difftime)
247{
248 lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
249 (time_t)(luaL_optnumber(L, 2, (lua_Number)0))));
250 return 1;
251}
252
253/* ------------------------------------------------------------------------ */
254
255LJLIB_CF(os_setlocale)
256{
257 GCstr *s = lj_lib_optstr(L, 1);
258 const char *str = s ? strdata(s) : NULL;
259 int opt = lj_lib_checkopt(L, 2, 6,
260 "\5ctype\7numeric\4time\7collate\10monetary\1\377\3all");
261 if (opt == 0) opt = LC_CTYPE;
262 else if (opt == 1) opt = LC_NUMERIC;
263 else if (opt == 2) opt = LC_TIME;
264 else if (opt == 3) opt = LC_COLLATE;
265 else if (opt == 4) opt = LC_MONETARY;
266 else if (opt == 6) opt = LC_ALL;
267 lua_pushstring(L, setlocale(opt, str));
268 return 1;
269}
270
271/* ------------------------------------------------------------------------ */
272
273#include "lj_libdef.h"
274
275LUALIB_API int luaopen_os(lua_State *L)
276{
277 LJ_LIB_REG(L, LUA_OSLIBNAME, os);
278 return 1;
279}
280
281