xref: /netbsd-src/external/mit/lua/dist/src/loslib.c (revision c2f76ff004a2cb67efe5b12d97bd3ef7fe89e18d)
1 /*	$NetBSD: loslib.c,v 1.1.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 
25 static 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 
40 static int os_execute (lua_State *L) {
41   lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));
42   return 1;
43 }
44 
45 
46 static 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 
52 static 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 
59 static 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 
70 static 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 
76 static 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 
90 static void setfield (lua_State *L, const char *key, int value) {
91   lua_pushinteger(L, value);
92   lua_setfield(L, -2, key);
93 }
94 
95 static 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 
102 static 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 
111 static 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 
126 static 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 
172 static 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 
197 static 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 
206 static 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 
218 static int os_exit (lua_State *L) {
219   exit(luaL_optint(L, 1, EXIT_SUCCESS));
220 }
221 
222 static 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 
241 LUALIB_API int luaopen_os (lua_State *L) {
242   luaL_register(L, LUA_OSLIBNAME, syslib);
243   return 1;
244 }
245 
246