diff options
| -rw-r--r-- | contrib/cgi/cgi.go | 22 | ||||
| -rw-r--r-- | contrib/cgi/cgi_test.go | 2 | ||||
| -rw-r--r-- | contrib/cgi/gemini.go | 14 | ||||
| -rw-r--r-- | contrib/cgi/gopher.go | 18 | ||||
| -rw-r--r-- | examples/cgi/main.go | 2 | ||||
| -rw-r--r-- | examples/gopher_fileserver/main.go | 2 | 
6 files changed, 35 insertions, 25 deletions
| diff --git a/contrib/cgi/cgi.go b/contrib/cgi/cgi.go index 48af04a..b7dd14a 100644 --- a/contrib/cgi/cgi.go +++ b/contrib/cgi/cgi.go @@ -11,6 +11,7 @@ import (  	"net"  	"os"  	"os/exec" +	"path/filepath"  	"strings"  	sr "tildegit.org/tjp/sliderule" @@ -88,16 +89,9 @@ func RunCGI(  	request *sr.Request,  	executable string,  	pathInfo string, +	workdir string,  	stderr io.Writer,  ) (*bytes.Buffer, int, error) { -	pathSegments := strings.Split(executable, "/") - -	dirPath := "." -	if len(pathSegments) > 1 { -		dirPath = strings.Join(pathSegments[:len(pathSegments)-1], "/") -	} -	basename := pathSegments[len(pathSegments)-1] -  	infoLen := len(pathInfo)  	if pathInfo == "/" {  		infoLen = 0 @@ -106,9 +100,14 @@ func RunCGI(  	scriptName := request.Path[:len(request.Path)-infoLen]  	scriptName = strings.TrimSuffix(scriptName, "/") -	cmd := exec.CommandContext(ctx, "./"+basename) +	execpath, err := filepath.Abs(executable) +	if err != nil { +		return nil, 0, err +	} + +	cmd := exec.CommandContext(ctx, execpath)  	cmd.Env = prepareCGIEnv(ctx, request, scriptName, pathInfo) -	cmd.Dir = dirPath +	cmd.Dir = workdir  	if body, ok := request.Meta.(io.Reader); ok {  		cmd.Stdin = body @@ -117,8 +116,7 @@ func RunCGI(  	cmd.Stdout = responseBuffer  	cmd.Stderr = stderr -	err := cmd.Run() -	if err != nil { +	if err := cmd.Run(); err != nil {  		var exErr *exec.ExitError  		if errors.As(err, &exErr) {  			return responseBuffer, exErr.ExitCode(), nil diff --git a/contrib/cgi/cgi_test.go b/contrib/cgi/cgi_test.go index 5469fc8..e5fb306 100644 --- a/contrib/cgi/cgi_test.go +++ b/contrib/cgi/cgi_test.go @@ -21,7 +21,7 @@ func TestCGIDirectory(t *testing.T) {  	tlsconf, err := gemini.FileTLS("testdata/server.crt", "testdata/server.key")  	require.Nil(t, err) -	handler := cgi.GeminiCGIDirectory("./testdata", "/cgi-bin") +	handler := cgi.GeminiCGIDirectory("./testdata", "/cgi-bin", "")  	server, err := gemini.NewServer(context.Background(), "localhost", "tcp", "127.0.0.1:0", handler, nil, tlsconf)  	require.Nil(t, err) diff --git a/contrib/cgi/gemini.go b/contrib/cgi/gemini.go index 3ad407d..0aa3044 100644 --- a/contrib/cgi/gemini.go +++ b/contrib/cgi/gemini.go @@ -4,6 +4,7 @@ import (  	"bytes"  	"context"  	"fmt" +	"path/filepath"  	"strings"  	sr "tildegit.org/tjp/sliderule" @@ -17,23 +18,28 @@ import (  // a request for /foo/bar/baz can also run an executable found at /foo or  /foo/bar. In  // such a case the PATH_INFO environment variable will include the remaining portion of  // the URI path. -func GeminiCGIDirectory(fsroot, urlroot string) sr.Handler { +func GeminiCGIDirectory(fsroot, urlroot, cmd string) sr.Handler {  	fsroot = strings.TrimRight(fsroot, "/")  	return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response {  		if !strings.HasPrefix(request.Path, urlroot) {  			return nil  		} -		filepath, pathinfo, err := ResolveCGI(request.Path[len(urlroot):], fsroot) +		execpath, pathinfo, err := ResolveCGI(request.Path[len(urlroot):], fsroot)  		if err != nil {  			return gemini.Failure(err)  		} -		if filepath == "" { +		if execpath == "" {  			return nil  		} +		workdir := filepath.Dir(execpath) + +		if cmd != "" { +			execpath = cmd +		}  		stderr := &bytes.Buffer{} -		stdout, exitCode, err := RunCGI(ctx, request, filepath, pathinfo, stderr) +		stdout, exitCode, err := RunCGI(ctx, request, execpath, pathinfo, workdir, stderr)  		if err != nil {  			return gemini.Failure(err)  		} diff --git a/contrib/cgi/gopher.go b/contrib/cgi/gopher.go index bb3e73e..7067a6d 100644 --- a/contrib/cgi/gopher.go +++ b/contrib/cgi/gopher.go @@ -21,7 +21,7 @@ import (  // a request for /foo/bar/baz can also run an executable found at /foo or  /foo/bar. In  // such a case the PATH_INFO environment variable will include the remaining portion of  // the URI path. -func GopherCGIDirectory(fsroot, urlroot string, settings *gophermap.FileSystemSettings) sr.Handler { +func GopherCGIDirectory(fsroot, urlroot, cmd string, settings *gophermap.FileSystemSettings) sr.Handler {  	if settings == nil || !settings.Exec {  		return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response { return nil })  	} @@ -41,12 +41,12 @@ func GopherCGIDirectory(fsroot, urlroot string, settings *gophermap.FileSystemSe  			return nil  		} -		return runGopherCGI(ctx, request, fullpath, pathinfo, *settings) +		return runGopherCGI(ctx, request, fullpath, pathinfo, cmd, *settings)  	})  }  // ExecGopherMaps runs any gophermaps -func ExecGopherMaps(fsroot, urlroot string, settings *gophermap.FileSystemSettings) sr.Handler { +func ExecGopherMaps(fsroot, urlroot, cmd string, settings *gophermap.FileSystemSettings) sr.Handler {  	if settings == nil || !settings.Exec {  		return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response { return nil })  	} @@ -85,7 +85,7 @@ func ExecGopherMaps(fsroot, urlroot string, settings *gophermap.FileSystemSettin  				if !m.IsRegular() || m&5 != 5 {  					continue  				} -				return runGopherCGI(ctx, request, fpath, "/", *settings) +				return runGopherCGI(ctx, request, fpath, "/", cmd, *settings)  			}  			return nil @@ -96,7 +96,7 @@ func ExecGopherMaps(fsroot, urlroot string, settings *gophermap.FileSystemSettin  			return nil  		} -		return runGopherCGI(ctx, request, fullpath, "/", *settings) +		return runGopherCGI(ctx, request, fullpath, "/", cmd, *settings)  	})  } @@ -105,10 +105,16 @@ func runGopherCGI(  	request *sr.Request,  	fullpath string,  	pathinfo string, +	cmd string,  	settings gophermap.FileSystemSettings,  ) *sr.Response { +	workdir := filepath.Dir(fullpath) +	if cmd != "" { +		fullpath = cmd +	} +  	stderr := &bytes.Buffer{} -	stdout, exitCode, err := RunCGI(ctx, request, fullpath, pathinfo, stderr) +	stdout, exitCode, err := RunCGI(ctx, request, fullpath, pathinfo, workdir, stderr)  	if err != nil {  		return gopher.Error(err).Response()  	} diff --git a/examples/cgi/main.go b/examples/cgi/main.go index 587c874..3443761 100644 --- a/examples/cgi/main.go +++ b/examples/cgi/main.go @@ -24,7 +24,7 @@ func main() {  	}  	// make use of a CGI request handler -	cgiHandler := cgi.GeminiCGIDirectory("./cgi-bin", "/cgi-bin") +	cgiHandler := cgi.GeminiCGIDirectory("./cgi-bin", "/cgi-bin", "")  	baseLog := logging.Base() diff --git a/examples/gopher_fileserver/main.go b/examples/gopher_fileserver/main.go index 9b8c33f..76718dd 100644 --- a/examples/gopher_fileserver/main.go +++ b/examples/gopher_fileserver/main.go @@ -16,7 +16,7 @@ func main() {  	handler := sr.FallthroughHandler(  		fs.GopherDirectoryDefault(".", "", nil),  		fs.GopherDirectoryListing(".", "", nil), -		cgi.GopherCGIDirectory("/cgi-bin", "./cgi-bin", nil), +		cgi.GopherCGIDirectory("/cgi-bin", "./cgi-bin", "", nil),  		fs.GopherFileHandler(".", "", nil),  	) | 
