4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Daemon log message. This can direct log messages to either stdout,
31 * an error log file or syslog (or any combination).
42 #include <fcode/private.h>
43 #include <fcode/log.h>
45 #define LOG_LINESIZE 256
46 #define LOG_EMIT_BUFSIZE LOG_LINESIZE
48 static FILE *error_log_fp
= NULL
;
49 static int syslog_opened
= 0;
50 static int error_log_flags
;
51 static int syslog_log_flags
;
52 static int do_emit_flag
= -1;
53 static int daemon_log_flag
;
54 static int min_syslog_level
= LOG_ERR
;
56 static int log_to_stdout(int);
57 static int log_to_error_log(int);
58 static int log_to_syslog(int);
59 static int msg_level_to_syslog(int);
62 * Complicated by not wanting to do any emit processing if no one's actually
68 static char emit_buf
[LOG_EMIT_BUFSIZE
];
69 static char *emit_p
= emit_buf
;
70 static int lastnl
= 1;
73 * No one has set the do_emit_flag, go ahead and figure it out.
75 if (do_emit_flag
< 0) {
76 do_emit_flag
= (log_to_stdout(MSG_EMIT
) |
77 log_to_error_log(MSG_EMIT
) | log_to_syslog(MSG_EMIT
));
84 * Check for buffer overflow.
86 if (emit_p
>= &emit_buf
[LOG_EMIT_BUFSIZE
- 1]) {
88 log_message(MSG_EMIT
, "emit: %s\n", emit_buf
);
94 * Fcode emit's may output both CR/LF, we go ahead and eat multiple
97 if (c
== '\n' || c
== '\r') {
100 log_message(MSG_EMIT
, "emit: %s\n", emit_buf
);
111 * If stdout is a tty and this is MSG_EMIT, we should have alredy output it.
112 * If running as daemon, output to stdout is a waste of time.
115 log_to_stdout(int msg_level
)
117 if (isatty(fileno(stdin
)) && (msg_level
& MSG_EMIT
) != 0)
119 return (daemon_log_flag
== 0);
123 * Can't turn off FATAL or ERROR messages to error log file.
126 log_to_error_log(int msg_level
)
130 if (msg_level
& (MSG_FATAL
|MSG_ERROR
))
132 return (msg_level
& error_log_flags
);
136 * Can't turn off FATAL or ERROR messages to syslog.
139 log_to_syslog(int msg_level
)
143 if (msg_level
& (MSG_FATAL
|MSG_ERROR
))
145 return (msg_level
& syslog_log_flags
);
149 * Turn internal MSG level to syslog msg level. Don't return a msg level
150 * lower priority than min_syslog_level.
153 msg_level_to_syslog(int msg_level
)
155 if (min_syslog_level
<= LOG_ERR
)
156 return (min_syslog_level
);
157 if (msg_level
& (MSG_FATAL
|MSG_ERROR
))
159 if (min_syslog_level
<= LOG_WARNING
)
160 return (min_syslog_level
);
161 if (msg_level
& MSG_WARN
)
162 return (LOG_WARNING
);
163 if (min_syslog_level
<= LOG_NOTICE
)
164 return (min_syslog_level
);
165 if (msg_level
& MSG_NOTE
)
167 if (min_syslog_level
<= LOG_INFO
)
168 return (min_syslog_level
);
169 if (msg_level
& MSG_INFO
)
171 return (min(min_syslog_level
, LOG_DEBUG
));
175 * Log a message to the appropriate places.
178 log_message(int msg_level
, char *fmt
, ...)
181 char msg
[LOG_LINESIZE
], *p
;
182 static char log_msg
[LOG_LINESIZE
];
186 vsprintf(msg
, fmt
, ap
);
188 if (log_to_stdout(msg_level
)) {
192 if (log_to_error_log(msg_level
)) {
193 fprintf(error_log_fp
, msg
);
194 fflush(error_log_fp
);
196 if (log_to_syslog(msg_level
)) {
197 if (strlen(log_msg
) + strlen(msg
) > LOG_LINESIZE
- 1) {
198 syslog(msg_level_to_syslog(msg_level
), log_msg
);
201 strcat(log_msg
, msg
);
202 if ((p
= strchr(log_msg
, '\n')) != NULL
) {
204 syslog(msg_level_to_syslog(msg_level
), log_msg
);
211 * Output debug message
214 debug_msg(int debug_level
, char *fmt
, ...)
217 char msg
[LOG_LINESIZE
];
219 if ((debug_level
& get_interpreter_debug_level()) == 0)
224 vsprintf(msg
, fmt
, ap
);
226 log_message(MSG_DEBUG
, msg
);
230 * Log a perror message to the appropriate places.
233 log_perror(int msg_level
, char *fmt
, ...)
236 char msg
[LOG_LINESIZE
], tmp
[LOG_LINESIZE
];
240 vsprintf(msg
, fmt
, ap
);
241 sprintf(tmp
, "%s: %s\n", msg
, strerror(errno
));
242 log_message(msg_level
, tmp
);
246 set_min_syslog_level(int level
)
248 min_syslog_level
= level
;
251 char *error_log_name
;
254 open_error_log(char *fname
, int errflags
)
256 if ((error_log_fp
= fopen(fname
, "a")) == NULL
) {
257 log_perror(MSG_FATAL
, fname
);
260 error_log_name
= STRDUP(fname
);
261 error_log_flags
= errflags
;
262 do_emit_flag
= (log_to_stdout(MSG_EMIT
) | log_to_error_log(MSG_EMIT
) |
263 log_to_syslog(MSG_EMIT
));
267 open_syslog_log(char *logname
, int logflags
)
269 openlog(logname
, LOG_PID
, LOG_DAEMON
);
270 syslog_log_flags
= logflags
;
271 do_emit_flag
= (log_to_stdout(MSG_EMIT
) | log_to_error_log(MSG_EMIT
) |
272 log_to_syslog(MSG_EMIT
));
277 * Turn on/off syslog LOG_DAEMON flag to syslog messages. Also controls
278 * outputting to stdout, which is a waste of time when we're running as a
282 set_daemon_log_flag(int flag
)
285 daemon_log_flag
= LOG_DAEMON
;
291 parse_msg_flags(char *flags
)
296 while ((c
= *flags
++) != '\0') {
298 case 'f': msgflags
|= MSG_FATAL
; break;
299 case 'e': msgflags
|= MSG_ERROR
; break;
300 case 'w': msgflags
|= MSG_WARN
; break;
301 case 'i': msgflags
|= MSG_INFO
; break;
302 case 'd': msgflags
|= MSG_DEBUG
; break;
303 case 'D': msgflags
|= MSG_FC_DEBUG
; break;
306 log_message(MSG_ERROR
, "Invalid msglvl flag: %c\n", c
);
313 #define MAXERRBUF 256
314 char error_buffer
[MAXERRBUF
];
317 dot_error_buffer(fcode_env_t
*env
)
319 log_message(MSG_INFO
, "%s\n", error_buffer
);
323 set_error_log(fcode_env_t
*env
)
329 fname
= pop_a_string(env
, NULL
);
331 if ((fp
= fopen(fname
, "a")) == NULL
) {
332 log_perror(MSG_ERROR
, "Can't open '%s'\n", fname
);
336 fclose(error_log_fp
);
338 FREE(error_log_name
);
340 error_log_name
= STRDUP(fname
);
341 error_log_flags
= MSG_FATAL
|MSG_ERROR
|MSG_WARN
|MSG_INFO
|
342 MSG_DEBUG
|MSG_FC_DEBUG
;
343 } else if (error_log_name
)
344 log_message(MSG_INFO
, "%s\n", error_log_name
);
346 log_message(MSG_INFO
, "NULL\n");
354 fcode_env_t
*env
= initial_env
;
359 FORTH(0, ".error-buffer", dot_error_buffer
);
360 FORTH(0, "set-error-log", set_error_log
);