/* Pure Load Balancer - (C)opyleft 2003 Jedi/Sector One <j@pureftpd.org> */

#include <config.h>
#include "plb.h"
#include "plb_globals.h"
#include "plb_log_p.h"
#ifdef WITH_DMALLOC
# include <dmalloc.h>
#endif

void plb_close_log(void)
{
    if (log_fd == -1) {
        return;
    }
    plb_log(LL_NOTIFY, "PLB has been shut down");
    (void) fsync(log_fd);
    while (close(log_fd) != 0 && errno == EINTR);
    log_fd = -1;
}

int plb_open_log(const char * const log_file)
{
    struct stat st;
    int already_probed = 0;
    int fd;

    open_again:
    if ((fd = open(log_file, O_WRONLY | O_APPEND | O_NOFOLLOW | O_CREAT,
                   (mode_t) 0644)) == -1) {
        plb_log(LL_ERROR, "Unable to open/create [%s] : [%s]", log_file,
                strerror(errno));
        plb_close_log();
        return -1;
    }
    if (fstat(fd, &st) != 0) {
        (void) close(fd);
        plb_log(LL_ERROR, "Unable to stat [%s] : [%s]", log_file,
                strerror(errno));
        plb_close_log();        
        return -1;
    }
    if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode)) {
        (void) close(fd);        
        plb_log(LL_ERROR, "Log file [%s] is not a regular file", log_file);
        plb_close_log();        
        return -1;
    }
    if (st.st_nlink > 1) {
        (void) close(fd);        
        if (already_probed == 0) {
            plb_log(LL_ERROR, "Log file [%s] has [%u] hard links - unlinking",
                    log_file, (unsigned int) st.st_nlink);
            (void) unlink(log_file);
            already_probed++;
            goto open_again;
        } else {
            plb_log(LL_ERROR, "Log file [%s] still has [%u] hard links",
                    log_file, (unsigned int) st.st_nlink);
        }
        plb_close_log();
        return -1;        
    }
    log_fd = fd;
    
    return 0;
}

void plb_log(const LogLevel level, const char * const fmt, ...)
{
    static char line[LINE_MAX];
    va_list va;    
    char *linepnt = line;
    size_t towrite;
    ssize_t written;

    if (log_level > level || log_fd == -1) {
        return;
    }
    va_start(va, fmt);
    vsnprintf(line, sizeof line - (size_t) 2U, fmt, va);
    if ((towrite = strlen(line)) <= (size_t) 0U) {
        return;
    }
    line[towrite] = '\n';
    towrite++;
    line[towrite] = 0;
    towrite++;
    for (;;) {
        while ((written = write(log_fd, linepnt, towrite)) < (ssize_t) 0 &&
               errno == EINTR);
        if (written < (ssize_t) 0) {
            while (write(log_fd, "-?-\n", (size_t) 5U) < (ssize_t) 0 &&
                   errno == EINTR);            
            break;
        }
        towrite -= (size_t) written;
        if (towrite <= (size_t) 0) {
            break;
        }
        linepnt += written;
    }    
    va_end(va);
}


syntax highlighted by Code2HTML, v. 0.9.1