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