1
0

oslib.go 4.6 KB

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