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