]> ruderich.org/simon Gitweb - safcm/safcm.git/blob - frontend/log.go
Use SPDX license identifiers
[safcm/safcm.git] / frontend / log.go
1 // Frontend: Logging functions for programs using the safcm library
2
3 // SPDX-License-Identifier: GPL-3.0-or-later
4 // Copyright (C) 2021-2024  Simon Ruderich
5
6 package frontend
7
8 import (
9         "fmt"
10         "log"
11
12         "ruderich.org/simon/safcm"
13         "ruderich.org/simon/safcm/rpc"
14 )
15
16 type Event struct {
17         Host Host
18
19         // Only one of Error, Log and ConnEvent is set in a single event
20         Error     error
21         Log       Log
22         ConnEvent rpc.ConnEvent
23
24         Escaped bool // true if untrusted input is already escaped
25 }
26
27 type Log struct {
28         Level safcm.LogLevel
29         Text  string
30 }
31
32 func (l *Loop) Log(host Host, level safcm.LogLevel, escaped bool,
33         msg string) {
34
35         l.events <- Event{
36                 Host: host,
37                 Log: Log{
38                         Level: level,
39                         Text:  msg,
40                 },
41                 Escaped: escaped,
42         }
43 }
44
45 // LogEvent logs events using the log package. It can be used to implement
46 // Loop.LogEventFunc. It's used by cmd/safcm to log events.
47 func LogEvent(x Event, level safcm.LogLevel, isTTY bool,
48         failed *bool) {
49
50         // We have multiple event sources so this is somewhat ugly.
51         var prefix, data string
52         var color Color
53         if x.Error != nil {
54                 prefix = "[error]"
55                 data = x.Error.Error()
56                 color = ColorRed
57                 // We logged an error, tell the caller
58                 *failed = true
59         } else if x.Log.Level != 0 {
60                 if level < x.Log.Level {
61                         return
62                 }
63                 // LogError and LogDebug3 should not occur here
64                 switch x.Log.Level {
65                 case safcm.LogInfo:
66                         prefix = "[info]"
67                 case safcm.LogVerbose:
68                         prefix = "[verbose]"
69                 case safcm.LogDebug:
70                         prefix = "[debug]"
71                 case safcm.LogDebug2:
72                         prefix = "[debug2]"
73                 default:
74                         prefix = fmt.Sprintf("[INVALID=%d]", x.Log.Level)
75                         color = ColorRed
76                 }
77                 data = x.Log.Text
78         } else {
79                 switch x.ConnEvent.Type {
80                 case rpc.ConnEventStderr:
81                         prefix = "[stderr]"
82                 case rpc.ConnEventDebug:
83                         prefix = "[debug3]"
84                 case rpc.ConnEventUpload:
85                         if level < safcm.LogInfo {
86                                 return
87                         }
88                         prefix = "[info]"
89                         x.ConnEvent.Data = "remote helper upload in progress"
90                 default:
91                         prefix = fmt.Sprintf("[INVALID=%d]", x.ConnEvent.Type)
92                         color = ColorRed
93                 }
94                 data = x.ConnEvent.Data
95         }
96
97         host := x.Host.Name()
98         if color != 0 {
99                 host = ColorString(isTTY, color, host)
100         }
101         // Make sure to escape control characters to prevent terminal
102         // injection attacks
103         if !x.Escaped {
104                 data = EscapeControlCharacters(isTTY, data)
105         }
106         log.Printf("%-9s [%s] %s", prefix, host, data)
107 }