2
** $Id: loslib.c,v 1.40 2012/10/19 15:54:02 roberto Exp $
3
** Standard Operating System library
4
** See Copyright Notice in lua.h
24
** list of valid conversion specifiers for the 'strftime' function
26
#if !defined(LUA_STRFTIMEOPTIONS)
28
#if !defined(LUA_USE_POSIX)
29
#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" }
31
#define LUA_STRFTIMEOPTIONS \
32
{ "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \
34
"O", "deHImMSuUVwWy" }
42
** By default, Lua uses tmpnam except when POSIX is available, where it
45
#if defined(LUA_USE_MKSTEMP)
47
#define LUA_TMPNAMBUFSIZE 32
48
#define lua_tmpnam(b,e) { \
49
strcpy(b, "/tmp/lua_XXXXXX"); \
51
if (e != -1) close(e); \
54
#elif !defined(lua_tmpnam)
56
#define LUA_TMPNAMBUFSIZE L_tmpnam
57
#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
63
** By default, Lua uses gmtime/localtime, except when POSIX is available,
64
** where it uses gmtime_r/localtime_r
66
#if defined(LUA_USE_GMTIME_R)
68
#define l_gmtime(t,r) gmtime_r(t,r)
69
#define l_localtime(t,r) localtime_r(t,r)
71
#elif !defined(l_gmtime)
73
#define l_gmtime(t,r) ((void)r, gmtime(t))
74
#define l_localtime(t,r) ((void)r, localtime(t))
80
static int os_execute (lua_State *L) {
81
const char *cmd = luaL_optstring(L, 1, NULL);
82
int stat = system(cmd);
84
return luaL_execresult(L, stat);
86
lua_pushboolean(L, stat); /* true if there is a shell */
92
static int os_remove (lua_State *L) {
93
const char *filename = luaL_checkstring(L, 1);
94
return luaL_fileresult(L, remove(filename) == 0, filename);
98
static int os_rename (lua_State *L) {
99
const char *fromname = luaL_checkstring(L, 1);
100
const char *toname = luaL_checkstring(L, 2);
101
return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
105
static int os_tmpname (lua_State *L) {
106
char buff[LUA_TMPNAMBUFSIZE];
108
lua_tmpnam(buff, err);
110
return luaL_error(L, "unable to generate a unique filename");
111
lua_pushstring(L, buff);
116
static int os_getenv (lua_State *L) {
117
lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
122
static int os_clock (lua_State *L) {
123
lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
129
** {======================================================
130
** Time/Date operations
131
** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
132
** wday=%w+1, yday=%j, isdst=? }
133
** =======================================================
136
static void setfield (lua_State *L, const char *key, int value) {
137
lua_pushinteger(L, value);
138
lua_setfield(L, -2, key);
141
static void setboolfield (lua_State *L, const char *key, int value) {
142
if (value < 0) /* undefined? */
143
return; /* does not set field */
144
lua_pushboolean(L, value);
145
lua_setfield(L, -2, key);
148
static int getboolfield (lua_State *L, const char *key) {
150
lua_getfield(L, -1, key);
151
res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
157
static int getfield (lua_State *L, const char *key, int d) {
159
lua_getfield(L, -1, key);
160
res = (int)lua_tointegerx(L, -1, &isnum);
163
return luaL_error(L, "field " LUA_QS " missing in date table", key);
171
static const char *checkoption (lua_State *L, const char *conv, char *buff) {
172
static const char *const options[] = LUA_STRFTIMEOPTIONS;
174
for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) {
175
if (*conv != '\0' && strchr(options[i], *conv) != NULL) {
177
if (*options[i + 1] == '\0') { /* one-char conversion specifier? */
178
buff[2] = '\0'; /* end buffer */
181
else if (*(conv + 1) != '\0' &&
182
strchr(options[i + 1], *(conv + 1)) != NULL) {
183
buff[2] = *(conv + 1); /* valid two-char conversion specifier */
184
buff[3] = '\0'; /* end buffer */
190
lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv));
191
return conv; /* to avoid warnings */
195
static int os_date (lua_State *L) {
196
const char *s = luaL_optstring(L, 1, "%c");
197
time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
199
if (*s == '!') { /* UTC? */
200
stm = l_gmtime(&t, &tmr);
204
stm = l_localtime(&t, &tmr);
205
if (stm == NULL) /* invalid date? */
207
else if (strcmp(s, "*t") == 0) {
208
lua_createtable(L, 0, 9); /* 9 = number of fields */
209
setfield(L, "sec", stm->tm_sec);
210
setfield(L, "min", stm->tm_min);
211
setfield(L, "hour", stm->tm_hour);
212
setfield(L, "day", stm->tm_mday);
213
setfield(L, "month", stm->tm_mon+1);
214
setfield(L, "year", stm->tm_year+1900);
215
setfield(L, "wday", stm->tm_wday+1);
216
setfield(L, "yday", stm->tm_yday+1);
217
setboolfield(L, "isdst", stm->tm_isdst);
223
luaL_buffinit(L, &b);
225
if (*s != '%') /* no conversion specifier? */
226
luaL_addchar(&b, *s++);
229
char buff[200]; /* should be big enough for any conversion result */
230
s = checkoption(L, s + 1, cc);
231
reslen = strftime(buff, sizeof(buff), cc, stm);
232
luaL_addlstring(&b, buff, reslen);
241
static int os_time (lua_State *L) {
243
if (lua_isnoneornil(L, 1)) /* called without args? */
244
t = time(NULL); /* get current time */
247
luaL_checktype(L, 1, LUA_TTABLE);
248
lua_settop(L, 1); /* make sure table is at the top */
249
ts.tm_sec = getfield(L, "sec", 0);
250
ts.tm_min = getfield(L, "min", 0);
251
ts.tm_hour = getfield(L, "hour", 12);
252
ts.tm_mday = getfield(L, "day", -1);
253
ts.tm_mon = getfield(L, "month", -1) - 1;
254
ts.tm_year = getfield(L, "year", -1) - 1900;
255
ts.tm_isdst = getboolfield(L, "isdst");
258
if (t == (time_t)(-1))
261
lua_pushnumber(L, (lua_Number)t);
266
static int os_difftime (lua_State *L) {
267
lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
268
(time_t)(luaL_optnumber(L, 2, 0))));
272
/* }====================================================== */
275
static int os_setlocale (lua_State *L) {
276
static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
277
LC_NUMERIC, LC_TIME};
278
static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
279
"numeric", "time", NULL};
280
const char *l = luaL_optstring(L, 1, NULL);
281
int op = luaL_checkoption(L, 2, "all", catnames);
282
lua_pushstring(L, setlocale(cat[op], l));
287
static int os_exit (lua_State *L) {
289
if (lua_isboolean(L, 1))
290
status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE);
292
status = luaL_optint(L, 1, EXIT_SUCCESS);
293
if (lua_toboolean(L, 2))
295
if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */
300
static const luaL_Reg syslib[] = {
303
{"difftime", os_difftime},
304
{"execute", os_execute},
306
{"getenv", os_getenv},
307
{"remove", os_remove},
308
{"rename", os_rename},
309
{"setlocale", os_setlocale},
311
{"tmpname", os_tmpname},
315
/* }====================================================== */
319
LUAMOD_API int luaopen_os (lua_State *L) {
320
luaL_newlib(L, syslib);