#include "cache.h" #define MAXNAME (256) static FILE *config_file; static int config_linenr; static int get_next_char(void) { int c; FILE *f; c = '\n'; if ((f = config_file) != NULL) { c = fgetc(f); if (c == '\r') { /* DOS like systems */ c = fgetc(f); if (c != '\n') { ungetc(c, f); c = '\r'; } } if (c == '\n') config_linenr++; if (c == EOF) { config_file = NULL; c = '\n'; } } return c; } static char *parse_value(void) { static char value[1024]; int quote = 0, comment = 0, len = 0, space = 0; for (;;) { int c = get_next_char(); if (len >= sizeof(value)) return NULL; if (c == '\n') { if (quote) return NULL; value[len] = 0; return value; } if (comment) continue; if (isspace(c) && !quote) { space = 1; continue; } if (space) { if (len) value[len++] = ' '; space = 0; } if (c == '\\') { c = get_next_char(); switch (c) { case '\n': continue; case 't': c = '\t'; break; case 'b': c = '\b'; break; case 'n': c = '\n'; break; /* Some characters escape as themselves */ case '\\': case '"': break; /* Reject unknown escape sequences */ default: return NULL; } value[len++] = c; continue; } if (c == '"') { quote = 1-quote; continue; } if (!quote) { if (c == ';' || c == '#') { comment = 1; continue; } } value[len++] = c; } } static int get_value(config_fn_t fn, char *name, unsigned int len) { int c; char *value; /* Get the full name */ for (;;) { c = get_next_char(); if (c == EOF) break; if (!isalnum(c)) break; name[len++] = tolower(c); if (len >= MAXNAME) return -1; } name[len] = 0; while (c == ' ' || c == '\t') c = get_next_char(); value = NULL; if (c != '\n') { if (c != '=') return -1; value = parse_value(); if (!value) return -1; } return fn(name, value); } static int get_base_var(char *name) { int baselen = 0; for (;;) { int c = get_next_char(); if (c == EOF) return -1; if (c == ']') return baselen; if (!isalnum(c)) return -1; if (baselen > MAXNAME / 2) return -1; name[baselen++] = tolower(c); } } static int git_parse_file(config_fn_t fn) { int comment = 0; int baselen = 0; static char var[MAXNAME]; for (;;) { int c = get_next_char(); if (c == '\n') { /* EOF? */ if (!config_file) return 0; comment = 0; continue; } if (comment || isspace(c)) continue; if (c == '#' || c == ';') { comment = 1; continue; } if (c == '[') { baselen = get_base_var(var); if (baselen <= 0) break; var[baselen++] = '.'; var[baselen] = 0; continue; } if (!isalpha(c)) break; var[baselen] = tolower(c); if (get_value(fn, var, baselen+1) < 0) break; } die("bad config file line %d", config_linenr); } int git_config_int(const char *name, const char *value) { if (value && *value) { char *end; int val = strtol(value, &end, 0); if (!*end) return val; } die("bad config value for '%s'", name); } int git_config_bool(const char *name, const char *value) { if (!value) return 1; if (!*value) return 0; if (!strcasecmp(value, "true")) return 1; if (!strcasecmp(value, "false")) return 0; return git_config_int(name, value) != 0; } int git_default_config(const char *var, const char *value) { /* This needs a better name */ if (!strcmp(var, "core.filemode")) { trust_executable_bit = git_config_bool(var, value); return 0; } if (!strcmp(var, "user.name")) { strncpy(git_default_name, value, sizeof(git_default_name)); return 0; } if (!strcmp(var, "user.email")) { strncpy(git_default_email, value, sizeof(git_default_email)); return 0; } /* Add other config variables here.. */ return 0; } int git_config(config_fn_t fn) { int ret; FILE *f = fopen(git_path("config"), "r"); ret = -1; if (f) { config_file = f; config_linenr = 1; ret = git_parse_file(fn); fclose(f); } return ret; }