Example #1
0
static int _parse_repo(const char *key, char *value, const char *file,
		int line, struct section_t *section)
{
	int ret = 0;
	config_repo_t *repo = section->repo;

	if(strcmp(key, "Server") == 0) {
		if(!value) {
			pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"),
					file, line, key);
			ret = 1;
		} else {
			repo->servers = alpm_list_add(repo->servers, strdup(value));
		}
	} else if(strcmp(key, "SigLevel") == 0) {
		if(!value) {
			pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"),
					file, line, key);
		} else {
			alpm_list_t *values = NULL;
			setrepeatingoption(value, "SigLevel", &values);
			if(values) {
				ret = process_siglevel(values, &repo->siglevel,
						&repo->siglevel_mask, file, line);
				FREELIST(values);
			}
		}
	} else if(strcmp(key, "Usage") == 0) {
		alpm_list_t *values = NULL;
		setrepeatingoption(value, "Usage", &values);
		if(values) {
			if(process_usage(values, &repo->usage, file, line)) {
				FREELIST(values);
				return 1;
			}
			FREELIST(values);
		}
	} else {
		pm_printf(ALPM_LOG_WARNING,
				_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"),
				file, line, key, repo->name);
	}

	return ret;
}
Example #2
0
static int _parse_options(const char *key, char *value,
		const char *file, int linenum)
{
	if(value == NULL) {
		/* options without settings */
		if(strcmp(key, "UseSyslog") == 0) {
			config->usesyslog = 1;
			pm_printf(ALPM_LOG_DEBUG, "config: usesyslog\n");
		} else if(strcmp(key, "ILoveCandy") == 0) {
			config->chomp = 1;
			pm_printf(ALPM_LOG_DEBUG, "config: chomp\n");
		} else if(strcmp(key, "VerbosePkgLists") == 0) {
			config->verbosepkglists = 1;
			pm_printf(ALPM_LOG_DEBUG, "config: verbosepkglists\n");
		} else if(strcmp(key, "UseDelta") == 0) {
			config->deltaratio = 0.7;
			pm_printf(ALPM_LOG_DEBUG, "config: usedelta (default 0.7)\n");
		} else if(strcmp(key, "TotalDownload") == 0) {
			config->totaldownload = 1;
			pm_printf(ALPM_LOG_DEBUG, "config: totaldownload\n");
		} else if(strcmp(key, "CheckSpace") == 0) {
			config->checkspace = 1;
		} else if(strcmp(key, "Color") == 0) {
			if(config->color == PM_COLOR_UNSET) {
				config->color = isatty(fileno(stdout)) ? PM_COLOR_ON : PM_COLOR_OFF;
				enable_colors(config->color);
			}
		} else {
			pm_printf(ALPM_LOG_WARNING,
					_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"),
					file, linenum, key, "options");
		}
	} else {
		/* options with settings */
		if(strcmp(key, "NoUpgrade") == 0) {
			setrepeatingoption(value, "NoUpgrade", &(config->noupgrade));
		} else if(strcmp(key, "NoExtract") == 0) {
			setrepeatingoption(value, "NoExtract", &(config->noextract));
		} else if(strcmp(key, "IgnorePkg") == 0) {
			setrepeatingoption(value, "IgnorePkg", &(config->ignorepkg));
		} else if(strcmp(key, "IgnoreGroup") == 0) {
			setrepeatingoption(value, "IgnoreGroup", &(config->ignoregrp));
		} else if(strcmp(key, "HoldPkg") == 0) {
			setrepeatingoption(value, "HoldPkg", &(config->holdpkg));
		} else if(strcmp(key, "CacheDir") == 0) {
			setrepeatingoption(value, "CacheDir", &(config->cachedirs));
		} else if(strcmp(key, "Architecture") == 0) {
			if(!config->arch) {
				config_set_arch(value);
			}
		} else if(strcmp(key, "UseDelta") == 0) {
			double ratio;
			char *endptr;
			const char *oldlocale;

			/* set the locale to 'C' for consistent decimal parsing (0.7 and never
			 * 0,7) from config files, then restore old setting when we are done */
			oldlocale = setlocale(LC_NUMERIC, NULL);
			setlocale(LC_NUMERIC, "C");
			ratio = strtod(value, &endptr);
			setlocale(LC_NUMERIC, oldlocale);

			if(*endptr != '\0' || ratio < 0.0 || ratio > 2.0) {
				pm_printf(ALPM_LOG_ERROR,
						_("config file %s, line %d: invalid value for '%s' : '%s'\n"),
						file, linenum, "UseDelta", value);
				return 1;
			}
			config->deltaratio = ratio;
			pm_printf(ALPM_LOG_DEBUG, "config: usedelta = %f\n", ratio);
		} else if(strcmp(key, "DBPath") == 0) {
			/* don't overwrite a path specified on the command line */
			if(!config->dbpath) {
				config->dbpath = strdup(value);
				pm_printf(ALPM_LOG_DEBUG, "config: dbpath: %s\n", value);
			}
		} else if(strcmp(key, "RootDir") == 0) {
			/* don't overwrite a path specified on the command line */
			if(!config->rootdir) {
				config->rootdir = strdup(value);
				pm_printf(ALPM_LOG_DEBUG, "config: rootdir: %s\n", value);
			}
		} else if(strcmp(key, "GPGDir") == 0) {
			if(!config->gpgdir) {
				config->gpgdir = strdup(value);
				pm_printf(ALPM_LOG_DEBUG, "config: gpgdir: %s\n", value);
			}
		} else if(strcmp(key, "LogFile") == 0) {
			if(!config->logfile) {
				config->logfile = strdup(value);
				pm_printf(ALPM_LOG_DEBUG, "config: logfile: %s\n", value);
			}
		} else if(strcmp(key, "XferCommand") == 0) {
			config->xfercommand = strdup(value);
			pm_printf(ALPM_LOG_DEBUG, "config: xfercommand: %s\n", value);
		} else if(strcmp(key, "CleanMethod") == 0) {
			alpm_list_t *methods = NULL;
			setrepeatingoption(value, "CleanMethod", &methods);
			if(process_cleanmethods(methods, file, linenum)) {
				FREELIST(methods);
				return 1;
			}
			FREELIST(methods);
		} else if(strcmp(key, "SigLevel") == 0) {
			alpm_list_t *values = NULL;
			setrepeatingoption(value, "SigLevel", &values);
			if(process_siglevel(values, &config->siglevel,
						&config->siglevel_mask, file, linenum)) {
				FREELIST(values);
				return 1;
			}
			FREELIST(values);
		} else if(strcmp(key, "LocalFileSigLevel") == 0) {
			alpm_list_t *values = NULL;
			setrepeatingoption(value, "LocalFileSigLevel", &values);
			if(process_siglevel(values, &config->localfilesiglevel,
						&config->localfilesiglevel_mask, file, linenum)) {
				FREELIST(values);
				return 1;
			}
			FREELIST(values);
		} else if(strcmp(key, "RemoteFileSigLevel") == 0) {
			alpm_list_t *values = NULL;
			setrepeatingoption(value, "RemoteFileSigLevel", &values);
			if(process_siglevel(values, &config->remotefilesiglevel,
						&config->remotefilesiglevel_mask, file, linenum)) {
				FREELIST(values);
				return 1;
			}
			FREELIST(values);
		} else {
			pm_printf(ALPM_LOG_WARNING,
					_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"),
					file, linenum, key, "options");
		}

	}
	return 0;
}
Example #3
0
/** The "real" parseconfig. Each "Include" directive will recall this method so
 * recursion and stack depth are limited to 10 levels. The publicly visible
 * parseconfig calls this with a NULL section argument so we can recall from
 * within ourself on an include.
 * @param file path to the config file
 * @param section the current active section
 * @param parse_options whether to parse and call methods for the options
 * section; if 0, parse and call methods for the repos sections
 * @param depth the current recursion depth
 * @return 0 on success, 1 on failure
 */
