"Fossies" - the Fresh Open Source Software Archive

Member "memcached-1.6.15/vendor/lua/src/loslib.c" (1 Oct 2021, 11859 Bytes) of package /linux/www/memcached-1.6.15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

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