⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hosts.c

📁 distcc编译器的源代码.好像是readhat公司开发的.
💻 C
字号:
/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*- *  * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */                /* The lyf so short, the craft so long to lerne.                 * -- Chaucer */    /** * @file * * Routines to parse <tt>$DISTCC_HOSTS</tt>.  Actual decisions about * where to run a job are in where.c. * * The grammar of this variable is, informally: *  DISTCC_HOSTS = HOSTSPEC ...  HOSTSPEC = LOCAL_HOST | SSH_HOST | TCP_HOST | OLDSTYLE_TCP_HOST  LOCAL_HOST = localhost[/LIMIT]  SSH_HOST = [USER]@HOSTID[/LIMIT][:COMMAND][OPTIONS]  TCP_HOST = HOSTID[:PORT][/LIMIT][OPTIONS]  OLDSTYLE_TCP_HOST = HOSTID[/LIMIT][:PORT][OPTIONS]  HOSTID = HOSTNAME | IPV4  OPTIONS = ,OPTION[OPTIONS]  OPTION = lzo * * Any amount of whitespace may be present between hosts. * * The command specified for SSH defines the location of the remote * server, e.g. "/usr/local/bin/distccd".  This is provided as a * convenience who have trouble getting their PATH set correctly for * sshd to find distccd, and should not normally be needed. * * If you need to specify special options for ssh, they should be put * in ~/.ssh/config and referenced by the hostname. * * The TCP port defaults to 3632 and should not normally need to be * overridden. * * IPv6 literals are not supported yet.  They will need to be * surrounded by square brackets because they may contain a colon, * which would otherwise be ambiguous.  This is consistent with other * URL-like schemes. *//*       Alexandre Oliva writes        I take this opportunity to plead people to consider such issues when        proposing additional syntax for DISTCC_HOSTS: if it was possible to        handle DISTCC_HOSTS as a single shell word (perhaps after turning        blanks into say commas), without the risk of any shell active        characters such as {, }, ~, $, quotes getting in the way, outputting        distcc commands that override DISTCC_HOSTS would be far        simpler.  TODO: Perhaps entries in the host list that "look like files" (start    with '/' or '~') should be read in as files?  This could even be    recursive.*/#include "config.h"#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <time.h>#include <ctype.h>#include "distcc.h"#include "trace.h"#include "util.h"#include "hosts.h"#include "exitcode.h"#include "snprintf.h"const int dcc_default_port = DISTCC_DEFAULT_PORT;#ifndef HAVE_STRNDUP/** * Copy at most @p size characters from @p src, plus a terminating nul. * * Really this needs to be in util.c, but it's only used here. **/static char *strndup(const char *src, size_t size){    char *dst;    dst = malloc(size + 1);    if (dst == NULL)        return NULL;    strncpy(dst, src, size);    dst[size] = '\0';    return dst;}#endif/** * Get a list of hosts to use. * * Hosts are taken from DISTCC_HOSTS, if that exists.  Otherwise, they are * taken from $DISTCC_DIR/hosts, if that exists.  Otherwise, they are taken * from ${sysconfdir}/distcc/hosts, if that exists.  Otherwise, we fail. **/int dcc_get_hostlist(struct dcc_hostdef **ret_list,                     int *ret_nhosts){    char *env;    char *path, *top;    int ret;    if ((env = getenv("DISTCC_HOSTS")) != NULL) {        rs_trace("read hosts from environment");        return dcc_parse_hosts(env, "$DISTCC_HOSTS", ret_list, ret_nhosts);    }    /* $DISTCC_DIR or ~/.distcc */    if ((ret = dcc_get_top_dir(&top)) == 0) {        /* if we failed to get it, just warn */        asprintf(&path, "%s/hosts", top);        if (access(path, R_OK) == 0) {            ret = dcc_parse_hosts_file(path, ret_list, ret_nhosts);            free(path);            return ret;        } else {            rs_trace("not reading %s: %s", path, strerror(errno));            free(path);        }    }    asprintf(&path, "%s/distcc/hosts", SYSCONFDIR);    if (access(path, R_OK) == 0) {        ret = dcc_parse_hosts_file(path, ret_list, ret_nhosts);        free(path);        return ret;    } else {        rs_trace("not reading %s: %s", path, strerror(errno));        free(path);    }        /* FIXME: Clearer message? */    rs_log_warning("no hostlist is set; can't distribute work");    return EXIT_BAD_HOSTSPEC;}/** * Parse an optionally present multiplier. * * *psrc is the current parse cursor; it is advanced over what is read. * * If a multiplier is present, *psrc points to a substring starting with '/'. * The host defintion is updated to the numeric value following.  Otherwise * the hostdef is unchanged. **/static int dcc_parse_multiplier(const char **psrc, struct dcc_hostdef *hostdef){    const char *token = *psrc;    if ((*psrc)[0] == '/') {        int val;        (*psrc)++;        val = atoi(*psrc);        if (val == 0) {            rs_log_error("bad multiplier \"%s\" in host specification", token);            return EXIT_BAD_HOSTSPEC;        }        while (isdigit(**psrc))            (*psrc)++;        hostdef->n_slots = val;    }    return 0;}/** * Parse an optionally present option string. * * At the moment the only option we have is "lzo" for compression, so this is * pretty damn simple. **/static int dcc_parse_options(const char **psrc,                             struct dcc_hostdef *host){    const char *started = *psrc, *p = *psrc;    while (p[0] == ',') {        p++;        if (str_startswith("lzo", p)) {            rs_trace("got LZO option");            host->protover = DCC_VER_2;            host->compr = DCC_COMPRESS_LZO1X;            p += 3;        } else {            rs_log_warning("unrecognized option in host specification %s",                           started);            return EXIT_BAD_HOSTSPEC;        }    }    *psrc = p;        return 0;}static int dcc_parse_ssh_host(struct dcc_hostdef *hostdef,                              const char *token_start){    int ret;    const char *token = token_start;        /* Everything up to '@' is the username */    if ((ret = dcc_dup_part(&token, &hostdef->user, "@")) != 0)        return ret;    if (token[0] != '@') {        rs_log_error("expected '@' to start ssh token");        return EXIT_BAD_HOSTSPEC;    }    token++;    if ((ret = dcc_dup_part(&token, &hostdef->hostname, "/: \t\n\r\f,")) != 0)        return ret;    if (!hostdef->hostname) {        rs_log_error("hostname is required in SSH host specification \"%s\"",                     token_start);        return EXIT_BAD_HOSTSPEC;    }    if ((ret = dcc_parse_multiplier(&token, hostdef)) != 0)        return ret;    if (token[0] == ':') {        token++;        if ((ret = dcc_dup_part(&token, &hostdef->ssh_command, " \t\n\r\f,")))            return ret;    }        if ((ret = dcc_parse_options(&token, hostdef)))        return ret;    hostdef->mode = DCC_MODE_SSH;    return 0;}static int dcc_parse_tcp_host(struct dcc_hostdef *hostdef,                              const char * const token_start){    int ret;    const char *token = token_start;        if ((ret = dcc_dup_part(&token, &hostdef->hostname, "/: \t\n\r\f,")))        return ret;    if (!hostdef->hostname) {        rs_log_error("hostname is required in tcp host specification \"%s\"",                     token_start);        return EXIT_BAD_HOSTSPEC;    }    if ((ret = dcc_parse_multiplier(&token, hostdef)) != 0)        return ret;    hostdef->port = dcc_default_port;    if (token[0] == ':') {        char *tail;        token++;        hostdef->port = strtol(token, &tail, 10);        if (*tail != '\0' && !isspace(*tail) && *tail != '/' && *tail != ',') {            rs_log_error("invalid tcp port specification in \"%s\"", token);            return EXIT_BAD_HOSTSPEC;         } else {            token = tail;        }    }            if ((ret = dcc_parse_multiplier(&token, hostdef)) != 0)        return ret;    if ((ret = dcc_parse_options(&token, hostdef)))        return ret;    hostdef->mode = DCC_MODE_TCP;    return 0;}static int dcc_parse_localhost(struct dcc_hostdef *hostdef,                               const char * token_start){    const char *token = token_start + strlen("localhost");    hostdef->mode = DCC_MODE_LOCAL;    hostdef->hostname = strdup("localhost");    /* Run only two tasks on localhost by default.     *     * It might be nice to run more if there are more CPUs, but determining     * the number of CPUs on Linux is a bit expensive since it requires     * examining mtab and /proc/stat.  Anyone lucky enough to have a >2 CPU     * machine can specify a number in the host list.     */    hostdef->n_slots = 2;        return dcc_parse_multiplier(&token, hostdef);}/** * @p where is the host list, taken either from the environment or file. * * @return 0 if parsed successfully; nonzero if there were any errors, * or if no hosts were defined. **/int dcc_parse_hosts(const char *where, const char *source_name,                    struct dcc_hostdef **ret_list,                    int *ret_nhosts){    int ret;    struct dcc_hostdef *prev, *curr;    /* TODO: Check for '/' in places where it might cause trouble with     * a lock file name. */    prev = NULL;    *ret_list = NULL;    *ret_nhosts = 0;    /* A simple, hardcoded scanner.  Some of the GNU routines might be     * useful here, but they won't work on less capable systems.     *     * We repeatedly attempt to extract a whitespace-delimited host     * definition from the string until none remain.  Allocate an     * entry; hook to previous entry.  We then determine if there is a     * '@' in it, which tells us whether it is an SSH or TCP     * definition.  We then duplicate the relevant subcomponents into     * the relevant fields. */    while (1) {        int token_len;        const char *token_start;        int has_at;                if (where[0] == '\0')            break;              /* end of string */                /* skip over comments */        if (where[0] == '#') {            do                where++;            while (where[0] != '\n' && where[0] != '\r' && where[0] != '\0');            continue;        }        if (isspace(where[0])) {            where++;            /* skip space */            continue;        }        token_start = where;        token_len = strcspn(where, " #\t\n\f\r");        /* Allocate new list item */        curr = calloc(1, sizeof(struct dcc_hostdef));        if (!curr) {            rs_log_crit("failed to allocate host definition");            return EXIT_OUT_OF_MEMORY;        }        /* Store verbatim hostname */        if (!(curr->hostdef_string = strndup(token_start, (size_t) token_len))) {            rs_log_crit("failed to allocate hostdef_string");            return EXIT_OUT_OF_MEMORY;        }        /* Link into list */        if (prev) {            prev->next = curr;        } else {            *ret_list = curr;   /* first */        }        /* Default task limit.  A bit higher than the local limit to allow for         * some files in transit. */        curr->n_slots = 4;        curr->protover = DCC_VER_1; /* default */        curr->compr = DCC_COMPRESS_NONE;                    has_at = (memchr(token_start, '@', (size_t) token_len) != NULL);        if (!strncmp(token_start, "localhost", 9)            && (token_len == 9 || token_start[9] == '/')) {            rs_trace("found localhost token \"%.*s\"", token_len, token_start);            if ((ret = dcc_parse_localhost(curr, token_start)) != 0)                return ret;        } else if (has_at) {            rs_trace("found ssh token \"%.*s\"", token_len, token_start);            if ((ret = dcc_parse_ssh_host(curr, token_start)) != 0)                return ret;        } else {            rs_trace("found tcp token \"%.*s\"", token_len, token_start);            if ((ret = dcc_parse_tcp_host(curr, token_start)) != 0)                return ret;        }        /* continue to next token if any */        where = token_start + token_len;        prev = curr;        (*ret_nhosts)++;    }        if (*ret_nhosts) {        return 0;    } else {        rs_log_warning("%s contained no hosts; can't distribute work", source_name);         return EXIT_BAD_HOSTSPEC;    }}int dcc_free_hostdef(struct dcc_hostdef *host){    /* ANSI C requires free() to accept NULL */        free(host->user);    free(host->hostname);    free(host->ssh_command);    free(host->hostdef_string);    memset(host, 0xf1, sizeof *host);    free(host);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -