Skip to content

Commit

Permalink
Added named pipe option for stdin
Browse files Browse the repository at this point in the history
  • Loading branch information
itzg committed Oct 9, 2021
1 parent 111dd1a commit 16f5271
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 28 deletions.
19 changes: 19 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.194.3/containers/go/.devcontainer/base.Dockerfile

# [Choice] Go version: 1, 1.16, 1.17
ARG VARIANT="1.17"
FROM mcr.microsoft.com/vscode/devcontainers/go:0-${VARIANT}

# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
ARG NODE_VERSION="none"
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi

# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>

# [Optional] Uncomment the next line to use go get to install anything else you need
# RUN go get -x <your-dependency-or-tool>

# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
37 changes: 37 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.194.3/containers/go
{
"name": "Go",
"build": {
"dockerfile": "Dockerfile",
"args": {
// Update the VARIANT arg to pick a version of Go: 1, 1.16, 1.17
"VARIANT": "1.17",
// Options
"NODE_VERSION": "lts/*"
}
},
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],

// Set *default* container specific settings.json values on container create.
"settings": {
"go.toolsManagement.checkForUpdates": "local",
"go.useLanguageServer": true,
"go.gopath": "/go",
"go.goroot": "/usr/local/go"
},

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"golang.Go"
],

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "go version",

// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"
}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
/mc-server-runner.exe
/*.iml
/.idea/
/tmp/
/tmp/
/.vscode/
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ module github.com/itzg/mc-server-runner
go 1.13

require (
github.com/itzg/go-flagsfiller v1.4.2
github.com/itzg/go-flagsfiller v1.6.0
github.com/itzg/zapconfigs v0.1.0
github.com/karrick/godirwalk v1.15.5
github.com/stretchr/testify v1.4.0
go.uber.org/zap v1.13.0
)
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 h1:VHgatEHNcBFEB7inlalqfNqw65aNkM1lGX2yt3NmbS8=
github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
github.com/itzg/go-flagsfiller v1.4.2 h1:aQRyQ9/ps111FZYGhzxgKYiOewE7zbAks7rxF49Qlm8=
github.com/itzg/go-flagsfiller v1.4.2/go.mod h1:mfQgTahSs4OHn8PYev2Wwi1LJXUiYiGuZVCpBLxzbYs=
github.com/itzg/go-flagsfiller v1.6.0 h1:ovVbK2IM18AY5kgRZ/cb7yQrdSgyXmlaTUyDsx6k/Dk=
github.com/itzg/go-flagsfiller v1.6.0/go.mod h1:mfQgTahSs4OHn8PYev2Wwi1LJXUiYiGuZVCpBLxzbYs=
github.com/itzg/zapconfigs v0.1.0 h1:Gokocm8VaTNnZjvIiVA5NEhzZ1v7lEyXY/AbeBmq6YQ=
github.com/itzg/zapconfigs v0.1.0/go.mod h1:y4dArgRUOFbGRkUNJ8XSSw98FGn03wtkvMPy+OSA5Rc=
github.com/karrick/godirwalk v1.15.5 h1:ErdAEFW/cKxQ5+9Gm/hopxB8ki21/di+vyNb9mHnHrA=
github.com/karrick/godirwalk v1.15.5/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
Expand Down
32 changes: 12 additions & 20 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"context"
"flag"
"fmt"
"io"
Expand All @@ -25,6 +26,7 @@ type Args struct {
StopServerAnnounceDelay time.Duration `default:"0s" usage:"Amount of time in Golang duration to wait after announcing server shutdown"`
DetachStdin bool `usage:"Don't forward stdin and allow process to be put in background"`
Shell string `usage:"When set, pass the arguments to this shell"`
NamedPipe string `usage:"Optional path to create and read a named pipe for console input"`
}

func main() {
Expand Down Expand Up @@ -103,6 +105,15 @@ func main() {
}()
}

ctx, cancel := context.WithCancel(context.Background())

if args.NamedPipe != "" {
err2 := handleNamedPipe(ctx, args.NamedPipe, stdin)
if err2 != nil {
logger.Fatal("Failed to setup named pipe", zap.Error(err2))
}
}

cmdExitChan := make(chan int, 1)

go func() {
Expand Down Expand Up @@ -154,8 +165,8 @@ func main() {
}

case exitCode := <-cmdExitChan:
cancel()
logger.Info("Done")
defer logger.Sync()
os.Exit(exitCode)
}
}
Expand Down Expand Up @@ -216,22 +227,3 @@ func stopViaConsole(logger *zap.Logger, stdin io.Writer) {
logger.Error("Failed to write stop command to server console", zap.Error(err))
}
}

func fillServerJar(args []string, serverJar string) ([]string, error) {
result := make([]string, len(args))
found := false
for i, arg := range args {
if arg == "_SERVERJAR_" {
found = true
result[i] = serverJar
} else {
result[i] = arg
}
}

if !found {
return nil, fmt.Errorf("unable to locate _SERVERJAR_ placeholder in args")
} else {
return result, nil
}
}
13 changes: 13 additions & 0 deletions named_pipe.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:build !linux

package main

import (
"go.uber.org/zap"
"io"
)

func handleNamedPipe(ctx context.Context, path string, stdin io.Writer) error {
// does nothing on non-linux
return nil
}
47 changes: 47 additions & 0 deletions named_pipe_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package main

import (
"context"
"fmt"
"io"
"os"
"syscall"
)

func handleNamedPipe(ctx context.Context, path string, stdin io.Writer) error {
fi, statErr := os.Stat(path)
if statErr != nil {
if os.IsNotExist(statErr) {
mkErr := syscall.Mkfifo(path, 0666)
if mkErr != nil {
return fmt.Errorf("failed to create named pipe: %w", mkErr)
}
} else {
return fmt.Errorf("failed to stat named pipe: %w", statErr)
}
} else {
// already exists...named pipe?
if fi.Mode().Type()&os.ModeNamedPipe == 0 {
return fmt.Errorf("existing path '%s' is not a named pipe", path)
}
}

f, openErr := os.Open(path)
if openErr != nil {
return fmt.Errorf("failed to open named pipe: %w", openErr)
}

go func() {
_, _ = io.Copy(stdin, f)
// copy finished due to file closure (or error)
os.Remove(path)
}()

go func() {
<-ctx.Done()
// kick the copy operation above
f.Close()
}()

return nil
}

0 comments on commit 16f5271

Please sign in to comment.