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