github.com/shawnclovie/gopher-lua@v0.0.0-20200520092726-90b44ec0e2f2/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 if ln, ok := ret.(LNumber); ok { 19 return int(ln) 20 } 21 return v 22 } 23 24 func getBoolField(L *LState, tb *LTable, key string, v bool) bool { 25 ret := tb.RawGetString(key) 26 if lb, ok := ret.(LBool); ok { 27 return bool(lb) 28 } 29 return v 30 } 31 32 func OpenOs(L *LState) int { 33 osmod := L.RegisterModule(OsLibName, osFuncs) 34 L.Push(osmod) 35 return 1 36 } 37 38 var osFuncs = map[string]LGFunction{ 39 "clock": osClock, 40 "difftime": osDiffTime, 41 "execute": osExecute, 42 "exit": osExit, 43 "date": osDate, 44 "getenv": osGetEnv, 45 "remove": osRemove, 46 "rename": osRename, 47 "setenv": osSetEnv, 48 "setlocale": osSetLocale, 49 "time": osTime, 50 "tmpname": osTmpname, 51 } 52 53 func osClock(L *LState) int { 54 L.Push(LNumber(float64(time.Now().Sub(startedAt)) / float64(time.Second))) 55 return 1 56 } 57 58 func osDiffTime(L *LState) int { 59 L.Push(LNumber(L.CheckInt64(1) - L.CheckInt64(2))) 60 return 1 61 } 62 63 func osExecute(L *LState) int { 64 var procAttr os.ProcAttr 65 procAttr.Files = []*os.File{os.Stdin, os.Stdout, os.Stderr} 66 cmd, args := popenArgs(L.CheckString(1)) 67 args = append([]string{cmd}, args...) 68 process, err := os.StartProcess(cmd, args, &procAttr) 69 if err != nil { 70 L.Push(LNumber(1)) 71 return 1 72 } 73 74 ps, err := process.Wait() 75 if err != nil || !ps.Success() { 76 L.Push(LNumber(1)) 77 return 1 78 } 79 L.Push(LNumber(0)) 80 return 1 81 } 82 83 func osExit(L *LState) int { 84 L.Close() 85 os.Exit(L.OptInt(1, 0)) 86 return 1 87 } 88 89 func osDate(L *LState) int { 90 t := time.Now() 91 cfmt := "%c" 92 if L.GetTop() >= 1 { 93 cfmt = L.CheckString(1) 94 if strings.HasPrefix(cfmt, "!") { 95 t = time.Now().UTC() 96 cfmt = strings.TrimLeft(cfmt, "!") 97 } 98 if L.GetTop() >= 2 { 99 t = time.Unix(L.CheckInt64(2), 0) 100 } 101 if strings.HasPrefix(cfmt, "*t") { 102 ret := L.NewTable() 103 ret.RawSetString("year", LNumber(t.Year())) 104 ret.RawSetString("month", LNumber(t.Month())) 105 ret.RawSetString("day", LNumber(t.Day())) 106 ret.RawSetString("hour", LNumber(t.Hour())) 107 ret.RawSetString("min", LNumber(t.Minute())) 108 ret.RawSetString("sec", LNumber(t.Second())) 109 ret.RawSetString("wday", LNumber(t.Weekday()+1)) 110 // TODO yday & dst 111 ret.RawSetString("yday", LNumber(0)) 112 ret.RawSetString("isdst", LFalse) 113 L.Push(ret) 114 return 1 115 } 116 } 117 L.Push(LString(strftime(t, cfmt))) 118 return 1 119 } 120 121 func osGetEnv(L *LState) int { 122 v := os.Getenv(L.CheckString(1)) 123 if len(v) == 0 { 124 L.Push(LNil) 125 } else { 126 L.Push(LString(v)) 127 } 128 return 1 129 } 130 131 func osRemove(L *LState) int { 132 err := os.Remove(L.CheckString(1)) 133 if err != nil { 134 L.Push(LNil) 135 L.Push(LString(err.Error())) 136 return 2 137 } else { 138 L.Push(LTrue) 139 return 1 140 } 141 } 142 143 func osRename(L *LState) int { 144 err := os.Rename(L.CheckString(1), L.CheckString(2)) 145 if err != nil { 146 L.Push(LNil) 147 L.Push(LString(err.Error())) 148 return 2 149 } else { 150 L.Push(LTrue) 151 return 1 152 } 153 } 154 155 func osSetLocale(L *LState) int { 156 // setlocale is not supported 157 L.Push(LFalse) 158 return 1 159 } 160 161 func osSetEnv(L *LState) int { 162 err := os.Setenv(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 osTime(L *LState) int { 174 if L.GetTop() == 0 { 175 L.Push(LNumber(time.Now().Unix())) 176 } else { 177 tbl := L.CheckTable(1) 178 sec := getIntField(L, tbl, "sec", 0) 179 min := getIntField(L, tbl, "min", 0) 180 hour := getIntField(L, tbl, "hour", 12) 181 day := getIntField(L, tbl, "day", -1) 182 month := getIntField(L, tbl, "month", -1) 183 year := getIntField(L, tbl, "year", -1) 184 isdst := getBoolField(L, tbl, "isdst", false) 185 t := time.Date(year, time.Month(month), day, hour, min, sec, 0, time.Local) 186 // TODO dst 187 if false { 188 print(isdst) 189 } 190 L.Push(LNumber(t.Unix())) 191 } 192 return 1 193 } 194 195 func osTmpname(L *LState) int { 196 file, err := ioutil.TempFile("", "") 197 if err != nil { 198 L.RaiseError("unable to generate a unique filename") 199 } 200 file.Close() 201 os.Remove(file.Name()) // ignore errors 202 L.Push(LString(file.Name())) 203 return 1 204 } 205 206 //