diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib_os.c | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/src/lib_os.c b/src/lib_os.c new file mode 100644 index 00000000..bee7216a --- /dev/null +++ b/src/lib_os.c | |||
@@ -0,0 +1,249 @@ | |||
1 | /* | ||
2 | ** OS library. | ||
3 | ** Copyright (C) 2005-2009 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 | #ifdef LUA_USE_POSIX | ||
21 | #include <unistd.h> | ||
22 | #else | ||
23 | #include <stdio.h> | ||
24 | #endif | ||
25 | |||
26 | #include "lj_obj.h" | ||
27 | #include "lj_err.h" | ||
28 | #include "lj_lib.h" | ||
29 | |||
30 | /* ------------------------------------------------------------------------ */ | ||
31 | |||
32 | #define LJLIB_MODULE_os | ||
33 | |||
34 | static int os_pushresult(lua_State *L, int i, const char *filename) | ||
35 | { | ||
36 | int en = errno; /* calls to Lua API may change this value */ | ||
37 | if (i) { | ||
38 | setboolV(L->top-1, 1); | ||
39 | return 1; | ||
40 | } else { | ||
41 | setnilV(L->top-1); | ||
42 | lua_pushfstring(L, "%s: %s", filename, strerror(en)); | ||
43 | lua_pushinteger(L, en); | ||
44 | return 3; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | LJLIB_CF(os_execute) | ||
49 | { | ||
50 | lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); | ||
51 | return 1; | ||
52 | } | ||
53 | |||
54 | LJLIB_CF(os_remove) | ||
55 | { | ||
56 | const char *filename = luaL_checkstring(L, 1); | ||
57 | return os_pushresult(L, remove(filename) == 0, filename); | ||
58 | } | ||
59 | |||
60 | LJLIB_CF(os_rename) | ||
61 | { | ||
62 | const char *fromname = luaL_checkstring(L, 1); | ||
63 | const char *toname = luaL_checkstring(L, 2); | ||
64 | return os_pushresult(L, rename(fromname, toname) == 0, fromname); | ||
65 | } | ||
66 | |||
67 | LJLIB_CF(os_tmpname) | ||
68 | { | ||
69 | #ifdef LUA_USE_POSIX | ||
70 | char buf[15+1]; | ||
71 | int fp; | ||
72 | strcpy(buf, "/tmp/lua_XXXXXX"); | ||
73 | fp = mkstemp(buf); | ||
74 | if (fp != -1) | ||
75 | close(fp); | ||
76 | else | ||
77 | lj_err_caller(L, LJ_ERR_OSUNIQF); | ||
78 | #else | ||
79 | char buf[L_tmpnam]; | ||
80 | if (tmpnam(buf) == NULL) | ||
81 | lj_err_caller(L, LJ_ERR_OSUNIQF); | ||
82 | #endif | ||
83 | lua_pushstring(L, buf); | ||
84 | return 1; | ||
85 | } | ||
86 | |||
87 | LJLIB_CF(os_getenv) | ||
88 | { | ||
89 | lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ | ||
90 | return 1; | ||
91 | } | ||
92 | |||
93 | LJLIB_CF(os_exit) | ||
94 | { | ||
95 | exit(lj_lib_optint(L, 1, EXIT_SUCCESS)); | ||
96 | return 0; /* to avoid warnings */ | ||
97 | } | ||
98 | |||
99 | LJLIB_CF(os_clock) | ||
100 | { | ||
101 | setnumV(L->top++, ((lua_Number)clock())*(1.0/(lua_Number)CLOCKS_PER_SEC)); | ||
102 | return 1; | ||
103 | } | ||
104 | |||
105 | /* ------------------------------------------------------------------------ */ | ||
106 | |||
107 | static void setfield(lua_State *L, const char *key, int value) | ||
108 | { | ||
109 | lua_pushinteger(L, value); | ||
110 | lua_setfield(L, -2, key); | ||
111 | } | ||
112 | |||
113 | static void setboolfield(lua_State *L, const char *key, int value) | ||
114 | { | ||
115 | if (value < 0) /* undefined? */ | ||
116 | return; /* does not set field */ | ||
117 | lua_pushboolean(L, value); | ||
118 | lua_setfield(L, -2, key); | ||
119 | } | ||
120 | |||
121 | static int getboolfield(lua_State *L, const char *key) | ||
122 | { | ||
123 | int res; | ||
124 | lua_getfield(L, -1, key); | ||
125 | res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); | ||
126 | lua_pop(L, 1); | ||
127 | return res; | ||
128 | } | ||
129 | |||
130 | static int getfield(lua_State *L, const char *key, int d) | ||
131 | { | ||
132 | int res; | ||
133 | lua_getfield(L, -1, key); | ||
134 | if (lua_isnumber(L, -1)) { | ||
135 | res = (int)lua_tointeger(L, -1); | ||
136 | } else { | ||
137 | if (d < 0) | ||
138 | lj_err_callerv(L, LJ_ERR_OSDATEF, key); | ||
139 | res = d; | ||
140 | } | ||
141 | lua_pop(L, 1); | ||
142 | return res; | ||
143 | } | ||
144 | |||
145 | LJLIB_CF(os_date) | ||
146 | { | ||
147 | const char *s = luaL_optstring(L, 1, "%c"); | ||
148 | time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); | ||
149 | struct tm *stm; | ||
150 | if (*s == '!') { /* UTC? */ | ||
151 | stm = gmtime(&t); | ||
152 | s++; /* skip `!' */ | ||
153 | } else { | ||
154 | stm = localtime(&t); | ||
155 | } | ||
156 | if (stm == NULL) { /* invalid date? */ | ||
157 | setnilV(L->top-1); | ||
158 | } else if (strcmp(s, "*t") == 0) { | ||
159 | lua_createtable(L, 0, 9); /* 9 = number of fields */ | ||
160 | setfield(L, "sec", stm->tm_sec); | ||
161 | setfield(L, "min", stm->tm_min); | ||
162 | setfield(L, "hour", stm->tm_hour); | ||
163 | setfield(L, "day", stm->tm_mday); | ||
164 | setfield(L, "month", stm->tm_mon+1); | ||
165 | setfield(L, "year", stm->tm_year+1900); | ||
166 | setfield(L, "wday", stm->tm_wday+1); | ||
167 | setfield(L, "yday", stm->tm_yday+1); | ||
168 | setboolfield(L, "isdst", stm->tm_isdst); | ||
169 | } else { | ||
170 | char cc[3]; | ||
171 | luaL_Buffer b; | ||
172 | cc[0] = '%'; cc[2] = '\0'; | ||
173 | luaL_buffinit(L, &b); | ||
174 | for (; *s; s++) { | ||
175 | if (*s != '%' || *(s + 1) == '\0') { /* no conversion specifier? */ | ||
176 | luaL_addchar(&b, *s); | ||
177 | } else { | ||
178 | size_t reslen; | ||
179 | char buff[200]; /* should be big enough for any conversion result */ | ||
180 | cc[1] = *(++s); | ||
181 | reslen = strftime(buff, sizeof(buff), cc, stm); | ||
182 | luaL_addlstring(&b, buff, reslen); | ||
183 | } | ||
184 | } | ||
185 | luaL_pushresult(&b); | ||
186 | } | ||
187 | return 1; | ||
188 | } | ||
189 | |||
190 | LJLIB_CF(os_time) | ||
191 | { | ||
192 | time_t t; | ||
193 | if (lua_isnoneornil(L, 1)) { /* called without args? */ | ||
194 | t = time(NULL); /* get current time */ | ||
195 | } else { | ||
196 | struct tm ts; | ||
197 | luaL_checktype(L, 1, LUA_TTABLE); | ||
198 | lua_settop(L, 1); /* make sure table is at the top */ | ||
199 | ts.tm_sec = getfield(L, "sec", 0); | ||
200 | ts.tm_min = getfield(L, "min", 0); | ||
201 | ts.tm_hour = getfield(L, "hour", 12); | ||
202 | ts.tm_mday = getfield(L, "day", -1); | ||
203 | ts.tm_mon = getfield(L, "month", -1) - 1; | ||
204 | ts.tm_year = getfield(L, "year", -1) - 1900; | ||
205 | ts.tm_isdst = getboolfield(L, "isdst"); | ||
206 | t = mktime(&ts); | ||
207 | } | ||
208 | if (t == (time_t)(-1)) | ||
209 | lua_pushnil(L); | ||
210 | else | ||
211 | lua_pushnumber(L, (lua_Number)t); | ||
212 | return 1; | ||
213 | } | ||
214 | |||
215 | LJLIB_CF(os_difftime) | ||
216 | { | ||
217 | lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), | ||
218 | (time_t)(luaL_optnumber(L, 2, (lua_Number)0)))); | ||
219 | return 1; | ||
220 | } | ||
221 | |||
222 | /* ------------------------------------------------------------------------ */ | ||
223 | |||
224 | LJLIB_CF(os_setlocale) | ||
225 | { | ||
226 | GCstr *s = lj_lib_optstr(L, 1); | ||
227 | const char *str = s ? strdata(s) : NULL; | ||
228 | int opt = lj_lib_checkopt(L, 2, 6, | ||
229 | "\5ctype\7numeric\4time\7collate\10monetary\1\377\3all"); | ||
230 | if (opt == 0) opt = LC_CTYPE; | ||
231 | else if (opt == 1) opt = LC_NUMERIC; | ||
232 | else if (opt == 2) opt = LC_TIME; | ||
233 | else if (opt == 3) opt = LC_COLLATE; | ||
234 | else if (opt == 4) opt = LC_MONETARY; | ||
235 | else if (opt == 6) opt = LC_ALL; | ||
236 | lua_pushstring(L, setlocale(opt, str)); | ||
237 | return 1; | ||
238 | } | ||
239 | |||
240 | /* ------------------------------------------------------------------------ */ | ||
241 | |||
242 | #include "lj_libdef.h" | ||
243 | |||
244 | LUALIB_API int luaopen_os(lua_State *L) | ||
245 | { | ||
246 | LJ_LIB_REG(L, os); | ||
247 | return 1; | ||
248 | } | ||
249 | |||