From 08bb7073cdab954c7176e1b91118483e1b9b315b Mon Sep 17 00:00:00 2001 From: Aidan Date: Wed, 22 Jul 2020 00:22:39 -0700 Subject: [PATCH] incomplete work: big call lib refactor --- cmd/shs.go | 4 + cmd/test_shell.go | 36 +++++++ go.mod | 1 + go.sum | 2 + resources/icon/icon.kra | Bin 0 -> 49587 bytes stdlib/{call.go => shell.go} | 177 ++++++++++++++++++++++++----------- 6 files changed, 163 insertions(+), 57 deletions(-) create mode 100644 cmd/test_shell.go create mode 100644 resources/icon/icon.kra rename stdlib/{call.go => shell.go} (76%) diff --git a/cmd/shs.go b/cmd/shs.go index 3379c7c..cd2087a 100644 --- a/cmd/shs.go +++ b/cmd/shs.go @@ -25,6 +25,7 @@ import ( "gitlab.com/whom/shs/ast" "gitlab.com/whom/shs/log" "gitlab.com/whom/shs/util" + "gitlab.com/whom/shs/stdlib" "gitlab.com/whom/shs/config" ) @@ -124,6 +125,9 @@ func main() { defer histFile.Close() } + stdlib.InitShellFeatures() + defer stdlib.TeardownShell() + for { setLogLvl(vars) var prePrompt string diff --git a/cmd/test_shell.go b/cmd/test_shell.go new file mode 100644 index 0000000..f783dc7 --- /dev/null +++ b/cmd/test_shell.go @@ -0,0 +1,36 @@ +/* SHS: Syntactically Homogeneous Shell + * Copyright (C) 2019 Aidan Hahn + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package main + +import ( + "fmt" + "time" + "gitlab.com/whom/shs/log" + "gitlab.com/whom/shs/stdlib" +) + +func main() { + log.SetLogLvl(3) + stdlib.InitShellFeatures() + stdlib.LaunchProcess("/usr/bin/vim", []string{"test.txt"}, false) + + fmt.Println("process started, now sleeping for 10 sec") + time.Sleep(10 * time.Second) + + stdlib.TeardownShell() +} diff --git a/go.mod b/go.mod index 2b85407..63a9008 100644 --- a/go.mod +++ b/go.mod @@ -5,4 +5,5 @@ go 1.14 require ( github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/peterh/liner v1.2.0 // indirect + golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666 ) diff --git a/go.sum b/go.sum index 285b298..ee825b8 100644 --- a/go.sum +++ b/go.sum @@ -4,3 +4,5 @@ github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8Bz github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/peterh/liner v1.2.0 h1:w/UPXyl5GfahFxcTOz2j9wCIHNI+pUPr2laqpojKNCg= github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666 h1:gVCS+QOncANNPlmlO1AhlU3oxs4V9z+gTtPwIk3p2N8= +golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/resources/icon/icon.kra b/resources/icon/icon.kra new file mode 100644 index 0000000000000000000000000000000000000000..3b77b37df949706e95d56b997f44346df761c553 GIT binary patch literal 49587 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 literal 0 HcmV?d00001 diff --git a/stdlib/call.go b/stdlib/shell.go similarity index 76% rename from stdlib/call.go rename to stdlib/shell.go index 99e0647..83f7c13 100644 --- a/stdlib/call.go +++ b/stdlib/shell.go @@ -19,30 +19,135 @@ package stdlib import ( "os" - "fmt" - "bytes" - "strconv" + "errors" "os/exec" + "context" "syscall" - "os/signal" - "gitlab.com/whom/shs/ast" + "golang.org/x/sys/unix" "gitlab.com/whom/shs/log" ) -var bgProcs = make([]*exec.Cmd, 0) -var sigs = []os.Signal{ - os.Interrupt, - syscall.SIGTERM, - syscall.SIGTSTP, - syscall.SIGTTIN, - syscall.SIGTTOU, - syscall.SIGCONT, +func tcsetpgrp(fd int, pgrp int) error { + return unix.IoctlSetPointerInt(fd, unix.TIOCSPGRP, pgrp) +} + +var sigChan chan os.Signal +var waitChan chan error + +/* mapping of pid to Proc + */ +var JobMap = map[int]Proc{} + +/* id of shell process group + */ +var pgid int + +/* Holds an os/exec Cmd object and its context cancel function + */ +type Proc struct { + Ctl *exec.Cmd + Cancel context.CancelFunc +} + +var catchMe = []os.Signal{ + syscall.SIGINT, } /* Exit code of last run process */ var LastExitCode int +// Job control handlers +func signalHandler() { + for { + sig := <- sigChan + switch sig { + case syscall.SIGINT: + log.Log(log.DEBUG, + "caught SIGINT!", + "jobctl") + } + } +} + +func waitHandler() { + for { + w := <- waitChan + exit := 0 + if w != nil { + log.Log(log.ERR, + "Child returned error: " + w.Error(), + "jobctl") + + // something outrageous + exit = -1024 + var e *exec.ExitError + if errors.As(w, &e) { + exit = e.Pid() + } + + LastExitCode = exit + } + } +} + +/* Sets pgid + * Installs a sigchld handler + * returns true if success, false on error + */ +func InitShellFeatures() bool { + // TODO: adjust, make configurable, i dunno + sigChan = make(chan os.Signal, 5) + waitChan = make(chan error, 5) + + go signalHandler() + go waitHandler() + + pid := os.Getpid() + pgid = syscall.Getpgrp() + if pid != pgid { + syscall.Setpgid(0, 0) + } + tcsetpgrp(0, pid) + + return true +} + +/* Tears down session + */ +func TeardownShell() { + close(sigChan) + close(waitChan) + // TODO: Exit all processes in the JobMap +} + +/* Makes and stores a new process in the job control + * uses os/exec Cmd object. sets SysProcAttr.Foreground + * calls Cmd.Start() + */ +func LaunchProcess(path string, args []string, background bool) { + c, cancel := context.WithCancel(context.Background()) + cmd := exec.CommandContext(c, path, args...) + cmd.SysProcAttr = &syscall.SysProcAttr{Foreground: !background, Pgid: pgid} + + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + cmd.Start() + pid := cmd.Process.Pid + + // TODO: check for clobber? + JobMap[pid] = Proc{ Ctl: cmd, Cancel: cancel } + go func(){ + waitChan <- cmd.Wait() + }() + + if background { + cmd.Process.Signal(syscall.SIGTSTP) + } +} + /* Takes n arguments (list of tokens generated by lexing a shell command) * Evaluates arguments, but does not err on undefined symbols (note the last arg to Eval(...)) * Executes shell command and returns nil @@ -76,35 +181,7 @@ func Call(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { args = append(args, i.Value()) } - var cmd *exec.Cmd - if len(args) > 0 { - cmd = exec.Command(path, args...) - } else { - cmd = exec.Command(path) - } - cmd.Env = os.Environ() - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - signalChan := make(chan os.Signal, 2) - signal.Notify(signalChan, sigs...) - go func() { - sig := <-signalChan - cmd.Process.Signal(sig) - }() - - err = cmd.Run() - close(signalChan) - signal.Reset(sigs...) - if err != nil { - if exitError, ok := err.(*exec.ExitError); ok { - LastExitCode = exitError.ExitCode() - } else { - log.Log(log.ERR, "Execution step returned unparsable error: " + err.Error(), "call") - } - } - + LaunchProcess(path, args, false) return nil } @@ -139,21 +216,7 @@ func Bgcall(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { args = append(args, i.Value()) } - var cmd *exec.Cmd - if len(args) > 0 { - cmd = exec.Command(path, args...) - } else { - cmd = exec.Command(path) - } - cmd.Stderr = os.Stderr - - bgProcs = append(bgProcs, cmd) - cmd.Stdout = os.Stdout - cmd.Stdin = os.Stdin - cmd.Stderr = os.Stderr - - cmd.Start() - cmd.Process.Signal(syscall.SIGTSTP) + LaunchProcess(path, args, true) return nil }