// Frontend: Logging functions for programs using the safcm library // SPDX-License-Identifier: GPL-3.0-or-later // Copyright (C) 2021-2024 Simon Ruderich package frontend import ( "fmt" "log" "ruderich.org/simon/safcm" "ruderich.org/simon/safcm/rpc" ) type Event struct { Host Host // Only one of Error, Log and ConnEvent is set in a single event Error error Log Log ConnEvent rpc.ConnEvent Escaped bool // true if untrusted input is already escaped } type Log struct { Level safcm.LogLevel Text string } func (l *Loop) Log(host Host, level safcm.LogLevel, escaped bool, msg string) { l.events <- Event{ Host: host, Log: Log{ Level: level, Text: msg, }, Escaped: escaped, } } // LogEvent logs events using the log package. It can be used to implement // Loop.LogEventFunc. It's used by cmd/safcm to log events. func LogEvent(x Event, level safcm.LogLevel, isTTY bool, failed *bool) { // We have multiple event sources so this is somewhat ugly. var prefix, data string var color Color if x.Error != nil { prefix = "[error]" data = x.Error.Error() color = ColorRed // We logged an error, tell the caller *failed = true } else if x.Log.Level != 0 { if level < x.Log.Level { return } // LogError and LogDebug3 should not occur here switch x.Log.Level { case safcm.LogInfo: prefix = "[info]" case safcm.LogVerbose: prefix = "[verbose]" case safcm.LogDebug: prefix = "[debug]" case safcm.LogDebug2: prefix = "[debug2]" default: prefix = fmt.Sprintf("[INVALID=%d]", x.Log.Level) color = ColorRed } data = x.Log.Text } else { switch x.ConnEvent.Type { case rpc.ConnEventStderr: prefix = "[stderr]" case rpc.ConnEventDebug: prefix = "[debug3]" case rpc.ConnEventUpload: if level < safcm.LogInfo { return } prefix = "[info]" x.ConnEvent.Data = "remote helper upload in progress" default: prefix = fmt.Sprintf("[INVALID=%d]", x.ConnEvent.Type) color = ColorRed } data = x.ConnEvent.Data } host := x.Host.Name() if color != 0 { host = ColorString(isTTY, color, host) } // Make sure to escape control characters to prevent terminal // injection attacks if !x.Escaped { data = EscapeControlCharacters(isTTY, data) } log.Printf("%-9s [%s] %s", prefix, host, data) }