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
;
238 len
= offsetof(struct syslog_message
, message
) + strlen(debug_extra
) + strlen(s
) + 1;
244 msg
->len
= strlen(debug_extra
) + strlen(s
);
245 strcpy(msg
->message
, debug_extra
);
246 strcat(msg
->message
, s
);
248 if (syslogd_is_started
== 0) {
249 syslog(msg
->level
, "%s", msg
->message
);
251 syslog_fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
252 if (syslog_fd
== -1) {
253 printf("Failed to create syslog socket\n");
258 syslog_sin
.sin_family
= AF_INET
;
259 syslog_sin
.sin_port
= htons(CTDB_PORT
);
260 syslog_sin
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
262 (void) sendto(syslog_fd
, msg
, len
, 0,
263 (struct sockaddr
*)&syslog_sin
,
265 /* no point in checking here since we cant log an error */
275 log file logging function
277 static void ctdb_logfile_log(void *private_ptr
, int dbglevel
, const char *s
)
285 t
= timeval_current();
286 tm
= localtime(&t
.tv_sec
);
288 strftime(tbuf
,sizeof(tbuf
)-1,"%Y/%m/%d %H:%M:%S", tm
);
290 ret
= asprintf(&s2
, "%s.%06u [%s%5u]: %s\n",
291 tbuf
, (unsigned)t
.tv_usec
,
292 debug_extra
, (unsigned)getpid(), s
);
294 const char *errstr
= "asprintf failed\n";
295 sys_write(log_state
->fd
, errstr
, strlen(errstr
));
299 sys_write(log_state
->fd
, s2
, strlen(s2
));
305 choose the logfile location
307 int ctdb_set_logfile(struct ctdb_context
*ctdb
, const char *logfile
, bool use_syslog
)
309 debug_callback_fn callback
;
312 ctdb
->log
= talloc_zero(ctdb
, struct ctdb_log_state
);
313 if (ctdb
->log
== NULL
) {
314 printf("talloc_zero failed\n");
318 ctdb
->log
->ctdb
= ctdb
;
319 log_state
= ctdb
->log
;
322 callback
= ctdb_syslog_log
;
323 ctdb
->log
->use_syslog
= true;
324 } else if (logfile
== NULL
|| strcmp(logfile
, "-") == 0) {
325 callback
= ctdb_logfile_log
;
327 /* also catch stderr of subcommands to stdout */
330 printf("dup2 failed: %s\n", strerror(errno
));
334 callback
= ctdb_logfile_log
;
336 ctdb
->log
->fd
= open(logfile
, O_WRONLY
|O_APPEND
|O_CREAT
, 0666);
337 if (ctdb
->log
->fd
== -1) {
338 printf("Failed to open logfile %s\n", logfile
);
343 debug_set_callback(NULL
, callback
);
348 /* Note that do_debug always uses the global log state. */
349 static void write_to_log(struct ctdb_log_state
*log
,
350 const char *buf
, unsigned int len
)
352 if (script_log_level
<= DEBUGLEVEL
) {
353 if (log
!= NULL
&& log
->prefix
!= NULL
) {
354 dbgtext("%s: %*.*s\n", log
->prefix
, len
, len
, buf
);
356 dbgtext("%*.*s\n", len
, len
, buf
);
358 /* log it in the eventsystem as well */
359 if (log
&& log
->logfn
) {
360 log
->logfn(log
->buf
, len
, log
->logfn_private
);
366 called when log data comes in from a child process
368 static void ctdb_log_handler(struct event_context
*ev
, struct fd_event
*fde
,
369 uint16_t flags
, void *private)
371 struct ctdb_log_state
*log
= talloc_get_type(private, struct ctdb_log_state
);
375 if (!(flags
& EVENT_FD_READ
)) {
379 n
= sys_read(log
->pfd
, &log
->buf
[log
->buf_used
],
380 sizeof(log
->buf
) - log
->buf_used
);
384 if (log
!= log_state
) {
390 while (log
->buf_used
> 0 &&
391 (p
= memchr(log
->buf
, '\n', log
->buf_used
)) != NULL
) {
392 int n1
= (p
- log
->buf
)+1;
394 /* swallow \r from child processes */
395 if (n2
> 0 && log
->buf
[n2
-1] == '\r') {
398 write_to_log(log
, log
->buf
, n2
);
399 memmove(log
->buf
, p
+1, sizeof(log
->buf
) - n1
);
403 /* the buffer could have completely filled - unfortunately we have
404 no choice but to dump it out straight away */
405 if (log
->buf_used
== sizeof(log
->buf
)) {
406 write_to_log(log
, log
->buf
, log
->buf_used
);
411 static int log_context_destructor(struct ctdb_log_state
*log
)
413 /* Flush buffer in case it wasn't \n-terminated. */
414 if (log
->buf_used
> 0) {
415 write_to_log(log
, log
->buf
, log
->buf_used
);
421 * vfork + exec, redirecting child output to logging and specified callback.
423 struct ctdb_log_state
*ctdb_vfork_with_logging(TALLOC_CTX
*mem_ctx
,
424 struct ctdb_context
*ctdb
,
425 const char *log_prefix
,
428 const char **helper_argv
,
429 void (*logfn
)(const char *, uint16_t, void *),
430 void *logfn_private
, pid_t
*pid
)
433 struct ctdb_log_state
*log
;
434 struct tevent_fd
*fde
;
438 log
= talloc_zero(mem_ctx
, struct ctdb_log_state
);
439 CTDB_NO_MEMORY_NULL(ctdb
, log
);
442 log
->prefix
= log_prefix
;
444 log
->logfn_private
= logfn_private
;
447 DEBUG(DEBUG_ERR
, (__location__
" Failed to setup pipe for child logging\n"));
451 argv
= talloc_array(mem_ctx
, char *, helper_argc
+ 2);
453 DEBUG(DEBUG_ERR
, (__location__
"Failed to allocate memory for helper\n"));
456 argv
[0] = discard_const(helper
);
457 argv
[1] = talloc_asprintf(argv
, "%d", p
[1]);
458 if (argv
[1] == NULL
) {
459 DEBUG(DEBUG_ERR
, (__location__
"Failed to allocate memory for helper\n"));
464 for (i
=0; i
<helper_argc
; i
++) {
465 argv
[i
+2] = discard_const(helper_argv
[i
]);
476 DEBUG(DEBUG_ERR
, (__location__
"vfork failed for helper process\n"));
481 ctdb_track_child(ctdb
, *pid
);
484 set_close_on_exec(log
->pfd
);
485 talloc_set_destructor(log
, log_context_destructor
);
486 fde
= tevent_add_fd(ctdb
->ev
, log
, log
->pfd
, EVENT_FD_READ
,
487 ctdb_log_handler
, log
);
488 tevent_fd_set_auto_close(fde
);
499 setup for logging of child process stdout
501 int ctdb_set_child_logging(struct ctdb_context
*ctdb
)
504 int old_stdout
, old_stderr
;
505 struct tevent_fd
*fde
;
507 if (ctdb
->log
->fd
== STDOUT_FILENO
) {
508 /* not needed for stdout logging */
512 /* setup a pipe to catch IO from subprocesses */
514 DEBUG(DEBUG_ERR
,(__location__
" Failed to setup for child logging pipe\n"));
518 /* We'll fail if stderr/stdout not already open; it's simpler. */
519 old_stdout
= dup(STDOUT_FILENO
);
520 old_stderr
= dup(STDERR_FILENO
);
521 if (old_stdout
< 0 || old_stderr
< 0) {
522 DEBUG(DEBUG_ERR
, ("Failed to dup stdout/stderr for child logging\n"));
525 if (dup2(p
[1], STDOUT_FILENO
) < 0 || dup2(p
[1], STDERR_FILENO
) < 0) {
526 int saved_errno
= errno
;
527 dup2(old_stdout
, STDOUT_FILENO
);
528 dup2(old_stderr
, STDERR_FILENO
);
535 printf(__location__
" dup2 failed: %s\n",
543 fde
= event_add_fd(ctdb
->ev
, ctdb
->log
, p
[0],
544 EVENT_FD_READ
, ctdb_log_handler
, ctdb
->log
);
545 tevent_fd_set_auto_close(fde
);
547 ctdb
->log
->pfd
= p
[0];
549 DEBUG(DEBUG_DEBUG
, (__location__
" Created PIPE FD:%d for logging\n", p
[0]));
556 * set up a log handler to catch logging from TEVENT
558 static void ctdb_tevent_logging(void *private_data
,
559 enum tevent_debug_level level
,
563 enum debug_level lvl
= DEBUG_CRIT
;
566 case TEVENT_DEBUG_FATAL
:
569 case TEVENT_DEBUG_ERROR
:
572 case TEVENT_DEBUG_WARNING
:
575 case TEVENT_DEBUG_TRACE
:
580 if (lvl
<= DEBUGLEVEL
) {
585 int ctdb_init_tevent_logging(struct ctdb_context
*ctdb
)
589 ret
= tevent_set_debug(ctdb
->ev
,