123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- package lua
- import (
- "os"
- "strings"
- "time"
- )
- var startedAt time.Time
- func init() {
- startedAt = time.Now()
- }
- func getIntField(L *LState, tb *LTable, key string, v int) int {
- ret := tb.RawGetString(key)
- switch lv := ret.(type) {
- case LNumber:
- return int(lv)
- case LString:
- slv := string(lv)
- slv = strings.TrimLeft(slv, " ")
- if strings.HasPrefix(slv, "0") && !strings.HasPrefix(slv, "0x") && !strings.HasPrefix(slv, "0X") {
- // Standard lua interpreter only support decimal and hexadecimal
- slv = strings.TrimLeft(slv, "0")
- if slv == "" {
- return 0
- }
- }
- if num, err := parseNumber(slv); err == nil {
- return int(num)
- }
- default:
- return v
- }
- return v
- }
- func getBoolField(L *LState, tb *LTable, key string, v bool) bool {
- ret := tb.RawGetString(key)
- if lb, ok := ret.(LBool); ok {
- return bool(lb)
- }
- return v
- }
- func OpenOs(L *LState) int {
- osmod := L.RegisterModule(OsLibName, osFuncs)
- L.Push(osmod)
- return 1
- }
- var osFuncs = map[string]LGFunction{
- "clock": osClock,
- "difftime": osDiffTime,
- "execute": osExecute,
- "exit": osExit,
- "date": osDate,
- "getenv": osGetEnv,
- "remove": osRemove,
- "rename": osRename,
- "setenv": osSetEnv,
- "setlocale": osSetLocale,
- "time": osTime,
- "tmpname": osTmpname,
- }
- func osClock(L *LState) int {
- L.Push(LNumber(float64(time.Now().Sub(startedAt)) / float64(time.Second)))
- return 1
- }
- func osDiffTime(L *LState) int {
- L.Push(LNumber(L.CheckInt64(1) - L.CheckInt64(2)))
- return 1
- }
- func osExecute(L *LState) int {
- var procAttr os.ProcAttr
- procAttr.Files = []*os.File{os.Stdin, os.Stdout, os.Stderr}
- cmd, args := popenArgs(L.CheckString(1))
- args = append([]string{cmd}, args...)
- process, err := os.StartProcess(cmd, args, &procAttr)
- if err != nil {
- L.Push(LNumber(1))
- return 1
- }
- ps, err := process.Wait()
- if err != nil || !ps.Success() {
- L.Push(LNumber(1))
- return 1
- }
- L.Push(LNumber(0))
- return 1
- }
- func osExit(L *LState) int {
- L.Close()
- os.Exit(L.OptInt(1, 0))
- return 1
- }
- func osDate(L *LState) int {
- t := time.Now()
- isUTC := false
- cfmt := "%c"
- if L.GetTop() >= 1 {
- cfmt = L.CheckString(1)
- if strings.HasPrefix(cfmt, "!") {
- cfmt = strings.TrimLeft(cfmt, "!")
- isUTC = true
- }
- if L.GetTop() >= 2 {
- t = time.Unix(L.CheckInt64(2), 0)
- }
- if isUTC {
- t = t.UTC()
- }
- if strings.HasPrefix(cfmt, "*t") {
- ret := L.NewTable()
- ret.RawSetString("year", LNumber(t.Year()))
- ret.RawSetString("month", LNumber(t.Month()))
- ret.RawSetString("day", LNumber(t.Day()))
- ret.RawSetString("hour", LNumber(t.Hour()))
- ret.RawSetString("min", LNumber(t.Minute()))
- ret.RawSetString("sec", LNumber(t.Second()))
- ret.RawSetString("wday", LNumber(t.Weekday()+1))
- // TODO yday & dst
- ret.RawSetString("yday", LNumber(0))
- ret.RawSetString("isdst", LFalse)
- L.Push(ret)
- return 1
- }
- }
- L.Push(LString(strftime(t, cfmt)))
- return 1
- }
- func osGetEnv(L *LState) int {
- v := os.Getenv(L.CheckString(1))
- if len(v) == 0 {
- L.Push(LNil)
- } else {
- L.Push(LString(v))
- }
- return 1
- }
- func osRemove(L *LState) int {
- err := os.Remove(L.CheckString(1))
- if err != nil {
- L.Push(LNil)
- L.Push(LString(err.Error()))
- return 2
- } else {
- L.Push(LTrue)
- return 1
- }
- }
- func osRename(L *LState) int {
- err := os.Rename(L.CheckString(1), L.CheckString(2))
- if err != nil {
- L.Push(LNil)
- L.Push(LString(err.Error()))
- return 2
- } else {
- L.Push(LTrue)
- return 1
- }
- }
- func osSetLocale(L *LState) int {
- // setlocale is not supported
- L.Push(LFalse)
- return 1
- }
- func osSetEnv(L *LState) int {
- err := os.Setenv(L.CheckString(1), L.CheckString(2))
- if err != nil {
- L.Push(LNil)
- L.Push(LString(err.Error()))
- return 2
- } else {
- L.Push(LTrue)
- return 1
- }
- }
- func osTime(L *LState) int {
- if L.GetTop() == 0 {
- L.Push(LNumber(time.Now().Unix()))
- } else {
- lv := L.CheckAny(1)
- if lv == LNil {
- L.Push(LNumber(time.Now().Unix()))
- } else {
- tbl, ok := lv.(*LTable)
- if !ok {
- L.TypeError(1, LTTable)
- }
- sec := getIntField(L, tbl, "sec", 0)
- min := getIntField(L, tbl, "min", 0)
- hour := getIntField(L, tbl, "hour", 12)
- day := getIntField(L, tbl, "day", -1)
- month := getIntField(L, tbl, "month", -1)
- year := getIntField(L, tbl, "year", -1)
- isdst := getBoolField(L, tbl, "isdst", false)
- t := time.Date(year, time.Month(month), day, hour, min, sec, 0, time.Local)
- // TODO dst
- if false {
- print(isdst)
- }
- L.Push(LNumber(t.Unix()))
- }
- }
- return 1
- }
- func osTmpname(L *LState) int {
- file, err := os.CreateTemp("", "")
- if err != nil {
- L.RaiseError("unable to generate a unique filename")
- }
- file.Close()
- os.Remove(file.Name()) // ignore errors
- L.Push(LString(file.Name()))
- return 1
- }
- //
|