* lib/scanasm.exp (hidden-scan-for): Add XCOFF support.
[official-gcc.git] / libgo / go / log / syslog / syslog.go
blob9e888dd1d9dd4d92ba9a7b71847cdbec27fec3e7
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 and prefix.
106 func New(priority Priority, tag string) (*Writer, error) {
107 return Dial("", "", priority, tag)
110 // Dial establishes a connection to a log daemon by connecting to
111 // address raddr on the specified network. Each write to the returned
112 // writer sends a log message with the given facility, severity and
113 // tag.
114 // If network is empty, Dial will connect to the local syslog server.
115 func Dial(network, raddr string, priority Priority, tag string) (*Writer, error) {
116 if priority < 0 || priority > LOG_LOCAL7|LOG_DEBUG {
117 return nil, errors.New("log/syslog: invalid priority")
120 if tag == "" {
121 tag = os.Args[0]
123 hostname, _ := os.Hostname()
125 w := &Writer{
126 priority: priority,
127 tag: tag,
128 hostname: hostname,
129 network: network,
130 raddr: raddr,
133 w.mu.Lock()
134 defer w.mu.Unlock()
136 err := w.connect()
137 if err != nil {
138 return nil, err
140 return w, err
143 // connect makes a connection to the syslog server.
144 // It must be called with w.mu held.
145 func (w *Writer) connect() (err error) {
146 if w.conn != nil {
147 // ignore err from close, it makes sense to continue anyway
148 w.conn.close()
149 w.conn = nil
152 if w.network == "" {
153 w.conn, err = unixSyslog()
154 if w.hostname == "" {
155 w.hostname = "localhost"
157 } else {
158 var c net.Conn
159 c, err = net.Dial(w.network, w.raddr)
160 if err == nil {
161 w.conn = &netConn{conn: c}
162 if w.hostname == "" {
163 w.hostname = c.LocalAddr().String()
167 return
170 // Write sends a log message to the syslog daemon.
171 func (w *Writer) Write(b []byte) (int, error) {
172 return w.writeAndRetry(w.priority, string(b))
175 // Close closes a connection to the syslog daemon.
176 func (w *Writer) Close() error {
177 w.mu.Lock()
178 defer w.mu.Unlock()
180 if w.conn != nil {
181 err := w.conn.close()
182 w.conn = nil
183 return err
185 return nil
188 // Emerg logs a message with severity LOG_EMERG, ignoring the severity
189 // passed to New.
190 func (w *Writer) Emerg(m string) error {
191 _, err := w.writeAndRetry(LOG_EMERG, m)
192 return err
195 // Alert logs a message with severity LOG_ALERT, ignoring the severity
196 // passed to New.
197 func (w *Writer) Alert(m string) error {
198 _, err := w.writeAndRetry(LOG_ALERT, m)
199 return err
202 // Crit logs a message with severity LOG_CRIT, ignoring the severity
203 // passed to New.
204 func (w *Writer) Crit(m string) error {
205 _, err := w.writeAndRetry(LOG_CRIT, m)
206 return err
209 // Err logs a message with severity LOG_ERR, ignoring the severity
210 // passed to New.
211 func (w *Writer) Err(m string) error {
212 _, err := w.writeAndRetry(LOG_ERR, m)
213 return err
216 // Warning logs a message with severity LOG_WARNING, ignoring the
217 // severity passed to New.
218 func (w *Writer) Warning(m string) error {
219 _, err := w.writeAndRetry(LOG_WARNING, m)
220 return err
223 // Notice logs a message with severity LOG_NOTICE, ignoring the
224 // severity passed to New.
225 func (w *Writer) Notice(m string) error {
226 _, err := w.writeAndRetry(LOG_NOTICE, m)
227 return err
230 // Info logs a message with severity LOG_INFO, ignoring the severity
231 // passed to New.
232 func (w *Writer) Info(m string) error {
233 _, err := w.writeAndRetry(LOG_INFO, m)
234 return err
237 // Debug logs a message with severity LOG_DEBUG, ignoring the severity
238 // passed to New.
239 func (w *Writer) Debug(m string) error {
240 _, err := w.writeAndRetry(LOG_DEBUG, m)
241 return err
244 func (w *Writer) writeAndRetry(p Priority, s string) (int, error) {
245 pr := (w.priority & facilityMask) | (p & severityMask)
247 w.mu.Lock()
248 defer w.mu.Unlock()
250 if w.conn != nil {
251 if n, err := w.write(pr, s); err == nil {
252 return n, err
255 if err := w.connect(); err != nil {
256 return 0, err
258 return w.write(pr, s)
261 // write generates and writes a syslog formatted string. The
262 // format is as follows: <PRI>TIMESTAMP HOSTNAME TAG[PID]: MSG
263 func (w *Writer) write(p Priority, msg string) (int, error) {
264 // ensure it ends in a \n
265 nl := ""
266 if !strings.HasSuffix(msg, "\n") {
267 nl = "\n"
270 err := w.conn.writeString(p, w.hostname, w.tag, msg, nl)
271 if err != nil {
272 return 0, err
274 // Note: return the length of the input, not the number of
275 // bytes printed by Fprintf, because this must behave like
276 // an io.Writer.
277 return len(msg), nil
280 func (n *netConn) writeString(p Priority, hostname, tag, msg, nl string) error {
281 if n.local {
282 // Compared to the network form below, the changes are:
283 // 1. Use time.Stamp instead of time.RFC3339.
284 // 2. Drop the hostname field from the Fprintf.
285 timestamp := time.Now().Format(time.Stamp)
286 _, err := fmt.Fprintf(n.conn, "<%d>%s %s[%d]: %s%s",
287 p, timestamp,
288 tag, os.Getpid(), msg, nl)
289 return err
291 timestamp := time.Now().Format(time.RFC3339)
292 _, err := fmt.Fprintf(n.conn, "<%d>%s %s %s[%d]: %s%s",
293 p, timestamp, hostname,
294 tag, os.Getpid(), msg, nl)
295 return err
298 func (n *netConn) close() error {
299 return n.conn.Close()
302 // NewLogger creates a log.Logger whose output is written to
303 // the system log service with the specified priority. The logFlag
304 // argument is the flag set passed through to log.New to create
305 // the Logger.
306 func NewLogger(p Priority, logFlag int) (*log.Logger, error) {
307 s, err := New(p, "")
308 if err != nil {
309 return nil, err
311 return log.New(s, "", logFlag), nil