loslib.c revision 1.1
1/* $NetBSD: loslib.c,v 1.1 2010/10/31 11:16:58 mbalmer Exp $ */ 2 3/* 4** Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp 5** Standard Operating System library 6** See Copyright Notice in lua.h 7*/ 8 9 10#include <errno.h> 11#include <locale.h> 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 25static int os_pushresult (lua_State *L, int i, const char *filename) { 26 int en = errno; /* calls to Lua API may change this value */ 27 if (i) { 28 lua_pushboolean(L, 1); 29 return 1; 30 } 31 else { 32 lua_pushnil(L); 33 lua_pushfstring(L, "%s: %s", filename, strerror(en)); 34 lua_pushinteger(L, en); 35 return 3; 36 } 37} 38 39 40static int os_execute (lua_State *L) { 41 lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); 42 return 1; 43} 44 45 46static int os_remove (lua_State *L) { 47 const char *filename = luaL_checkstring(L, 1); 48 return os_pushresult(L, remove(filename) == 0, filename); 49} 50 51 52static int os_rename (lua_State *L) { 53 const char *fromname = luaL_checkstring(L, 1); 54 const char *toname = luaL_checkstring(L, 2); 55 return os_pushresult(L, rename(fromname, toname) == 0, fromname); 56} 57 58 59static int os_tmpname (lua_State *L) { 60 char buff[LUA_TMPNAMBUFSIZE]; 61 int err; 62 lua_tmpnam(buff, err); 63 if (err) 64 return luaL_error(L, "unable to generate a unique filename"); 65 lua_pushstring(L, buff); 66 return 1; 67} 68 69 70static int os_getenv (lua_State *L) { 71 lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ 72 return 1; 73} 74 75 76static int os_clock (lua_State *L) { 77 lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); 78 return 1; 79} 80 81 82/* 83** {====================================================== 84** Time/Date operations 85** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, 86** wday=%w+1, yday=%j, isdst=? } 87** ======================================================= 88*/ 89 90static void setfield (lua_State *L, const char *key, int value) { 91 lua_pushinteger(L, value); 92 lua_setfield(L, -2, key); 93} 94 95static void setboolfield (lua_State *L, const char *key, int value) { 96 if (value < 0) /* undefined? */ 97 return; /* does not set field */ 98 lua_pushboolean(L, value); 99 lua_setfield(L, -2, key); 100} 101 102static int getboolfield (lua_State *L, const char *key) { 103 int res; 104 lua_getfield(L, -1, key); 105 res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); 106 lua_pop(L, 1); 107 return res; 108} 109 110 111static int getfield (lua_State *L, const char *key, int d) { 112 int res; 113 lua_getfield(L, -1, key); 114 if (lua_isnumber(L, -1)) 115 res = (int)lua_tointeger(L, -1); 116 else { 117 if (d < 0) 118 return luaL_error(L, "field " LUA_QS " missing in date table", key); 119 res = d; 120 } 121 lua_pop(L, 1); 122 return res; 123} 124 125 126static int os_date (lua_State *L) { 127 const char *s = luaL_optstring(L, 1, "%c"); 128 time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); 129 struct tm *stm; 130 if (*s == '!') { /* UTC? */ 131 stm = gmtime(&t); 132 s++; /* skip `!' */ 133 } 134 else 135 stm = localtime(&t); 136 if (stm == NULL) /* invalid date? */ 137 lua_pushnil(L); 138 else if (strcmp(s, "*t") == 0) { 139 lua_createtable(L, 0, 9); /* 9 = number of fields */ 140 setfield(L, "sec", stm->tm_sec); 141 setfield(L, "min", stm->tm_min); 142 setfield(L, "hour", stm->tm_hour); 143 setfield(L, "day", stm->tm_mday); 144 setfield(L, "month", stm->tm_mon+1); 145 setfield(L, "year", stm->tm_year+1900); 146 setfield(L, "wday", stm->tm_wday+1); 147 setfield(L, "yday", stm->tm_yday+1); 148 setboolfield(L, "isdst", stm->tm_isdst); 149 } 150 else { 151 char cc[3]; 152 luaL_Buffer b; 153 cc[0] = '%'; cc[2] = '\0'; 154 luaL_buffinit(L, &b); 155 for (; *s; s++) { 156 if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ 157 luaL_addchar(&b, *s); 158 else { 159 size_t reslen; 160 char buff[200]; /* should be big enough for any conversion result */ 161 cc[1] = *(++s); 162 reslen = strftime(buff, sizeof(buff), cc, stm); 163 luaL_addlstring(&b, buff, reslen); 164 } 165 } 166 luaL_pushresult(&b); 167 } 168 return 1; 169} 170 171 172static int os_time (lua_State *L) { 173 time_t t; 174 if (lua_isnoneornil(L, 1)) /* called without args? */ 175 t = time(NULL); /* get current time */ 176 else { 177 struct tm ts; 178 luaL_checktype(L, 1, LUA_TTABLE); 179 lua_settop(L, 1); /* make sure table is at the top */ 180 ts.tm_sec = getfield(L, "sec", 0); 181 ts.tm_min = getfield(L, "min", 0); 182 ts.tm_hour = getfield(L, "hour", 12); 183 ts.tm_mday = getfield(L, "day", -1); 184 ts.tm_mon = getfield(L, "month", -1) - 1; 185 ts.tm_year = getfield(L, "year", -1) - 1900; 186 ts.tm_isdst = getboolfield(L, "isdst"); 187 t = mktime(&ts); 188 } 189 if (t == (time_t)(-1)) 190 lua_pushnil(L); 191 else 192 lua_pushnumber(L, (lua_Number)t); 193 return 1; 194} 195 196 197static int os_difftime (lua_State *L) { 198 lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), 199 (time_t)(luaL_optnumber(L, 2, 0)))); 200 return 1; 201} 202 203/* }====================================================== */ 204 205 206static int os_setlocale (lua_State *L) { 207 static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, 208 LC_NUMERIC, LC_TIME}; 209 static const char *const catnames[] = {"all", "collate", "ctype", "monetary", 210 "numeric", "time", NULL}; 211 const char *l = luaL_optstring(L, 1, NULL); 212 int op = luaL_checkoption(L, 2, "all", catnames); 213 lua_pushstring(L, setlocale(cat[op], l)); 214 return 1; 215} 216 217 218static int os_exit (lua_State *L) { 219 exit(luaL_optint(L, 1, EXIT_SUCCESS)); 220} 221 222static const luaL_Reg syslib[] = { 223 {"clock", os_clock}, 224 {"date", os_date}, 225 {"difftime", os_difftime}, 226 {"execute", os_execute}, 227 {"exit", os_exit}, 228 {"getenv", os_getenv}, 229 {"remove", os_remove}, 230 {"rename", os_rename}, 231 {"setlocale", os_setlocale}, 232 {"time", os_time}, 233 {"tmpname", os_tmpname}, 234 {NULL, NULL} 235}; 236 237/* }====================================================== */ 238 239 240 241LUALIB_API int luaopen_os (lua_State *L) { 242 luaL_register(L, LUA_OSLIBNAME, syslib); 243 return 1; 244} 245 246