176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** $Id: loslib.c,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** Standard Operating System library
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** See Copyright Notice in lua.h
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <errno.h>
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef SYSLINUX
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <locale.h>
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdlib.h>
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h>
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <time.h>
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define loslib_c
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LUA_LIB
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lua.h"
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lauxlib.h"
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lualib.h"
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef SYSLINUX
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** list of valid conversion specifiers for the 'strftime' function
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if !defined(LUA_STRFTIMEOPTIONS)
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if !defined(LUA_USE_POSIX)
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LUA_STRFTIMEOPTIONS	{ "aAbBcdHIjmMpSUwWxXyYz%", "" }
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LUA_STRFTIMEOPTIONS \
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{ "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	  "", "E", "cCxXyY",  \
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	  "O", "deHImMSuUVwWy" }
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** By default, Lua uses tmpnam except when POSIX is available, where it
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** uses mkstemp.
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(LUA_USE_MKSTEMP)
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <unistd.h>
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LUA_TMPNAMBUFSIZE	32
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define lua_tmpnam(b,e) { \
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        strcpy(b, "/tmp/lua_XXXXXX"); \
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        e = mkstemp(b); \
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (e != -1) close(e); \
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        e = (e == -1); }
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#elif !defined(lua_tmpnam)
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LUA_TMPNAMBUFSIZE	L_tmpnam
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define lua_tmpnam(b,e)		{ e = (tmpnam(b) == NULL); }
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** By default, Lua uses gmtime/localtime, except when POSIX is available,
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** where it uses gmtime_r/localtime_r
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if defined(LUA_USE_GMTIME_R)
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define l_gmtime(t,r)		gmtime_r(t,r)
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define l_localtime(t,r)	localtime_r(t,r)
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#elif !defined(l_gmtime)
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define l_gmtime(t,r)		((void)r, gmtime(t))
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define l_localtime(t,r)  	((void)r, localtime(t))
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int os_execute (lua_State *L) {
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  const char *cmd = luaL_optstring(L, 1, NULL);
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int stat = system(cmd);
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (cmd != NULL)
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return luaL_execresult(L, stat);
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else {
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    lua_pushboolean(L, stat);  /* true if there is a shell */
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 1;
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int os_remove (lua_State *L) {
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  const char *filename = luaL_checkstring(L, 1);
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return luaL_fileresult(L, remove(filename) == 0, filename);
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int os_rename (lua_State *L) {
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  const char *fromname = luaL_checkstring(L, 1);
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  const char *toname = luaL_checkstring(L, 2);
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int os_tmpname (lua_State *L) {
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  char buff[LUA_TMPNAMBUFSIZE];
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int err;
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_tmpnam(buff, err);
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (err)
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return luaL_error(L, "unable to generate a unique filename");
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_pushstring(L, buff);
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* SYSLINUX */
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int os_getenv (lua_State *L) {
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_pushstring(L, getenv(luaL_checkstring(L, 1)));  /* if NULL push nil */
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef SYSLINUX
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int os_clock (lua_State *L) {
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** {======================================================
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** Time/Date operations
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman**   wday=%w+1, yday=%j, isdst=? }
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** =======================================================
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void setfield (lua_State *L, const char *key, int value) {
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_pushinteger(L, value);
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_setfield(L, -2, key);
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void setboolfield (lua_State *L, const char *key, int value) {
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (value < 0)  /* undefined? */
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return;  /* does not set field */
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_pushboolean(L, value);
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_setfield(L, -2, key);
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int getboolfield (lua_State *L, const char *key) {
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int res;
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_getfield(L, -1, key);
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_pop(L, 1);
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return res;
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int getfield (lua_State *L, const char *key, int d) {
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int res, isnum;
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_getfield(L, -1, key);
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  res = (int)lua_tointegerx(L, -1, &isnum);
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (!isnum) {
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (d < 0)
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return luaL_error(L, "field " LUA_QS " missing in date table", key);
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    res = d;
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_pop(L, 1);
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return res;
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic const char *checkoption (lua_State *L, const char *conv, char *buff) {
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  static const char *const options[] = LUA_STRFTIMEOPTIONS;
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  unsigned int i;
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) {
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (*conv != '\0' && strchr(options[i], *conv) != NULL) {
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      buff[1] = *conv;
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (*options[i + 1] == '\0') {  /* one-char conversion specifier? */
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        buff[2] = '\0';  /* end buffer */
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return conv + 1;
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else if (*(conv + 1) != '\0' &&
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman               strchr(options[i + 1], *(conv + 1)) != NULL) {
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        buff[2] = *(conv + 1);  /* valid two-char conversion specifier */
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        buff[3] = '\0';  /* end buffer */
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return conv + 2;
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  luaL_argerror(L, 1,
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv));
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return conv;  /* to avoid warnings */
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int os_date (lua_State *L) {
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  const char *s = luaL_optstring(L, 1, "%c");
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  struct tm tmr, *stm;
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (*s == '!') {  /* UTC? */
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    stm = l_gmtime(&t, &tmr);
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    s++;  /* skip `!' */
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    stm = l_localtime(&t, &tmr);
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (stm == NULL)  /* invalid date? */
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    lua_pushnil(L);
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else if (strcmp(s, "*t") == 0) {
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    lua_createtable(L, 0, 9);  /* 9 = number of fields */
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    setfield(L, "sec", stm->tm_sec);
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    setfield(L, "min", stm->tm_min);
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    setfield(L, "hour", stm->tm_hour);
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    setfield(L, "day", stm->tm_mday);
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    setfield(L, "month", stm->tm_mon+1);
21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    setfield(L, "year", stm->tm_year+1900);
22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    setfield(L, "wday", stm->tm_wday+1);
22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    setfield(L, "yday", stm->tm_yday+1);
22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    setboolfield(L, "isdst", stm->tm_isdst);
22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else {
22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char cc[4];
22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    luaL_Buffer b;
22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cc[0] = '%';
22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    luaL_buffinit(L, &b);
22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while (*s) {
23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (*s != '%')  /* no conversion specifier? */
23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        luaL_addchar(&b, *s++);
23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      else {
23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        size_t reslen;
23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        char buff[200];  /* should be big enough for any conversion result */
23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        s = checkoption(L, s + 1, cc);
23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        reslen = strftime(buff, sizeof(buff), cc, stm);
23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        luaL_addlstring(&b, buff, reslen);
23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    luaL_pushresult(&b);
24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int os_time (lua_State *L) {
24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  time_t t;
24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (lua_isnoneornil(L, 1))  /* called without args? */
24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    t = time(NULL);  /* get current time */
25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else {
25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct tm ts;
25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    luaL_checktype(L, 1, LUA_TTABLE);
25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    lua_settop(L, 1);  /* make sure table is at the top */
25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ts.tm_sec = getfield(L, "sec", 0);
25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ts.tm_min = getfield(L, "min", 0);
25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ts.tm_hour = getfield(L, "hour", 12);
25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ts.tm_mday = getfield(L, "day", -1);
25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ts.tm_mon = getfield(L, "month", -1) - 1;
25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ts.tm_year = getfield(L, "year", -1) - 1900;
26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ts.tm_isdst = getboolfield(L, "isdst");
26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    t = mktime(&ts);
26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (t == (time_t)(-1))
26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    lua_pushnil(L);
26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else
26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    lua_pushnumber(L, (lua_Number)t);
26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef LUA_NUMBER_INTEGRAL
27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int os_difftime (lua_State *L) {
27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                             (time_t)(luaL_optnumber(L, 2, 0))));
27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* }====================================================== */
28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int os_setlocale (lua_State *L) {
28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                      LC_NUMERIC, LC_TIME};
28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     "numeric", "time", NULL};
28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  const char *l = luaL_optstring(L, 1, NULL);
28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int op = luaL_checkoption(L, 2, "all", catnames);
28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  lua_pushstring(L, setlocale(cat[op], l));
29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* SYSLINUX */
29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int os_exit (lua_State *L) {
29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int status;
29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (lua_isboolean(L, 1))
29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE);
29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else
30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    status = luaL_optint(L, 1, EXIT_SUCCESS);
30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (lua_toboolean(L, 2))
30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    lua_close(L);
30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (L) exit(status);  /* 'if' to avoid warnings for unreachable 'return' */
30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 0;
30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic const luaL_Reg syslib[] = {
30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef SYSLINUX
31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {"clock",     os_clock},
31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {"date",      os_date},
31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef LUA_NUMBER_INTEGRAL
31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {"difftime",  os_difftime},
31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {"execute",   os_execute},
31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {"exit",      os_exit},
31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {"getenv",    os_getenv},
31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef SYSLINUX
32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {"remove",    os_remove},
32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {"rename",    os_rename},
32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {"setlocale", os_setlocale},
32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {"time",      os_time},
32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {"tmpname",   os_tmpname},
32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {NULL, NULL}
32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* }====================================================== */
33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
33376d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanLUAMOD_API int luaopen_os (lua_State *L) {
33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  luaL_newlib(L, syslib);
33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
338