github.com/tul/gopher-lua@v0.0.0-20181008131706-f6fcaab0c612/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  //