Skip to content

Commit

Permalink
Merge pull request joewalnes#56 from asergeyev/pathchecks
Browse files Browse the repository at this point in the history
Changing how websocketd works with arguments that point it to directories.
  • Loading branch information
joewalnes committed Mar 30, 2014
2 parents c091e95 + a67a4b8 commit 596ca45
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 53 deletions.
100 changes: 66 additions & 34 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
Expand Down Expand Up @@ -49,10 +50,13 @@ var defaultPassEnv = map[string]string{
"windows": "SystemRoot,COMSPEC,PATHEXT,WINDIR",
}

func parseCommandLine() Config {
func parseCommandLine() *Config {
var mainConfig Config
var config libwebsocketd.Config

flag.Usage = func() {}
flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ContinueOnError)

// If adding new command line options, also update the help text in help.go.
// The flag library's auto-generate help message isn't pretty enough.

Expand All @@ -78,7 +82,15 @@ func parseCommandLine() Config {
devConsoleFlag := flag.Bool("devconsole", false, "Enable development console (cannot be used in conjunction with --staticdir)")
passEnvFlag := flag.String("passenv", defaultPassEnv[runtime.GOOS], "List of envvars to pass to subprocesses (others will be cleaned out)")

flag.Parse()
err := flag.CommandLine.Parse(os.Args[1:])
if err != nil {
if err == flag.ErrHelp {
PrintHelp()
} else {
ShortHelp()
}
os.Exit(2)
}

port := *portFlag
if port == 0 {
Expand All @@ -99,28 +111,10 @@ func parseCommandLine() Config {
}
mainConfig.MaxForks = *maxForksFlag
mainConfig.BasePath = *basePathFlag

switch *logLevelFlag {
case "debug":
mainConfig.LogLevel = libwebsocketd.LogDebug
break
case "trace":
mainConfig.LogLevel = libwebsocketd.LogTrace
break
case "access":
mainConfig.LogLevel = libwebsocketd.LogAccess
break
case "info":
mainConfig.LogLevel = libwebsocketd.LogInfo
break
case "error":
mainConfig.LogLevel = libwebsocketd.LogError
break
case "fatal":
mainConfig.LogLevel = libwebsocketd.LogFatal
break
default:
PrintHelp()
mainConfig.LogLevel = libwebsocketd.LevelFromString(*logLevelFlag)
if mainConfig.LogLevel == libwebsocketd.LogUnknown {
fmt.Printf("Incorrect loglevel flag '%s'. Use --help to see allowed values.\n", *logLevelFlag)
ShortHelp()
os.Exit(1)
}

Expand All @@ -134,17 +128,18 @@ func parseCommandLine() Config {
config.ServerSoftware = fmt.Sprintf("websocketd/%s", Version())

if len(os.Args) == 1 {
PrintHelp()
fmt.Printf("Command line arguments are missing.\n")
ShortHelp()
os.Exit(1)
}

if *versionFlag {
fmt.Printf("%s %s\n", filepath.Base(os.Args[0]), Version())
fmt.Printf("%s %s\n", HelpProcessName(), Version())
os.Exit(2)
}

if *licenseFlag {
fmt.Printf("%s %s\n", filepath.Base(os.Args[0]), Version())
fmt.Printf("%s %s\n", HelpProcessName(), Version())
fmt.Printf("%s\n", libwebsocketd.License)
os.Exit(2)
}
Expand Down Expand Up @@ -184,30 +179,67 @@ func parseCommandLine() Config {
args := flag.Args()
if len(args) < 1 && config.ScriptDir == "" && config.StaticDir == "" && config.CgiDir == "" {
fmt.Fprintf(os.Stderr, "Please specify COMMAND or provide --dir, --staticdir or --cgidir argument.\n")
ShortHelp()
os.Exit(1)
}

if len(args) > 0 {
if config.ScriptDir != "" {
fmt.Fprintf(os.Stderr, "Ambiguous. Provided COMMAND and --dir argument. Please only specify just one.\n")
ShortHelp()
os.Exit(1)
}
if path, err := exec.LookPath(args[0]); err == nil {
config.CommandName = path // This can be command in PATH that we are able to execute
config.CommandArgs = flag.Args()[1:]
config.UsingScriptDir = false
} else {
fmt.Fprintf(os.Stderr, "Unable to locate specified COMMAND '%s' in OS path.\n", args[0])
ShortHelp()
os.Exit(1)
}
config.CommandName = args[0]
config.CommandArgs = flag.Args()[1:]
config.UsingScriptDir = false
}

if len(config.ScriptDir) > 0 {
if config.ScriptDir != "" {
scriptDir, err := filepath.Abs(config.ScriptDir)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not resolve absolute path to dir '%s'.\n", config.ScriptDir)
ShortHelp()
os.Exit(1)
}
inf, err := os.Stat(scriptDir)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not find your script dir '%s'.\n", config.ScriptDir)
ShortHelp()
os.Exit(1)
}
if !inf.IsDir() {
fmt.Fprintf(os.Stderr, "Did you mean to specify COMMAND instead of --dir '%s'?\n", config.ScriptDir)
ShortHelp()
os.Exit(1)
} else {
config.ScriptDir = scriptDir
config.UsingScriptDir = true
}
}

if config.CgiDir != "" {
if inf, err := os.Stat(config.CgiDir); err != nil || !inf.IsDir() {
fmt.Fprintf(os.Stderr, "Your CGI dir '%s' is not pointing to an accessible directory.\n", config.CgiDir)
ShortHelp()
os.Exit(1)
}
}

if config.StaticDir != "" {
if inf, err := os.Stat(config.StaticDir); err != nil || !inf.IsDir() {
fmt.Fprintf(os.Stderr, "Your static dir '%s' is not pointing to an accessible directory.\n", config.StaticDir)
ShortHelp()
os.Exit(1)
}
config.ScriptDir = scriptDir
config.UsingScriptDir = true
}

mainConfig.Config = &config

return mainConfig
return &mainConfig
}
59 changes: 42 additions & 17 deletions help.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@ a WebSocket server.
Usage:
Export a single executable program a WebSocket server:
{{binary}} [options] program [program args]
{{binary}} [options] COMMAND [command args]
Or, export an entire directory of executables as WebSocket endpoints:
{{binary}} [options] --dir=SOMEDIR
Options:
Expand All @@ -38,12 +36,12 @@ Options:
Use square brackets to specify IPv6 address.
Default: "" (all)
--ssl Listen for HTTPS socket instead of regular HTTP.
--sslcert=FILE All three options must be used together or all of
--ssl Listen for HTTPS socket instead of HTTP.
--sslcert=FILE All three options must be used or all of
--sslkey=FILE them should be omitted.
--passenv VAR[,VAR...] Lists environment variables allowed to be passed
to executed scripts.
--passenv VAR[,VAR...] Lists environment variables allowed to be
passed to executed scripts.
--basepath=PATH Base path in URLs to serve from.
Default: / (root of domain)
Expand Down Expand Up @@ -76,23 +74,50 @@ Options:
This flag cannot be used in conjunction
with --staticdir or --cgidir.
--loglevel={debug, Log level to use (from most to least
trace, verbose).
access, Default: access
info,
error,
fatal}
--loglevel=LEVEL Log level to use (default access).
From most to least verbose:
debug, trace, access, info, error, fatal
Full documentation at http://websocketd.com/
Copyright 2013 Joe Walnes and the websocketd team. All rights reserved.
BSD license: Run '{{binary}} --license' for details.
`
short = `
Usage:
Export a single executable program a WebSocket server:
{{binary}} [options] COMMAND [command args]
Or, export an entire directory of executables as WebSocket endpoints:
{{binary}} [options] --dir=SOMEDIR
Or, show extended help message using:
{{binary}} --help
`
)

func get_help_message(content string) string {
msg := strings.Trim(content, " \n")
msg = strings.Replace(msg, "{{binary}}", HelpProcessName(), -1)
return strings.Replace(msg, "{{version}}", Version(), -1)
}

func HelpProcessName() string {
binary := os.Args[0]
if strings.Contains(binary, "/go-build") { // this was run using "go run", let's use something appropriate
binary = "websocketd"
} else {
binary = filepath.Base(binary)
}
return binary
}

func PrintHelp() {
msg := strings.Trim(help, " \n")
msg = strings.Replace(msg, "{{binary}}", filepath.Base(os.Args[0]), -1)
msg = strings.Replace(msg, "{{version}}", Version(), -1)
fmt.Fprintf(os.Stderr, "%s\n", msg)
fmt.Fprintf(os.Stderr, "%s\n", get_help_message(help))
}

func ShortHelp() {
// Shown after some error
fmt.Fprintf(os.Stderr, "\n%s\n", get_help_message(short))
}
24 changes: 24 additions & 0 deletions libwebsocketd/logscope.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ const (
LogInfo
LogError
LogFatal

LogNone = 126
LogUnknown = 127
)

type LogFunc func(logScope *LogScope, level LogLevel, levelName string, category string, msg string, args ...interface{})
Expand Down Expand Up @@ -85,3 +88,24 @@ func RootLogScope(minLevel LogLevel, logFunc LogFunc) *LogScope {
func Timestamp() string {
return time.Now().Format(time.RFC1123Z)
}

func LevelFromString(s string) LogLevel {
switch s {
case "debug":
return LogDebug
case "trace":
return LogTrace
case "access":
return LogAccess
case "info":
return LogInfo
case "error":
return LogError
case "fatal":
return LogFatal
case "none":
return LogNone
default:
return LogUnknown
}
}
2 changes: 0 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
package main

import (
"flag"
"fmt"
"net/http"
"os"
Expand Down Expand Up @@ -35,7 +34,6 @@ func log(l *libwebsocketd.LogScope, level libwebsocketd.LogLevel, levelName stri
}

func main() {
flag.Usage = PrintHelp
config := parseCommandLine()

log := libwebsocketd.RootLogScope(config.LogLevel, log)
Expand Down

0 comments on commit 596ca45

Please sign in to comment.