Example #1
0
/**
 * Set log to the final destination after options have been read.
 **/
static void dcc_setup_real_log(void)
{
    int fd;

    /* Even in inetd mode, we might want to log to stderr, because that will
     * work OK for ssh connections. */

    if (opt_log_stderr) {
        rs_remove_all_loggers();
        rs_add_logger(rs_logger_file, opt_log_level_num, 0, STDERR_FILENO);
        return;
    }

    if (arg_log_file) {
        /* Don't remove loggers yet, in case this fails and needs to go to the
         * default. */
        if ((fd = open(arg_log_file, O_CREAT|O_APPEND|O_WRONLY, 0666)) == -1) {
            rs_log_error("failed to open %s: %s", arg_log_file,
                         strerror(errno));
            /* continue and use syslog */
        } else {
            rs_remove_all_loggers();
            rs_add_logger(rs_logger_file, opt_log_level_num, NULL, fd);
            return;
        }
    }

    rs_remove_all_loggers();
    openlog("distccd", LOG_PID, LOG_DAEMON);
    rs_add_logger(rs_logger_syslog, opt_log_level_num, NULL, 0);
}
Example #2
0
/**
 * Errors during startup (e.g. bad options) need to be reported somewhere,
 * although we have not yet parsed the options to work out where the user
 * wants them.
 *
 * In inetd mode, we can't write to stderr because that will corrupt the
 * stream, so if it looks like stderr is a socket we go to syslog instead.
 **/
static int dcc_setup_startup_log(void)
{
    rs_trace_set_level(RS_LOG_INFO);
    if (!is_a_socket(STDERR_FILENO)) {
        rs_add_logger(rs_logger_file, RS_LOG_DEBUG, 0, STDERR_FILENO);
    } else {
        openlog("distccd", LOG_PID, LOG_DAEMON);
        rs_add_logger(rs_logger_syslog, RS_LOG_DEBUG, NULL, 0);
    }

    return 0;
}
Example #3
0
File: trace.c Project: aosm/distcc
/**
 * If you don't initialize a logger before first logging, then we
 * write to stderr by default.
 **/
static void rs_lazy_default(void)
{
    static int called;

    if (called)
        return;

    called = 1;
    if (logger_list == NULL)
        rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, STDERR_FILENO);
}
Example #4
0
int main(int argc, char **argv) {
  rs_program_name = argv[0];
  rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, STDERR_FILENO);
  rs_trace_set_level(RS_LOG_DEBUG);
  if (argc != 4) {
    rs_log_error("Usage: %s <filename> <client-path> <server-path>",
                 rs_program_name);
    exit(1);
  }
  return dcc_fix_debug_info(argv[1], argv[2], argv[3]);
}
Example #5
0
int main(int argc, char *argv[])
{
    rs_trace_set_level(RS_LOG_DEBUG);
    rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, STDERR_FILENO);
    if (argc < 2) {
        rs_log_error(USAGE);
        return 1;
    }

    if (strcmp(argv[1], "dcc_fresh_dependency_exists") == 0) {
        if (argc != 5) {
            rs_log_error("dcc_fresh_dependency_exists expects DOTD_FNAME "
                         "EXCL_PAT REF_TIME");
            return 1;
        }
        errno = 0;
        char *ptr;
        time_t ref_time = (time_t)strtol(argv[4], &ptr, 0);
        if (errno || (*ptr != '\0')) {
            rs_log_error("strtol failed");
            return 1;
        } else {
            char *result;
            int ret;
            ret = dcc_fresh_dependency_exists((const char *)argv[2],
                                              (const char *)argv[3],
                                              ref_time,
                                              &result);
            if (ret)
                printf("h_compile.c: UNEXPECTED RETURN VALUE\n");
            else
                printf("result %s\n", result ? result : "(NULL)");
            if (result) free(result);
        }
    } else if (strcmp(argv[1], "dcc_discrepancy_filename") == 0) {
        if (argc != 2) {
            rs_log_error("dcc_discrepancy_filename expects no arguments");
            return 1;
        }
        char *result;
        int ret = dcc_discrepancy_filename(&result);
        if (ret)
            printf("h_compile.c: UNEXPECTED RETURN VALUE\n");
        else
            printf("%s", result ? result : "(NULL)");
    } else {
        rs_log_error(USAGE);
        return 1;
    }
    return 0;
}
Example #6
0
/**
 * Setup client error/trace output.
 *
 * Trace goes to the file specified by DISTCC_LOG, if any.  Otherwise, it goes
 * to stderr, except that UNCACHED_ERR_FD can redirect it elsewhere, for use
 * under ccache.
 *
 * The exact setting of log level is a little strange, but for a good
 * reason: if you ask for verbose, you get everything.  Otherwise, if
 * you set a file, you get INFO and above.  Otherwise, you only get
 * WARNING messages.  In practice this seems to be a nice balance.
 **/
