summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/d5/tengo/v2/stdlib/os.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/d5/tengo/v2/stdlib/os.go')
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/os.go564
1 files changed, 564 insertions, 0 deletions
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/os.go b/vendor/github.com/d5/tengo/v2/stdlib/os.go
new file mode 100644
index 00000000..576bc94b
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/os.go
@@ -0,0 +1,564 @@
+package stdlib
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+
+ "github.com/d5/tengo/v2"
+)
+
+var osModule = map[string]tengo.Object{
+ "o_rdonly": &tengo.Int{Value: int64(os.O_RDONLY)},
+ "o_wronly": &tengo.Int{Value: int64(os.O_WRONLY)},
+ "o_rdwr": &tengo.Int{Value: int64(os.O_RDWR)},
+ "o_append": &tengo.Int{Value: int64(os.O_APPEND)},
+ "o_create": &tengo.Int{Value: int64(os.O_CREATE)},
+ "o_excl": &tengo.Int{Value: int64(os.O_EXCL)},
+ "o_sync": &tengo.Int{Value: int64(os.O_SYNC)},
+ "o_trunc": &tengo.Int{Value: int64(os.O_TRUNC)},
+ "mode_dir": &tengo.Int{Value: int64(os.ModeDir)},
+ "mode_append": &tengo.Int{Value: int64(os.ModeAppend)},
+ "mode_exclusive": &tengo.Int{Value: int64(os.ModeExclusive)},
+ "mode_temporary": &tengo.Int{Value: int64(os.ModeTemporary)},
+ "mode_symlink": &tengo.Int{Value: int64(os.ModeSymlink)},
+ "mode_device": &tengo.Int{Value: int64(os.ModeDevice)},
+ "mode_named_pipe": &tengo.Int{Value: int64(os.ModeNamedPipe)},
+ "mode_socket": &tengo.Int{Value: int64(os.ModeSocket)},
+ "mode_setuid": &tengo.Int{Value: int64(os.ModeSetuid)},
+ "mode_setgui": &tengo.Int{Value: int64(os.ModeSetgid)},
+ "mode_char_device": &tengo.Int{Value: int64(os.ModeCharDevice)},
+ "mode_sticky": &tengo.Int{Value: int64(os.ModeSticky)},
+ "mode_type": &tengo.Int{Value: int64(os.ModeType)},
+ "mode_perm": &tengo.Int{Value: int64(os.ModePerm)},
+ "path_separator": &tengo.Char{Value: os.PathSeparator},
+ "path_list_separator": &tengo.Char{Value: os.PathListSeparator},
+ "dev_null": &tengo.String{Value: os.DevNull},
+ "seek_set": &tengo.Int{Value: int64(io.SeekStart)},
+ "seek_cur": &tengo.Int{Value: int64(io.SeekCurrent)},
+ "seek_end": &tengo.Int{Value: int64(io.SeekEnd)},
+ "args": &tengo.UserFunction{
+ Name: "args",
+ Value: osArgs,
+ }, // args() => array(string)
+ "chdir": &tengo.UserFunction{
+ Name: "chdir",
+ Value: FuncASRE(os.Chdir),
+ }, // chdir(dir string) => error
+ "chmod": osFuncASFmRE("chmod", os.Chmod), // chmod(name string, mode int) => error
+ "chown": &tengo.UserFunction{
+ Name: "chown",
+ Value: FuncASIIRE(os.Chown),
+ }, // chown(name string, uid int, gid int) => error
+ "clearenv": &tengo.UserFunction{
+ Name: "clearenv",
+ Value: FuncAR(os.Clearenv),
+ }, // clearenv()
+ "environ": &tengo.UserFunction{
+ Name: "environ",
+ Value: FuncARSs(os.Environ),
+ }, // environ() => array(string)
+ "exit": &tengo.UserFunction{
+ Name: "exit",
+ Value: FuncAIR(os.Exit),
+ }, // exit(code int)
+ "expand_env": &tengo.UserFunction{
+ Name: "expand_env",
+ Value: osExpandEnv,
+ }, // expand_env(s string) => string
+ "getegid": &tengo.UserFunction{
+ Name: "getegid",
+ Value: FuncARI(os.Getegid),
+ }, // getegid() => int
+ "getenv": &tengo.UserFunction{
+ Name: "getenv",
+ Value: FuncASRS(os.Getenv),
+ }, // getenv(s string) => string
+ "geteuid": &tengo.UserFunction{
+ Name: "geteuid",
+ Value: FuncARI(os.Geteuid),
+ }, // geteuid() => int
+ "getgid": &tengo.UserFunction{
+ Name: "getgid",
+ Value: FuncARI(os.Getgid),
+ }, // getgid() => int
+ "getgroups": &tengo.UserFunction{
+ Name: "getgroups",
+ Value: FuncARIsE(os.Getgroups),
+ }, // getgroups() => array(string)/error
+ "getpagesize": &tengo.UserFunction{
+ Name: "getpagesize",
+ Value: FuncARI(os.Getpagesize),
+ }, // getpagesize() => int
+ "getpid": &tengo.UserFunction{
+ Name: "getpid",
+ Value: FuncARI(os.Getpid),
+ }, // getpid() => int
+ "getppid": &tengo.UserFunction{
+ Name: "getppid",
+ Value: FuncARI(os.Getppid),
+ }, // getppid() => int
+ "getuid": &tengo.UserFunction{
+ Name: "getuid",
+ Value: FuncARI(os.Getuid),
+ }, // getuid() => int
+ "getwd": &tengo.UserFunction{
+ Name: "getwd",
+ Value: FuncARSE(os.Getwd),
+ }, // getwd() => string/error
+ "hostname": &tengo.UserFunction{
+ Name: "hostname",
+ Value: FuncARSE(os.Hostname),
+ }, // hostname() => string/error
+ "lchown": &tengo.UserFunction{
+ Name: "lchown",
+ Value: FuncASIIRE(os.Lchown),
+ }, // lchown(name string, uid int, gid int) => error
+ "link": &tengo.UserFunction{
+ Name: "link",
+ Value: FuncASSRE(os.Link),
+ }, // link(oldname string, newname string) => error
+ "lookup_env": &tengo.UserFunction{
+ Name: "lookup_env",
+ Value: osLookupEnv,
+ }, // lookup_env(key string) => string/false
+ "mkdir": osFuncASFmRE("mkdir", os.Mkdir), // mkdir(name string, perm int) => error
+ "mkdir_all": osFuncASFmRE("mkdir_all", os.MkdirAll), // mkdir_all(name string, perm int) => error
+ "readlink": &tengo.UserFunction{
+ Name: "readlink",
+ Value: FuncASRSE(os.Readlink),
+ }, // readlink(name string) => string/error
+ "remove": &tengo.UserFunction{
+ Name: "remove",
+ Value: FuncASRE(os.Remove),
+ }, // remove(name string) => error
+ "remove_all": &tengo.UserFunction{
+ Name: "remove_all",
+ Value: FuncASRE(os.RemoveAll),
+ }, // remove_all(name string) => error
+ "rename": &tengo.UserFunction{
+ Name: "rename",
+ Value: FuncASSRE(os.Rename),
+ }, // rename(oldpath string, newpath string) => error
+ "setenv": &tengo.UserFunction{
+ Name: "setenv",
+ Value: FuncASSRE(os.Setenv),
+ }, // setenv(key string, value string) => error
+ "symlink": &tengo.UserFunction{
+ Name: "symlink",
+ Value: FuncASSRE(os.Symlink),
+ }, // symlink(oldname string newname string) => error
+ "temp_dir": &tengo.UserFunction{
+ Name: "temp_dir",
+ Value: FuncARS(os.TempDir),
+ }, // temp_dir() => string
+ "truncate": &tengo.UserFunction{
+ Name: "truncate",
+ Value: FuncASI64RE(os.Truncate),
+ }, // truncate(name string, size int) => error
+ "unsetenv": &tengo.UserFunction{
+ Name: "unsetenv",
+ Value: FuncASRE(os.Unsetenv),
+ }, // unsetenv(key string) => error
+ "create": &tengo.UserFunction{
+ Name: "create",
+ Value: osCreate,
+ }, // create(name string) => imap(file)/error
+ "open": &tengo.UserFunction{
+ Name: "open",
+ Value: osOpen,
+ }, // open(name string) => imap(file)/error
+ "open_file": &tengo.UserFunction{
+ Name: "open_file",
+ Value: osOpenFile,
+ }, // open_file(name string, flag int, perm int) => imap(file)/error
+ "find_process": &tengo.UserFunction{
+ Name: "find_process",
+ Value: osFindProcess,
+ }, // find_process(pid int) => imap(process)/error
+ "start_process": &tengo.UserFunction{
+ Name: "start_process",
+ Value: osStartProcess,
+ }, // start_process(name string, argv array(string), dir string, env array(string)) => imap(process)/error
+ "exec_look_path": &tengo.UserFunction{
+ Name: "exec_look_path",
+ Value: FuncASRSE(exec.LookPath),
+ }, // exec_look_path(file) => string/error
+ "exec": &tengo.UserFunction{
+ Name: "exec",
+ Value: osExec,
+ }, // exec(name, args...) => command
+ "stat": &tengo.UserFunction{
+ Name: "stat",
+ Value: osStat,
+ }, // stat(name) => imap(fileinfo)/error
+ "read_file": &tengo.UserFunction{
+ Name: "read_file",
+ Value: osReadFile,
+ }, // readfile(name) => array(byte)/error
+}
+
+func osReadFile(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ fname, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ bytes, err := ioutil.ReadFile(fname)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ if len(bytes) > tengo.MaxBytesLen {
+ return nil, tengo.ErrBytesLimit
+ }
+ return &tengo.Bytes{Value: bytes}, nil
+}
+
+func osStat(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ fname, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ stat, err := os.Stat(fname)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ fstat := &tengo.ImmutableMap{
+ Value: map[string]tengo.Object{
+ "name": &tengo.String{Value: stat.Name()},
+ "mtime": &tengo.Time{Value: stat.ModTime()},
+ "size": &tengo.Int{Value: stat.Size()},
+ "mode": &tengo.Int{Value: int64(stat.Mode())},
+ },
+ }
+ if stat.IsDir() {
+ fstat.Value["directory"] = tengo.TrueValue
+ } else {
+ fstat.Value["directory"] = tengo.FalseValue
+ }
+ return fstat, nil
+}
+
+func osCreate(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, err := os.Create(s1)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return makeOSFile(res), nil
+}
+
+func osOpen(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, err := os.Open(s1)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return makeOSFile(res), nil
+}
+
+func osOpenFile(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 3 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ i3, ok := tengo.ToInt(args[2])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "int(compatible)",
+ Found: args[2].TypeName(),
+ }
+ }
+ res, err := os.OpenFile(s1, i2, os.FileMode(i3))
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return makeOSFile(res), nil
+}
+
+func osArgs(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ arr := &tengo.Array{}
+ for _, osArg := range os.Args {
+ if len(osArg) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ arr.Value = append(arr.Value, &tengo.String{Value: osArg})
+ }
+ return arr, nil
+}
+
+func osFuncASFmRE(
+ name string,
+ fn func(string, os.FileMode) error,
+) *tengo.UserFunction {
+ return &tengo.UserFunction{
+ Name: name,
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ i2, ok := tengo.ToInt64(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ return wrapError(fn(s1, os.FileMode(i2))), nil
+ },
+ }
+}
+
+func osLookupEnv(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, ok := os.LookupEnv(s1)
+ if !ok {
+ return tengo.FalseValue, nil
+ }
+ if len(res) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: res}, nil
+}
+
+func osExpandEnv(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ var vlen int
+ var failed bool
+ s := os.Expand(s1, func(k string) string {
+ if failed {
+ return ""
+ }
+ v := os.Getenv(k)
+
+ // this does not count the other texts that are not being replaced
+ // but the code checks the final length at the end
+ vlen += len(v)
+ if vlen > tengo.MaxStringLen {
+ failed = true
+ return ""
+ }
+ return v
+ })
+ if failed || len(s) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: s}, nil
+}
+
+func osExec(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) == 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ name, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ var execArgs []string
+ for idx, arg := range args[1:] {
+ execArg, ok := tengo.ToString(arg)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: fmt.Sprintf("args[%d]", idx),
+ Expected: "string(compatible)",
+ Found: args[1+idx].TypeName(),
+ }
+ }
+ execArgs = append(execArgs, execArg)
+ }
+ return makeOSExecCommand(exec.Command(name, execArgs...)), nil
+}
+
+func osFindProcess(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ proc, err := os.FindProcess(i1)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return makeOSProcess(proc), nil
+}
+
+func osStartProcess(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 4 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ name, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ var argv []string
+ var err error
+ switch arg1 := args[1].(type) {
+ case *tengo.Array:
+ argv, err = stringArray(arg1.Value, "second")
+ if err != nil {
+ return nil, err
+ }
+ case *tengo.ImmutableArray:
+ argv, err = stringArray(arg1.Value, "second")
+ if err != nil {
+ return nil, err
+ }
+ default:
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "array",
+ Found: arg1.TypeName(),
+ }
+ }
+
+ dir, ok := tengo.ToString(args[2])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "string(compatible)",
+ Found: args[2].TypeName(),
+ }
+ }
+
+ var env []string
+ switch arg3 := args[3].(type) {
+ case *tengo.Array:
+ env, err = stringArray(arg3.Value, "fourth")
+ if err != nil {
+ return nil, err
+ }
+ case *tengo.ImmutableArray:
+ env, err = stringArray(arg3.Value, "fourth")
+ if err != nil {
+ return nil, err
+ }
+ default:
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "fourth",
+ Expected: "array",
+ Found: arg3.TypeName(),
+ }
+ }
+
+ proc, err := os.StartProcess(name, argv, &os.ProcAttr{
+ Dir: dir,
+ Env: env,
+ })
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return makeOSProcess(proc), nil
+}
+
+func stringArray(arr []tengo.Object, argName string) ([]string, error) {
+ var sarr []string
+ for idx, elem := range arr {
+ str, ok := elem.(*tengo.String)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: fmt.Sprintf("%s[%d]", argName, idx),
+ Expected: "string",
+ Found: elem.TypeName(),
+ }
+ }
+ sarr = append(sarr, str.Value)
+ }
+ return sarr, nil
+}