oslib.go 4.6 KB

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