1*8e3e3a7aSWarner Losh /* 2*8e3e3a7aSWarner Losh ** $Id: loslib.c,v 1.65 2016/07/18 17:58:58 roberto Exp $ 3*8e3e3a7aSWarner Losh ** Standard Operating System library 4*8e3e3a7aSWarner Losh ** See Copyright Notice in lua.h 5*8e3e3a7aSWarner Losh */ 6*8e3e3a7aSWarner Losh 7*8e3e3a7aSWarner Losh #define loslib_c 8*8e3e3a7aSWarner Losh #define LUA_LIB 9*8e3e3a7aSWarner Losh 10*8e3e3a7aSWarner Losh #include "lprefix.h" 11*8e3e3a7aSWarner Losh 12*8e3e3a7aSWarner Losh 13*8e3e3a7aSWarner Losh #include <errno.h> 14*8e3e3a7aSWarner Losh #include <locale.h> 15*8e3e3a7aSWarner Losh #include <stdlib.h> 16*8e3e3a7aSWarner Losh #include <string.h> 17*8e3e3a7aSWarner Losh #include <time.h> 18*8e3e3a7aSWarner Losh 19*8e3e3a7aSWarner Losh #include "lua.h" 20*8e3e3a7aSWarner Losh 21*8e3e3a7aSWarner Losh #include "lauxlib.h" 22*8e3e3a7aSWarner Losh #include "lualib.h" 23*8e3e3a7aSWarner Losh 24*8e3e3a7aSWarner Losh 25*8e3e3a7aSWarner Losh /* 26*8e3e3a7aSWarner Losh ** {================================================================== 27*8e3e3a7aSWarner Losh ** List of valid conversion specifiers for the 'strftime' function; 28*8e3e3a7aSWarner Losh ** options are grouped by length; group of length 2 start with '||'. 29*8e3e3a7aSWarner Losh ** =================================================================== 30*8e3e3a7aSWarner Losh */ 31*8e3e3a7aSWarner Losh #if !defined(LUA_STRFTIMEOPTIONS) /* { */ 32*8e3e3a7aSWarner Losh 33*8e3e3a7aSWarner Losh /* options for ANSI C 89 (only 1-char options) */ 34*8e3e3a7aSWarner Losh #define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%" 35*8e3e3a7aSWarner Losh 36*8e3e3a7aSWarner Losh /* options for ISO C 99 and POSIX */ 37*8e3e3a7aSWarner Losh #define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ 38*8e3e3a7aSWarner Losh "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ 39*8e3e3a7aSWarner Losh 40*8e3e3a7aSWarner Losh /* options for Windows */ 41*8e3e3a7aSWarner Losh #define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \ 42*8e3e3a7aSWarner Losh "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ 43*8e3e3a7aSWarner Losh 44*8e3e3a7aSWarner Losh #if defined(LUA_USE_WINDOWS) 45*8e3e3a7aSWarner Losh #define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN 46*8e3e3a7aSWarner Losh #elif defined(LUA_USE_C89) 47*8e3e3a7aSWarner Losh #define LUA_STRFTIMEOPTIONS L_STRFTIMEC89 48*8e3e3a7aSWarner Losh #else /* C99 specification */ 49*8e3e3a7aSWarner Losh #define LUA_STRFTIMEOPTIONS L_STRFTIMEC99 50*8e3e3a7aSWarner Losh #endif 51*8e3e3a7aSWarner Losh 52*8e3e3a7aSWarner Losh #endif /* } */ 53*8e3e3a7aSWarner Losh /* }================================================================== */ 54*8e3e3a7aSWarner Losh 55*8e3e3a7aSWarner Losh 56*8e3e3a7aSWarner Losh /* 57*8e3e3a7aSWarner Losh ** {================================================================== 58*8e3e3a7aSWarner Losh ** Configuration for time-related stuff 59*8e3e3a7aSWarner Losh ** =================================================================== 60*8e3e3a7aSWarner Losh */ 61*8e3e3a7aSWarner Losh 62*8e3e3a7aSWarner Losh #if !defined(l_time_t) /* { */ 63*8e3e3a7aSWarner Losh /* 64*8e3e3a7aSWarner Losh ** type to represent time_t in Lua 65*8e3e3a7aSWarner Losh */ 66*8e3e3a7aSWarner Losh #define l_timet lua_Integer 67*8e3e3a7aSWarner Losh #define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) 68*8e3e3a7aSWarner Losh 69*8e3e3a7aSWarner Losh static time_t l_checktime (lua_State *L, int arg) { 70*8e3e3a7aSWarner Losh lua_Integer t = luaL_checkinteger(L, arg); 71*8e3e3a7aSWarner Losh luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); 72*8e3e3a7aSWarner Losh return (time_t)t; 73*8e3e3a7aSWarner Losh } 74*8e3e3a7aSWarner Losh 75*8e3e3a7aSWarner Losh #endif /* } */ 76*8e3e3a7aSWarner Losh 77*8e3e3a7aSWarner Losh 78*8e3e3a7aSWarner Losh #if !defined(l_gmtime) /* { */ 79*8e3e3a7aSWarner Losh /* 80*8e3e3a7aSWarner Losh ** By default, Lua uses gmtime/localtime, except when POSIX is available, 81*8e3e3a7aSWarner Losh ** where it uses gmtime_r/localtime_r 82*8e3e3a7aSWarner Losh */ 83*8e3e3a7aSWarner Losh 84*8e3e3a7aSWarner Losh #if defined(LUA_USE_POSIX) /* { */ 85*8e3e3a7aSWarner Losh 86*8e3e3a7aSWarner Losh #define l_gmtime(t,r) gmtime_r(t,r) 87*8e3e3a7aSWarner Losh #define l_localtime(t,r) localtime_r(t,r) 88*8e3e3a7aSWarner Losh 89*8e3e3a7aSWarner Losh #else /* }{ */ 90*8e3e3a7aSWarner Losh 91*8e3e3a7aSWarner Losh /* ISO C definitions */ 92*8e3e3a7aSWarner Losh #define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t)) 93*8e3e3a7aSWarner Losh #define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t)) 94*8e3e3a7aSWarner Losh 95*8e3e3a7aSWarner Losh #endif /* } */ 96*8e3e3a7aSWarner Losh 97*8e3e3a7aSWarner Losh #endif /* } */ 98*8e3e3a7aSWarner Losh 99*8e3e3a7aSWarner Losh /* }================================================================== */ 100*8e3e3a7aSWarner Losh 101*8e3e3a7aSWarner Losh 102*8e3e3a7aSWarner Losh /* 103*8e3e3a7aSWarner Losh ** {================================================================== 104*8e3e3a7aSWarner Losh ** Configuration for 'tmpnam': 105*8e3e3a7aSWarner Losh ** By default, Lua uses tmpnam except when POSIX is available, where 106*8e3e3a7aSWarner Losh ** it uses mkstemp. 107*8e3e3a7aSWarner Losh ** =================================================================== 108*8e3e3a7aSWarner Losh */ 109*8e3e3a7aSWarner Losh #if !defined(lua_tmpnam) /* { */ 110*8e3e3a7aSWarner Losh 111*8e3e3a7aSWarner Losh #if defined(LUA_USE_POSIX) /* { */ 112*8e3e3a7aSWarner Losh 113*8e3e3a7aSWarner Losh #include <unistd.h> 114*8e3e3a7aSWarner Losh 115*8e3e3a7aSWarner Losh #define LUA_TMPNAMBUFSIZE 32 116*8e3e3a7aSWarner Losh 117*8e3e3a7aSWarner Losh #if !defined(LUA_TMPNAMTEMPLATE) 118*8e3e3a7aSWarner Losh #define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX" 119*8e3e3a7aSWarner Losh #endif 120*8e3e3a7aSWarner Losh 121*8e3e3a7aSWarner Losh #define lua_tmpnam(b,e) { \ 122*8e3e3a7aSWarner Losh strcpy(b, LUA_TMPNAMTEMPLATE); \ 123*8e3e3a7aSWarner Losh e = mkstemp(b); \ 124*8e3e3a7aSWarner Losh if (e != -1) close(e); \ 125*8e3e3a7aSWarner Losh e = (e == -1); } 126*8e3e3a7aSWarner Losh 127*8e3e3a7aSWarner Losh #else /* }{ */ 128*8e3e3a7aSWarner Losh 129*8e3e3a7aSWarner Losh /* ISO C definitions */ 130*8e3e3a7aSWarner Losh #define LUA_TMPNAMBUFSIZE L_tmpnam 131*8e3e3a7aSWarner Losh #define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } 132*8e3e3a7aSWarner Losh 133*8e3e3a7aSWarner Losh #endif /* } */ 134*8e3e3a7aSWarner Losh 135*8e3e3a7aSWarner Losh #endif /* } */ 136*8e3e3a7aSWarner Losh /* }================================================================== */ 137*8e3e3a7aSWarner Losh 138*8e3e3a7aSWarner Losh 139*8e3e3a7aSWarner Losh 140*8e3e3a7aSWarner Losh 141*8e3e3a7aSWarner Losh static int os_execute (lua_State *L) { 142*8e3e3a7aSWarner Losh const char *cmd = luaL_optstring(L, 1, NULL); 143*8e3e3a7aSWarner Losh int stat = system(cmd); 144*8e3e3a7aSWarner Losh if (cmd != NULL) 145*8e3e3a7aSWarner Losh return luaL_execresult(L, stat); 146*8e3e3a7aSWarner Losh else { 147*8e3e3a7aSWarner Losh lua_pushboolean(L, stat); /* true if there is a shell */ 148*8e3e3a7aSWarner Losh return 1; 149*8e3e3a7aSWarner Losh } 150*8e3e3a7aSWarner Losh } 151*8e3e3a7aSWarner Losh 152*8e3e3a7aSWarner Losh 153*8e3e3a7aSWarner Losh static int os_remove (lua_State *L) { 154*8e3e3a7aSWarner Losh const char *filename = luaL_checkstring(L, 1); 155*8e3e3a7aSWarner Losh return luaL_fileresult(L, remove(filename) == 0, filename); 156*8e3e3a7aSWarner Losh } 157*8e3e3a7aSWarner Losh 158*8e3e3a7aSWarner Losh 159*8e3e3a7aSWarner Losh static int os_rename (lua_State *L) { 160*8e3e3a7aSWarner Losh const char *fromname = luaL_checkstring(L, 1); 161*8e3e3a7aSWarner Losh const char *toname = luaL_checkstring(L, 2); 162*8e3e3a7aSWarner Losh return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); 163*8e3e3a7aSWarner Losh } 164*8e3e3a7aSWarner Losh 165*8e3e3a7aSWarner Losh 166*8e3e3a7aSWarner Losh static int os_tmpname (lua_State *L) { 167*8e3e3a7aSWarner Losh char buff[LUA_TMPNAMBUFSIZE]; 168*8e3e3a7aSWarner Losh int err; 169*8e3e3a7aSWarner Losh lua_tmpnam(buff, err); 170*8e3e3a7aSWarner Losh if (err) 171*8e3e3a7aSWarner Losh return luaL_error(L, "unable to generate a unique filename"); 172*8e3e3a7aSWarner Losh lua_pushstring(L, buff); 173*8e3e3a7aSWarner Losh return 1; 174*8e3e3a7aSWarner Losh } 175*8e3e3a7aSWarner Losh 176*8e3e3a7aSWarner Losh 177*8e3e3a7aSWarner Losh static int os_getenv (lua_State *L) { 178*8e3e3a7aSWarner Losh lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ 179*8e3e3a7aSWarner Losh return 1; 180*8e3e3a7aSWarner Losh } 181*8e3e3a7aSWarner Losh 182*8e3e3a7aSWarner Losh 183*8e3e3a7aSWarner Losh static int os_clock (lua_State *L) { 184*8e3e3a7aSWarner Losh lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); 185*8e3e3a7aSWarner Losh return 1; 186*8e3e3a7aSWarner Losh } 187*8e3e3a7aSWarner Losh 188*8e3e3a7aSWarner Losh 189*8e3e3a7aSWarner Losh /* 190*8e3e3a7aSWarner Losh ** {====================================================== 191*8e3e3a7aSWarner Losh ** Time/Date operations 192*8e3e3a7aSWarner Losh ** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, 193*8e3e3a7aSWarner Losh ** wday=%w+1, yday=%j, isdst=? } 194*8e3e3a7aSWarner Losh ** ======================================================= 195*8e3e3a7aSWarner Losh */ 196*8e3e3a7aSWarner Losh 197*8e3e3a7aSWarner Losh static void setfield (lua_State *L, const char *key, int value) { 198*8e3e3a7aSWarner Losh lua_pushinteger(L, value); 199*8e3e3a7aSWarner Losh lua_setfield(L, -2, key); 200*8e3e3a7aSWarner Losh } 201*8e3e3a7aSWarner Losh 202*8e3e3a7aSWarner Losh static void setboolfield (lua_State *L, const char *key, int value) { 203*8e3e3a7aSWarner Losh if (value < 0) /* undefined? */ 204*8e3e3a7aSWarner Losh return; /* does not set field */ 205*8e3e3a7aSWarner Losh lua_pushboolean(L, value); 206*8e3e3a7aSWarner Losh lua_setfield(L, -2, key); 207*8e3e3a7aSWarner Losh } 208*8e3e3a7aSWarner Losh 209*8e3e3a7aSWarner Losh 210*8e3e3a7aSWarner Losh /* 211*8e3e3a7aSWarner Losh ** Set all fields from structure 'tm' in the table on top of the stack 212*8e3e3a7aSWarner Losh */ 213*8e3e3a7aSWarner Losh static void setallfields (lua_State *L, struct tm *stm) { 214*8e3e3a7aSWarner Losh setfield(L, "sec", stm->tm_sec); 215*8e3e3a7aSWarner Losh setfield(L, "min", stm->tm_min); 216*8e3e3a7aSWarner Losh setfield(L, "hour", stm->tm_hour); 217*8e3e3a7aSWarner Losh setfield(L, "day", stm->tm_mday); 218*8e3e3a7aSWarner Losh setfield(L, "month", stm->tm_mon + 1); 219*8e3e3a7aSWarner Losh setfield(L, "year", stm->tm_year + 1900); 220*8e3e3a7aSWarner Losh setfield(L, "wday", stm->tm_wday + 1); 221*8e3e3a7aSWarner Losh setfield(L, "yday", stm->tm_yday + 1); 222*8e3e3a7aSWarner Losh setboolfield(L, "isdst", stm->tm_isdst); 223*8e3e3a7aSWarner Losh } 224*8e3e3a7aSWarner Losh 225*8e3e3a7aSWarner Losh 226*8e3e3a7aSWarner Losh static int getboolfield (lua_State *L, const char *key) { 227*8e3e3a7aSWarner Losh int res; 228*8e3e3a7aSWarner Losh res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); 229*8e3e3a7aSWarner Losh lua_pop(L, 1); 230*8e3e3a7aSWarner Losh return res; 231*8e3e3a7aSWarner Losh } 232*8e3e3a7aSWarner Losh 233*8e3e3a7aSWarner Losh 234*8e3e3a7aSWarner Losh /* maximum value for date fields (to avoid arithmetic overflows with 'int') */ 235*8e3e3a7aSWarner Losh #if !defined(L_MAXDATEFIELD) 236*8e3e3a7aSWarner Losh #define L_MAXDATEFIELD (INT_MAX / 2) 237*8e3e3a7aSWarner Losh #endif 238*8e3e3a7aSWarner Losh 239*8e3e3a7aSWarner Losh static int getfield (lua_State *L, const char *key, int d, int delta) { 240*8e3e3a7aSWarner Losh int isnum; 241*8e3e3a7aSWarner Losh int t = lua_getfield(L, -1, key); /* get field and its type */ 242*8e3e3a7aSWarner Losh lua_Integer res = lua_tointegerx(L, -1, &isnum); 243*8e3e3a7aSWarner Losh if (!isnum) { /* field is not an integer? */ 244*8e3e3a7aSWarner Losh if (t != LUA_TNIL) /* some other value? */ 245*8e3e3a7aSWarner Losh return luaL_error(L, "field '%s' is not an integer", key); 246*8e3e3a7aSWarner Losh else if (d < 0) /* absent field; no default? */ 247*8e3e3a7aSWarner Losh return luaL_error(L, "field '%s' missing in date table", key); 248*8e3e3a7aSWarner Losh res = d; 249*8e3e3a7aSWarner Losh } 250*8e3e3a7aSWarner Losh else { 251*8e3e3a7aSWarner Losh if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) 252*8e3e3a7aSWarner Losh return luaL_error(L, "field '%s' is out-of-bound", key); 253*8e3e3a7aSWarner Losh res -= delta; 254*8e3e3a7aSWarner Losh } 255*8e3e3a7aSWarner Losh lua_pop(L, 1); 256*8e3e3a7aSWarner Losh return (int)res; 257*8e3e3a7aSWarner Losh } 258*8e3e3a7aSWarner Losh 259*8e3e3a7aSWarner Losh 260*8e3e3a7aSWarner Losh static const char *checkoption (lua_State *L, const char *conv, 261*8e3e3a7aSWarner Losh ptrdiff_t convlen, char *buff) { 262*8e3e3a7aSWarner Losh const char *option = LUA_STRFTIMEOPTIONS; 263*8e3e3a7aSWarner Losh int oplen = 1; /* length of options being checked */ 264*8e3e3a7aSWarner Losh for (; *option != '\0' && oplen <= convlen; option += oplen) { 265*8e3e3a7aSWarner Losh if (*option == '|') /* next block? */ 266*8e3e3a7aSWarner Losh oplen++; /* will check options with next length (+1) */ 267*8e3e3a7aSWarner Losh else if (memcmp(conv, option, oplen) == 0) { /* match? */ 268*8e3e3a7aSWarner Losh memcpy(buff, conv, oplen); /* copy valid option to buffer */ 269*8e3e3a7aSWarner Losh buff[oplen] = '\0'; 270*8e3e3a7aSWarner Losh return conv + oplen; /* return next item */ 271*8e3e3a7aSWarner Losh } 272*8e3e3a7aSWarner Losh } 273*8e3e3a7aSWarner Losh luaL_argerror(L, 1, 274*8e3e3a7aSWarner Losh lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); 275*8e3e3a7aSWarner Losh return conv; /* to avoid warnings */ 276*8e3e3a7aSWarner Losh } 277*8e3e3a7aSWarner Losh 278*8e3e3a7aSWarner Losh 279*8e3e3a7aSWarner Losh /* maximum size for an individual 'strftime' item */ 280*8e3e3a7aSWarner Losh #define SIZETIMEFMT 250 281*8e3e3a7aSWarner Losh 282*8e3e3a7aSWarner Losh 283*8e3e3a7aSWarner Losh static int os_date (lua_State *L) { 284*8e3e3a7aSWarner Losh size_t slen; 285*8e3e3a7aSWarner Losh const char *s = luaL_optlstring(L, 1, "%c", &slen); 286*8e3e3a7aSWarner Losh time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); 287*8e3e3a7aSWarner Losh const char *se = s + slen; /* 's' end */ 288*8e3e3a7aSWarner Losh struct tm tmr, *stm; 289*8e3e3a7aSWarner Losh if (*s == '!') { /* UTC? */ 290*8e3e3a7aSWarner Losh stm = l_gmtime(&t, &tmr); 291*8e3e3a7aSWarner Losh s++; /* skip '!' */ 292*8e3e3a7aSWarner Losh } 293*8e3e3a7aSWarner Losh else 294*8e3e3a7aSWarner Losh stm = l_localtime(&t, &tmr); 295*8e3e3a7aSWarner Losh if (stm == NULL) /* invalid date? */ 296*8e3e3a7aSWarner Losh luaL_error(L, "time result cannot be represented in this installation"); 297*8e3e3a7aSWarner Losh if (strcmp(s, "*t") == 0) { 298*8e3e3a7aSWarner Losh lua_createtable(L, 0, 9); /* 9 = number of fields */ 299*8e3e3a7aSWarner Losh setallfields(L, stm); 300*8e3e3a7aSWarner Losh } 301*8e3e3a7aSWarner Losh else { 302*8e3e3a7aSWarner Losh char cc[4]; /* buffer for individual conversion specifiers */ 303*8e3e3a7aSWarner Losh luaL_Buffer b; 304*8e3e3a7aSWarner Losh cc[0] = '%'; 305*8e3e3a7aSWarner Losh luaL_buffinit(L, &b); 306*8e3e3a7aSWarner Losh while (s < se) { 307*8e3e3a7aSWarner Losh if (*s != '%') /* not a conversion specifier? */ 308*8e3e3a7aSWarner Losh luaL_addchar(&b, *s++); 309*8e3e3a7aSWarner Losh else { 310*8e3e3a7aSWarner Losh size_t reslen; 311*8e3e3a7aSWarner Losh char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); 312*8e3e3a7aSWarner Losh s++; /* skip '%' */ 313*8e3e3a7aSWarner Losh s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */ 314*8e3e3a7aSWarner Losh reslen = strftime(buff, SIZETIMEFMT, cc, stm); 315*8e3e3a7aSWarner Losh luaL_addsize(&b, reslen); 316*8e3e3a7aSWarner Losh } 317*8e3e3a7aSWarner Losh } 318*8e3e3a7aSWarner Losh luaL_pushresult(&b); 319*8e3e3a7aSWarner Losh } 320*8e3e3a7aSWarner Losh return 1; 321*8e3e3a7aSWarner Losh } 322*8e3e3a7aSWarner Losh 323*8e3e3a7aSWarner Losh 324*8e3e3a7aSWarner Losh static int os_time (lua_State *L) { 325*8e3e3a7aSWarner Losh time_t t; 326*8e3e3a7aSWarner Losh if (lua_isnoneornil(L, 1)) /* called without args? */ 327*8e3e3a7aSWarner Losh t = time(NULL); /* get current time */ 328*8e3e3a7aSWarner Losh else { 329*8e3e3a7aSWarner Losh struct tm ts; 330*8e3e3a7aSWarner Losh luaL_checktype(L, 1, LUA_TTABLE); 331*8e3e3a7aSWarner Losh lua_settop(L, 1); /* make sure table is at the top */ 332*8e3e3a7aSWarner Losh ts.tm_sec = getfield(L, "sec", 0, 0); 333*8e3e3a7aSWarner Losh ts.tm_min = getfield(L, "min", 0, 0); 334*8e3e3a7aSWarner Losh ts.tm_hour = getfield(L, "hour", 12, 0); 335*8e3e3a7aSWarner Losh ts.tm_mday = getfield(L, "day", -1, 0); 336*8e3e3a7aSWarner Losh ts.tm_mon = getfield(L, "month", -1, 1); 337*8e3e3a7aSWarner Losh ts.tm_year = getfield(L, "year", -1, 1900); 338*8e3e3a7aSWarner Losh ts.tm_isdst = getboolfield(L, "isdst"); 339*8e3e3a7aSWarner Losh t = mktime(&ts); 340*8e3e3a7aSWarner Losh setallfields(L, &ts); /* update fields with normalized values */ 341*8e3e3a7aSWarner Losh } 342*8e3e3a7aSWarner Losh if (t != (time_t)(l_timet)t || t == (time_t)(-1)) 343*8e3e3a7aSWarner Losh luaL_error(L, "time result cannot be represented in this installation"); 344*8e3e3a7aSWarner Losh l_pushtime(L, t); 345*8e3e3a7aSWarner Losh return 1; 346*8e3e3a7aSWarner Losh } 347*8e3e3a7aSWarner Losh 348*8e3e3a7aSWarner Losh 349*8e3e3a7aSWarner Losh static int os_difftime (lua_State *L) { 350*8e3e3a7aSWarner Losh time_t t1 = l_checktime(L, 1); 351*8e3e3a7aSWarner Losh time_t t2 = l_checktime(L, 2); 352*8e3e3a7aSWarner Losh lua_pushnumber(L, (lua_Number)difftime(t1, t2)); 353*8e3e3a7aSWarner Losh return 1; 354*8e3e3a7aSWarner Losh } 355*8e3e3a7aSWarner Losh 356*8e3e3a7aSWarner Losh /* }====================================================== */ 357*8e3e3a7aSWarner Losh 358*8e3e3a7aSWarner Losh 359*8e3e3a7aSWarner Losh static int os_setlocale (lua_State *L) { 360*8e3e3a7aSWarner Losh static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, 361*8e3e3a7aSWarner Losh LC_NUMERIC, LC_TIME}; 362*8e3e3a7aSWarner Losh static const char *const catnames[] = {"all", "collate", "ctype", "monetary", 363*8e3e3a7aSWarner Losh "numeric", "time", NULL}; 364*8e3e3a7aSWarner Losh const char *l = luaL_optstring(L, 1, NULL); 365*8e3e3a7aSWarner Losh int op = luaL_checkoption(L, 2, "all", catnames); 366*8e3e3a7aSWarner Losh lua_pushstring(L, setlocale(cat[op], l)); 367*8e3e3a7aSWarner Losh return 1; 368*8e3e3a7aSWarner Losh } 369*8e3e3a7aSWarner Losh 370*8e3e3a7aSWarner Losh 371*8e3e3a7aSWarner Losh static int os_exit (lua_State *L) { 372*8e3e3a7aSWarner Losh int status; 373*8e3e3a7aSWarner Losh if (lua_isboolean(L, 1)) 374*8e3e3a7aSWarner Losh status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); 375*8e3e3a7aSWarner Losh else 376*8e3e3a7aSWarner Losh status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS); 377*8e3e3a7aSWarner Losh if (lua_toboolean(L, 2)) 378*8e3e3a7aSWarner Losh lua_close(L); 379*8e3e3a7aSWarner Losh if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ 380*8e3e3a7aSWarner Losh return 0; 381*8e3e3a7aSWarner Losh } 382*8e3e3a7aSWarner Losh 383*8e3e3a7aSWarner Losh 384*8e3e3a7aSWarner Losh static const luaL_Reg syslib[] = { 385*8e3e3a7aSWarner Losh {"clock", os_clock}, 386*8e3e3a7aSWarner Losh {"date", os_date}, 387*8e3e3a7aSWarner Losh {"difftime", os_difftime}, 388*8e3e3a7aSWarner Losh {"execute", os_execute}, 389*8e3e3a7aSWarner Losh {"exit", os_exit}, 390*8e3e3a7aSWarner Losh {"getenv", os_getenv}, 391*8e3e3a7aSWarner Losh {"remove", os_remove}, 392*8e3e3a7aSWarner Losh {"rename", os_rename}, 393*8e3e3a7aSWarner Losh {"setlocale", os_setlocale}, 394*8e3e3a7aSWarner Losh {"time", os_time}, 395*8e3e3a7aSWarner Losh {"tmpname", os_tmpname}, 396*8e3e3a7aSWarner Losh {NULL, NULL} 397*8e3e3a7aSWarner Losh }; 398*8e3e3a7aSWarner Losh 399*8e3e3a7aSWarner Losh /* }====================================================== */ 400*8e3e3a7aSWarner Losh 401*8e3e3a7aSWarner Losh 402*8e3e3a7aSWarner Losh 403*8e3e3a7aSWarner Losh LUAMOD_API int luaopen_os (lua_State *L) { 404*8e3e3a7aSWarner Losh luaL_newlib(L, syslib); 405*8e3e3a7aSWarner Losh return 1; 406*8e3e3a7aSWarner Losh } 407*8e3e3a7aSWarner Losh 408