You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

341 line
8.2 KiB

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