4 Copyright (C) Andrew Tridgell 2008
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "../include/ctdb_client.h"
22 #include "../include/ctdb_private.h"
23 #include "system/syslog.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "lib/util/debug.h"
28 struct syslog_message
{
35 struct ctdb_syslog_state
{
40 static int syslogd_is_started
= 0;
42 /* called when child is finished
43 * this is for the syslog daemon, we can not use DEBUG here
45 static void ctdb_syslog_handler(struct event_context
*ev
, struct fd_event
*fde
,
46 uint16_t flags
, void *p
)
48 struct ctdb_syslog_state
*state
= talloc_get_type(p
, struct ctdb_syslog_state
);
52 struct syslog_message
*msg
;
58 count
= recv(state
->syslog_fd
, str
, sizeof(str
), 0);
59 if (count
< sizeof(struct syslog_message
)) {
62 msg
= (struct syslog_message
*)str
;
63 if (msg
->len
>= (sizeof(str
) - offsetof(struct syslog_message
, message
))) {
64 msg
->len
= (sizeof(str
)-1) - offsetof(struct syslog_message
, message
);
66 msg
->message
[msg
->len
] = '\0';
68 syslog(msg
->level
, "%s", msg
->message
);
72 /* called when the pipe from the main daemon has closed
73 * this is for the syslog daemon, we can not use DEBUG here
75 static void ctdb_syslog_terminate_handler(struct event_context
*ev
, struct fd_event
*fde
,
76 uint16_t flags
, void *p
)
78 syslog(LOG_ERR
, "Shutting down SYSLOG daemon with pid:%d", (int)getpid());
85 * this is for the syslog daemon, we can not use DEBUG here
87 int start_syslog_daemon(struct ctdb_context
*ctdb
)
89 struct sockaddr_in syslog_sin
;
90 struct ctdb_syslog_state
*state
;
91 struct tevent_fd
*fde
;
95 state
= talloc(ctdb
, struct ctdb_syslog_state
);
96 CTDB_NO_MEMORY(ctdb
, state
);
98 if (pipe(state
->fd
) != 0) {
99 printf("Failed to create syslog pipe\n");
104 if (pipe(startup_fd
) != 0) {
105 printf("Failed to create syslog startup pipe\n");
112 ctdb
->syslogd_pid
= ctdb_fork(ctdb
);
113 if (ctdb
->syslogd_pid
== (pid_t
)-1) {
114 printf("Failed to create syslog child process\n");
117 close(startup_fd
[0]);
118 close(startup_fd
[1]);
123 if (ctdb
->syslogd_pid
!= 0) {
127 DEBUG(DEBUG_ERR
,("Starting SYSLOG child process with pid:%d\n", (int)ctdb
->syslogd_pid
));
130 set_close_on_exec(state
->fd
[0]);
132 close(startup_fd
[1]);
133 n
= sys_read(startup_fd
[0], &dummy
, sizeof(dummy
));
134 close(startup_fd
[0]);
135 if (n
< sizeof(dummy
)) {
139 syslogd_is_started
= 1;
143 debug_extra
= talloc_asprintf(NULL
, "syslogd:");
144 talloc_free(ctdb
->ev
);
145 ctdb
->ev
= event_context_init(NULL
);
147 syslog(LOG_ERR
, "Starting SYSLOG daemon with pid:%d", (int)getpid());
148 ctdb_set_process_name("ctdb_syslogd");
151 close(startup_fd
[0]);
152 set_close_on_exec(state
->fd
[1]);
153 set_close_on_exec(startup_fd
[1]);
154 fde
= event_add_fd(ctdb
->ev
, state
, state
->fd
[1], EVENT_FD_READ
,
155 ctdb_syslog_terminate_handler
, state
);
156 tevent_fd_set_auto_close(fde
);
158 state
->syslog_fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
159 if (state
->syslog_fd
== -1) {
160 printf("Failed to create syslog socket\n");
161 close(startup_fd
[1]);
165 set_close_on_exec(state
->syslog_fd
);
167 syslog_sin
.sin_family
= AF_INET
;
168 syslog_sin
.sin_port
= htons(CTDB_PORT
);
169 syslog_sin
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
171 if (bind(state
->syslog_fd
, (struct sockaddr
*)&syslog_sin
,
172 sizeof(syslog_sin
)) == -1)
174 printf("syslog daemon failed to bind to socket. errno:%d(%s)\n", errno
, strerror(errno
));
175 close(startup_fd
[1]);
180 fde
= event_add_fd(ctdb
->ev
, state
, state
->syslog_fd
, EVENT_FD_READ
,
181 ctdb_syslog_handler
, state
);
182 tevent_fd_set_auto_close(fde
);
184 /* Tell parent that we're up */
186 sys_write(startup_fd
[1], &ret
, sizeof(ret
));
187 close(startup_fd
[1]);
189 event_loop_wait(ctdb
->ev
);
191 /* this should not happen */
195 struct ctdb_log_state
{
196 struct ctdb_context
*ctdb
;
202 void (*logfn
)(const char *, uint16_t, void *);
206 /* we need this global to keep the DEBUG() syntax */
207 static struct ctdb_log_state
*log_state
;
210 syslog logging function
212 static void ctdb_syslog_log(void *private_ptr
, int dbglevel
, const char *s
)
214 struct syslog_message
*msg
;
215 int level
= LOG_DEBUG
;
218 struct sockaddr_in syslog_sin
;
247 len
= offsetof(struct syslog_message
, message
) + strlen(debug_extra
) + strlen(s
) + 1;
253 msg
->len
= strlen(debug_extra
) + strlen(s
);
254 strcpy(msg
->message
, debug_extra
);
255 strcat(msg
->message
, s
);
257 if (syslogd_is_started
== 0) {
258 syslog(msg
->level
, "%s", msg
->message
);
260 syslog_fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
261 if (syslog_fd
== -1) {
262 printf("Failed to create syslog socket\n");
267 syslog_sin
.sin_family
= AF_INET
;
268 syslog_sin
.sin_port
= htons(CTDB_PORT
);
269 syslog_sin
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
271 (void) sendto(syslog_fd
, msg
, len
, 0,
272 (struct sockaddr
*)&syslog_sin
,
274 /* no point in checking here since we cant log an error */
284 log file logging function
286 static void ctdb_logfile_log(void *private_ptr
, int dbglevel
, const char *s
)
294 t
= timeval_current();
295 tm
= localtime(&t
.tv_sec
);
297 strftime(tbuf
,sizeof(tbuf
)-1,"%Y/%m/%d %H:%M:%S", tm
);
299 ret
= asprintf(&s2
, "%s.%06u [%s%5u]: %s",
300 tbuf
, (unsigned)t
.tv_usec
,
301 debug_extra
, (unsigned)getpid(), s
);
303 const char *errstr
= "asprintf failed\n";
304 sys_write(log_state
->fd
, errstr
, strlen(errstr
));
308 sys_write(log_state
->fd
, s2
, strlen(s2
));
314 choose the logfile location
316 int ctdb_set_logfile(struct ctdb_context
*ctdb
, const char *logfile
, bool use_syslog
)
318 debug_callback_fn callback
;
321 ctdb
->log
= talloc_zero(ctdb
, struct ctdb_log_state
);
322 if (ctdb
->log
== NULL
) {
323 printf("talloc_zero failed\n");
327 ctdb
->log
->ctdb
= ctdb
;
328 log_state
= ctdb
->log
;
331 callback
= ctdb_syslog_log
;
332 ctdb
->log
->use_syslog
= true;
333 } else if (logfile
== NULL
|| strcmp(logfile
, "-") == 0) {
334 callback
= ctdb_logfile_log
;
336 /* also catch stderr of subcommands to stdout */
339 printf("dup2 failed: %s\n", strerror(errno
));
343 callback
= ctdb_logfile_log
;
345 ctdb
->log
->fd
= open(logfile
, O_WRONLY
|O_APPEND
|O_CREAT
, 0666);
346 if (ctdb
->log
->fd
== -1) {
347 printf("Failed to open logfile %s\n", logfile
);
352 debug_set_callback(NULL
, callback
);
357 /* Note that do_debug always uses the global log state. */
358 static void write_to_log(struct ctdb_log_state
*log
,
359 const char *buf
, unsigned int len
)
361 if (script_log_level
<= DEBUGLEVEL
) {
362 if (log
!= NULL
&& log
->prefix
!= NULL
) {
363 dbgtext("%s: %*.*s\n", log
->prefix
, len
, len
, buf
);
365 dbgtext("%*.*s\n", len
, len
, buf
);
367 /* log it in the eventsystem as well */
368 if (log
&& log
->logfn
) {
369 log
->logfn(log
->buf
, len
, log
->logfn_private
);
375 called when log data comes in from a child process
377 static void ctdb_log_handler(struct event_context
*ev
, struct fd_event
*fde
,
378 uint16_t flags
, void *private)
380 struct ctdb_log_state
*log
= talloc_get_type(private, struct ctdb_log_state
);
384 if (!(flags
& EVENT_FD_READ
)) {
388 n
= sys_read(log
->pfd
, &log
->buf
[log
->buf_used
],
389 sizeof(log
->buf
) - log
->buf_used
);
393 if (log
!= log_state
) {
399 while (log
->buf_used
> 0 &&
400 (p
= memchr(log
->buf
, '\n', log
->buf_used
)) != NULL
) {
401 int n1
= (p
- log
->buf
)+1;
403 /* swallow \r from child processes */
404 if (n2
> 0 && log
->buf
[n2
-1] == '\r') {
407 write_to_log(log
, log
->buf
, n2
);
408 memmove(log
->buf
, p
+1, sizeof(log
->buf
) - n1
);
412 /* the buffer could have completely filled - unfortunately we have
413 no choice but to dump it out straight away */
414 if (log
->buf_used
== sizeof(log
->buf
)) {
415 write_to_log(log
, log
->buf
, log
->buf_used
);
420 static int log_context_destructor(struct ctdb_log_state
*log
)
422 /* Flush buffer in case it wasn't \n-terminated. */
423 if (log
->buf_used
> 0) {
424 write_to_log(log
, log
->buf
, log
->buf_used
);
430 * vfork + exec, redirecting child output to logging and specified callback.
432 struct ctdb_log_state
*ctdb_vfork_with_logging(TALLOC_CTX
*mem_ctx
,
433 struct ctdb_context
*ctdb
,
434 const char *log_prefix
,
437 const char **helper_argv
,
438 void (*logfn
)(const char *, uint16_t, void *),
439 void *logfn_private
, pid_t
*pid
)
442 struct ctdb_log_state
*log
;
443 struct tevent_fd
*fde
;
447 log
= talloc_zero(mem_ctx
, struct ctdb_log_state
);
448 CTDB_NO_MEMORY_NULL(ctdb
, log
);
451 log
->prefix
= log_prefix
;
453 log
->logfn_private
= logfn_private
;
456 DEBUG(DEBUG_ERR
, (__location__
" Failed to setup pipe for child logging\n"));
460 argv
= talloc_array(mem_ctx
, char *, helper_argc
+ 2);
462 DEBUG(DEBUG_ERR
, (__location__
"Failed to allocate memory for helper\n"));
465 argv
[0] = discard_const(helper
);
466 argv
[1] = talloc_asprintf(argv
, "%d", p
[1]);
467 if (argv
[1] == NULL
) {
468 DEBUG(DEBUG_ERR
, (__location__
"Failed to allocate memory for helper\n"));
473 for (i
=0; i
<helper_argc
; i
++) {
474 argv
[i
+2] = discard_const(helper_argv
[i
]);
485 DEBUG(DEBUG_ERR
, (__location__
"vfork failed for helper process\n"));
490 ctdb_track_child(ctdb
, *pid
);
493 set_close_on_exec(log
->pfd
);
494 talloc_set_destructor(log
, log_context_destructor
);
495 fde
= tevent_add_fd(ctdb
->ev
, log
, log
->pfd
, EVENT_FD_READ
,
496 ctdb_log_handler
, log
);
497 tevent_fd_set_auto_close(fde
);
508 setup for logging of child process stdout
510 int ctdb_set_child_logging(struct ctdb_context
*ctdb
)
513 int old_stdout
, old_stderr
;
514 struct tevent_fd
*fde
;
516 if (ctdb
->log
->fd
== STDOUT_FILENO
) {
517 /* not needed for stdout logging */
521 /* setup a pipe to catch IO from subprocesses */
523 DEBUG(DEBUG_ERR
,(__location__
" Failed to setup for child logging pipe\n"));
527 /* We'll fail if stderr/stdout not already open; it's simpler. */
528 old_stdout
= dup(STDOUT_FILENO
);
529 old_stderr
= dup(STDERR_FILENO
);
530 if (old_stdout
< 0 || old_stderr
< 0) {
531 DEBUG(DEBUG_ERR
, ("Failed to dup stdout/stderr for child logging\n"));
534 if (dup2(p
[1], STDOUT_FILENO
) < 0 || dup2(p
[1], STDERR_FILENO
) < 0) {
535 int saved_errno
= errno
;
536 dup2(old_stdout
, STDOUT_FILENO
);
537 dup2(old_stderr
, STDERR_FILENO
);
544 printf(__location__
" dup2 failed: %s\n",
552 fde
= event_add_fd(ctdb
->ev
, ctdb
->log
, p
[0],
553 EVENT_FD_READ
, ctdb_log_handler
, ctdb
->log
);
554 tevent_fd_set_auto_close(fde
);
556 ctdb
->log
->pfd
= p
[0];
558 DEBUG(DEBUG_DEBUG
, (__location__
" Created PIPE FD:%d for logging\n", p
[0]));
565 * set up a log handler to catch logging from TEVENT
567 static void ctdb_tevent_logging(void *private_data
,
568 enum tevent_debug_level level
,
572 enum debug_level lvl
= DEBUG_CRIT
;
575 case TEVENT_DEBUG_FATAL
:
578 case TEVENT_DEBUG_ERROR
:
581 case TEVENT_DEBUG_WARNING
:
584 case TEVENT_DEBUG_TRACE
:
589 if (lvl
<= DEBUGLEVEL
) {
594 int ctdb_init_tevent_logging(struct ctdb_context
*ctdb
)
598 ret
= tevent_set_debug(ctdb
->ev
,