github.com/awirix/lua@v1.6.0/oslib.go (about)

     1  package lua
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"strings"
     7  	"time"
     8  )
     9  
    10  var startedAt time.Time
    11  
    12  func init() {
    13  	startedAt = time.Now()
    14  }
    15  
    16  func getIntField(L *LState, tb *LTable, key string, v int) int {
    17  	ret := tb.RawGetString(key)
    18  
    19  	switch lv := ret.(type) {
    20  	case LNumber:
    21  		return int(lv)
    22  	case LString:
    23  		slv := string(lv)
    24  		slv = strings.TrimLeft(slv, " ")
    25  		if strings.HasPrefix(slv, "0") && !strings.HasPrefix(slv, "0x") && !strings.HasPrefix(slv, "0X") {
    26  			//Standard lua interpreter only support decimal and hexadecimal
    27  			slv = strings.TrimLeft(slv, "0")
    28  			if slv == "" {
    29  				return 0
    30  			}
    31  		}
    32  		if num, err := parseNumber(slv); err == nil {
    33  			return int(num)
    34  		}
    35  	default:
    36  		return v
    37  	}
    38  
    39  	return v
    40  }
    41  
    42  func getBoolField(L *LState, tb *LTable, key string, v bool) bool {
    43  	ret := tb.RawGetString(key)
    44  	if lb, ok := ret.(LBool); ok {
    45  		return bool(lb)
    46  	}
    47  	return v
    48  }
    49  
    50  func OpenOs(L *LState) int {
    51  	osmod := L.RegisterModule(OsLibName, osFuncs)
    52  	L.Push(osmod)
    53  	return 1
    54  }
    55  
    56  var osFuncs = map[string]LGFunction{
    57  	"clock":     osClock,
    58  	"difftime":  osDiffTime,
    59  	"execute":   osExecute,
    60  	"exit":      osExit,
    61  	"date":      osDate,
    62  	"getenv":    osGetEnv,
    63  	"remove":    osRemove,
    64  	"rename":    osRename,
    65  	"setenv":    osSetEnv,
    66  	"setlocale": osSetLocale,
    67  	"time":      osTime,
    68  	"tmpname":   osTmpname,
    69  }
    70  
    71  func osClock(L *LState) int {
    72  	L.Push(LNumber(float64(time.Now().Sub(startedAt)) / float64(time.Second)))
    73  	return 1
    74  }
    75  
    76  func osDiffTime(L *LState) int {
    77  	L.Push(LNumber(L.CheckInt64(1) - L.CheckInt64(2)))
    78  	return 1
    79  }
    80  
    81  func osExecute(L *LState) int {
    82  	var procAttr os.ProcAttr
    83  	procAttr.Files = []*os.File{os.Stdin, os.Stdout, os.Stderr}
    84  	cmd, args := popenArgs(L.CheckString(1))
    85  	args = append([]string{cmd}, args...)
    86  	process, err := os.StartProcess(cmd, args, &procAttr)
    87  	if err != nil {
    88  		L.Push(LNumber(1))
    89  		return 1
    90  	}
    91  
    92  	ps, err := process.Wait()
    93  	if err != nil || !ps.Success() {
    94  		L.Push(LNumber(1))
    95  		return 1
    96  	}
    97  	L.Push(LNumber(0))
    98  	return 1
    99  }
   100  
   101  func osExit(L *LState) int {
   102  	L.Close()
   103  	os.Exit(L.OptInt(1, 0))
   104  	return 1
   105  }
   106  
   107  func osDate(L *LState) int {
   108  	t := time.Now()
   109  	cfmt := "%c"
   110  	if L.GetTop() >= 1 {
   111  		cfmt = L.CheckString(1)
   112  		if strings.HasPrefix(cfmt, "!") {
   113  			t = time.Now().UTC()
   114  			cfmt = strings.TrimLeft(cfmt, "!")
   115  		}
   116  		if L.GetTop() >= 2 {
   117  			t = time.Unix(L.CheckInt64(2), 0)
   118  		}
   119  		if strings.HasPrefix(cfmt, "*t") {
   120  			ret := L.NewTable()
   121  			ret.RawSetString("year", LNumber(t.Year()))
   122  			ret.RawSetString("month", LNumber(t.Month()))
   123  			ret.RawSetString("day", LNumber(t.Day()))
   124  			ret.RawSetString("hour", LNumber(t.Hour()))
   125  			ret.RawSetString("min", LNumber(t.Minute()))
   126  			ret.RawSetString("sec", LNumber(t.Second()))
   127  			ret.RawSetString("wday", LNumber(t.Weekday()+1))
   128  			// TODO yday & dst
   129  			ret.RawSetString("yday", LNumber(0))
   130  			ret.RawSetString("isdst", LFalse)
   131  			L.Push(ret)
   132  			return 1
   133  		}
   134  	}
   135  	L.Push(LString(strftime(t, cfmt)))
   136  	return 1
   137  }
   138  
   139  func osGetEnv(L *LState) int {
   140  	v := os.Getenv(L.CheckString(1))
   141  	if len(v) == 0 {
   142  		L.Push(LNil)
   143  	} else {
   144  		L.Push(LString(v))
   145  	}
   146  	return 1
   147  }
   148  
   149  func osRemove(L *LState) int {
   150  	err := os.Remove(L.CheckString(1))
   151  	if err != nil {
   152  		L.Push(LNil)
   153  		L.Push(LString(err.Error()))
   154  		return 2
   155  	} else {
   156  		L.Push(LTrue)
   157  		return 1
   158  	}
   159  }
   160  
   161  func osRename(L *LState) int {
   162  	err := os.Rename(L.CheckString(1), L.CheckString(2))
   163  	if err != nil {
   164  		L.Push(LNil)
   165  		L.Push(LString(err.Error()))
   166  		return 2
   167  	} else {
   168  		L.Push(LTrue)
   169  		return 1
   170  	}
   171  }
   172  
   173  func osSetLocale(L *LState) int {
   174  	// setlocale is not supported
   175  	L.Push(LFalse)
   176  	return 1
   177  }
   178  
   179  func osSetEnv(L *LState) int {
   180  	err := os.Setenv(L.CheckString(1), L.CheckString(2))
   181  	if err != nil {
   182  		L.Push(LNil)
   183  		L.Push(LString(err.Error()))
   184  		return 2
   185  	} else {
   186  		L.Push(LTrue)
   187  		return 1
   188  	}
   189  }
   190  
   191  func osTime(L *LState) int {
   192  	if L.GetTop() == 0 {
   193  		L.Push(LNumber(time.Now().Unix()))
   194  	} else {
   195  		lv := L.CheckAny(1)
   196  		if lv == LNil {
   197  			L.Push(LNumber(time.Now().Unix()))
   198  		} else {
   199  			tbl, ok := lv.(*LTable)
   200  			if !ok {
   201  				L.TypeError(1, LTTable)
   202  			}
   203  			sec := getIntField(L, tbl, "sec", 0)
   204  			min := getIntField(L, tbl, "min", 0)
   205  			hour := getIntField(L, tbl, "hour", 12)
   206  			day := getIntField(L, tbl, "day", -1)
   207  			month := getIntField(L, tbl, "month", -1)
   208  			year := getIntField(L, tbl, "year", -1)
   209  			isdst := getBoolField(L, tbl, "isdst", false)
   210  			t := time.Date(year, time.Month(month), day, hour, min, sec, 0, time.Local)
   211  			// TODO dst
   212  			if false {
   213  				print(isdst)
   214  			}
   215  			L.Push(LNumber(t.Unix()))
   216  		}
   217  	}
   218  	return 1
   219  }
   220  
   221  func osTmpname(L *LState) int {
   222  	file, err := ioutil.TempFile("", "")
   223  	if err != nil {
   224  		L.RaiseError("unable to generate a unique filename")
   225  	}
   226  	file.Close()
   227  	os.Remove(file.Name()) // ignore errors
   228  	L.Push(LString(file.Name()))
   229  	return 1
   230  }
   231  
   232  //