X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Flog.c;h=90373adf0a074410a14284375d4ae0045fca266f;hb=28d2eab1414ef8d20ff0fde7026aa52fd01ef795;hp=bb6902ea082af8b86d7c72494c1f136655e057bf;hpb=b6c1434e4765d1a53efa2f3046bfb20ba682b5d2;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/log.c b/src/src/log.c index bb6902ea0..90373adf0 100644 --- a/src/src/log.c +++ b/src/src/log.c @@ -299,9 +299,12 @@ return fd; -/* Inspired by OpenSSH's mm_send_fd(). Thanks! */ +/* Inspired by OpenSSH's mm_send_fd(). Thanks! +Send fd over socketpair. +Return: true iff good. +*/ -static int +static BOOL log_send_fd(const int sock, const int fd) { struct msghdr msg; @@ -310,8 +313,8 @@ union { char buf[CMSG_SPACE(sizeof(int))]; } cmsgbuf; struct cmsghdr *cmsg; -struct iovec vec; char ch = 'A'; +struct iovec vec = {.iov_base = &ch, .iov_len = 1}; ssize_t n; memset(&msg, 0, sizeof(msg)); @@ -325,17 +328,16 @@ cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; *(int *)CMSG_DATA(cmsg) = fd; -vec.iov_base = &ch; -vec.iov_len = 1; msg.msg_iov = &vec; msg.msg_iovlen = 1; while ((n = sendmsg(sock, &msg, 0)) == -1 && errno == EINTR); -if (n != 1) return -1; -return 0; +return n == 1; } -/* Inspired by OpenSSH's mm_receive_fd(). Thanks! */ +/* Inspired by OpenSSH's mm_receive_fd(). Thanks! +Return fd passed over socketpair, or -1 on error. +*/ static int log_recv_fd(const int sock) @@ -346,14 +348,12 @@ union { char buf[CMSG_SPACE(sizeof(int))]; } cmsgbuf; struct cmsghdr *cmsg; -struct iovec vec; -ssize_t n; char ch = '\0'; -int fd = -1; +struct iovec vec = {.iov_base = &ch, .iov_len = 1}; +ssize_t n; +int fd; memset(&msg, 0, sizeof(msg)); -vec.iov_base = &ch; -vec.iov_len = 1; msg.msg_iov = &vec; msg.msg_iovlen = 1; @@ -361,14 +361,12 @@ memset(&cmsgbuf, 0, sizeof(cmsgbuf)); msg.msg_control = &cmsgbuf.buf; msg.msg_controllen = sizeof(cmsgbuf.buf); -while ((n = recvmsg(sock, &msg, 0)) == -1 && errno == EINTR); +while ((n = recvmsg(sock, &msg, 0)) == -1 && errno == EINTR) ; if (n != 1 || ch != 'A') return -1; -cmsg = CMSG_FIRSTHDR(&msg); -if (cmsg == NULL) return -1; +if (!(cmsg = CMSG_FIRSTHDR(&msg))) return -1; if (cmsg->cmsg_type != SCM_RIGHTS) return -1; -fd = *(const int *)CMSG_DATA(cmsg); -if (fd < 0) return -1; +if ((fd = *(const int *)CMSG_DATA(cmsg)) < 0) return -1; return fd; } @@ -395,28 +393,26 @@ int fd = -1; const uid_t euid = geteuid(); if (euid == exim_uid) - { fd = log_open_already_exim(name); - } else if (euid == root_uid) { int sock[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock) == 0) { - const pid_t pid = exim_fork(US"logfile-open"); + const pid_t pid = fork(); if (pid == 0) { (void)close(sock[0]); - if (setgroups(1, &exim_gid) != 0) _exit(EXIT_FAILURE); - if (setgid(exim_gid) != 0) _exit(EXIT_FAILURE); - if (setuid(exim_uid) != 0) _exit(EXIT_FAILURE); + if ( setgroups(1, &exim_gid) != 0 + || setgid(exim_gid) != 0 + || setuid(exim_uid) != 0 - if (getuid() != exim_uid || geteuid() != exim_uid) _exit(EXIT_FAILURE); - if (getgid() != exim_gid || getegid() != exim_gid) _exit(EXIT_FAILURE); + || getuid() != exim_uid || geteuid() != exim_uid + || getgid() != exim_gid || getegid() != exim_gid - fd = log_open_already_exim(name); - if (fd < 0) _exit(EXIT_FAILURE); - if (log_send_fd(sock[1], fd) != 0) _exit(EXIT_FAILURE); + || (fd = log_open_already_exim(name)) < 0 + || !log_send_fd(sock[1], fd) + ) _exit(EXIT_FAILURE); (void)close(sock[1]); _exit(EXIT_SUCCESS); } @@ -440,9 +436,7 @@ if (fd >= 0) if (flags != -1) (void)fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); } else - { errno = EACCES; - } return fd; } @@ -493,62 +487,53 @@ people want, I hope. */ ok = string_format(buffer, sizeof(buffer), CS file_path, log_names[type]); -/* Save the name of the mainlog for rollover processing. Without a datestamp, -it gets statted to see if it has been cycled. With a datestamp, the datestamp -will be compared. The static slot for saving it is the same size as buffer, -and the text has been checked above to fit, so this use of strcpy() is OK. */ - -if (type == lt_main) - { - Ustrcpy(mainlog_name, buffer); - if (string_datestamp_offset > 0) - mainlog_datestamp = mainlog_name + string_datestamp_offset; - } - -/* Ditto for the reject log */ - -else if (type == lt_reject) +switch (type) { - Ustrcpy(rejectlog_name, buffer); - if (string_datestamp_offset > 0) - rejectlog_datestamp = rejectlog_name + string_datestamp_offset; - } - -/* and deal with the debug log (which keeps the datestamp, but does not -update it) */ - -else if (type == lt_debug) - { - Ustrcpy(debuglog_name, buffer); - if (tag) - { - /* this won't change the offset of the datestamp */ - ok2 = string_format(buffer, sizeof(buffer), "%s%s", - debuglog_name, tag); - if (ok2) - Ustrcpy(debuglog_name, buffer); - } - } - -/* Remove any datestamp if this is the panic log. This is rare, so there's no -need to optimize getting the datestamp length. We remove one non-alphanumeric -char afterwards if at the start, otherwise one before. */ - -else if (string_datestamp_offset >= 0) - { - uschar * from = buffer + string_datestamp_offset; - uschar * to = from + string_datestamp_length; + case lt_main: + /* Save the name of the mainlog for rollover processing. Without a datestamp, + it gets statted to see if it has been cycled. With a datestamp, the datestamp + will be compared. The static slot for saving it is the same size as buffer, + and the text has been checked above to fit, so this use of strcpy() is OK. */ + Ustrcpy(mainlog_name, buffer); + if (string_datestamp_offset > 0) + mainlog_datestamp = mainlog_name + string_datestamp_offset; + case lt_reject: + /* Ditto for the reject log */ + Ustrcpy(rejectlog_name, buffer); + if (string_datestamp_offset > 0) + rejectlog_datestamp = rejectlog_name + string_datestamp_offset; + case lt_debug: + /* and deal with the debug log (which keeps the datestamp, but does not + update it) */ + Ustrcpy(debuglog_name, buffer); + if (tag) + { + /* this won't change the offset of the datestamp */ + ok2 = string_format(buffer, sizeof(buffer), "%s%s", + debuglog_name, tag); + if (ok2) + Ustrcpy(debuglog_name, buffer); + } + default: + /* Remove any datestamp if this is the panic log. This is rare, so there's no + need to optimize getting the datestamp length. We remove one non-alphanumeric + char afterwards if at the start, otherwise one before. */ + if (string_datestamp_offset >= 0) + { + uschar * from = buffer + string_datestamp_offset; + uschar * to = from + string_datestamp_length; - if (from == buffer || from[-1] == '/') - { - if (!isalnum(*to)) to++; - } - else - if (!isalnum(from[-1])) from--; + if (from == buffer || from[-1] == '/') + { + if (!isalnum(*to)) to++; + } + else + if (!isalnum(from[-1])) from--; - /* This copy is ok, because we know that to is a substring of from. But - due to overlap we must use memmove() not Ustrcpy(). */ - memmove(from, to, Ustrlen(to)+1); + /* This copy is ok, because we know that to is a substring of from. But + due to overlap we must use memmove() not Ustrcpy(). */ + memmove(from, to, Ustrlen(to)+1); + } } /* If the file name is too long, it is an unrecoverable disaster */ @@ -716,18 +701,36 @@ return total_written; } - -static void -set_file_path(void) +void +set_file_path(BOOL *multiple) { +uschar *s; int sep = ':'; /* Fixed separator - outside use */ -uschar *t; -const uschar *tt = US LOG_FILE_PATH; -while ((t = string_nextinlist(&tt, &sep, log_buffer, LOG_BUFFER_SIZE))) +uschar *ss = *log_file_path ? log_file_path : LOG_FILE_PATH; + +logging_mode = 0; +while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE))) { - if (Ustrcmp(t, "syslog") == 0 || t[0] == 0) continue; - file_path = string_copy(t); - break; + if (Ustrcmp(s, "syslog") == 0) + logging_mode |= LOG_MODE_SYSLOG; + else if (logging_mode & LOG_MODE_FILE) /* we know a file already */ + { + if (multiple) *multiple = TRUE; + } + else + { + logging_mode |= LOG_MODE_FILE; + + /* If a non-empty path is given, use it */ + + if (*s) + file_path = string_copy(s); + + /* If the path is empty, we want to use the first non-empty, non- + syslog item in LOG_FILE_PATH, if there is one, since the value of + log_file_path may have been set at runtime. If there is no such item, + use the ultimate default in the spool directory. */ + } } } @@ -735,7 +738,11 @@ while ((t = string_nextinlist(&tt, &sep, log_buffer, LOG_BUFFER_SIZE))) void mainlog_close(void) { -if (mainlogfd < 0) return; +/* avoid closing it if it is closed already or if we do not see a chance +to open the file mainlog later again */ +if (mainlogfd < 0 /* already closed */ + || !(geteuid() == 0 || geteuid() == exim_uid)) + return; (void)close(mainlogfd); mainlogfd = -1; mainlog_inode = 0; @@ -850,38 +857,7 @@ if (!path_inspected) /* If nothing has been set, don't waste effort... the default values for the statics are file_path="" and logging_mode = LOG_MODE_FILE. */ - if (*log_file_path) - { - int sep = ':'; /* Fixed separator - outside use */ - uschar *s; - const uschar *ss = log_file_path; - - logging_mode = 0; - while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE))) - { - if (Ustrcmp(s, "syslog") == 0) - logging_mode |= LOG_MODE_SYSLOG; - else if (logging_mode & LOG_MODE_FILE) - multiple = TRUE; - else - { - logging_mode |= LOG_MODE_FILE; - - /* If a non-empty path is given, use it */ - - if (*s) - file_path = string_copy(s); - - /* If the path is empty, we want to use the first non-empty, non- - syslog item in LOG_FILE_PATH, if there is one, since the value of - log_file_path may have been set at runtime. If there is no such item, - use the ultimate default in the spool directory. */ - - else - set_file_path(); /* Empty item in log_file_path */ - } /* First non-syslog item in log_file_path */ - } /* Scan of log_file_path */ - } + if (*log_file_path) set_file_path(&multiple); /* If no modes have been selected, it is a major disaster */ @@ -1499,7 +1475,7 @@ if (opts) resulting in certain setup not having been done. Hack this for now so we do not segfault; note that nondefault log locations will not work */ -if (!*file_path) set_file_path(); +if (!*file_path) set_file_path(NULL); open_log(&fd, lt_debug, tag_name); @@ -1521,5 +1497,12 @@ debug_file = NULL; unlink_log(lt_debug); } +void +open_logs(const char *m) +{ +set_file_path(NULL); +open_log(&mainlogfd, lt_main, 0); +open_log(&rejectlogfd, lt_reject, 0); +} /* End of log.c */