static int _parseconfig(const char *file, struct section_t *section,
		int parse_options, int depth)
{
	FILE *fp = NULL;
	char line[PATH_MAX];
	int linenum = 0;
	int ret = 0;
	const int max_depth = 10;

	if(depth >= max_depth) {
		pm_printf(ALPM_LOG_ERROR,
				_("config parsing exceeded max recursion depth of %d.\n"), max_depth);
		ret = 1;
		goto cleanup;
	}

	pm_printf(ALPM_LOG_DEBUG, "config: attempting to read file %s\n", file);
	fp = fopen(file, "r");
	if(fp == NULL) {
		pm_printf(ALPM_LOG_ERROR, _("config file %s could not be read: %s\n"),
				file, strerror(errno));
		ret = 1;
		goto cleanup;
	}

	while(fgets(line, PATH_MAX, fp)) {
		char *key, *value, *ptr;
		size_t line_len;

		linenum++;

		/* ignore whole line and end of line comments */
		if((ptr = strchr(line, '#'))) {
			*ptr = '\0';
		}

		line_len = strtrim(line);

		if(line_len == 0) {
			continue;
		}

		if(line[0] == '[' && line[line_len - 1] == ']') {
			char *name;
			/* only possibility here is a line == '[]' */
			if(line_len <= 2) {
				pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: bad section name.\n"),
						file, linenum);
				ret = 1;
				goto cleanup;
			}
			/* new config section, skip the '[' */
			name = strdup(line + 1);
			name[line_len - 2] = '\0';
			/* we're at a new section; perform any post-actions for the prior */
			if(finish_section(section, parse_options)) {
				ret = 1;
				goto cleanup;
			}
			pm_printf(ALPM_LOG_DEBUG, "config: new section '%s'\n", name);
			section->name = name;
			section->is_options = (strcmp(name, "options") == 0);
			continue;
		}

		/* directive */
		/* strsep modifies the 'line' string: 'key \0 value' */
		key = line;
		value = line;
		strsep(&value, "=");
		strtrim(key);
		strtrim(value);

		if(key == NULL) {
			pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: syntax error in config file- missing key.\n"),
					file, linenum);
			ret = 1;
			goto cleanup;
		}
		/* For each directive, compare to the camelcase string. */
		if(section->name == NULL) {
			pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: All directives must belong to a section.\n"),
					file, linenum);
			ret = 1;
			goto cleanup;
		}
		/* Include is allowed in both options and repo sections */
		if(strcmp(key, "Include") == 0) {
			glob_t globbuf;
			int globret;
			size_t gindex;

			if(value == NULL) {
				pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"),
						file, linenum, key);
				ret = 1;
				goto cleanup;
			}
			/* Ignore include failures... assume non-critical */
			globret = glob(value, GLOB_NOCHECK, NULL, &globbuf);
			switch(globret) {
				case GLOB_NOSPACE:
					pm_printf(ALPM_LOG_DEBUG,
							"config file %s, line %d: include globbing out of space\n",
							file, linenum);
				break;
				case GLOB_ABORTED:
					pm_printf(ALPM_LOG_DEBUG,
							"config file %s, line %d: include globbing read error for %s\n",
							file, linenum, value);
				break;
				case GLOB_NOMATCH:
					pm_printf(ALPM_LOG_DEBUG,
							"config file %s, line %d: no include found for %s\n",
							file, linenum, value);
				break;
				default:
					for(gindex = 0; gindex < globbuf.gl_pathc; gindex++) {
						pm_printf(ALPM_LOG_DEBUG, "config file %s, line %d: including %s\n",
								file, linenum, globbuf.gl_pathv[gindex]);
						_parseconfig(globbuf.gl_pathv[gindex], section, parse_options, depth + 1);
					}
				break;
			}
			globfree(&globbuf);
			continue;
		}
		if(parse_options && section->is_options) {
			/* we are either in options ... */
			if((ret = _parse_options(key, value, file, linenum)) != 0) {
				goto cleanup;
			}
		} else if(!parse_options && !section->is_options) {
			/* ... or in a repo section */
			if(strcmp(key, "Server") == 0) {
				if(value == NULL) {
					pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"),
							file, linenum, key);
					ret = 1;
					goto cleanup;
				}
				section->servers = alpm_list_add(section->servers, strdup(value));
			} else if(strcmp(key, "SigLevel") == 0) {
				alpm_list_t *values = NULL;
				setrepeatingoption(value, "SigLevel", &values);
				if(values) {
					if(section->siglevel == ALPM_SIG_USE_DEFAULT) {
						section->siglevel = config->siglevel;
					}
					if(process_siglevel(values, &section->siglevel, file, linenum)) {
						FREELIST(values);
						ret = 1;
						goto cleanup;
					}
					FREELIST(values);
				}
			} else {
				pm_printf(ALPM_LOG_WARNING,
						_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"),
						file, linenum, key, section->name);
			}
		}
	}

	if(depth == 0) {
		ret = finish_section(section, parse_options);
	}

cleanup:
	if(fp) {
		fclose(fp);
	}
	pm_printf(ALPM_LOG_DEBUG, "config: finished parsing %s\n", file);
	return ret;
}