diff --git a/internal/readpassword/read.go b/internal/readpassword/read.go index f316846..1f2a9fa 100644 --- a/internal/readpassword/read.go +++ b/internal/readpassword/read.go @@ -16,9 +16,6 @@ const ( exitCode = 9 ) -// TODO -var colorReset, colorRed string - // Once() tries to get a password from the user, either from the terminal, // extpass or stdin. func Once(extpass string) string { @@ -43,7 +40,7 @@ func Twice(extpass string) string { p1 := readPasswordTerminal("Password: ") p2 := readPasswordTerminal("Repeat: ") if p1 != p2 { - toggledlog.Fatal.Println(colorRed + "Passwords do not match" + colorReset) + toggledlog.Fatal.Println("Passwords do not match") os.Exit(exitCode) } return p1 @@ -57,12 +54,12 @@ func readPasswordTerminal(prompt string) string { // terminal.ReadPassword removes the trailing newline p, err := terminal.ReadPassword(fd) if err != nil { - toggledlog.Fatal.Printf(colorRed+"Could not read password from terminal: %v\n"+colorReset, err) + toggledlog.Fatal.Printf("Could not read password from terminal: %v\n", err) os.Exit(exitCode) } fmt.Fprintf(os.Stderr, "\n") if len(p) == 0 { - toggledlog.Fatal.Println(colorRed + "Password is empty" + colorReset) + toggledlog.Fatal.Println("Password is empty") os.Exit(exitCode) } return string(p) @@ -75,7 +72,7 @@ func readPasswordStdin() string { p := readLineUnbuffered(os.Stdin) if len(p) == 0 { fmt.Fprintf(os.Stderr, "FOOOOOO\n") - toggledlog.Fatal.Println(colorRed + "Got empty password from stdin" + colorReset) + toggledlog.Fatal.Println("Got empty password from stdin") os.Exit(exitCode) } return p @@ -91,19 +88,19 @@ func readPasswordExtpass(extpass string) string { cmd.Stderr = os.Stderr pipe, err := cmd.StdoutPipe() if err != nil { - toggledlog.Fatal.Printf(colorRed+"extpass pipe setup failed: %v\n"+colorReset, err) + toggledlog.Fatal.Printf("extpass pipe setup failed: %v", err) os.Exit(exitCode) } err = cmd.Start() if err != nil { - toggledlog.Fatal.Printf(colorRed+"extpass cmd start failed: %v\n"+colorReset, err) + toggledlog.Fatal.Printf("extpass cmd start failed: %v", err) os.Exit(exitCode) } p := readLineUnbuffered(pipe) pipe.Close() cmd.Wait() if len(p) == 0 { - toggledlog.Fatal.Println(colorRed + "extpass: password is empty" + colorReset) + toggledlog.Fatal.Println("extpass: password is empty") os.Exit(exitCode) } return p @@ -119,7 +116,7 @@ func readLineUnbuffered(r io.Reader) (l string) { return l } if err != nil { - toggledlog.Fatal.Printf(colorRed+"readLineUnbuffered: %v\n"+colorReset, err) + toggledlog.Fatal.Printf("readLineUnbuffered: %v", err) os.Exit(exitCode) } if n == 0 { diff --git a/internal/toggledlog/log.go b/internal/toggledlog/log.go index 23d7347..30fab18 100644 --- a/internal/toggledlog/log.go +++ b/internal/toggledlog/log.go @@ -5,6 +5,8 @@ import ( "fmt" "log" "os" + + "golang.org/x/crypto/ssh/terminal" ) const ( @@ -12,6 +14,10 @@ const ( wpanicMsg = "-wpanic turns this warning into a panic: " ) +// Escape sequences for terminal colors. These will be empty strings if stdout +// is not a terminal. +var ColorReset, ColorGrey, ColorRed, ColorGreen, ColorYellow string + func JSONDump(obj interface{}) string { b, err := json.MarshalIndent(obj, "", "\t") if err != nil { @@ -27,6 +33,10 @@ type toggledLogger struct { Enabled bool // Panic after logging a message, useful in regression tests Wpanic bool + // Private prefix and postfix are used for coloring + prefix string + postfix string + *log.Logger } @@ -34,7 +44,7 @@ func (l *toggledLogger) Printf(format string, v ...interface{}) { if !l.Enabled { return } - l.Logger.Printf(format, v...) + l.Logger.Printf(l.prefix + fmt.Sprintf(format, v...) + l.postfix) if l.Wpanic { l.Logger.Panic(wpanicMsg + fmt.Sprintf(format, v...)) } @@ -43,9 +53,9 @@ func (l *toggledLogger) Println(v ...interface{}) { if !l.Enabled { return } - l.Logger.Println(v...) + l.Logger.Println(l.prefix + fmt.Sprint(v...) + l.postfix) if l.Wpanic { - l.Logger.Panic(wpanicMsg + fmt.Sprintln(v...)) + l.Logger.Panic(wpanicMsg + fmt.Sprint(v...)) } } @@ -65,8 +75,29 @@ var Warn *toggledLogger var Fatal *toggledLogger func init() { - Debug = &toggledLogger{false, false, log.New(os.Stdout, "", 0)} - Info = &toggledLogger{true, false, log.New(os.Stdout, "", 0)} - Warn = &toggledLogger{true, false, log.New(os.Stderr, "", 0)} - Fatal = &toggledLogger{true, false, log.New(os.Stderr, "", 0)} + if terminal.IsTerminal(int(os.Stdout.Fd())) { + ColorReset = "\033[0m" + ColorGrey = "\033[2m" + ColorRed = "\033[31m" + ColorGreen = "\033[32m" + ColorYellow = "\033[33m" + } + + Debug = &toggledLogger{ + Logger: log.New(os.Stdout, "", 0), + } + Info = &toggledLogger{ + Enabled: true, + Logger: log.New(os.Stdout, "", 0), + } + Warn = &toggledLogger{ + Enabled: true, + Logger: log.New(os.Stderr, "", 0), + } + Fatal = &toggledLogger{ + Enabled: true, + Logger: log.New(os.Stderr, "", 0), + prefix: ColorRed, + postfix: ColorReset, + } } diff --git a/main.go b/main.go index 61b56e6..6c40253 100644 --- a/main.go +++ b/main.go @@ -16,8 +16,6 @@ import ( "syscall" "time" - "golang.org/x/crypto/ssh/terminal" - "github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse/nodefs" "github.com/hanwen/go-fuse/fuse/pathfs" @@ -61,7 +59,7 @@ var GitVersionFuse = "[version not set - please compile using ./build.bash]" func initDir(args *argContainer) { err := checkDirEmpty(args.cipherdir) if err != nil { - toggledlog.Fatal.Printf("Invalid cipherdir: %v\n", err) + toggledlog.Fatal.Printf("Invalid cipherdir: %v", err) os.Exit(ERREXIT_INIT) } @@ -88,7 +86,7 @@ func initDir(args *argContainer) { } } - toggledlog.Info.Printf(colorGreen + "The filesystem has been created successfully." + colorReset) + toggledlog.Info.Printf(toggledlog.ColorGreen + "The filesystem has been created successfully." + toggledlog.ColorReset) wd, _ := os.Getwd() friendlyPath, _ := filepath.Rel(wd, args.cipherdir) if strings.HasPrefix(friendlyPath, "../") { @@ -96,7 +94,7 @@ func initDir(args *argContainer) { // keep the absolute path. friendlyPath = args.cipherdir } - toggledlog.Info.Printf(colorGrey+"You can now mount it using: %s %s MOUNTPOINT"+colorReset, + toggledlog.Info.Printf(toggledlog.ColorGrey+"You can now mount it using: %s %s MOUNTPOINT"+toggledlog.ColorReset, toggledlog.ProgramName, friendlyPath) os.Exit(0) } @@ -118,14 +116,14 @@ func loadConfig(args *argContainer) (masterkey []byte, confFile *configfile.Conf // Check if the file exists at all before prompting for a password _, err := os.Stat(args.config) if err != nil { - toggledlog.Fatal.Printf(colorRed+"Config file not found: %v\n"+colorReset, err) + toggledlog.Fatal.Printf("Config file not found: %v", err) os.Exit(ERREXIT_LOADCONF) } pw := readpassword.Once(args.extpass) toggledlog.Info.Println("Decrypting master key") masterkey, confFile, err = configfile.LoadConfFile(args.config, pw) if err != nil { - toggledlog.Fatal.Println(colorRed + err.Error() + colorReset) + toggledlog.Fatal.Println(err.Error()) os.Exit(ERREXIT_LOADCONF) } @@ -158,7 +156,6 @@ func main() { runtime.GOMAXPROCS(4) var err error var args argContainer - setupColors() // Parse command line arguments var opensslAuto string @@ -202,7 +199,7 @@ func main() { } else { args.openssl, err = strconv.ParseBool(opensslAuto) if err != nil { - toggledlog.Fatal.Printf(colorRed+"Invalid \"-openssl\" setting: %v\n"+colorReset, err) + toggledlog.Fatal.Printf("Invalid \"-openssl\" setting: %v", err) os.Exit(ERREXIT_USAGE) } } @@ -229,7 +226,7 @@ func main() { args.cipherdir, _ = filepath.Abs(flagSet.Arg(0)) err = checkDir(args.cipherdir) if err != nil { - toggledlog.Fatal.Printf(colorRed+"Invalid cipherdir: %v\n"+colorReset, err) + toggledlog.Fatal.Printf("Invalid cipherdir: %v", err) os.Exit(ERREXIT_CIPHERDIR) } } else { @@ -244,7 +241,7 @@ func main() { if args.config != "" { args.config, err = filepath.Abs(args.config) if err != nil { - toggledlog.Fatal.Printf(colorRed+"Invalid \"-config\" setting: %v\n"+colorReset, err) + toggledlog.Fatal.Printf("Invalid \"-config\" setting: %v", err) os.Exit(ERREXIT_INIT) } toggledlog.Info.Printf("Using config file at custom location %s", args.config) @@ -291,7 +288,7 @@ func main() { // "-init" if args.init { if flagSet.NArg() > 1 { - toggledlog.Fatal.Printf("Usage: %s -init [OPTIONS] CIPHERDIR\n", toggledlog.ProgramName) + toggledlog.Fatal.Printf("Usage: %s -init [OPTIONS] CIPHERDIR", toggledlog.ProgramName) os.Exit(ERREXIT_USAGE) } initDir(&args) // does not return @@ -299,7 +296,7 @@ func main() { // "-passwd" if args.passwd { if flagSet.NArg() > 1 { - toggledlog.Fatal.Printf("Usage: %s -passwd [OPTIONS] CIPHERDIR\n", toggledlog.ProgramName) + toggledlog.Fatal.Printf("Usage: %s -passwd [OPTIONS] CIPHERDIR", toggledlog.ProgramName) os.Exit(ERREXIT_USAGE) } changePassword(&args) // does not return @@ -307,17 +304,17 @@ func main() { // Mount // Check mountpoint if flagSet.NArg() != 2 { - toggledlog.Fatal.Printf("Usage: %s [OPTIONS] CIPHERDIR MOUNTPOINT\n", toggledlog.ProgramName) + toggledlog.Fatal.Printf("Usage: %s [OPTIONS] CIPHERDIR MOUNTPOINT", toggledlog.ProgramName) os.Exit(ERREXIT_USAGE) } args.mountpoint, err = filepath.Abs(flagSet.Arg(1)) if err != nil { - toggledlog.Fatal.Printf(colorRed+"Invalid mountpoint: %v\n"+colorReset, err) + toggledlog.Fatal.Printf("Invalid mountpoint: %v", err) os.Exit(ERREXIT_MOUNTPOINT) } err = checkDirEmpty(args.mountpoint) if err != nil { - toggledlog.Fatal.Printf(colorRed+"Invalid mountpoint: %v\n"+colorReset, err) + toggledlog.Fatal.Printf("Invalid mountpoint: %v", err) os.Exit(ERREXIT_MOUNTPOINT) } // Get master key @@ -341,7 +338,7 @@ func main() { // Initialize FUSE server toggledlog.Debug.Printf("cli args: %v", args) srv := initFuseFrontend(masterkey, args, confFile) - toggledlog.Info.Println(colorGreen + "Filesystem mounted and ready." + colorReset) + toggledlog.Info.Println(toggledlog.ColorGreen + "Filesystem mounted and ready." + toggledlog.ColorReset) // We are ready - send USR1 signal to our parent and switch to syslog if args.notifypid > 0 { sendUsr1(args.notifypid) @@ -410,8 +407,8 @@ func initFuseFrontend(key []byte, args argContainer, confFile *configfile.ConfFi var mOpts fuse.MountOptions mOpts.AllowOther = false if args.allow_other { - toggledlog.Info.Printf(colorYellow + "The option \"-allow_other\" is set. Make sure the file " + - "permissions protect your data from unwanted access." + colorReset) + toggledlog.Info.Printf(toggledlog.ColorYellow + "The option \"-allow_other\" is set. Make sure the file " + + "permissions protect your data from unwanted access." + toggledlog.ColorReset) mOpts.AllowOther = true // Make the kernel check the file permissions for us mOpts.Options = append(mOpts.Options, "default_permissions") @@ -455,16 +452,3 @@ func handleSigint(srv *fuse.Server, mountpoint string) { os.Exit(1) }() } - -// Escape sequences for terminal colors -var colorReset, colorGrey, colorRed, colorGreen, colorYellow string - -func setupColors() { - if terminal.IsTerminal(int(os.Stdout.Fd())) { - colorReset = "\033[0m" - colorGrey = "\033[2m" - colorRed = "\033[31m" - colorGreen = "\033[32m" - colorYellow = "\033[33m" - } -} diff --git a/masterkey.go b/masterkey.go index 5216f72..55da1ea 100644 --- a/masterkey.go +++ b/masterkey.go @@ -35,7 +35,7 @@ If the gocryptfs.conf file becomes corrupted or you ever forget your password, there is only one hope for recovery: The master key. Print it to a piece of paper and store it in a drawer. -`, colorGrey+hChunked+colorReset) +`, toggledlog.ColorGrey+hChunked+toggledlog.ColorReset) } // parseMasterKey - Parse a hex-encoded master key that was passed on the command line