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"
27 struct syslog_message
{
34 struct ctdb_syslog_state
{
39 static int syslogd_is_started
= 0;
41 /* called when child is finished
42 * this is for the syslog daemon, we can not use DEBUG here
44 static void ctdb_syslog_handler(struct event_context
*ev
, struct fd_event
*fde
,
45 uint16_t flags
, void *p
)
47 struct ctdb_syslog_state
*state
= talloc_get_type(p
, struct ctdb_syslog_state
);
51 struct syslog_message
*msg
;
57 count
= recv(state
->syslog_fd
, str
, sizeof(str
), 0);
58 if (count
< sizeof(struct syslog_message
)) {
61 msg
= (struct syslog_message
*)str
;
62 if (msg
->len
>= (sizeof(str
) - offsetof(struct syslog_message
, message
))) {
63 msg
->len
= (sizeof(str
)-1) - offsetof(struct syslog_message
, message
);
65 msg
->message
[msg
->len
] = '\0';
67 syslog(msg
->level
, "%s", msg
->message
);
71 /* called when the pipe from the main daemon has closed
72 * this is for the syslog daemon, we can not use DEBUG here
74 static void ctdb_syslog_terminate_handler(struct event_context
*ev
, struct fd_event
*fde
,
75 uint16_t flags
, void *p
)
77 syslog(LOG_ERR
, "Shutting down SYSLOG daemon with pid:%d", (int)getpid());
84 * this is for the syslog daemon, we can not use DEBUG here
86 int start_syslog_daemon(struct ctdb_context
*ctdb
)
88 struct sockaddr_in syslog_sin
;
89 struct ctdb_syslog_state
*state
;
90 struct tevent_fd
*fde
;
94 state
= talloc(ctdb
, struct ctdb_syslog_state
);
95 CTDB_NO_MEMORY(ctdb
, state
);
97 if (pipe(state
->fd
) != 0) {
98 printf("Failed to create syslog pipe\n");
103 if (pipe(startup_fd
) != 0) {
104 printf("Failed to create syslog startup pipe\n");
111 ctdb
->syslogd_pid
= ctdb_fork(ctdb
);
112 if (ctdb
->syslogd_pid
== (pid_t
)-1) {
113 printf("Failed to create syslog child process\n");
116 close(startup_fd
[0]);
117 close(startup_fd
[1]);
122 if (ctdb
->syslogd_pid
!= 0) {
126 DEBUG(DEBUG_ERR
,("Starting SYSLOG child process with pid:%d\n", (int)ctdb
->syslogd_pid
));
129 set_close_on_exec(state
->fd
[0]);
131 close(startup_fd
[1]);
132 n
= read(startup_fd
[0], &dummy
, sizeof(dummy
));
133 close(startup_fd
[0]);
134 if (n
< sizeof(dummy
)) {
138 syslogd_is_started
= 1;
142 debug_extra
= talloc_asprintf(NULL
, "syslogd:");
143 talloc_free(ctdb
->ev
);
144 ctdb
->ev
= event_context_init(NULL
);
146 syslog(LOG_ERR
, "Starting SYSLOG daemon with pid:%d", (int)getpid());
147 ctdb_set_process_name("ctdb_syslogd");
150 close(startup_fd
[0]);
151 set_close_on_exec(state
->fd
[1]);
152 set_close_on_exec(startup_fd
[1]);
153 fde
= event_add_fd(ctdb
->ev
, state
, state
->fd
[1], EVENT_FD_READ
,
154 ctdb_syslog_terminate_handler
, state
);
155 tevent_fd_set_auto_close(fde
);
157 state
->syslog_fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
158 if (state
->syslog_fd
== -1) {
159 printf("Failed to create syslog socket\n");
160 close(startup_fd
[1]);
164 set_close_on_exec(state
->syslog_fd
);
166 syslog_sin
.sin_family
= AF_INET
;
167 syslog_sin
.sin_port
= htons(CTDB_PORT
);
168 syslog_sin
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
170 if (bind(state
->syslog_fd
, (struct sockaddr
*)&syslog_sin
,
171 sizeof(syslog_sin
)) == -1)
173 printf("syslog daemon failed to bind to socket. errno:%d(%s)\n", errno
, strerror(errno
));
174 close(startup_fd
[1]);
179 fde
= event_add_fd(ctdb
->ev
, state
, state
->syslog_fd
, EVENT_FD_READ
,
180 ctdb_syslog_handler
, state
);
181 tevent_fd_set_auto_close(fde
);
183 /* Tell parent that we're up */
185 write(startup_fd
[1], &ret
, sizeof(ret
));
186 close(startup_fd
[1]);
188 event_loop_wait(ctdb
->ev
);
190 /* this should not happen */
194 struct ctdb_log_state
{
195 struct ctdb_context
*ctdb
;
201 void (*logfn
)(const char *, uint16_t, void *);
205 /* we need this global to keep the DEBUG() syntax */
206 static struct ctdb_log_state
*log_state
;
209 syslog logging function
211 static void ctdb_syslog_log(const char *format
, va_list ap
)
213 struct syslog_message
*msg
;
214 int level
= LOG_DEBUG
;
218 struct sockaddr_in syslog_sin
;
220 ret
= vasprintf(&s
, format
, ap
);
225 switch (this_log_level
) {
252 len
= offsetof(struct syslog_message
, message
) + strlen(debug_extra
) + strlen(s
) + 1;
259 msg
->len
= strlen(debug_extra
) + strlen(s
);
260 strcpy(msg
->message
, debug_extra
);
261 strcat(msg
->message
, s
);
263 if (syslogd_is_started
== 0) {
264 syslog(msg
->level
, "%s", msg
->message
);
266 syslog_fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
267 if (syslog_fd
== -1) {
268 printf("Failed to create syslog socket\n");
274 syslog_sin
.sin_family
= AF_INET
;
275 syslog_sin
.sin_port
= htons(CTDB_PORT
);
276 syslog_sin
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
278 ret
= sendto(syslog_fd
, msg
, len
, 0,
279 (struct sockaddr
*)&syslog_sin
,
281 /* no point in checking here since we cant log an error */
292 log file logging function
294 static void ctdb_logfile_log(const char *format
, va_list ap
)
303 ret
= vasprintf(&s
, format
, ap
);
305 const char *errstr
= "vasprintf failed\n";
307 write(log_state
->fd
, errstr
, strlen(errstr
));
311 t
= timeval_current();
312 tm
= localtime(&t
.tv_sec
);
314 strftime(tbuf
,sizeof(tbuf
)-1,"%Y/%m/%d %H:%M:%S", tm
);
316 ret
= asprintf(&s2
, "%s.%06u [%s%5u]: %s",
317 tbuf
, (unsigned)t
.tv_usec
,
318 debug_extra
, (unsigned)getpid(), s
);
321 const char *errstr
= "asprintf failed\n";
322 write(log_state
->fd
, errstr
, strlen(errstr
));
326 write(log_state
->fd
, s2
, strlen(s2
));
331 static void ctdb_logfile_log_add(const char *format
, va_list ap
)
336 ret
= vasprintf(&s
, format
, ap
);
338 const char *errstr
= "vasprintf failed\n";
340 write(log_state
->fd
, errstr
, strlen(errstr
));
345 write(log_state
->fd
, s
, strlen(s
));
353 choose the logfile location
355 int ctdb_set_logfile(struct ctdb_context
*ctdb
, const char *logfile
, bool use_syslog
)
359 ctdb
->log
= talloc_zero(ctdb
, struct ctdb_log_state
);
360 if (ctdb
->log
== NULL
) {
361 printf("talloc_zero failed\n");
365 ctdb
->log
->ctdb
= ctdb
;
366 log_state
= ctdb
->log
;
369 do_debug_v
= ctdb_syslog_log
;
370 do_debug_add_v
= ctdb_syslog_log
;
371 ctdb
->log
->use_syslog
= true;
372 } else if (logfile
== NULL
|| strcmp(logfile
, "-") == 0) {
373 do_debug_v
= ctdb_logfile_log
;
374 do_debug_add_v
= ctdb_logfile_log_add
;
376 /* also catch stderr of subcommands to stdout */
379 printf("dup2 failed: %s\n", strerror(errno
));
383 do_debug_v
= ctdb_logfile_log
;
384 do_debug_add_v
= ctdb_logfile_log_add
;
386 ctdb
->log
->fd
= open(logfile
, O_WRONLY
|O_APPEND
|O_CREAT
, 0666);
387 if (ctdb
->log
->fd
== -1) {
388 printf("Failed to open logfile %s\n", logfile
);
396 /* Note that do_debug always uses the global log state. */
397 static void write_to_log(struct ctdb_log_state
*log
,
398 const char *buf
, unsigned int len
)
400 if (script_log_level
<= LogLevel
) {
401 if (log
!= NULL
&& log
->prefix
!= NULL
) {
402 do_debug("%s: %*.*s\n", log
->prefix
, len
, len
, buf
);
404 do_debug("%*.*s\n", len
, len
, buf
);
406 /* log it in the eventsystem as well */
407 if (log
&& log
->logfn
) {
408 log
->logfn(log
->buf
, len
, log
->logfn_private
);
414 called when log data comes in from a child process
416 static void ctdb_log_handler(struct event_context
*ev
, struct fd_event
*fde
,
417 uint16_t flags
, void *private)
419 struct ctdb_log_state
*log
= talloc_get_type(private, struct ctdb_log_state
);
423 if (!(flags
& EVENT_FD_READ
)) {
427 n
= read(log
->pfd
, &log
->buf
[log
->buf_used
],
428 sizeof(log
->buf
) - log
->buf_used
);
432 if (log
!= log_state
) {
438 this_log_level
= script_log_level
;
440 while (log
->buf_used
> 0 &&
441 (p
= memchr(log
->buf
, '\n', log
->buf_used
)) != NULL
) {
442 int n1
= (p
- log
->buf
)+1;
444 /* swallow \r from child processes */
445 if (n2
> 0 && log
->buf
[n2
-1] == '\r') {
448 write_to_log(log
, log
->buf
, n2
);
449 memmove(log
->buf
, p
+1, sizeof(log
->buf
) - n1
);
453 /* the buffer could have completely filled - unfortunately we have
454 no choice but to dump it out straight away */
455 if (log
->buf_used
== sizeof(log
->buf
)) {
456 write_to_log(log
, log
->buf
, log
->buf_used
);
461 static int log_context_destructor(struct ctdb_log_state
*log
)
463 /* Flush buffer in case it wasn't \n-terminated. */
464 if (log
->buf_used
> 0) {
465 this_log_level
= script_log_level
;
466 write_to_log(log
, log
->buf
, log
->buf_used
);
472 * vfork + exec, redirecting child output to logging and specified callback.
474 struct ctdb_log_state
*ctdb_vfork_with_logging(TALLOC_CTX
*mem_ctx
,
475 struct ctdb_context
*ctdb
,
476 const char *log_prefix
,
479 const char **helper_argv
,
480 void (*logfn
)(const char *, uint16_t, void *),
481 void *logfn_private
, pid_t
*pid
)
484 struct ctdb_log_state
*log
;
485 struct tevent_fd
*fde
;
489 log
= talloc_zero(mem_ctx
, struct ctdb_log_state
);
490 CTDB_NO_MEMORY_NULL(ctdb
, log
);
493 log
->prefix
= log_prefix
;
495 log
->logfn_private
= logfn_private
;
498 DEBUG(DEBUG_ERR
, (__location__
" Failed to setup pipe for child logging\n"));
502 argv
= talloc_array(mem_ctx
, char *, helper_argc
+ 2);
504 DEBUG(DEBUG_ERR
, (__location__
"Failed to allocate memory for helper\n"));
507 argv
[0] = discard_const(helper
);
508 argv
[1] = talloc_asprintf(argv
, "%d", p
[1]);
509 if (argv
[1] == NULL
) {
510 DEBUG(DEBUG_ERR
, (__location__
"Failed to allocate memory for helper\n"));
515 for (i
=0; i
<helper_argc
; i
++) {
516 argv
[i
+2] = discard_const(helper_argv
[i
]);
527 DEBUG(DEBUG_ERR
, (__location__
"vfork failed for helper process\n"));
532 ctdb_track_child(ctdb
, *pid
);
535 set_close_on_exec(log
->pfd
);
536 talloc_set_destructor(log
, log_context_destructor
);
537 fde
= tevent_add_fd(ctdb
->ev
, log
, log
->pfd
, EVENT_FD_READ
,
538 ctdb_log_handler
, log
);
539 tevent_fd_set_auto_close(fde
);
550 setup for logging of child process stdout
552 int ctdb_set_child_logging(struct ctdb_context
*ctdb
)
555 int old_stdout
, old_stderr
;
556 struct tevent_fd
*fde
;
558 if (ctdb
->log
->fd
== STDOUT_FILENO
) {
559 /* not needed for stdout logging */
563 /* setup a pipe to catch IO from subprocesses */
565 DEBUG(DEBUG_ERR
,(__location__
" Failed to setup for child logging pipe\n"));
569 /* We'll fail if stderr/stdout not already open; it's simpler. */
570 old_stdout
= dup(STDOUT_FILENO
);
571 old_stderr
= dup(STDERR_FILENO
);
572 if (old_stdout
< 0 || old_stderr
< 0) {
573 DEBUG(DEBUG_ERR
, ("Failed to dup stdout/stderr for child logging\n"));
576 if (dup2(p
[1], STDOUT_FILENO
) < 0 || dup2(p
[1], STDERR_FILENO
) < 0) {
577 int saved_errno
= errno
;
578 dup2(old_stdout
, STDOUT_FILENO
);
579 dup2(old_stderr
, STDERR_FILENO
);
586 printf(__location__
" dup2 failed: %s\n",
594 fde
= event_add_fd(ctdb
->ev
, ctdb
->log
, p
[0],
595 EVENT_FD_READ
, ctdb_log_handler
, ctdb
->log
);
596 tevent_fd_set_auto_close(fde
);
598 ctdb
->log
->pfd
= p
[0];
600 DEBUG(DEBUG_DEBUG
, (__location__
" Created PIPE FD:%d for logging\n", p
[0]));
607 * set up a log handler to catch logging from TEVENT
609 static void ctdb_tevent_logging(void *private_data
,
610 enum tevent_debug_level level
,
614 enum debug_level lvl
= DEBUG_CRIT
;
617 case TEVENT_DEBUG_FATAL
:
620 case TEVENT_DEBUG_ERROR
:
623 case TEVENT_DEBUG_WARNING
:
626 case TEVENT_DEBUG_TRACE
:
631 if (lvl
<= LogLevel
) {
632 this_log_level
= lvl
;
637 int ctdb_init_tevent_logging(struct ctdb_context
*ctdb
)
641 ret
= tevent_set_debug(ctdb
->ev
,