diff --git a/Makefile b/Makefile index 2ff04f7..0b142bb 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,8 @@ PACKAGES = \ pkg/sessionpool \ pkg/ban \ pkg/htmlfilter \ - pkg/freezer + pkg/freezer \ + pkg/logtarget GCFLAGS = \ -Ipkg/cryptstate/_obj \ @@ -29,7 +30,8 @@ GCFLAGS = \ -Ipkg/sessionpool/_obj \ -Ipkg/ban/_obj \ -Ipkg/htmlfilter/_obj \ - -Ipkg/freezer/_obj + -Ipkg/freezer/_obj \ + -Ipkg/logtarget/_obj LDFLAGS = \ -Lpkg/cryptstate/_obj \ @@ -40,7 +42,8 @@ LDFLAGS = \ -Lpkg/sessionpool/_obj \ -Lpkg/ban/_obj \ -Lpkg/htmlfilter/_obj \ - -Lpkg/freezer/_obj + -Lpkg/freezer/_obj \ + -Lpkg/logtarget/_obj GOFILES = \ grumble.go \ @@ -55,7 +58,6 @@ GOFILES = \ gencert.go \ register.go \ ssh.go \ - log.go \ args.go \ ifeq ($(SQLITE),1) diff --git a/grumble.go b/grumble.go index f9ad908..f77cdc1 100644 --- a/grumble.go +++ b/grumble.go @@ -8,6 +8,7 @@ import ( "flag" "fmt" "grumble/blobstore" + "grumble/logtarget" "log" "os" "path/filepath" @@ -25,7 +26,7 @@ func main() { return } - err = LogTarget.OpenFile(Args.LogPath) + err = logtarget.Target.OpenFile(Args.LogPath) if err != nil { fmt.Fprintf(os.Stderr, "Unable to open log file: %v", err) return @@ -33,10 +34,9 @@ func main() { log.SetPrefix("[G] ") log.SetFlags(log.LstdFlags | log.Lmicroseconds) - log.SetOutput(&LogTarget) + log.SetOutput(&logtarget.Target) log.Printf("Grumble") - log.Printf("Using data directory: %s", Args.DataDir) // Open the blobstore diff --git a/log.go b/log.go deleted file mode 100644 index e83066d..0000000 --- a/log.go +++ /dev/null @@ -1,53 +0,0 @@ -package main - -import ( - "bytes" - "os" - "sync" -) - -type logTarget struct { - mu sync.Mutex - logfn string - file *os.File - memLog *bytes.Buffer -} - -var LogTarget logTarget - -func (target *logTarget) Write(in []byte) (int, error) { - target.mu.Lock() - defer target.mu.Unlock() - - return target.file.Write(in) -} - -// Open a log file for writing. -// This method will open the file in append-only mode. -func (target *logTarget) OpenFile(fn string) (err error) { - target.logfn = fn - target.file, err = os.OpenFile(target.logfn, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0650) - if err != nil { - return err - } - return nil -} - -// Perform a log rotation -func (target *logTarget) Rotate() error { - target.mu.Lock() - defer target.mu.Unlock() - - // Close the existing log file - err := target.file.Close() - if err != nil { - return err - } - - target.file, err = os.OpenFile(target.logfn, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0650) - if err != nil { - return err - } - - return nil -} diff --git a/pkg/logtarget/Makefile b/pkg/logtarget/Makefile new file mode 100644 index 0000000..6f3ce8b --- /dev/null +++ b/pkg/logtarget/Makefile @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc + +TARG = grumble/logtarget +GOFILES = \ + logtarget.go + +include $(GOROOT)/src/Make.pkg diff --git a/pkg/logtarget/logtarget.go b/pkg/logtarget/logtarget.go new file mode 100644 index 0000000..62f572a --- /dev/null +++ b/pkg/logtarget/logtarget.go @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The Grumble Authors +// The use of this source code is goverened by a BSD-style +// license that can be found in the LICENSE-file. + +// Package logtarget implements a multiplexing logging target +package logtarget + +import ( + "bytes" + "os" + "sync" +) + +// LogTarget implements the io.Writer interface, allowing +// LogTarget to be registered with the regular Go log package. +// LogTarget multiplexes its incoming writes to multiple optional +// output writers, and one main output writer (the log file). +type LogTarget struct { + mu sync.Mutex + logfn string + file *os.File + memLog *bytes.Buffer +} + +var Target LogTarget + +// Write writes a log message to all registered io.Writers +func (target *LogTarget) Write(in []byte) (int, error) { + target.mu.Lock() + defer target.mu.Unlock() + + return target.file.Write(in) +} + +// OpenFile opens the main log file for writing. +// This method will open the file in append-only mode. +func (target *LogTarget) OpenFile(fn string) (err error) { + target.logfn = fn + target.file, err = os.OpenFile(target.logfn, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0650) + if err != nil { + return err + } + return nil +} + +// Rotate rotates the current log file. +// This method holds a lock while rotating the log file, +// and all log writes will be held back until the rotation +// is complete. +func (target *LogTarget) Rotate() error { + target.mu.Lock() + defer target.mu.Unlock() + + // Close the existing log file + err := target.file.Close() + if err != nil { + return err + } + + target.file, err = os.OpenFile(target.logfn, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0650) + if err != nil { + return err + } + + return nil +} diff --git a/server.go b/server.go index 463dfad..dd2b05e 100644 --- a/server.go +++ b/server.go @@ -20,6 +20,7 @@ import ( "grumble/cryptstate" "grumble/freezer" "grumble/htmlfilter" + "grumble/logtarget" "grumble/mumbleproto" "grumble/serverconf" "grumble/sessionpool" @@ -165,7 +166,7 @@ func NewServer(id int64, addr string, port int) (s *Server, err error) { s.Channels[0] = NewChannel(0, "Root") s.nextChanId = 1 - s.Logger = log.New(&LogTarget, fmt.Sprintf("[%v] ", s.Id), log.LstdFlags|log.Lmicroseconds) + s.Logger = log.New(&logtarget.Target, fmt.Sprintf("[%v] ", s.Id), log.LstdFlags|log.Lmicroseconds) return } diff --git a/signal_unix.go b/signal_unix.go index ecab22b..c737fef 100644 --- a/signal_unix.go +++ b/signal_unix.go @@ -6,6 +6,7 @@ package main import ( "fmt" + "grumble/logtarget" "os" "os/signal" ) @@ -15,7 +16,7 @@ func SignalHandler() { sig := <-signal.Incoming if sig == os.SIGUSR2 { - err := LogTarget.Rotate() + err := logtarget.Target.Rotate() if err != nil { fmt.Fprintf(os.Stderr, "Unable to rotate log file: %v", err) }