void dcc_set_trace_from_env(void)
{
    const char *logfile, *logfd_name;
    int fd;

    if ((logfile = getenv("DISTCC_LOG")) && logfile[0]) {
        rs_trace_set_level(RS_LOG_INFO);

        fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0666);
        if (fd == -1) {
            /* use stderr instead */
            int save_errno = errno;
            
            rs_trace_set_level(RS_LOG_WARNING);
            rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, STDERR_FILENO);

            rs_log_error("failed to open logfile %s: %s",
                         logfile, strerror(save_errno));
        } else {
            rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, fd);
            rs_trace_set_level(RS_LOG_INFO);
        }
    } else {
        if ((logfd_name = getenv("UNCACHED_ERR_FD")) == NULL ||
            (fd = atoi(logfd_name)) == 0) {
            fd = STDERR_FILENO;
        }
            
        rs_trace_set_level(RS_LOG_WARNING);
        rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, fd);
    }

    if (dcc_getenv_bool("DISTCC_VERBOSE", 0)) {
        rs_trace_set_level(RS_LOG_DEBUG);
    }
}
Example #7
0
File: serve.c Project: aosm/distcc
/**
 * Copy all server messages to the error file, so that they can be
 * echoed back to the client if necessary.
 **/
static int dcc_add_log_to_file(const char *err_fname)
{
    if (dcc_compile_log_fd != -1) {
        rs_log_crit("compile log already open?");
        return 0;               /* continue? */
    }
    
    dcc_compile_log_fd = open(err_fname, O_WRONLY|O_CREAT|O_TRUNC, 0600);
    if (dcc_compile_log_fd == -1) {
        rs_log_error("failed to open %s: %s", err_fname, strerror(errno));
        return EXIT_IO_ERROR;
    }

    /* Only send fairly serious errors back */
    rs_add_logger(rs_logger_file, RS_LOG_WARNING, NULL, dcc_compile_log_fd);

    return 0;
}
Example #8
0
File: traceenv.c Project: zma/mrcc
/**
 * Setup client error/trace output.
 *
 * Trace goes to the file specified by MRCC_LOG, if any.  Otherwise, it goes
 * to stderr, except that UNCACHED_ERR_FD can redirect it elsewhere, for use
 * under ccache.
 *
 * The exact setting of log level is a little strange, but for a good
 * reason: if you ask for verbose, you get everything.  Otherwise, if
 * you set a file, you get INFO and above.  Otherwise, you only get
 * WARNING messages.  In practice this seems to be a nice balance.
 **/
