PR c++/86342 - -Wdeprecated-copy and system headers.
[official-gcc.git] / libgo / go / log / syslog / syslog.go
blobdfd0028e5c10e42e0b719f2c919515a28244b058
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build !windows,!nacl,!plan9
7 package syslog
9 import (
10 "errors"
11 "fmt"
12 "log"
13 "net"
14 "os"
15 "strings"
16 "sync"
17 "time"
20 // The Priority is a combination of the syslog facility and
21 // severity. For example, LOG_ALERT | LOG_FTP sends an alert severity
22 // message from the FTP facility. The default severity is LOG_EMERG;
23 // the default facility is LOG_KERN.
24 type Priority int
26 const severityMask = 0x07
27 const facilityMask = 0xf8
29 const (
30 // Severity.
32 // From /usr/include/sys/syslog.h.
33 // These are the same on Linux, BSD, and OS X.
34 LOG_EMERG Priority = iota
35 LOG_ALERT
36 LOG_CRIT
37 LOG_ERR
38 LOG_WARNING
39 LOG_NOTICE
40 LOG_INFO
41 LOG_DEBUG
44 const (
45 // Facility.
47 // From /usr/include/sys/syslog.h.
48 // These are the same up to LOG_FTP on Linux, BSD, and OS X.
49 LOG_KERN Priority = iota << 3
50 LOG_USER
51 LOG_MAIL
52 LOG_DAEMON
53 LOG_AUTH
54 LOG_SYSLOG
55 LOG_LPR
56 LOG_NEWS
57 LOG_UUCP
58 LOG_CRON
59 LOG_AUTHPRIV
60 LOG_FTP
61 _ // unused
62 _ // unused
63 _ // unused
64 _ // unused
65 LOG_LOCAL0
66 LOG_LOCAL1
67 LOG_LOCAL2
68 LOG_LOCAL3
69 LOG_LOCAL4
70 LOG_LOCAL5
71 LOG_LOCAL6
72 LOG_LOCAL7
75 // A Writer is a connection to a syslog server.
76 type Writer struct {
77 priority Priority
78 tag string
79 hostname string
80 network string
81 raddr string
83 mu sync.Mutex // guards conn
84 conn serverConn
87 // This interface and the separate syslog_unix.go file exist for
88 // Solaris support as implemented by gccgo. On Solaris you cannot
89 // simply open a TCP connection to the syslog daemon. The gccgo
90 // sources have a syslog_solaris.go file that implements unixSyslog to
91 // return a type that satisfies this interface and simply calls the C
92 // library syslog function.
93 type serverConn interface {
94 writeString(p Priority, hostname, tag, s, nl string) error
95 close() error
98 type netConn struct {
99 local bool
100 conn net.Conn
103 // New establishes a new connection to the system log daemon. Each
104 // write to the returned writer sends a log message with the given
105 // priority (a combination of the syslog facility and severity) and
106 // prefix tag. If tag is empty, the os.Args[0] is used.
107 func New(priority Priority, tag string) (*Writer, error) {
108 return Dial("", "", priority, tag)
111 // Dial establishes a connection to a log daemon by connecting to
112 // address raddr on the specified network. Each write to the returned
113 // writer sends a log message with the facility and severity
114 // (from priority) and tag. If tag is empty, the os.Args[0] is used.
115 // If network is empty, Dial will connect to the local syslog server.
116 // Otherwise, see the documentation for net.Dial for valid values
117 // of network and raddr.
118 func Dial(network, raddr string, priority Priority, tag string) (*Writer, error) {
119 if priority < 0 || priority > LOG_LOCAL7|LOG_DEBUG {
120 return nil, errors.New("log/syslog: invalid priority")
123 if tag == "" {
124 tag = os.Args[0]
126 hostname, _ := os.Hostname()
128 w := &Writer{
129 priority: priority,
130 tag: tag,
131 hostname: hostname,
132 network: network,
133 raddr: raddr,
136 w.mu.Lock()
137 defer w.mu.Unlock()
139 err := w.connect()
140 if err != nil {
141 return nil, err
143 return w, err
146 // connect makes a connection to the syslog server.
147 // It must be called with w.mu held.
148 func (w *Writer) connect() (err error) {
149 if w.conn != nil {
150 // ignore err from close, it makes sense to continue anyway
151 w.conn.close()
152 w.conn = nil
155 if w.network == "" {
156 w.conn, err = unixSyslog()
157 if w.hostname == "" {
158 w.hostname = "localhost"
160 } else {
161 var c net.Conn
162 c, err = net.Dial(w.network, w.raddr)
163 if err == nil {
164 w.conn = &netConn{conn: c}
165 if w.hostname == "" {
166 w.hostname = c.LocalAddr().String()
170 return
173 // Write sends a log message to the syslog daemon.
174 func (w *Writer) Write(b []byte) (int, error) {
175 return w.writeAndRetry(w.priority, string(b))
178 // Close closes a connection to the syslog daemon.
179 func (w *Writer) Close() error {
180 w.mu.Lock()
181 defer w.mu.Unlock()
183 if w.conn != nil {
184 err := w.conn.close()
185 w.conn = nil
186 return err
188 return nil
191 // Emerg logs a message with severity LOG_EMERG, ignoring the severity
192 // passed to New.
193 func (w *Writer) Emerg(m string) error {
194 _, err := w.writeAndRetry(LOG_EMERG, m)
195 return err
198 // Alert logs a message with severity LOG_ALERT, ignoring the severity
199 // passed to New.
200 func (w *Writer) Alert(m string) error {
201 _, err := w.writeAndRetry(LOG_ALERT, m)
202 return err
205 // Crit logs a message with severity LOG_CRIT, ignoring the severity
206 // passed to New.
207 func (w *Writer) Crit(m string) error {
208 _, err := w.writeAndRetry(LOG_CRIT, m)
209 return err
212 // Err logs a message with severity LOG_ERR, ignoring the severity
213 // passed to New.
214 func (w *Writer) Err(m string) error {
215 _, err := w.writeAndRetry(LOG_ERR, m)
216 return err
219 // Warning logs a message with severity LOG_WARNING, ignoring the
220 // severity passed to New.
221 func (w *Writer) Warning(m string) error {
222 _, err := w.writeAndRetry(LOG_WARNING, m)
223 return err
226 // Notice logs a message with severity LOG_NOTICE, ignoring the
227 // severity passed to New.
228 func (w *Writer) Notice(m string) error {
229 _, err := w.writeAndRetry(LOG_NOTICE, m)
230 return err
233 // Info logs a message with severity LOG_INFO, ignoring the severity
234 // passed to New.
235 func (w *Writer) Info(m string) error {
236 _, err := w.writeAndRetry(LOG_INFO, m)
237 return err
240 // Debug logs a message with severity LOG_DEBUG, ignoring the severity
241 // passed to New.
242 func (w *Writer) Debug(m string) error {
243 _, err := w.writeAndRetry(LOG_DEBUG, m)
244 return err
247 func (w *Writer) writeAndRetry(p Priority, s string) (int, error) {
248 pr := (w.priority & facilityMask) | (p & severityMask)
250 w.mu.Lock()
251 defer w.mu.Unlock()
253 if w.conn != nil {
254 if n, err := w.write(pr, s); err == nil {
255 return n, err
258 if err := w.connect(); err != nil {
259 return 0, err
261 return w.write(pr, s)
264 // write generates and writes a syslog formatted string. The
265 // format is as follows: <PRI>TIMESTAMP HOSTNAME TAG[PID]: MSG
266 func (w *Writer) write(p Priority, msg string) (int, error) {
267 // ensure it ends in a \n
268 nl := ""
269 if !strings.HasSuffix(msg, "\n") {
270 nl = "\n"
273 err := w.conn.writeString(p, w.hostname, w.tag, msg, nl)
274 if err != nil {
275 return 0, err
277 // Note: return the length of the input, not the number of
278 // bytes printed by Fprintf, because this must behave like
279 // an io.Writer.
280 return len(msg), nil
283 func (n *netConn) writeString(p Priority, hostname, tag, msg, nl string) error {
284 if n.local {
285 // Compared to the network form below, the changes are:
286 // 1. Use time.Stamp instead of time.RFC3339.
287 // 2. Drop the hostname field from the Fprintf.
288 timestamp := time.Now().Format(time.Stamp)
289 _, err := fmt.Fprintf(n.conn, "<%d>%s %s[%d]: %s%s",
290 p, timestamp,
291 tag, os.Getpid(), msg, nl)
292 return err
294 timestamp := time.Now().Format(time.RFC3339)
295 _, err := fmt.Fprintf(n.conn, "<%d>%s %s %s[%d]: %s%s",
296 p, timestamp, hostname,
297 tag, os.Getpid(), msg, nl)
298 return err
301 func (n *netConn) close() error {
302 return n.conn.Close()
305 // NewLogger creates a log.Logger whose output is written to the
306 // system log service with the specified priority, a combination of
307 // the syslog facility and severity. The logFlag argument is the flag
308 // set passed through to log.New to create the Logger.
309 func NewLogger(p Priority, logFlag int) (*log.Logger, error) {
310 s, err := New(p, "")
311 if err != nil {
312 return nil, err
314 return log.New(s, "", logFlag), nil