Home | History | Annotate | Download | only in src
      1 /*
      2 ** $Id: loslib.c,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $
      3 ** Standard Operating System library
      4 ** See Copyright Notice in lua.h
      5 */
      6 
      7 
      8 #include <errno.h>
      9 #ifndef SYSLINUX
     10 #include <locale.h>
     11 #endif
     12 #include <stdlib.h>
     13 #include <string.h>
     14 #include <time.h>
     15 
     16 #define loslib_c
     17 #define LUA_LIB
     18 
     19 #include "lua.h"
     20 
     21 #include "lauxlib.h"
     22 #include "lualib.h"
     23 
     24 
     25 #ifndef SYSLINUX
     26 /*
     27 ** list of valid conversion specifiers for the 'strftime' function
     28 */
     29 #if !defined(LUA_STRFTIMEOPTIONS)
     30 
     31 #if !defined(LUA_USE_POSIX)
     32 #define LUA_STRFTIMEOPTIONS	{ "aAbBcdHIjmMpSUwWxXyYz%", "" }
     33 #else
     34 #define LUA_STRFTIMEOPTIONS \
     35 	{ "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \
     36 	  "", "E", "cCxXyY",  \
     37 	  "O", "deHImMSuUVwWy" }
     38 #endif
     39 
     40 #endif
     41 
     42 
     43 
     44 /*
     45 ** By default, Lua uses tmpnam except when POSIX is available, where it
     46 ** uses mkstemp.
     47 */
     48 #if defined(LUA_USE_MKSTEMP)
     49 #include <unistd.h>
     50 #define LUA_TMPNAMBUFSIZE	32
     51 #define lua_tmpnam(b,e) { \
     52         strcpy(b, "/tmp/lua_XXXXXX"); \
     53         e = mkstemp(b); \
     54         if (e != -1) close(e); \
     55         e = (e == -1); }
     56 
     57 #elif !defined(lua_tmpnam)
     58 
     59 #define LUA_TMPNAMBUFSIZE	L_tmpnam
     60 #define lua_tmpnam(b,e)		{ e = (tmpnam(b) == NULL); }
     61 
     62 #endif
     63 
     64 
     65 /*
     66 ** By default, Lua uses gmtime/localtime, except when POSIX is available,
     67 ** where it uses gmtime_r/localtime_r
     68 */
     69 #if defined(LUA_USE_GMTIME_R)
     70 
     71 #define l_gmtime(t,r)		gmtime_r(t,r)
     72 #define l_localtime(t,r)	localtime_r(t,r)
     73 
     74 #elif !defined(l_gmtime)
     75 
     76 #define l_gmtime(t,r)		((void)r, gmtime(t))
     77 #define l_localtime(t,r)  	((void)r, localtime(t))
     78 
     79 #endif
     80 
     81 
     82 
     83 static int os_execute (lua_State *L) {
     84   const char *cmd = luaL_optstring(L, 1, NULL);
     85   int stat = system(cmd);
     86   if (cmd != NULL)
     87     return luaL_execresult(L, stat);
     88   else {
     89     lua_pushboolean(L, stat);  /* true if there is a shell */
     90     return 1;
     91   }
     92 }
     93 
     94 
     95 static int os_remove (lua_State *L) {
     96   const char *filename = luaL_checkstring(L, 1);
     97   return luaL_fileresult(L, remove(filename) == 0, filename);
     98 }
     99 
    100 
    101 static int os_rename (lua_State *L) {
    102   const char *fromname = luaL_checkstring(L, 1);
    103   const char *toname = luaL_checkstring(L, 2);
    104   return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
    105 }
    106 
    107 
    108 static int os_tmpname (lua_State *L) {
    109   char buff[LUA_TMPNAMBUFSIZE];
    110   int err;
    111   lua_tmpnam(buff, err);
    112   if (err)
    113     return luaL_error(L, "unable to generate a unique filename");
    114   lua_pushstring(L, buff);
    115   return 1;
    116 }
    117 #endif /* SYSLINUX */
    118 
    119 
    120 static int os_getenv (lua_State *L) {
    121   lua_pushstring(L, getenv(luaL_checkstring(L, 1)));  /* if NULL push nil */
    122   return 1;
    123 }
    124 
    125 
    126 #ifndef SYSLINUX
    127 static int os_clock (lua_State *L) {
    128   lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
    129   return 1;
    130 }
    131 
    132 
    133 /*
    134 ** {======================================================
    135 ** Time/Date operations
    136 ** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
    137 **   wday=%w+1, yday=%j, isdst=? }
    138 ** =======================================================
    139 */
    140 
    141 static void setfield (lua_State *L, const char *key, int value) {
    142   lua_pushinteger(L, value);
    143   lua_setfield(L, -2, key);
    144 }
    145 
    146 static void setboolfield (lua_State *L, const char *key, int value) {
    147   if (value < 0)  /* undefined? */
    148     return;  /* does not set field */
    149   lua_pushboolean(L, value);
    150   lua_setfield(L, -2, key);
    151 }
    152 
    153 static int getboolfield (lua_State *L, const char *key) {
    154   int res;
    155   lua_getfield(L, -1, key);
    156   res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
    157   lua_pop(L, 1);
    158   return res;
    159 }
    160 
    161 
    162 static int getfield (lua_State *L, const char *key, int d) {
    163   int res, isnum;
    164   lua_getfield(L, -1, key);
    165   res = (int)lua_tointegerx(L, -1, &isnum);
    166   if (!isnum) {
    167     if (d < 0)
    168       return luaL_error(L, "field " LUA_QS " missing in date table", key);
    169     res = d;
    170   }
    171   lua_pop(L, 1);
    172   return res;
    173 }
    174 
    175 
    176 static const char *checkoption (lua_State *L, const char *conv, char *buff) {
    177   static const char *const options[] = LUA_STRFTIMEOPTIONS;
    178   unsigned int i;
    179   for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) {
    180     if (*conv != '\0' && strchr(options[i], *conv) != NULL) {
    181       buff[1] = *conv;
    182       if (*options[i + 1] == '\0') {  /* one-char conversion specifier? */
    183         buff[2] = '\0';  /* end buffer */
    184         return conv + 1;
    185       }
    186       else if (*(conv + 1) != '\0' &&
    187                strchr(options[i + 1], *(conv + 1)) != NULL) {
    188         buff[2] = *(conv + 1);  /* valid two-char conversion specifier */
    189         buff[3] = '\0';  /* end buffer */
    190         return conv + 2;
    191       }
    192     }
    193   }
    194   luaL_argerror(L, 1,
    195     lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv));
    196   return conv;  /* to avoid warnings */
    197 }
    198 
    199 
    200 static int os_date (lua_State *L) {
    201   const char *s = luaL_optstring(L, 1, "%c");
    202   time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
    203   struct tm tmr, *stm;
    204   if (*s == '!') {  /* UTC? */
    205     stm = l_gmtime(&t, &tmr);
    206     s++;  /* skip `!' */
    207   }
    208   else
    209     stm = l_localtime(&t, &tmr);
    210   if (stm == NULL)  /* invalid date? */
    211     lua_pushnil(L);
    212   else if (strcmp(s, "*t") == 0) {
    213     lua_createtable(L, 0, 9);  /* 9 = number of fields */
    214     setfield(L, "sec", stm->tm_sec);
    215     setfield(L, "min", stm->tm_min);
    216     setfield(L, "hour", stm->tm_hour);
    217     setfield(L, "day", stm->tm_mday);
    218     setfield(L, "month", stm->tm_mon+1);
    219     setfield(L, "year", stm->tm_year+1900);
    220     setfield(L, "wday", stm->tm_wday+1);
    221     setfield(L, "yday", stm->tm_yday+1);
    222     setboolfield(L, "isdst", stm->tm_isdst);
    223   }
    224   else {
    225     char cc[4];
    226     luaL_Buffer b;
    227     cc[0] = '%';
    228     luaL_buffinit(L, &b);
    229     while (*s) {
    230       if (*s != '%')  /* no conversion specifier? */
    231         luaL_addchar(&b, *s++);
    232       else {
    233         size_t reslen;
    234         char buff[200];  /* should be big enough for any conversion result */
    235         s = checkoption(L, s + 1, cc);
    236         reslen = strftime(buff, sizeof(buff), cc, stm);
    237         luaL_addlstring(&b, buff, reslen);
    238       }
    239     }
    240     luaL_pushresult(&b);
    241   }
    242   return 1;
    243 }
    244 
    245 
    246 static int os_time (lua_State *L) {
    247   time_t t;
    248   if (lua_isnoneornil(L, 1))  /* called without args? */
    249     t = time(NULL);  /* get current time */
    250   else {
    251     struct tm ts;
    252     luaL_checktype(L, 1, LUA_TTABLE);
    253     lua_settop(L, 1);  /* make sure table is at the top */
    254     ts.tm_sec = getfield(L, "sec", 0);
    255     ts.tm_min = getfield(L, "min", 0);
    256     ts.tm_hour = getfield(L, "hour", 12);
    257     ts.tm_mday = getfield(L, "day", -1);
    258     ts.tm_mon = getfield(L, "month", -1) - 1;
    259     ts.tm_year = getfield(L, "year", -1) - 1900;
    260     ts.tm_isdst = getboolfield(L, "isdst");
    261     t = mktime(&ts);
    262   }
    263   if (t == (time_t)(-1))
    264     lua_pushnil(L);
    265   else
    266     lua_pushnumber(L, (lua_Number)t);
    267   return 1;
    268 }
    269 
    270 
    271 #ifndef LUA_NUMBER_INTEGRAL
    272 static int os_difftime (lua_State *L) {
    273   lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
    274                              (time_t)(luaL_optnumber(L, 2, 0))));
    275   return 1;
    276 }
    277 #endif
    278 
    279 /* }====================================================== */
    280 
    281 
    282 static int os_setlocale (lua_State *L) {
    283   static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
    284                       LC_NUMERIC, LC_TIME};
    285   static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
    286      "numeric", "time", NULL};
    287   const char *l = luaL_optstring(L, 1, NULL);
    288   int op = luaL_checkoption(L, 2, "all", catnames);
    289   lua_pushstring(L, setlocale(cat[op], l));
    290   return 1;
    291 }
    292 #endif /* SYSLINUX */
    293 
    294 
    295 static int os_exit (lua_State *L) {
    296   int status;
    297   if (lua_isboolean(L, 1))
    298     status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE);
    299   else
    300     status = luaL_optint(L, 1, EXIT_SUCCESS);
    301   if (lua_toboolean(L, 2))
    302     lua_close(L);
    303   if (L) exit(status);  /* 'if' to avoid warnings for unreachable 'return' */
    304   return 0;
    305 }
    306 
    307 
    308 static const luaL_Reg syslib[] = {
    309 #ifndef SYSLINUX
    310   {"clock",     os_clock},
    311   {"date",      os_date},
    312 #ifndef LUA_NUMBER_INTEGRAL
    313   {"difftime",  os_difftime},
    314 #endif
    315   {"execute",   os_execute},
    316 #endif
    317   {"exit",      os_exit},
    318   {"getenv",    os_getenv},
    319 #ifndef SYSLINUX
    320   {"remove",    os_remove},
    321   {"rename",    os_rename},
    322   {"setlocale", os_setlocale},
    323   {"time",      os_time},
    324   {"tmpname",   os_tmpname},
    325 #endif
    326   {NULL, NULL}
    327 };
    328 
    329 /* }====================================================== */
    330 
    331 
    332 
    333 LUAMOD_API int luaopen_os (lua_State *L) {
    334   luaL_newlib(L, syslib);
    335   return 1;
    336 }
    337 
    338