/*
* conf.c
*
- * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2013 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
#include <errno.h>
#include <glob.h>
#include <limits.h>
+#include <locale.h> /* setlocale */
#include <fcntl.h> /* open */
#include <stdlib.h>
#include <stdio.h>
/* global config variable */
config_t *config = NULL;
+#define NOCOLOR "\033[0m"
+
+#define BOLD "\033[0;1m"
+
+#define BLACK "\033[0;30m"
+#define RED "\033[0;31m"
+#define GREEN "\033[0;32m"
+#define YELLOW "\033[0;33m"
+#define BLUE "\033[0;34m"
+#define MAGENTA "\033[0;35m"
+#define CYAN "\033[0;36m"
+#define WHITE "\033[0;37m"
+
+#define BOLDBLACK "\033[1;30m"
+#define BOLDRED "\033[1;31m"
+#define BOLDGREEN "\033[1;32m"
+#define BOLDYELLOW "\033[1;33m"
+#define BOLDBLUE "\033[1;34m"
+#define BOLDMAGENTA "\033[1;35m"
+#define BOLDCYAN "\033[1;36m"
+#define BOLDWHITE "\033[1;37m"
+
+void enable_colors(int colors)
+{
+ colstr_t *colstr = &config->colstr;
+
+ if(colors == PM_COLOR_ON) {
+ colstr->colon = BOLDBLUE "::" BOLD " ";
+ colstr->title = BOLD;
+ colstr->repo = BOLDMAGENTA;
+ colstr->version = BOLDGREEN;
+ colstr->groups = BOLDBLUE;
+ colstr->meta = BOLDCYAN;
+ colstr->warn = BOLDYELLOW;
+ colstr->err = BOLDRED;
+ colstr->nocolor = NOCOLOR;
+ }
+}
+
config_t *config_new(void)
{
config_t *newconfig = calloc(1, sizeof(config_t));
if(alpm_capabilities() & ALPM_CAPABILITY_SIGNATURES) {
newconfig->siglevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL |
ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL;
+ newconfig->localfilesiglevel = ALPM_SIG_USE_DEFAULT;
+ newconfig->remotefilesiglevel = ALPM_SIG_USE_DEFAULT;
}
+ newconfig->colstr.colon = ":: ";
+ newconfig->colstr.title = "";
+ newconfig->colstr.repo = "";
+ newconfig->colstr.version = "";
+ newconfig->colstr.groups = "";
+ newconfig->colstr.meta = "";
+ newconfig->colstr.warn = "";
+ newconfig->colstr.err = "";
+ newconfig->colstr.nocolor = "";
+
return newconfig;
}
alpm_list_free(oldconfig->explicit_removes);
FREELIST(oldconfig->holdpkg);
- FREELIST(oldconfig->syncfirst);
FREELIST(oldconfig->ignorepkg);
FREELIST(oldconfig->ignoregrp);
FREELIST(oldconfig->noupgrade);
}
/** Helper function for download_with_xfercommand() */
-static char *get_filename(const char *url) {
+static char *get_filename(const char *url)
+{
char *filename = strrchr(url, '/');
if(filename != NULL) {
filename++;
}
/** Helper function for download_with_xfercommand() */
-static char *get_destfile(const char *path, const char *filename) {
+static char *get_destfile(const char *path, const char *filename)
+{
char *destfile;
/* len = localpath len + filename len + null */
size_t len = strlen(path) + strlen(filename) + 1;
}
/** Helper function for download_with_xfercommand() */
-static char *get_tempfile(const char *path, const char *filename) {
+static char *get_tempfile(const char *path, const char *filename)
+{
char *tempfile;
/* len = localpath len + filename len + '.part' len + null */
size_t len = strlen(path) + strlen(filename) + 6;
/** External fetch callback */
static int download_with_xfercommand(const char *url, const char *localpath,
- int force) {
+ int force)
+{
int ret = 0, retval;
int usepart = 0;
int cwdfd;
struct stat st;
- char *parsedcmd,*tempcmd;
+ char *parsedcmd, *tempcmd;
char *destfile, *tempfile, *filename;
if(!config->xfercommand) {
cleanup:
/* restore the old cwd if we have it */
if(cwdfd >= 0) {
- int ret;
if(fchdir(cwdfd) != 0) {
pm_printf(ALPM_LOG_ERROR, _("could not restore working directory (%s)\n"),
strerror(errno));
}
- do {
- ret = close(cwdfd);
- } while(ret == -1 && errno == EINTR);
+ close(cwdfd);
}
if(ret == -1) {
if(strcmp(value, "Never") == 0) {
if(package) {
level &= ~ALPM_SIG_PACKAGE;
+ level |= ALPM_SIG_PACKAGE_SET;
}
if(database) {
level &= ~ALPM_SIG_DATABASE;
if(package) {
level |= ALPM_SIG_PACKAGE;
level |= ALPM_SIG_PACKAGE_OPTIONAL;
+ level |= ALPM_SIG_PACKAGE_SET;
}
if(database) {
level |= ALPM_SIG_DATABASE;
if(package) {
level |= ALPM_SIG_PACKAGE;
level &= ~ALPM_SIG_PACKAGE_OPTIONAL;
+ level |= ALPM_SIG_PACKAGE_SET;
}
if(database) {
level |= ALPM_SIG_DATABASE;
if(package) {
level &= ~ALPM_SIG_PACKAGE_MARGINAL_OK;
level &= ~ALPM_SIG_PACKAGE_UNKNOWN_OK;
+ level |= ALPM_SIG_PACKAGE_TRUST_SET;
}
if(database) {
level &= ~ALPM_SIG_DATABASE_MARGINAL_OK;
if(package) {
level |= ALPM_SIG_PACKAGE_MARGINAL_OK;
level |= ALPM_SIG_PACKAGE_UNKNOWN_OK;
+ level |= ALPM_SIG_PACKAGE_TRUST_SET;
}
if(database) {
level |= ALPM_SIG_DATABASE_MARGINAL_OK;
return ret;
}
+/**
+ * Merge the package entires of two signature verification levels.
+ * @param base initial siglevel
+ * @param over overridden siglevel, derived value is stored here
+ */
+static void merge_siglevel(alpm_siglevel_t *base, alpm_siglevel_t *over)
+{
+ alpm_siglevel_t level = *over;
+ if(level & ALPM_SIG_USE_DEFAULT) {
+ level = *base;
+ } else {
+ if(!(level & ALPM_SIG_PACKAGE_SET)) {
+ level |= *base & ALPM_SIG_PACKAGE;
+ level |= *base & ALPM_SIG_PACKAGE_OPTIONAL;
+ }
+ if(!(level & ALPM_SIG_PACKAGE_TRUST_SET)) {
+ level |= *base & ALPM_SIG_PACKAGE_MARGINAL_OK;
+ level |= *base & ALPM_SIG_PACKAGE_UNKNOWN_OK;
+ }
+ }
+
+ *over = level;
+}
+
static int process_cleanmethods(alpm_list_t *values,
const char *file, int linenum)
{
static void setrepeatingoption(char *ptr, const char *option,
alpm_list_t **list)
{
- char *q;
+ char *val, *saveptr;
- while((q = strchr(ptr, ' '))) {
- *q = '\0';
- *list = alpm_list_add(*list, strdup(ptr));
- pm_printf(ALPM_LOG_DEBUG, "config: %s: %s\n", option, ptr);
- ptr = q;
- ptr++;
+ val = strtok_r(ptr, " ", &saveptr);
+ while(val) {
+ *list = alpm_list_add(*list, strdup(val));
+ pm_printf(ALPM_LOG_DEBUG, "config: %s: %s\n", option, val);
+ val = strtok_r(NULL, " ", &saveptr);
}
- *list = alpm_list_add(*list, strdup(ptr));
- pm_printf(ALPM_LOG_DEBUG, "config: %s: %s\n", option, ptr);
}
static int _parse_options(const char *key, char *value,
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"),
setrepeatingoption(value, "IgnoreGroup", &(config->ignoregrp));
} else if(strcmp(key, "HoldPkg") == 0) {
setrepeatingoption(value, "HoldPkg", &(config->holdpkg));
- } else if(strcmp(key, "SyncFirst") == 0) {
- setrepeatingoption(value, "SyncFirst", &(config->syncfirst));
} else if(strcmp(key, "CacheDir") == 0) {
setrepeatingoption(value, "CacheDir", &(config->cachedirs));
} else if(strcmp(key, "Architecture") == 0) {
} 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"),
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, 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, 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"),
}
/** Sets up libalpm global stuff in one go. Called after the command line
- * and inital config file parsing. Once this is complete, we can see if any
+ * and initial config file parsing. Once this is complete, we can see if any
* paths were defined. If a rootdir was defined and nothing else, we want all
* of our paths to live under the rootdir that was specified. Safe to call
* multiple times (will only do anything the first time).
/* initialize library */
handle = alpm_initialize(config->rootdir, config->dbpath, &err);
if(!handle) {
- pm_printf(ALPM_LOG_ERROR, _("failed to initialize alpm library (%s)\n"),
- alpm_strerror(err));
+ pm_printf(ALPM_LOG_ERROR, _("failed to initialize alpm library\n(%s: %s)\n"),
+ alpm_strerror(err), config->dbpath);
if(err == ALPM_ERR_DB_VERSION) {
pm_printf(ALPM_LOG_ERROR, _(" try running pacman-db-upgrade\n"));
}
alpm_option_set_default_siglevel(handle, config->siglevel);
+ merge_siglevel(&config->siglevel, &config->localfilesiglevel);
+ merge_siglevel(&config->siglevel, &config->remotefilesiglevel);
+ alpm_option_set_local_file_siglevel(handle, config->localfilesiglevel);
+ alpm_option_set_remote_file_siglevel(handle, config->remotefilesiglevel);
+
if(config->xfercommand) {
alpm_option_set_fetchcb(handle, download_with_xfercommand);
} else if(!(alpm_capabilities() & ALPM_CAPABILITY_DOWNLOADER)) {
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.\n"), file);
+ pm_printf(ALPM_LOG_ERROR, _("config file %s could not be read: %s\n"),
+ file, strerror(errno));
ret = 1;
goto cleanup;
}