package stdlib import ( "io" "os" "os/exec" "github.com/d5/tengo/objects" ) var osModule = map[string]objects.Object{ "o_rdonly": &objects.Int{Value: int64(os.O_RDONLY)}, "o_wronly": &objects.Int{Value: int64(os.O_WRONLY)}, "o_rdwr": &objects.Int{Value: int64(os.O_RDWR)}, "o_append": &objects.Int{Value: int64(os.O_APPEND)}, "o_create": &objects.Int{Value: int64(os.O_CREATE)}, "o_excl": &objects.Int{Value: int64(os.O_EXCL)}, "o_sync": &objects.Int{Value: int64(os.O_SYNC)}, "o_trunc": &objects.Int{Value: int64(os.O_TRUNC)}, "mode_dir": &objects.Int{Value: int64(os.ModeDir)}, "mode_append": &objects.Int{Value: int64(os.ModeAppend)}, "mode_exclusive": &objects.Int{Value: int64(os.ModeExclusive)}, "mode_temporary": &objects.Int{Value: int64(os.ModeTemporary)}, "mode_symlink": &objects.Int{Value: int64(os.ModeSymlink)}, "mode_device": &objects.Int{Value: int64(os.ModeDevice)}, "mode_named_pipe": &objects.Int{Value: int64(os.ModeNamedPipe)}, "mode_socket": &objects.Int{Value: int64(os.ModeSocket)}, "mode_setuid": &objects.Int{Value: int64(os.ModeSetuid)}, "mode_setgui": &objects.Int{Value: int64(os.ModeSetgid)}, "mode_char_device": &objects.Int{Value: int64(os.ModeCharDevice)}, "mode_sticky": &objects.Int{Value: int64(os.ModeSticky)}, "mode_type": &objects.Int{Value: int64(os.ModeType)}, "mode_perm": &objects.Int{Value: int64(os.ModePerm)}, "path_separator": &objects.Char{Value: os.PathSeparator}, "path_list_separator": &objects.Char{Value: os.PathListSeparator}, "dev_null": &objects.String{Value: os.DevNull}, "seek_set": &objects.Int{Value: int64(io.SeekStart)}, "seek_cur": &objects.Int{Value: int64(io.SeekCurrent)}, "seek_end": &objects.Int{Value: int64(io.SeekEnd)}, "args": &objects.UserFunction{Value: osArgs}, // args() => array(string) "chdir": FuncASRE(os.Chdir), // chdir(dir string) => error "chmod": osFuncASFmRE(os.Chmod), // chmod(name string, mode int) => error "chown": FuncASIIRE(os.Chown), // chown(name string, uid int, gid int) => error "clearenv": FuncAR(os.Clearenv), // clearenv() "environ": FuncARSs(os.Environ), // environ() => array(string) "exit": FuncAIR(os.Exit), // exit(code int) "expand_env": FuncASRS(os.ExpandEnv), // expand_env(s string) => string "getegid": FuncARI(os.Getegid), // getegid() => int "getenv": FuncASRS(os.Getenv), // getenv(s string) => string "geteuid": FuncARI(os.Geteuid), // geteuid() => int "getgid": FuncARI(os.Getgid), // getgid() => int "getgroups": FuncARIsE(os.Getgroups), // getgroups() => array(string)/error "getpagesize": FuncARI(os.Getpagesize), // getpagesize() => int "getpid": FuncARI(os.Getpid), // getpid() => int "getppid": FuncARI(os.Getppid), // getppid() => int "getuid": FuncARI(os.Getuid), // getuid() => int "getwd": FuncARSE(os.Getwd), // getwd() => string/error "hostname": FuncARSE(os.Hostname), // hostname() => string/error "lchown": FuncASIIRE(os.Lchown), // lchown(name string, uid int, gid int) => error "link": FuncASSRE(os.Link), // link(oldname string, newname string) => error "lookup_env": &objects.UserFunction{Value: osLookupEnv}, // lookup_env(key string) => string/false "mkdir": osFuncASFmRE(os.Mkdir), // mkdir(name string, perm int) => error "mkdir_all": osFuncASFmRE(os.MkdirAll), // mkdir_all(name string, perm int) => error "readlink": FuncASRSE(os.Readlink), // readlink(name string) => string/error "remove": FuncASRE(os.Remove), // remove(name string) => error "remove_all": FuncASRE(os.RemoveAll), // remove_all(name string) => error "rename": FuncASSRE(os.Rename), // rename(oldpath string, newpath string) => error "setenv": FuncASSRE(os.Setenv), // setenv(key string, value string) => error "symlink": FuncASSRE(os.Symlink), // symlink(oldname string newname string) => error "temp_dir": FuncARS(os.TempDir), // temp_dir() => string "truncate": FuncASI64RE(os.Truncate), // truncate(name string, size int) => error "unsetenv": FuncASRE(os.Unsetenv), // unsetenv(key string) => error "create": &objects.UserFunction{Value: osCreate}, // create(name string) => imap(file)/error "open": &objects.UserFunction{Value: osOpen}, // open(name string) => imap(file)/error "open_file": &objects.UserFunction{Value: osOpenFile}, // open_file(name string, flag int, perm int) => imap(file)/error "find_process": &objects.UserFunction{Value: osFindProcess}, // find_process(pid int) => imap(process)/error "start_process": &objects.UserFunction{Value: osStartProcess}, // start_process(name string, argv array(string), dir string, env array(string)) => imap(process)/error "exec_look_path": FuncASRSE(exec.LookPath), // exec_look_path(file) => string/error "exec": &objects.UserFunction{Value: osExec}, // exec(name, args...) => command } func osCreate(args ...objects.Object) (objects.Object, error) { if len(args) != 1 { return nil, objects.ErrWrongNumArguments } s1, ok := objects.ToString(args[0]) if !ok { return nil, objects.ErrInvalidTypeConversion } res, err := os.Create(s1) if err != nil { return wrapError(err), nil } return makeOSFile(res), nil } func osOpen(args ...objects.Object) (objects.Object, error) { if len(args) != 1 { return nil, objects.ErrWrongNumArguments } s1, ok := objects.ToString(args[0]) if !ok { return nil, objects.ErrInvalidTypeConversion } res, err := os.Open(s1) if err != nil { return wrapError(err), nil } return makeOSFile(res), nil } func osOpenFile(args ...objects.Object) (objects.Object, error) { if len(args) != 3 { return nil, objects.ErrWrongNumArguments } s1, ok := objects.ToString(args[0]) if !ok { return nil, objects.ErrInvalidTypeConversion } i2, ok := objects.ToInt(args[1]) if !ok { return nil, objects.ErrInvalidTypeConversion } i3, ok := objects.ToInt(args[2]) if !ok { return nil, objects.ErrInvalidTypeConversion } res, err := os.OpenFile(s1, i2, os.FileMode(i3)) if err != nil { return wrapError(err), nil } return makeOSFile(res), nil } func osArgs(args ...objects.Object) (objects.Object, error) { if len(args) != 0 { return nil, objects.ErrWrongNumArguments } arr := &objects.Array{} for _, osArg := range os.Args { arr.Value = append(arr.Value, &objects.String{Value: osArg}) } return arr, nil } func osFuncASFmRE(fn func(string, os.FileMode) error) *objects.UserFunction { return &objects.UserFunction{ Value: func(args ...objects.Object) (objects.Object, error) { if len(args) != 2 { return nil, objects.ErrWrongNumArguments } s1, ok := objects.ToString(args[0]) if !ok { return nil, objects.ErrInvalidTypeConversion } i2, ok := objects.ToInt64(args[1]) if !ok { return nil, objects.ErrInvalidTypeConversion } return wrapError(fn(s1, os.FileMode(i2))), nil }, } } func osLookupEnv(args ...objects.Object) (objects.Object, error) { if len(args) != 1 { return nil, objects.ErrWrongNumArguments } s1, ok := objects.ToString(args[0]) if !ok { return nil, objects.ErrInvalidTypeConversion } res, ok := os.LookupEnv(s1) if !ok { return objects.FalseValue, nil } return &objects.String{Value: res}, nil } func osExec(args ...objects.Object) (objects.Object, error) { if len(args) == 0 { return nil, objects.ErrWrongNumArguments } name, ok := objects.ToString(args[0]) if !ok { return nil, objects.ErrInvalidTypeConversion } var execArgs []string for _, arg := range args[1:] { execArg, ok := objects.ToString(arg) if !ok { return nil, objects.ErrInvalidTypeConversion } execArgs = append(execArgs, execArg) } return makeOSExecCommand(exec.Command(name, execArgs...)), nil } func osFindProcess(args ...objects.Object) (objects.Object, error) { if len(args) != 1 { return nil, objects.ErrWrongNumArguments } i1, ok := objects.ToInt(args[0]) if !ok { return nil, objects.ErrInvalidTypeConversion } proc, err := os.FindProcess(i1) if err != nil { return wrapError(err), nil } return makeOSProcess(proc), nil } func osStartProcess(args ...objects.Object) (objects.Object, error) { if len(args) != 4 { return nil, objects.ErrWrongNumArguments } name, ok := objects.ToString(args[0]) if !ok { return nil, objects.ErrInvalidTypeConversion } argv, err := stringArray(args[1]) if err != nil { return nil, err } dir, ok := objects.ToString(args[2]) if !ok { return nil, objects.ErrInvalidTypeConversion } env, err := stringArray(args[3]) if err != nil { return nil, err } 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(o objects.Object) ([]string, error) { arr, ok := o.(*objects.Array) if !ok { return nil, objects.ErrInvalidTypeConversion } var sarr []string for _, elem := range arr.Value { str, ok := elem.(*objects.String) if !ok { return nil, objects.ErrInvalidTypeConversion } sarr = append(sarr, str.Value) } return sarr, nil }