void set_trace_from_env(void)
{
    const char *logfile, *logfd_name;
    int fd;
    int failed_to_open_logfile = 0;
    int save_errno = 0;
    int level = RS_LOG_WARNING; /* by default, warnings only */

    /* let the decision on what to log rest on the loggers */
    /* the email-an-error functionality in emaillog.c depends on this */
    rs_trace_set_level(RS_LOG_DEBUG);

    if ((logfile = getenv("MRCC_LOG")) && logfile[0]) {
        fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0666);
        if (fd != -1) {
            /* asked for a file, and we can open that file:
               include info messages */
            level = RS_LOG_INFO;
        } else {
            /* asked for a file, can't use it; use stderr instead */
            fd = STDERR_FILENO;
            save_errno = errno;
            failed_to_open_logfile = 1;
        }
    } else {
        /* not asked for file */
        if ((logfd_name = getenv("UNCACHED_ERR_FD")) == NULL ||
            (fd = atoi(logfd_name)) == 0) {
            fd = STDERR_FILENO;
        }
    }

    if (getenv_bool("MRCC_VERBOSE", 0)) {
        level = RS_LOG_DEBUG;
    }

    rs_add_logger(rs_logger_file, level, NULL, fd);

    if (failed_to_open_logfile) {
        rs_log_error("failed to open logfile %s: %s",
                     logfile, strerror(save_errno));
    }
}
Example #9
0
/* Get the host list from zeroconf */
int dcc_zeroconf_add_hosts(struct dcc_hostdef **ret_list, int *ret_nhosts, int n_slots, struct dcc_hostdef **ret_prev) {
    char host_file[PATH_MAX], lock_file[PATH_MAX], *s = NULL;
    int lock_fd = -1, host_fd = -1;
    int fork_daemon = 0;
    int r = -1;
    char *dir;
    struct stat st;

    if (get_zeroconf_dir(&dir) != 0) {
        rs_log_crit("failed to get zeroconf dir.\n");
        goto finish;
    }

    snprintf(lock_file, sizeof(lock_file), "%s/lock", dir);
    snprintf(host_file, sizeof(host_file), "%s/hosts", dir);

    /* Open lock file */
    if ((lock_fd = open(lock_file, O_RDWR|O_CREAT, 0666)) < 0) {
        rs_log_crit("open('%s') failed: %s\n", lock_file, strerror(errno));
        goto finish;
    }

    /* Try to lock the lock file */
    if (generic_lock(lock_fd, 1, 1, 0) >= 0) {
        /* The lock succeeded => there's no daemon running yet! */
        fork_daemon = 1;
        generic_lock(lock_fd, 1, 0, 0);
    }

    close(lock_fd);

    /* Shall we fork a new daemon? */
    if (fork_daemon) {
        pid_t pid;

        rs_log_info("Spawning zeroconf daemon.\n");

        if ((pid = fork()) == -1) {
            rs_log_crit("fork() failed: %s\n", strerror(errno));
            goto finish;
        } else if (pid == 0) {
            int fd;
            /* Child */

            /* Close file descriptors and replace them by /dev/null */
            close(0);
            close(1);
            close(2);
            fd = open("/dev/null", O_RDWR);
            assert(fd == 0);
            fd = dup(0);
            assert(fd == 1);
            fd = dup(0);
            assert(fd == 2);

#ifdef HAVE_SETSID
            setsid();
#endif

            chdir("/");
            rs_add_logger(rs_logger_syslog, RS_LOG_DEBUG, NULL, 0);
            _exit(daemon_proc(host_file, lock_file, n_slots));
        }

        /* Parent */

        /* Wait some time for initial host gathering */
        usleep(1000000);         /* 1000 ms */
    }

    /* Open host list read-only */
    if ((host_fd = open(host_file, O_RDONLY)) < 0) {
        rs_log_crit("open('%s') failed: %s\n", host_file, strerror(errno));
        goto finish;
    }

    /* A read lock */
    if (generic_lock(host_fd, 0, 1, 1) < 0) {
        rs_log_crit("lock failed: %s\n", strerror(errno));
        goto finish;
    }

    /* Get file size */
    if (fstat(host_fd, &st) < 0) {
        rs_log_crit("stat() failed: %s\n", strerror(errno));
        goto finish;
    }

    if (st.st_size >= MAX_FILE_SIZE) {
        rs_log_crit("file too large.\n");
        goto finish;
    }

    /* read file data */
    s = malloc((size_t) st.st_size+1);
    assert(s);

    if (dcc_readx(host_fd, s, (size_t) st.st_size) != 0) {
        rs_log_crit("failed to read from file.\n");
        goto finish;
    }
    s[st.st_size] = 0;

    /* Parse host data */
    if (dcc_parse_hosts(s, host_file, ret_list, ret_nhosts, ret_prev) != 0) {
        rs_log_crit("failed to parse host file.\n");
        goto finish;
    }

    r = 0;

finish:
    if (host_fd >= 0) {
        generic_lock(host_fd, 0, 0, 1);
        close(host_fd);
    }

    free(s);

    return r;
}
Example #10
0
/* The main function of the background daemon */
static int daemon_proc(const char *host_file, const char *lock_file, int n_slots) {
    int ret = 1;
    int lock_fd = -1;
    struct daemon_data d;
    time_t clip_time;
    int error;
    char machine[64], version[64], stype[128];

    rs_add_logger(rs_logger_syslog, RS_LOG_DEBUG, NULL, 0);

    /* Prepare daemon data structure */
    d.fd = -1;
    d.hosts = NULL;
    d.n_slots = n_slots;
    d.simple_poll = NULL;
    d.browser = NULL;
    d.client = NULL;
    clip_time = time(NULL);

    rs_log_info("Zeroconf daemon running.\n");

    /* Open daemon lock file and lock it */
    if ((lock_fd = open(lock_file, O_RDWR|O_CREAT, 0666)) < 0) {
        rs_log_crit("open('%s') failed: %s\n", lock_file, strerror(errno));
        goto finish;
    }

    if (generic_lock(lock_fd, 1, 1, 0) < 0) {
        /* lock failed, there's probably already another daemon running */
        goto finish;
    }

    /* Open host file */
    if ((d.fd = open(host_file, O_RDWR|O_CREAT, 0666)) < 0) {
        rs_log_crit("open('%s') failed: %s\n", host_file, strerror(errno));
        goto finish;
    }

    /* Clear host file */
    write_hosts(&d);

    if (!(d.simple_poll = avahi_simple_poll_new())) {
        rs_log_crit("Failed to create simple poll object.\n");
        goto finish;
    }

    if (!(d.client = avahi_client_new(
                  avahi_simple_poll_get(d.simple_poll),
                  0,
                  client_callback,
                  &d,
                  &error))) {
        rs_log_crit("Failed to create Avahi client object: %s\n", avahi_strerror(error));
        goto finish;
    }

    if (dcc_get_gcc_version(version, sizeof(version)) &&
        dcc_get_gcc_machine(machine, sizeof(machine))) {

        dcc_make_dnssd_subtype(stype, sizeof(stype), version, machine);
    } else {
        rs_log_warning("Warning, failed to get CC version and machine type.\n");

        strncpy(stype, DCC_DNS_SERVICE_TYPE, sizeof(stype));
        stype[sizeof(stype)-1] = 0;
    }

    rs_log_info("Browsing for '%s'.\n", stype);

    if (!(d.browser = avahi_service_browser_new(
                  d.client,
                  AVAHI_IF_UNSPEC,
                  AVAHI_PROTO_UNSPEC,
                  stype,
                  NULL,
                  0,
                  browse_reply,
                  &d))) {
        rs_log_crit("Failed to create service browser object: %s\n", avahi_strerror(avahi_client_errno(d.client)));
        goto finish;
    }

    /* Check whether the host file has been used recently */
    while (fd_last_used(d.fd, clip_time) <= MAX_IDLE_TIME) {

        /* Iterate the main loop for 5s */
        if (avahi_simple_poll_iterate(d.simple_poll, 5000) != 0) {
            rs_log_crit("Event loop exited abnormaly.\n");
            goto finish;
        }
    }

    /* Wer are idle */
    rs_log_info("Zeroconf daemon unused.\n");

    ret = 0;

finish:

    /* Cleanup */
    if (lock_fd >= 0) {
        generic_lock(lock_fd, 1, 0, 0);
        close(lock_fd);
    }

    if (d.fd >= 0)
        close(d.fd);

    while (d.hosts) {
        struct host *h = d.hosts;
        d.hosts = d.hosts->next;
        free_host(h);
    }

    if (d.client)
        avahi_client_free(d.client);

    if (d.simple_poll)
        avahi_simple_poll_free(d.simple_poll);

    rs_log_info("zeroconf daemon ended.\n");

    return ret;
}