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 //