1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
|
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* SYSLOG -- print message on log file
*
* This routine looks a lot like printf, except that it
* outputs to the log file instead of the standard output.
* Also:
* adds a timestamp,
* prints the module name in front of the message,
* has some other formatting types (or will sometime),
* adds a newline on the end of the message.
*
* The output of this routine is intended to be read by /etc/syslogd.
*
* Author: Eric Allman
* Modified to use UNIX domain IPC by Ralph Campbell
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/signal.h>
#include <sys/syslog.h>
#include <sys/time.h>
#include <sys/unistd.h>
#include <netdb.h>
#include <strings.h>
#include <stdarg.h>
#include <vfork.h>
#include <stdio.h>
#include <errno.h>
#include <malloc.h>
#define MAXLINE 1024 /* max message size */
#define PRIMASK(p) (1 << ((p) & LOG_PRIMASK))
#define PRIFAC(p) (((p) & LOG_FACMASK) >> 3)
#define IMPORTANT LOG_ERR
static char *logname = "/dev/log";
static char *ctty = "/dev/console";
static char *sysmsg = "/dev/sysmsg";
static struct _syslog {
int _LogFile;
int _LogStat;
char *_LogTag;
int _LogMask;
struct sockaddr _SyslogAddr;
char *_SyslogHost;
int _LogFacility;
} *_syslog;
#define LogFile (_syslog->_LogFile)
#define LogStat (_syslog->_LogStat)
#define LogTag (_syslog->_LogTag)
#define LogMask (_syslog->_LogMask)
#define SyslogAddr (_syslog->_SyslogAddr)
#define SyslogHost (_syslog->_SyslogHost)
#define LogFacility (_syslog->_LogFacility)
extern char *strerror(int);
extern time_t time();
void vsyslog(int, char *, va_list);
void openlog(char *, int, int);
static int snprintf(char *, size_t, char *, ...);
static int vsnprintf(char *, size_t, char *, va_list ap);
static int
allocstatic(void)
{
_syslog = (struct _syslog *)calloc(1, sizeof (struct _syslog));
if (_syslog == 0)
return (0); /* can't do it */
LogFile = -1; /* fd for log */
LogStat = 0; /* status bits, set by openlog() */
LogTag = "syslog"; /* string to tag the entry with */
LogMask = 0xff; /* mask of priorities to be logged */
LogFacility = LOG_USER; /* default facility code */
return (1);
}
void
syslog(int pri, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsyslog(pri, fmt, ap);
va_end(ap);
}
void
vsyslog(int pri, char *fmt, va_list ap)
{
char buf[MAXLINE + 1], outline[MAXLINE + 1];
char *b, *f, *o;
int c;
long now;
int pid, olderrno = errno;
int retsiz, outsiz = MAXLINE + 1;
int taglen;
/*
* Maximum tag length is 256 (the pad in outline) minus the size of the
* other things that can go in the pad.
*/
#define MAX_TAG 230
if (_syslog == 0 && !allocstatic())
return;
/* see if we should just throw out this message */
if (pri <= 0 || PRIFAC(pri) >= LOG_NFACILITIES ||
(PRIMASK(pri) & LogMask) == 0)
return;
if (LogFile < 0)
openlog(LogTag, LogStat | LOG_NDELAY, 0);
/* set default facility if none specified */
if ((pri & LOG_FACMASK) == 0)
pri |= LogFacility;
/* build the message */
o = outline;
(void) time(&now);
(void) sprintf(o, "<%d>%.15s ", pri, ctime(&now) + 4);
o += strlen(o);
if (LogTag) {
taglen = strlen(LogTag) < MAX_TAG ? strlen(LogTag) : MAX_TAG;
strncpy(o, LogTag, taglen);
o[taglen] = '\0';
o += strlen(o);
}
if (LogStat & LOG_PID) {
(void) sprintf(o, "[%d]", getpid());
o += strlen(o);
}
if (LogTag) {
(void) strcpy(o, ": ");
o += 2;
}
b = buf;
f = fmt;
while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) {
char *errstr;
if (c != '%') {
*b++ = c;
continue;
}
if ((c = *f++) != 'm') {
*b++ = '%';
*b++ = c;
continue;
}
if ((errstr = strerror(olderrno)) == NULL)
(void) snprintf(b, &buf[MAXLINE] - b, "error %d",
olderrno);
else {
while (*errstr != '\0' && b < &buf[MAXLINE]) {
if (*errstr == '%') {
strcpy(b, "%%");
b += 2;
}
else
*b++ = *errstr;
errstr++;
}
*b = '\0';
}
b += strlen(b);
}
if (b > buf && *(b-1) != '\n') /* ensure at least one newline */
*b++ = '\n';
*b = '\0';
(void) vsnprintf(o, &outline[sizeof (outline)] - o, buf, ap);
c = strlen(outline) + 1; /* add one for NULL byte */
if (c > MAXLINE) {
c = MAXLINE;
outline[MAXLINE-1] = '\0';
}
/* output the message to the local logger */
if (sendto(LogFile, outline, c, 0, &SyslogAddr,
sizeof (SyslogAddr)) >= 0)
return;
if (!(LogStat & LOG_CONS))
return;
/* output the message to the console */
pid = vfork();
if (pid == -1)
return;
if (pid == 0) {
int fd;
(void) signal(SIGALRM, SIG_DFL);
(void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
(void) alarm(5);
if (((fd = open(sysmsg, O_WRONLY)) >= 0) ||
(fd = open(ctty, O_WRONLY)) >= 0) {
(void) alarm(0);
if (outsiz > 2) { /* Just in case */
(void) strcat(o, "\r\n");
c += 2;
}
o = index(outline, '>') + 1;
(void) write(fd, o, c - (o - outline));
(void) close(fd);
} else
(void) alarm(0);
_exit(0);
}
if (!(LogStat & LOG_NOWAIT))
while ((c = wait((int *)0)) > 0 && c != pid)
;
}
/*
* OPENLOG -- open system log
*/
void
openlog(char *ident, int logstat, int logfac)
{
if (_syslog == 0 && !allocstatic())
return;
if (ident != NULL)
LogTag = ident;
LogStat = logstat;
if (logfac != 0)
LogFacility = logfac & LOG_FACMASK;
if (LogFile >= 0)
return;
SyslogAddr.sa_family = AF_UNIX;
(void) strncpy(SyslogAddr.sa_data, logname,
sizeof (SyslogAddr.sa_data));
if (LogStat & LOG_NDELAY) {
LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
(void) fcntl(LogFile, F_SETFD, 1);
}
}
/*
* CLOSELOG -- close the system log
*/
void
closelog(void)
{
if (_syslog == 0)
return;
(void) close(LogFile);
LogFile = -1;
}
/*
* SETLOGMASK -- set the log mask level
*/
int
setlogmask(int pmask)
{
int omask;
if (_syslog == 0 && !allocstatic())
return (-1);
omask = LogMask;
if (pmask != 0)
LogMask = pmask;
return (omask);
}
/*
* snprintf/vsnprintf -- These routines are here
* temporarily to solve bugid 1220257. Perhaps
* they could become a public interface at some
* point but not for now.
*/
extern int _doprnt();
static int
snprintf(char *string, size_t n, char *format, ...)
{
int count;
FILE siop;
va_list ap;
if (n == 0)
return (0);
siop._cnt = n - 1;
siop._base = siop._ptr = (unsigned char *)string;
siop._flag = _IOWRT+_IOSTRG;
va_start(ap, format);
count = _doprnt(format, ap, &siop);
va_end(ap);
*siop._ptr = '\0'; /* plant terminating null character */
return (count);
}
static int
vsnprintf(char *string, size_t n, char *format, va_list ap)
{
int count;
FILE siop;
if (n == 0)
return (0);
siop._cnt = n - 1;
siop._base = siop._ptr = (unsigned char *)string;
siop._flag = _IOWRT+_IOSTRG;
count = _doprnt(format, ap, &siop);
*siop._ptr = '\0'; /* plant terminating null character */
return (count);
}
|