rework the configuration and program flag setting system

Signed-off-by: kim (grufwub) <grufwub@gmail.com>
master
kim (grufwub) 4 years ago
parent 5ad8a97721
commit c45d62899c

@ -6,26 +6,6 @@ import (
"time"
)
var (
/* Global file caches */
GlobalFileCache *FileCache
)
func startFileCaching() {
/* Create gophermap file cache */
GlobalFileCache = new(FileCache)
GlobalFileCache.Init(*CacheSize)
/* Parse the supplied CacheCheckFreq */
sleepTime, err := time.ParseDuration(*CacheCheckFreq)
if err != nil {
logSystemFatal("Error parsing supplied cache check frequency %s: %s\n", *CacheCheckFreq, err)
}
/* Start file monitor in separate goroutine */
go startFileMonitor(sleepTime)
}
func startFileMonitor(sleepTime time.Duration) {
go func() {
for {
@ -37,27 +17,27 @@ func startFileMonitor(sleepTime time.Duration) {
}
/* We shouldn't have reached here */
logSystemFatal("FileCache monitor escaped run loop!\n")
Config.LogSystemFatal("FileCache monitor escaped run loop!\n")
}()
}
func checkCacheFreshness() {
/* Before anything, get cache write lock (in case we have to delete) */
GlobalFileCache.CacheMutex.Lock()
Config.FileCache.CacheMutex.Lock()
/* Iterate through paths in cache map to query file last modified times */
for path := range GlobalFileCache.CacheMap.Map {
for path := range Config.FileCache.CacheMap.Map {
stat, err := os.Stat(path)
if err != nil {
/* Log file as not in cache, then delete */
logSystemError("Failed to stat file in cache: %s\n", path)
GlobalFileCache.CacheMap.Remove(path)
Config.LogSystemError("Failed to stat file in cache: %s\n", path)
Config.FileCache.CacheMap.Remove(path)
continue
}
timeModified := stat.ModTime().UnixNano()
/* Get file pointer, no need for lock as we have write lock */
file := GlobalFileCache.CacheMap.Get(path)
file := Config.FileCache.CacheMap.Get(path)
/* If the file is marked as fresh, but file on disk newer, mark as unfresh */
if file.IsFresh() && file.LastRefresh() < timeModified {
@ -66,18 +46,20 @@ func checkCacheFreshness() {
}
/* Done! We can release cache read lock */
GlobalFileCache.CacheMutex.Unlock()
Config.FileCache.CacheMutex.Unlock()
}
/* TODO: see if there is more efficienct setup */
type FileCache struct {
CacheMap *FixedMap
CacheMutex sync.RWMutex
CacheMap *FixedMap
CacheMutex sync.RWMutex
FileSizeMax int64
}
func (fc *FileCache) Init(size int) {
fc.CacheMap = NewFixedMap(size)
fc.CacheMutex = sync.RWMutex{}
func (fc *FileCache) Init(size int, fileSizeMax float64) {
fc.CacheMap = NewFixedMap(size)
fc.CacheMutex = sync.RWMutex{}
fc.FileSizeMax = int64(BytesInMegaByte * fileSizeMax)
}
func (fc *FileCache) FetchRegular(path string) ([]byte, *GophorError) {
@ -153,7 +135,7 @@ func (fc *FileCache) Fetch(path string, newFileContents func(string) FileContent
/* Compare file size (in MB) to CacheFileSizeMax, if larger just get file
* contents, unlock all mutex and don't bother caching.
*/
if float64(stat.Size()) / BytesInMegaByte > *CacheFileSizeMax {
if stat.Size() > fc.FileSizeMax {
b := file.Contents()
fc.CacheMutex.RUnlock()
return b, nil

@ -0,0 +1,49 @@
package main
import (
"regexp"
"log"
)
type ServerConfig struct {
/* Base settings */
RootDir string
Hostname string
Port string
/* Caps.txt information */
Description string
AdminEmail string
Geolocation string
/* Content settings */
PageWidth int
RestrictedFiles []*regexp.Regexp
/* Logging */
SystemLogger *log.Logger
AccessLogger *log.Logger
/* Cache */
FileCache *FileCache
}
func (config *ServerConfig) LogSystem(fmt string, args ...interface{}) {
config.SystemLogger.Printf(":: I :: "+fmt, args...)
}
func (config *ServerConfig) LogSystemError(fmt string, args ...interface{}) {
config.SystemLogger.Printf(":: E :: "+fmt, args...)
}
func (config *ServerConfig) LogSystemFatal(fmt string, args ...interface{}) {
config.SystemLogger.Fatalf(":: F :: "+fmt, args...)
}
func (config *ServerConfig) LogAccess(sourceAddr, fmt string, args ...interface{}) {
config.AccessLogger.Printf(":: I :: ("+sourceAddr+") "+fmt, args...)
}
func (config *ServerConfig) LogAccessError(sourceAddr, fmt string, args ...interface{}) {
config.AccessLogger.Printf(":: E :: ("+sourceAddr+") "+fmt, args...)
}

@ -17,7 +17,7 @@ const (
NullSelector = "-"
NullHost = "null.host"
NullPort = 0
NullPort = "0"
SelectorErrorStr = "selector_length_error"
GophermapRenderErrorStr = ""

@ -166,7 +166,7 @@ func (e ErrorResponseCode) String() string {
return "503 Service Unavailable"
default:
/* Should not have reached here */
logSystemFatal("Unhandled ErrorResponseCode type\n")
Config.LogSystemFatal("Unhandled ErrorResponseCode type\n")
return ""
}
}

@ -180,7 +180,7 @@ func readGophermap(path string) ([]GophermapSection, *GophorError) {
fileContents, gophorErr := readIntoGophermap(line[1:])
if gophorErr != nil {
/* Failed to read file, insert error line */
logSystem("Error: %s\n", gophorErr)
Config.LogSystem("Error: %s\n", gophorErr)
sections = append(sections, NewGophermapText(buildInfoLine("Error reading subgophermap: "+line[1:])))
} else {
sections = append(sections, NewGophermapText(fileContents))
@ -205,7 +205,7 @@ func readGophermap(path string) ([]GophermapSection, *GophorError) {
default:
/* Replace pre-set strings */
line = strings.Replace(line, ReplaceStrHostname, *ServerHostname, -1)
line = strings.Replace(line, ReplaceStrHostname, Config.Hostname, -1)
sections = append(sections, NewGophermapText([]byte(line+DOSLineEnd)))
}
@ -274,9 +274,9 @@ func readIntoGophermap(path string) ([]byte, *GophorError) {
}
func minWidth(w int) int {
if w <= *PageWidth {
if w <= Config.PageWidth {
return w
} else {
return *PageWidth
return Config.PageWidth
}
}

@ -56,7 +56,7 @@ func (fm *FixedMap) Put(key string, value *File) {
delete(fm.Map, key)
fm.List.Remove(element)
logSystem("Popped key: %s\n", key)
Config.LogSystem("Popped key: %s\n", key)
}
}

@ -1,34 +0,0 @@
package main
import (
"flag"
)
var (
/* Base server settings */
ServerRoot = flag.String("root", "/var/gopher", "Change server root directory.")
ServerHostname = flag.String("hostname", "127.0.0.1", "Change server hostname (FQDN).")
ServerPort = flag.Int("port", 70, "Change server port (0 to disable unencrypted traffic).")
ServerBindAddr = flag.String("bind-addr", "127.0.0.1", "Change server socket bind address")
ExecAsUid = flag.Int("uid", 1000, "Change UID to drop executable privileges to.")
ExecAsGid = flag.Int("gid", 100, "Change GID to drop executable privileges to.")
/* User supplied caps.txt information */
ServerDescription = flag.String("description", "Gophor: a Gopher server in GoLang", "Change server description in auto-generated caps.txt.")
ServerAdmin = flag.String("admin-email", "", "Change admin email in auto-generated caps.txt.")
ServerGeoloc = flag.String("geoloc", "", "Change server gelocation string in auto-generated caps.txt.")
/* Content settings */
PageWidth = flag.Int("page-width", 80, "Change page width used when formatting output.")
RestrictedFiles = flag.String("restrict-files", "", "New-line separated list of regex statements restricting files from showing in directory listings.")
/* Logging settings */
SystemLog = flag.String("system-log", "", "Change server system log file (blank outputs to stderr).")
AccessLog = flag.String("access-log", "", "Change server access log file (blank outputs to stderr).")
LoggingType = flag.Int("log-type", 0, "Change server log file handling -- 0:default 1:disable")
/* Cache settings */
CacheCheckFreq = flag.String("cache-check", "60s", "Change file cache freshness check frequency.")
CacheSize = flag.Int("cache-size", 50, "Change file cache size, measured in file count.")
CacheFileSizeMax = flag.Float64("cache-file-max", 0.5, "Change maximum file size to be cached (in megabytes).")
)

@ -1,7 +1,6 @@
package main
import (
"strconv"
"strings"
)
@ -71,12 +70,12 @@ func buildError(selector string) []byte {
return []byte(ret)
}
func buildLine(t ItemType, name, selector, host string, port int) []byte {
func buildLine(t ItemType, name, selector, host string, port string) []byte {
ret := string(t)
/* Add name, truncate name if too long */
if len(name) > *PageWidth {
ret += name[:*PageWidth-4]+"...\t"
if len(name) > Config.PageWidth {
ret += name[:Config.PageWidth-4]+"...\t"
} else {
ret += name+"\t"
}
@ -90,7 +89,7 @@ func buildLine(t ItemType, name, selector, host string, port int) []byte {
}
/* Add host + port */
ret += host+"\t"+strconv.Itoa(port)+DOSLineEnd
ret += host+"\t"+port+DOSLineEnd
return []byte(ret)
}

16
fs.go

@ -210,13 +210,13 @@ func _listDir(dirPath string, hidden map[string]bool) ([]byte, *GophorError) {
case file.Mode() & os.ModeDir != 0:
/* Directory -- create directory listing */
itemPath := path.Join(dirPath, file.Name())
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, *ServerHostname, *ServerPort)...)
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, Config.Hostname, Config.Port)...)
case file.Mode() & os.ModeType == 0:
/* Regular file -- find item type and creating listing */
itemPath := path.Join(dirPath, file.Name())
itemType := getItemType(itemPath)
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, *ServerHostname, *ServerPort)...)
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, Config.Hostname, Config.Port)...)
default:
/* Ignore */
@ -238,13 +238,13 @@ func _listDirRegexMatch(dirPath string, hidden map[string]bool) ([]byte, *Gophor
case file.Mode() & os.ModeDir != 0:
/* Directory -- create directory listing */
itemPath := path.Join(dirPath, file.Name())
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, *ServerHostname, *ServerPort)...)
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, Config.Hostname, Config.Port)...)
case file.Mode() & os.ModeType == 0:
/* Regular file -- find item type and creating listing */
itemPath := path.Join(dirPath, file.Name())
itemType := getItemType(itemPath)
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, *ServerHostname, *ServerPort)...)
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, Config.Hostname, Config.Port)...)
default:
/* Ignore */
@ -256,14 +256,14 @@ func _listDirBase(dirPath string, iterFunc func(dirContents *[]byte, file os.Fil
/* Open directory file descriptor */
fd, err := os.Open(dirPath)
if err != nil {
logSystemError("failed to open %s: %s\n", dirPath, err.Error())
Config.LogSystemError("failed to open %s: %s\n", dirPath, err.Error())
return nil, &GophorError{ FileOpenErr, err }
}
/* Read files in directory */
files, err := fd.Readdir(-1)
if err != nil {
logSystemError("failed to enumerate dir %s: %s\n", dirPath, err.Error())
Config.LogSystemError("failed to enumerate dir %s: %s\n", dirPath, err.Error())
return nil, &GophorError{ DirListErr, err }
}
@ -274,10 +274,10 @@ func _listDirBase(dirPath string, iterFunc func(dirContents *[]byte, file os.Fil
dirContents := make([]byte, 0)
/* First add a title */
dirContents = append(dirContents, buildLine(TypeInfo, "[ "+*ServerHostname+dirPath+" ]", "TITLE", NullHost, NullPort)...)
dirContents = append(dirContents, buildLine(TypeInfo, "[ "+Config.Hostname+dirPath+" ]", "TITLE", NullHost, NullPort)...)
/* Add a 'back' entry. GoLang Readdir() seems to miss this */
dirContents = append(dirContents, buildLine(TypeDirectory, "..", path.Join(fd.Name(), ".."), *ServerHostname, *ServerPort)...)
dirContents = append(dirContents, buildLine(TypeDirectory, "..", path.Join(fd.Name(), ".."), Config.Hostname, Config.Port)...)
/* Walk through files :D */
for _, file := range files { iterFunc(&dirContents, file) }

@ -1,13 +1,13 @@
package main
import (
"log"
"os"
"strconv"
"syscall"
"os/signal"
"flag"
"net"
"time"
)
/*
@ -29,69 +29,30 @@ import (
import "C"
var (
PreviouslyConnected []string
Config *ServerConfig
)
func main() {
/* Setup global logger */
log.SetOutput(os.Stderr)
log.SetFlags(0)
/* Parse run-time arguments */
flag.Parse()
/* Setup _OUR_ loggers */
loggingSetup()
/* Enter server dir */
enterServerDir()
logSystem("Entered server directory: %s\n", *ServerRoot)
/* Try enter chroot if requested */
chrootServerDir()
logSystem("Chroot success, new root: %s\n", *ServerRoot)
/* Setup listeners */
listeners := make([]net.Listener, 0)
/* If provided unencrypted port, setup listener! */
if *ServerPort != 0 {
l, err := net.Listen("tcp", *ServerBindAddr+":"+strconv.Itoa(*ServerPort))
if err != nil {
logSystemFatal("Error setting up listener on %s: %s\n", *ServerBindAddr+":"+strconv.Itoa(*ServerPort), err.Error())
}
defer l.Close()
logSystem("Listening (unencrypted): gopher://%s\n", l.Addr())
listeners = append(listeners, l)
}
/* Now we've made system calls, drop privileges */
setPrivileges()
/* Setup the entire server, getting slice of listeners in return */
listeners := setupServer()
/* Handle signals so we can _actually_ shutdowm */
signals := make(chan os.Signal)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)
/* Compile user restricted files regex if supplied */
compileUserRestrictedFilesRegex()
/* Start file cache system */
startFileCaching()
/* Start accepting connections on any supplied listeners */
for _, l := range listeners {
go func() {
for {
newConn, err := l.Accept()
if err != nil {
logSystemError("Error accepting connection: %s\n", err.Error())
Config.LogSystemError("Error accepting connection: %s\n", err.Error())
continue
}
/* Run this in it's own goroutine so we can go straight back to accepting */
go func() {
w := NewWorker(&newConn)
w := NewWorker(&newConn, Config.Port)
w.Serve()
}()
}
@ -100,56 +61,157 @@ func main() {
/* When OS signal received, we close-up */
sig := <-signals
logSystem("Signal received: %v. Shutting down...\n", sig)
Config.LogSystem("Signal received: %v. Shutting down...\n", sig)
os.Exit(0)
}
func enterServerDir() {
err := syscall.Chdir(*ServerRoot)
func setupServer() []net.Listener {
/* First we setup all the flags and parse them... */
/* Base server settings */
serverRoot := flag.String("root", "/var/gopher", "Change server root directory.")
serverHostname := flag.String("hostname", "127.0.0.1", "Change server hostname (FQDN).")
serverPort := flag.Int("port", 70, "Change server port (0 to disable unencrypted traffic).")
serverBindAddr := flag.String("bind-addr", "127.0.0.1", "Change server socket bind address")
execUid := flag.Int("uid", 1000, "Change UID to drop executable privileges to.")
execGid := flag.Int("gid", 100, "Change GID to drop executable privileges to.")
/* User supplied caps.txt information */
serverDescription := flag.String("description", "Gophor: a Gopher server in GoLang", "Change server description in auto-generated caps.txt.")
serverAdmin := flag.String("admin-email", "", "Change admin email in auto-generated caps.txt.")
serverGeoloc := flag.String("geoloc", "", "Change server gelocation string in auto-generated caps.txt.")
/* Content settings */
pageWidth := flag.Int("page-width", 80, "Change page width used when formatting output.")
restrictedFiles := flag.String("restrict-files", "", "New-line separated list of regex statements restricting files from showing in directory listings.")
/* Logging settings */
systemLogPath := flag.String("system-log", "", "Change server system log file (blank outputs to stderr).")
accessLogPath := flag.String("access-log", "", "Change server access log file (blank outputs to stderr).")
logType := flag.Int("log-type", 0, "Change server log file handling -- 0:default 1:disable")
/* Cache settings */
cacheCheckFreq := flag.String("cache-check", "60s", "Change file cache freshness check frequency.")
cacheSize := flag.Int("cache-size", 50, "Change file cache size, measured in file count.")
cacheFileSizeMax := flag.Float64("cache-file-max", 0.5, "Change maximum file size to be cached (in megabytes).")
/* Parse parse parse!! */
flag.Parse()
/* Setup the server configuration instance and enter as much as we can right now */
Config = new(ServerConfig)
Config.RootDir = *serverRoot
Config.Hostname = *serverHostname
Config.Port = strconv.Itoa(*serverPort)
Config.Description = *serverDescription
Config.AdminEmail = *serverAdmin
Config.Geolocation = *serverGeoloc
Config.PageWidth = *pageWidth
/* Setup Gophor logging system */
Config.SystemLogger, Config.AccessLogger = setupLogging(*logType, *systemLogPath, *accessLogPath)
/* Enter server dir */
enterServerDir(*serverRoot)
Config.LogSystem("Entered server directory: %s\n", *serverRoot)
/* Try enter chroot if requested */
chrootServerDir(*serverRoot)
Config.LogSystem("Chroot success, new root: %s\n", *serverRoot)
/* Setup listeners */
listeners := make([]net.Listener, 0)
/* If provided unencrypted port, setup listener! */
if Config.Port == NullPort {
Config.LogSystemFatal("%s is not a valid port to bind to!\n", NullPort)
}
l, err := net.Listen("tcp", *serverBindAddr+":"+Config.Port)
if err != nil {
Config.LogSystemFatal("Error setting up listener on %s: %s\n", *serverBindAddr+":"+Config.Port, err.Error())
}
Config.LogSystem("Listening (unencrypted): gopher://%s\n", l.Addr())
listeners = append(listeners, l)
/* Drop privileges */
setPrivileges(*execUid, *execGid)
/* Compile user restricted files regex if supplied */
if *restrictedFiles != "" {
Config.RestrictedFiles = compileUserRestrictedFilesRegex(*restrictedFiles)
/* Setup the listDir function to use regex matching */
listDir = _listDirRegexMatch
} else {
/* Setup the listDir function to skip regex matching */
listDir = _listDir
}
/* Parse suppled cache check frequency time */
fileMonitorSleepTime, err := time.ParseDuration(*cacheCheckFreq)
if err != nil {
Config.LogSystemFatal("Error parsing supplied cache check frequency %s: %s\n", *cacheCheckFreq, err)
}
/* Setup file cache */
Config.FileCache = new(FileCache)
Config.FileCache.Init(*cacheSize, *cacheFileSizeMax)
/* Start file cache freshness checker */
go startFileMonitor(fileMonitorSleepTime)
/* Return the created listeners slice :) */
return listeners
}
func enterServerDir(path string) {
err := syscall.Chdir(path)
if err != nil {
logSystemFatal("Error changing dir to server root %s: %s\n", *ServerRoot, err.Error())
Config.LogSystemFatal("Error changing dir to server root %s: %s\n", path, err.Error())
}
}
func chrootServerDir() {
err := syscall.Chroot(*ServerRoot)
func chrootServerDir(path string) {
err := syscall.Chroot(path)
if err != nil {
logSystemFatal("Error chroot'ing into server root %s: %s\n", *ServerRoot, err.Error())
Config.LogSystemFatal("Error chroot'ing into server root %s: %s\n", path, err.Error())
}
/* Change to server root just to ensure we're sitting at root of chroot */
err = syscall.Chdir("/")
if err != nil {
logSystemFatal("Error changing to root of chroot dir: %s\n", err.Error())
Config.LogSystemFatal("Error changing to root of chroot dir: %s\n", err.Error())
}
}
func setPrivileges() {
func setPrivileges(execUid, execGid int) {
/* Check root privileges aren't being requested */
if *ExecAsUid == 0 || *ExecAsGid == 0 {
logSystemFatal("Gophor does not support directly running as root\n")
if execUid == 0 || execGid == 0 {
Config.LogSystemFatal("Gophor does not support directly running as root\n")
}
/* Get currently running user info */
uid, gid := syscall.Getuid(), syscall.Getgid()
/* Set GID if necessary */
if gid != *ExecAsGid || gid == 0 {
if gid != execUid {
/* C-bind setgid */
result := C.setgid(C.uint(*ExecAsGid))
result := C.setgid(C.uint(execGid))
if result != 0 {
logSystemFatal("Failed setting GID %d: %d\n", *ExecAsGid, result)
Config.LogSystemFatal("Failed setting GID %d: %d\n", execGid, result)
}
logSystem("Dropping to GID: %d\n", *ExecAsGid)
Config.LogSystem("Dropping to GID: %d\n", execGid)
}
/* Set UID if necessary */
if uid != *ExecAsUid || uid == 0 {
if uid != execGid {
/* C-bind setuid */
result := C.setuid(C.uint(*ExecAsUid))
result := C.setuid(C.uint(execUid))
if result != 0 {
logSystemFatal("Failed setting UID %d: %d\n", *ExecAsUid, result)
Config.LogSystemFatal("Failed setting UID %d: %d\n", execUid, result)
}
logSystem("Dropping to UID: %d\n", *ExecAsUid)
Config.LogSystem("Dropping to UID: %d\n", execUid)
}
}

@ -7,23 +7,24 @@ import (
"io/ioutil"
)
var (
systemLogger *log.Logger
accessLogger *log.Logger
)
func setupLogging(loggingType int, systemLogPath, accessLogPath string) (*log.Logger, *log.Logger) {
/* Setup global logger */
log.SetOutput(os.Stderr)
log.SetFlags(0)
func loggingSetup() {
useSame := (*SystemLog == *AccessLog)
/* Calculate now, because, *shrug* */
useSame := (systemLogPath == accessLogPath)
/* Check requested logging type */
switch *LoggingType {
var systemLogger, accessLogger *log.Logger
switch loggingType {
case 0:
/* Default */
/* Setup system logger to output to file, or stderr if none supplied */
var systemWriter io.Writer
if *SystemLog != "" {
fd, err := os.OpenFile(*SystemLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if systemLogPath != "" {
fd, err := os.OpenFile(systemLogPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
log.Fatalf("Failed to create system logger: %s\n", err.Error())
}
@ -36,13 +37,12 @@ func loggingSetup() {
/* If both output to same, may as well use same logger for both */
if useSame {
accessLogger = systemLogger
return
}
/* Setup access logger to output to file, or stderr if none supplied */
var accessWriter io.Writer
if *AccessLog != "" {
fd, err := os.OpenFile(*AccessLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if accessLogPath != "" {
fd, err := os.OpenFile(accessLogPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
log.Fatalf("Failed to create access logger: %s\n", err.Error())
}
@ -56,29 +56,10 @@ func loggingSetup() {
/* Disable -- pipe logs to "discard". May as well use same for both */
systemLogger = log.New(ioutil.Discard, "", 0)
accessLogger = systemLogger
return
default:
log.Fatalf("Unrecognized logging type: %d\n", *LoggingType)
log.Fatalf("Unrecognized logging type: %d\n", loggingType)
}
}
func logSystem(fmt string, args ...interface{}) {
systemLogger.Printf(":: I :: "+fmt, args...)
}
func logSystemError(fmt string, args ...interface{}) {
systemLogger.Printf(":: E :: "+fmt, args...)
}
func logSystemFatal(fmt string, args ...interface{}) {
systemLogger.Fatalf(":: F :: "+fmt, args...)
}
func logAccess(fmt string, args ...interface{}) {
accessLogger.Printf(":: I :: "+fmt, args...)
}
func logAccessError(fmt string, args ...interface{}) {
accessLogger.Printf(":: E :: "+fmt, args...)
return systemLogger, accessLogger
}

@ -18,11 +18,11 @@ func generateCapsTxt() []byte {
text += DOSLineEnd
text += "ServerSoftware=Gophor"+DOSLineEnd
text += "ServerSoftwareVersion="+GophorVersion+DOSLineEnd
text += "ServerDescription="+*ServerDescription+DOSLineEnd
text += "ServerGeolocationString="+*ServerGeoloc+DOSLineEnd
text += "ServerDescription="+Config.Description+DOSLineEnd
text += "ServerGeolocationString="+Config.Geolocation+DOSLineEnd
text += "ServerDefaultEncoding=ascii"+DOSLineEnd
text += DOSLineEnd
text += "ServerAdmin="+*ServerAdmin+DOSLineEnd
text += "ServerAdmin="+Config.AdminEmail+DOSLineEnd
return []byte(text)
}

@ -5,33 +5,26 @@ import (
"strings"
)
var RestrictedFilesRegex []*regexp.Regexp
func compileUserRestrictedFilesRegex() {
if *RestrictedFiles == "" {
/* User not supplied any restricted files, return here */
listDir = _listDir
return
}
func compileUserRestrictedFilesRegex(restrictedFiles string) []*regexp.Regexp {
/* Try compiling the RestrictedFilesRegex from finalRegex */
logSystem("Compiling restricted file regular expressions\n")
Config.LogSystem("Compiling restricted file regular expressions\n")
restrictedFilesRegex := make([]*regexp.Regexp, 0)
/* Split the user supplied RestrictedFiles string by new-line */
RestrictedFilesRegex = make([]*regexp.Regexp, 0)
for _, expr := range strings.Split(*RestrictedFiles, "\n") {
for _, expr := range strings.Split(restrictedFiles, "\n") {
regex, err := regexp.Compile(expr)
if err != nil {
logSystemFatal("Failed compiling user restricted files regex: %s\n", expr)
Config.LogSystemFatal("Failed compiling user restricted files regex: %s\n", expr)
}
RestrictedFilesRegex = append(RestrictedFilesRegex, regex)
restrictedFilesRegex = append(restrictedFilesRegex, regex)
}
listDir = _listDirRegexMatch
return restrictedFilesRegex
}
func isRestrictedFile(name string) bool {
for _, regex := range RestrictedFilesRegex {
for _, regex := range Config.RestrictedFiles {
if regex.MatchString(name) {
return true
}

@ -20,14 +20,14 @@ const (
)
type Worker struct {
Socket net.Conn
LogPrefix string
Conn net.Conn
Port string
}
func NewWorker(socket *net.Conn) *Worker {
func NewWorker(conn *net.Conn, port string) *Worker {
worker := new(Worker)
worker.Socket = *socket
worker.LogPrefix = worker.Socket.RemoteAddr().String()+" "
worker.Conn = *conn
worker.Port = port
return worker
}
@ -35,7 +35,7 @@ func (worker *Worker) Serve() {
go func() {
defer func() {
/* Close-up shop */
worker.Socket.Close()
worker.Conn.Close()
}()
var count int
@ -49,9 +49,9 @@ func (worker *Worker) Serve() {
iter := 0
for {
/* Buffered read from listener */
count, err = worker.Socket.Read(buf)
count, err = worker.Conn.Read(buf)
if err != nil {
logSystemError("Error reading from socket %s: %s\n", worker.Socket, err.Error())
Config.LogSystemError("Error reading from socket %s: %s\n", worker.Conn, err.Error())
return
}
@ -66,7 +66,7 @@ func (worker *Worker) Serve() {
/* Hit max read chunk size, send error + close connection */
if iter == MaxSocketReadChunks {
logSystemError("Reached max socket read size %d. Closing connection...\n", MaxSocketReadChunks*SocketReadBufSize)
Config.LogSystemError("Reached max socket read size %d. Closing connection...\n", MaxSocketReadChunks*SocketReadBufSize)
return
}
@ -79,7 +79,7 @@ func (worker *Worker) Serve() {
/* Handle any error */
if gophorErr != nil {
logSystemError("%s\n", gophorErr.Error())
Config.LogSystemError("%s\n", gophorErr.Error())
/* Try generate response bytes from error code */
response := generateGopherErrorResponseFromCode(gophorErr.Code)
@ -94,7 +94,7 @@ func (worker *Worker) Serve() {
}
func (worker *Worker) SendRaw(b []byte) *GophorError {
count, err := worker.Socket.Write(b)
count, err := worker.Conn.Write(b)
if err != nil {
return &GophorError{ SocketWriteErr, err }
} else if count != len(b) {
@ -104,11 +104,11 @@ func (worker *Worker) SendRaw(b []byte) *GophorError {
}
func (worker *Worker) Log(format string, args ...interface{}) {
logAccess(worker.LogPrefix+format, args...)
Config.LogAccess(worker.Conn.RemoteAddr().String(), format, args...)
}
func (worker *Worker) LogError(format string, args ...interface{}) {
logAccessError(worker.LogPrefix+format, args...)
Config.LogAccessError(worker.Conn.RemoteAddr().String(), format, args...)
}
func (worker *Worker) RespondGopher(data []byte) *GophorError {
@ -176,7 +176,7 @@ func (worker *Worker) RespondGopher(data []byte) *GophorError {
case FileTypeDir:
/* First try to serve gopher map */
gophermapPath := path.Join(requestPath, "/"+GophermapFileStr)
fileContents, gophorErr := GlobalFileCache.FetchGophermap(gophermapPath)
fileContents, gophorErr := Config.FileCache.FetchGophermap(gophermapPath)
if gophorErr != nil {
/* Get directory listing instead */
fileContents, gophorErr = listDir(requestPath, map[string]bool{})
@ -199,7 +199,7 @@ func (worker *Worker) RespondGopher(data []byte) *GophorError {
/* Regular file */
case FileTypeRegular:
/* Read file contents */
fileContents, gophorErr := GlobalFileCache.FetchRegular(requestPath)
fileContents, gophorErr := Config.FileCache.FetchRegular(requestPath)
if gophorErr != nil {
return gophorErr
}

Loading…
Cancel
Save