Skip to content
Extraits de code Groupes Projets
Sélectionner une révision Git
  • 40fdee19318cc9f317dc89b1ff7c8e65778cdabb
  • master par défaut protégée
  • rust-playlist-sync
  • rust
  • fix-qt-deprecated-qvariant-type
  • fix-mpris-qtwindow-race-condition
  • rust-appimage-wayland
  • windows-build-rebased
  • v2.5 protégée
  • v2.4 protégée
  • v2.3-1 protégée
  • v2.3 protégée
  • v2.2 protégée
  • v2.1 protégée
  • v2.0 protégée
  • v1.8-3 protégée
  • v1.8-2 protégée
  • v1.8-1 protégée
  • v1.8 protégée
  • v1.7 protégée
  • v1.6 protégée
  • v1.5 protégée
  • v1.4 protégée
  • v1.3 protégée
  • v1.2 protégée
  • v1.1 protégée
  • v1.0 protégée
27 résultats

config.c

Blame
  • config.c 7,58 Kio
    #define _POSIX_C_SOURCE 200809L
    
    #include <common/common.h>
    #include <lektor/config.h>
    #include <lektor/database.h>
    #include <lektor/net.h>
    #include <lektor/reg.h>
    
    #include <strings.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <dlfcn.h>
    #include <stdio.h>
    #include <pwd.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <limits.h>
    #include <ctype.h>
    
    static inline char *
    strip(char *s)
    {
        char *p = s + strlen(s);
        while (p > s && isspace(*(--p)))
            *p = 0;
        return s;
    }
    
    static inline char *
    skip(char *s)
    {
        while (*s && isspace(*s))
            s++;
        return s;
    }
    
    static int
    handler(volatile sqlite3 *user, const char *section, const char *name,
            const char *value)
    {
        RETURN_UNLESS(section && name && value,
                      "I can't complete the database with incomplete lines", 1);
        RETURN_UNLESS(database_config_set(user, section, name, value),
                      "Failed to update the database", 1);
        return 0;
    }
    
    static inline void
    __set_log_level(const char *name, const char *level)
    {
        if (!STR_MATCH(name, "log")) {
            LOG_WARN("CONFIG", "Invalid option '%s[:=]%s' with no section",
                     name, level);
            return;
        }
    
        if (!level[0]) {
            LOG_WARN("CONFIG", "%s", "Invalid empty 'log' option");
            return;
        }
    
        if (STR_MATCH(level, "error"))
            log_level = ERROR;
        else if (STR_MATCH(level, "warn") || STR_MATCH(level, "warning"))
            log_level = WARN;
        else if (STR_MATCH(level, "info"))
            log_level = INFO;
        else if (STR_MATCH(level, "debug"))
            log_level = DEBUG;
        else
            log_level = strtol(level, NULL, 0);
    
        LOG_INFO("CONFIG", "Log level set to %d", log_level);
    }
    
    static inline int
    ini_parse(const char *path, volatile sqlite3 *db)
    {
        char *start, *end, *name, *value;
        char section[INI_MAX_SECTION_LEN], line[INI_MAX_LINE_LEN];
        int error = 0, linenum = 0, len;
        FILE *file = fopen(path, "r");
        if (!file) {
            LOG_ERROR("PARSER", "Failed to open config file '%s'", path);
            return 1;
        }
    
        memset(section, 0, INI_MAX_SECTION_LEN);
        memset(line, 0, INI_MAX_LINE_LEN);
    
        /* Parse the file */
        while (NULL != fgets(line, INI_MAX_LINE_LEN, file)) {
            ++linenum;
            start = skip(strip(line));
    
            /* Skip comments */
            if (strspn(start, ";#"))
                continue;
    
            /* Handle sections */
            else if (start[0] == '[') {
                end = &start[1 + strcspn(start + 1, "]")];
                if (end[0] == ']') {
                    end[0] = '\0';
                    len = strlen(&start[1]);
                    len = MIN(len + 1, INI_MAX_SECTION_LEN);
                    memcpy(section, &start[1], len);
                    section[INI_MAX_SECTION_LEN - 1] = '\0';
                }
    
                else {
                    error = 1;
                    LOG_ERROR("PARSER", "Invalid section name at line '%d'",
                              linenum);
                }
            }
    
            /* Handle name[:=]name pair */
            else if (start[0]) {
                end = &start[1 + strcspn(start + 1, ":=")];
                if (end[0] == '=' || end[0] == ':') {
                    end[0] = '\0';
                    name   = strip(start);
                    value  = &end[1];
    
                    /* Find a comment */
                    end = &value[strcspn(value, ";#")];
                    if (end[0])
                        end[0] = '\0';
    
                    /* Skip all spaces */
                    value = skip(value);
                    strip(value);
    
                    /* Handle the SECTION, NAME[:=]VALUE
                       The only option that has no SECTION is the log level:
                       log[:=]ERROR|WARN|INFO|DEBUG|\d+ */
                    if (section[0]) {
                        if (handler(db, section, name, value)) {
                            error = 1;
                            LOG_ERROR("PARSER", "Failed to '[handle] %s, "
                                      "%s{:,=}%s' at line '%d'",
                                      section, name, value, linenum);
                        }
                    } else
                        __set_log_level(name, value);
                }
    
                else {
                    error = 1;
                    LOG_ERROR("PARSER", "Invalid name[:=]value pair at "
                              "line '%d'", linenum);
                }
            }
        }
    
        /* End of the function */
        fclose(file);
        if (error)
            LOG_ERROR("PARSER", "An error occured while parsing the "
                      "file '%s'", path);
        return error;
    }
    
    int
    config_detect_file(char *conf, size_t conf_len)
    {
        bool is_malloc = false;
        struct passwd *pw = getpwuid(getuid());
        char *home;
    
        if (conf == NULL)
            return 1;
    
        memset(conf, 0, conf_len * sizeof(char));
    
        /* Try the current working dir config file. */
        if (getcwd(conf, conf_len - 1) != NULL) {
            strncat(conf, "/lektor.ini", conf_len - 1);
            LOG_INFO("CONFIG", "Trying %s", conf);
            if (!access(conf, R_OK | F_OK))
                goto found;
        }
    
        /* Try the config file from the config directory. */
        home = getenv("XDG_CONFIG_HOME");
        if (home && strlen(home) < conf_len) {
            /* Skip the strncat to not append the '.config/' to
               the XDG_CONFIG_HOME which must already have this directory in it */
            strncat(conf, "/lektor/lektor.ini", conf_len - 1);
            goto skip_this_strcat;
        }
        if (!home || (strlen(home) >= conf_len))
            home = getenv("HOME");
        if (!home || (strlen(home) >= conf_len))
            home = pw->pw_dir;
        if (!home || (strlen(home) >= conf_len))
            goto no_config_directory;
        memcpy(conf, home, (strlen(home) + 1) * sizeof(char));
        strncat(conf, "/.config/lektor/lektor.ini", conf_len - 1);
    skip_this_strcat:
        LOG_INFO("CONFIG", "Trying %s", conf);
        if (!access(conf, R_OK | F_OK))
            goto found;
    
    no_config_directory:
        /* Try the '/opt/lektor' file. */
        memcpy(conf, "/opt/lektor/lektor.ini",
               sizeof("/opt/lektor/lektor.ini"));
        LOG_INFO("CONFIG", "Trying %s", conf);
        if (!access(conf, R_OK | F_OK))
            goto found;
    
        /* Try the '/usr/local/etc/lektor.ini' file. */
        memcpy(conf, "/usr/local/etc/lektor.ini",
               sizeof("/usr/local/etc/lektor.ini"));
        LOG_INFO("CONFIG", "Trying %s", conf);
        if (!access(conf, R_OK | F_OK))
            goto found;
    
        /* Try the '/etc/lektor.ini' file. */
        memcpy(conf, "/etc/lektor.ini", sizeof("/etc/lektor.ini"));
        LOG_INFO("CONFIG", "Trying %s", conf);
        if (!access(conf, R_OK | F_OK))
            goto found;
    
        /* Error */
        LOG_ERROR("CONFIG", "An error occured with file %s: %s",
                  conf, strerror(errno));
        if (is_malloc)
            free(conf);
        return 1;
    found:
        LOG_INFO("CONFIG", "Using file %s", conf);
        return 0;
    }
    
    int
    config_new(volatile sqlite3 *db, const char *conf)
    {
        if (ini_parse(conf, db)) {
            LOG_ERROR("CONFIG", "Failed to parse file %s", conf);
            goto error;
        }
    
        if (!database_validate_conf(db)) {
            LOG_ERROR("CONFIG", "Configuration file %s is incomplete", conf);
            goto error;
        }
    
        return 0;
    error:
        LOG_ERROR("CONFIG", "%s", "Errors detected, here is a default config");
        config_default(stdout);
        return 1;
    }
    
    void
    config_default(FILE *output)
    {
        fwrite(lkt_default_config_file, sizeof(char),
               strlen(lkt_default_config_file), output);
    }
    
    int
    config_open(volatile sqlite3 *db)
    {
        char conf_file[PATH_MAX];
        int ret = 1;
        GOTO_IF(config_detect_file(conf_file, PATH_MAX),
                "Error while searching for a config file", error);
        GOTO_IF(config_new(db, conf_file),
                "Failed to read configuration file", error);
        ret = 0;
    error:
        return ret;
    }