2005-03-14 20:51:43 -05:00
|
|
|
/*
|
|
|
|
* pacman.c
|
2007-08-21 21:28:05 -04:00
|
|
|
*
|
2009-07-01 03:08:33 -04:00
|
|
|
* Copyright (c) 2006-2009 Pacman Development Team <pacman-dev@archlinux.org>
|
|
|
|
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
|
2007-08-21 21:28:05 -04:00
|
|
|
*
|
2005-03-14 20:51:43 -05:00
|
|
|
* 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
|
2007-12-10 23:55:22 -05:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2005-03-14 20:51:43 -05:00
|
|
|
*/
|
|
|
|
|
2005-10-06 03:28:30 -04:00
|
|
|
#include "config.h"
|
2007-03-05 17:13:33 -05:00
|
|
|
|
2008-05-31 12:53:51 -04:00
|
|
|
/* special handling of package version for GIT */
|
|
|
|
#if defined(GIT_VERSION)
|
|
|
|
#undef PACKAGE_VERSION
|
|
|
|
#define PACKAGE_VERSION GIT_VERSION
|
|
|
|
#endif
|
|
|
|
|
2007-08-16 16:19:06 -04:00
|
|
|
#include <stdlib.h> /* atoi */
|
2005-03-14 20:51:43 -05:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <signal.h>
|
2007-04-25 02:21:12 -04:00
|
|
|
#include <unistd.h>
|
2006-12-05 01:55:52 -05:00
|
|
|
#include <sys/types.h>
|
2007-08-16 16:19:06 -04:00
|
|
|
#include <sys/utsname.h> /* uname */
|
|
|
|
#include <locale.h> /* setlocale */
|
|
|
|
#include <time.h> /* time_t */
|
2008-10-12 22:07:49 -04:00
|
|
|
#include <errno.h>
|
2007-10-26 21:31:25 -04:00
|
|
|
#if defined(PACMAN_DEBUG) && defined(HAVE_MCHECK_H)
|
2007-06-07 20:49:31 -04:00
|
|
|
#include <mcheck.h> /* debug tracing (mtrace) */
|
|
|
|
#endif
|
2005-03-14 20:51:43 -05:00
|
|
|
|
2007-04-25 02:21:12 -04:00
|
|
|
/* alpm */
|
2005-03-14 20:51:43 -05:00
|
|
|
#include <alpm.h>
|
2007-01-19 04:28:44 -05:00
|
|
|
#include <alpm_list.h>
|
2007-03-05 17:13:33 -05:00
|
|
|
|
2005-03-14 20:51:43 -05:00
|
|
|
/* pacman */
|
2007-04-25 02:21:12 -04:00
|
|
|
#include "pacman.h"
|
2005-03-14 20:51:43 -05:00
|
|
|
#include "util.h"
|
2007-04-25 20:02:07 -04:00
|
|
|
#include "callback.h"
|
2005-03-14 20:51:43 -05:00
|
|
|
#include "conf.h"
|
|
|
|
#include "package.h"
|
2006-03-13 15:34:47 -05:00
|
|
|
|
2006-11-20 04:10:23 -05:00
|
|
|
pmdb_t *db_local;
|
2005-03-14 20:51:43 -05:00
|
|
|
/* list of targets specified on command line */
|
2007-01-19 04:28:44 -05:00
|
|
|
static alpm_list_t *pm_targets;
|
2005-03-14 20:51:43 -05:00
|
|
|
|
2007-07-23 16:58:04 -04:00
|
|
|
/** Display usage/syntax for the specified operation.
|
2007-03-28 16:14:42 -04:00
|
|
|
* @param op the operation code requested
|
|
|
|
* @param myname basename(argv[0])
|
2006-03-13 15:34:47 -05:00
|
|
|
*/
|
2007-10-31 12:43:04 -04:00
|
|
|
static void usage(int op, const char * const myname)
|
2005-03-14 20:51:43 -05:00
|
|
|
{
|
2007-03-27 20:26:54 -04:00
|
|
|
/* prefetch some strings for usage below, which moves a lot of calls
|
|
|
|
* out of gettext. */
|
2007-10-31 12:43:04 -04:00
|
|
|
char const * const str_opt = _("options");
|
2009-05-21 19:06:33 -04:00
|
|
|
char const * const str_file = _("file(s)");
|
|
|
|
char const * const str_pkg = _("package(s)");
|
2007-10-31 12:43:04 -04:00
|
|
|
char const * const str_usg = _("usage");
|
|
|
|
char const * const str_opr = _("operation");
|
2007-03-27 20:26:54 -04:00
|
|
|
|
2006-03-13 15:34:47 -05:00
|
|
|
if(op == PM_OP_MAIN) {
|
2007-03-28 11:20:18 -04:00
|
|
|
printf("%s: %s <%s> [...]\n", str_usg, myname, str_opr);
|
2008-08-07 13:50:07 -04:00
|
|
|
printf(_("operations:\n"));
|
2007-03-27 20:26:54 -04:00
|
|
|
printf(" %s {-h --help}\n", myname);
|
|
|
|
printf(" %s {-V --version}\n", myname);
|
|
|
|
printf(" %s {-Q --query} [%s] [%s]\n", myname, str_opt, str_pkg);
|
|
|
|
printf(" %s {-R --remove} [%s] <%s>\n", myname, str_opt, str_pkg);
|
|
|
|
printf(" %s {-S --sync} [%s] [%s]\n", myname, str_opt, str_pkg);
|
|
|
|
printf(" %s {-U --upgrade} [%s] <%s>\n", myname, str_opt, str_file);
|
2008-08-07 13:50:07 -04:00
|
|
|
printf(_("\nuse '%s {-h --help}' with an operation for available options\n"),
|
|
|
|
myname);
|
2006-03-13 15:34:47 -05:00
|
|
|
} else {
|
2007-12-02 15:04:18 -05:00
|
|
|
if(op == PM_OP_REMOVE) {
|
2007-03-28 11:20:18 -04:00
|
|
|
printf("%s: %s {-R --remove} [%s] <%s>\n", str_usg, myname, str_opt, str_pkg);
|
2007-03-27 20:26:54 -04:00
|
|
|
printf("%s:\n", str_opt);
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" -c, --cascade remove packages and all packages that depend on them\n"));
|
|
|
|
printf(_(" -d, --nodeps skip dependency checks\n"));
|
|
|
|
printf(_(" -k, --dbonly only remove database entry, do not remove files\n"));
|
|
|
|
printf(_(" -n, --nosave remove configuration files as well\n"));
|
2008-03-03 16:09:21 -05:00
|
|
|
printf(_(" -s, --recursive remove dependencies also (that won't break packages)\n"
|
|
|
|
" (-ss includes explicitly installed dependencies too)\n"));
|
2007-11-18 12:45:46 -05:00
|
|
|
printf(_(" -u, --unneeded remove unneeded packages (that won't break packages)\n"));
|
2006-03-13 15:34:47 -05:00
|
|
|
} else if(op == PM_OP_UPGRADE) {
|
2007-11-21 12:25:50 -05:00
|
|
|
printf("%s: %s {-U --upgrade} [%s] <%s>\n", str_usg, myname, str_opt, str_file);
|
2007-03-27 20:26:54 -04:00
|
|
|
printf("%s:\n", str_opt);
|
2007-07-15 12:44:18 -04:00
|
|
|
printf(_(" --asdeps install packages as non-explicitly installed\n"));
|
2008-01-13 16:15:10 -05:00
|
|
|
printf(_(" --asexplicit install packages as explicitly installed\n"));
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" -d, --nodeps skip dependency checks\n"));
|
|
|
|
printf(_(" -f, --force force install, overwrite conflicting files\n"));
|
2006-03-13 15:34:47 -05:00
|
|
|
} else if(op == PM_OP_QUERY) {
|
2007-03-28 11:20:18 -04:00
|
|
|
printf("%s: %s {-Q --query} [%s] [%s]\n", str_usg, myname, str_opt, str_pkg);
|
2007-03-27 20:26:54 -04:00
|
|
|
printf("%s:\n", str_opt);
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" -c, --changelog view the changelog of a package\n"));
|
2009-05-14 10:15:20 -04:00
|
|
|
printf(_(" -d, --deps list packages installed as dependencies [filter]\n"));
|
|
|
|
printf(_(" -e, --explicit list packages explicitly installed [filter]\n"));
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" -g, --groups view all members of a package group\n"));
|
2007-09-26 12:59:40 -04:00
|
|
|
printf(_(" -i, --info view package information (-ii for backup files)\n"));
|
2009-03-30 12:48:15 -04:00
|
|
|
printf(_(" -k, --check check that the files owned by the package(s) are present\n"));
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" -l, --list list the contents of the queried package\n"));
|
2009-05-14 10:15:20 -04:00
|
|
|
printf(_(" -m, --foreign list installed packages not found in sync db(s) [filter]\n"));
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" -o, --owns <file> query the package that owns <file>\n"));
|
2007-03-22 14:19:49 -04:00
|
|
|
printf(_(" -p, --file <package> query a package file instead of the database\n"));
|
|
|
|
printf(_(" -s, --search <regex> search locally-installed packages for matching strings\n"));
|
2009-05-14 10:15:20 -04:00
|
|
|
printf(_(" -t, --unrequired list packages not required by any package [filter]\n"));
|
|
|
|
printf(_(" -u, --upgrades list outdated packages [filter]\n"));
|
2007-12-04 10:56:28 -05:00
|
|
|
printf(_(" -q, --quiet show less information for query and search\n"));
|
2006-03-13 15:34:47 -05:00
|
|
|
} else if(op == PM_OP_SYNC) {
|
2007-03-28 11:20:18 -04:00
|
|
|
printf("%s: %s {-S --sync} [%s] [%s]\n", str_usg, myname, str_opt, str_pkg);
|
2007-03-27 20:26:54 -04:00
|
|
|
printf("%s:\n", str_opt);
|
2007-07-15 12:44:18 -04:00
|
|
|
printf(_(" --asdeps install packages as non-explicitly installed\n"));
|
2008-01-13 16:15:10 -05:00
|
|
|
printf(_(" --asexplicit install packages as explicitly installed\n"));
|
2007-02-18 23:13:13 -05:00
|
|
|
printf(_(" -c, --clean remove old packages from cache directory (-cc for all)\n"));
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" -d, --nodeps skip dependency checks\n"));
|
|
|
|
printf(_(" -f, --force force install, overwrite conflicting files\n"));
|
|
|
|
printf(_(" -g, --groups view all members of a package group\n"));
|
|
|
|
printf(_(" -i, --info view package information\n"));
|
2007-03-22 14:19:49 -04:00
|
|
|
printf(_(" -l, --list <repo> view a list of packages in a repo\n"));
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" -p, --print-uris print out URIs for given packages and their dependencies\n"));
|
2007-03-22 14:19:49 -04:00
|
|
|
printf(_(" -s, --search <regex> search remote repositories for matching strings\n"));
|
2009-05-14 12:25:16 -04:00
|
|
|
printf(_(" -u, --sysupgrade upgrade all outdated packages (-uu enables downgrade)\n"));
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" -w, --downloadonly download packages but do not install/upgrade anything\n"));
|
|
|
|
printf(_(" -y, --refresh download fresh package databases from the server\n"));
|
2008-05-31 09:06:30 -04:00
|
|
|
printf(_(" --needed don't reinstall up to date packages\n"));
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" --ignore <pkg> ignore a package upgrade (can be used more than once)\n"));
|
2007-11-13 18:38:11 -05:00
|
|
|
printf(_(" --ignoregroup <grp>\n"
|
|
|
|
" ignore a group upgrade (can be used more than once)\n"));
|
2008-08-25 14:00:45 -04:00
|
|
|
printf(_(" -q, --quiet show less information for query and search\n"));
|
2005-03-14 20:51:43 -05:00
|
|
|
}
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" --config <path> set an alternate configuration file\n"));
|
2007-10-05 10:18:29 -04:00
|
|
|
printf(_(" --logfile <path> set an alternate log file\n"));
|
2007-03-18 22:45:00 -04:00
|
|
|
printf(_(" --noconfirm do not ask for any confirmation\n"));
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" --noprogressbar do not show a progress bar when downloading files\n"));
|
2007-03-27 20:26:54 -04:00
|
|
|
printf(_(" --noscriptlet do not execute the install scriptlet if one exists\n"));
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" -v, --verbose be verbose\n"));
|
2009-03-22 12:13:29 -04:00
|
|
|
printf(_(" --debug display debug messages\n"));
|
2007-02-12 02:03:08 -05:00
|
|
|
printf(_(" -r, --root <path> set an alternate installation root\n"));
|
|
|
|
printf(_(" -b, --dbpath <path> set an alternate database location\n"));
|
2007-02-12 20:50:18 -05:00
|
|
|
printf(_(" --cachedir <dir> set an alternate package cache location\n"));
|
2009-07-22 00:03:25 -04:00
|
|
|
printf(_(" --arch <arch> set an alternate architecture\n"));
|
2006-02-01 13:20:13 -05:00
|
|
|
}
|
2005-03-14 20:51:43 -05:00
|
|
|
}
|
|
|
|
|
2007-07-23 16:58:04 -04:00
|
|
|
/** Output pacman version and copyright.
|
2006-10-15 15:34:52 -04:00
|
|
|
*/
|
2007-04-14 17:26:39 -04:00
|
|
|
static void version(void)
|
2006-10-15 15:34:52 -04:00
|
|
|
{
|
|
|
|
printf("\n");
|
2008-02-29 15:52:57 -05:00
|
|
|
printf(" .--. Pacman v%s - libalpm v%s\n", PACKAGE_VERSION, alpm_version());
|
2009-07-27 00:02:20 -04:00
|
|
|
printf("/ _.-' .-. .-. .-. Copyright (C) 2006-2009 Pacman Development Team\n");
|
|
|
|
printf("\\ '-. '-' '-' '-' Copyright (C) 2002-2006 Judd Vinet\n");
|
2007-03-27 20:26:54 -04:00
|
|
|
printf(" '--'\n");
|
|
|
|
printf(_(" This program may be freely redistributed under\n"
|
2008-06-08 14:50:01 -04:00
|
|
|
" the terms of the GNU General Public License.\n"));
|
2006-10-15 15:34:52 -04:00
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2007-07-23 16:58:04 -04:00
|
|
|
/** Sets up gettext localization. Safe to call multiple times.
|
2007-03-28 16:14:42 -04:00
|
|
|
*/
|
|
|
|
/* Inspired by the monotone function localize_monotone. */
|
2007-10-23 00:52:55 -04:00
|
|
|
#if defined(ENABLE_NLS)
|
2007-04-14 17:26:39 -04:00
|
|
|
static void localize(void)
|
2007-03-28 16:14:42 -04:00
|
|
|
{
|
|
|
|
static int init = 0;
|
|
|
|
if (!init) {
|
|
|
|
setlocale(LC_ALL, "");
|
|
|
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
|
|
textdomain(PACKAGE);
|
|
|
|
init = 1;
|
|
|
|
}
|
|
|
|
}
|
2007-10-23 00:52:55 -04:00
|
|
|
#endif
|
2007-03-28 16:14:42 -04:00
|
|
|
|
2007-07-23 16:58:04 -04:00
|
|
|
/** Set user agent environment variable.
|
2007-04-28 04:50:16 -04:00
|
|
|
*/
|
|
|
|
static void setuseragent(void)
|
|
|
|
{
|
|
|
|
char agent[101];
|
|
|
|
struct utsname un;
|
|
|
|
|
|
|
|
uname(&un);
|
2008-02-29 15:52:57 -05:00
|
|
|
snprintf(agent, 100, "pacman/%s (%s %s) libalpm/%s",
|
|
|
|
PACKAGE_VERSION, un.sysname, un.machine, alpm_version());
|
2007-04-28 04:50:16 -04:00
|
|
|
setenv("HTTP_USER_AGENT", agent, 0);
|
|
|
|
}
|
|
|
|
|
2009-07-22 00:03:25 -04:00
|
|
|
static void setarch(const char *arch)
|
|
|
|
{
|
|
|
|
if (strcmp(arch, "auto") == 0) {
|
|
|
|
struct utsname un;
|
|
|
|
uname(&un);
|
|
|
|
pm_printf(PM_LOG_DEBUG, "config: architecture: %s\n", un.machine);
|
|
|
|
alpm_option_set_arch(un.machine);
|
|
|
|
} else {
|
|
|
|
pm_printf(PM_LOG_DEBUG, "config: architecture: %s\n", arch);
|
|
|
|
alpm_option_set_arch(arch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-09 07:56:00 -04:00
|
|
|
/** Free the resources.
|
|
|
|
*
|
|
|
|
* @param ret the return value
|
|
|
|
*/
|
|
|
|
static void cleanup(int ret) {
|
|
|
|
/* free alpm library resources */
|
|
|
|
if(alpm_release() == -1) {
|
|
|
|
pm_printf(PM_LOG_ERROR, alpm_strerrorlast());
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free memory */
|
|
|
|
FREELIST(pm_targets);
|
|
|
|
if(config) {
|
|
|
|
config_free(config);
|
|
|
|
config = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
exit(ret);
|
|
|
|
}
|
|
|
|
|
2008-10-12 22:07:49 -04:00
|
|
|
/** Write function that correctly handles EINTR.
|
|
|
|
*/
|
|
|
|
static ssize_t xwrite(int fd, const void *buf, size_t count)
|
|
|
|
{
|
|
|
|
ssize_t ret;
|
|
|
|
while((ret = write(fd, buf, count)) == -1 && errno == EINTR);
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
2007-07-23 16:58:04 -04:00
|
|
|
/** Catches thrown signals. Performs necessary cleanup to ensure database is
|
|
|
|
* in a consistant state.
|
2007-03-28 16:14:42 -04:00
|
|
|
* @param signum the thrown signal
|
|
|
|
*/
|
2008-04-07 20:07:51 -04:00
|
|
|
static RETSIGTYPE handler(int signum)
|
2006-10-15 15:34:52 -04:00
|
|
|
{
|
2008-10-12 22:07:49 -04:00
|
|
|
int out = fileno(stdout);
|
|
|
|
int err = fileno(stderr);
|
|
|
|
if(signum == SIGSEGV) {
|
|
|
|
const char *msg1 = "error: segmentation fault\n";
|
|
|
|
const char *msg2 = "Internal pacman error: Segmentation fault.\n"
|
|
|
|
"Please submit a full bug report with --debug if appropriate.\n";
|
|
|
|
/* write a error message to out, the rest to err */
|
|
|
|
xwrite(out, msg1, strlen(msg1));
|
|
|
|
xwrite(err, msg2, strlen(msg2));
|
2006-10-15 15:34:52 -04:00
|
|
|
exit(signum);
|
2007-09-07 18:36:38 -04:00
|
|
|
} else if((signum == SIGINT)) {
|
2008-10-12 22:07:49 -04:00
|
|
|
const char *msg = "\nInterrupt signal received\n";
|
|
|
|
xwrite(err, msg, strlen(msg));
|
2007-09-07 18:36:38 -04:00
|
|
|
if(alpm_trans_interrupt() == 0) {
|
|
|
|
/* a transaction is being interrupted, don't exit pacman yet. */
|
|
|
|
return;
|
|
|
|
}
|
2008-01-11 00:07:52 -05:00
|
|
|
/* no commiting transaction, we can release it now and then exit pacman */
|
|
|
|
alpm_trans_release();
|
|
|
|
/* output a newline to be sure we clear any line we may be on */
|
2008-10-12 22:07:49 -04:00
|
|
|
xwrite(out, "\n", 1);
|
2006-10-15 15:34:52 -04:00
|
|
|
}
|
2008-03-09 07:56:00 -04:00
|
|
|
cleanup(signum);
|
2006-10-15 15:34:52 -04:00
|
|
|
}
|
|
|
|
|
2008-02-11 21:15:44 -05:00
|
|
|
/** Sets all libalpm required paths in one go. Called after the command line
|
|
|
|
* and inital 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).
|
2007-12-02 13:56:57 -05:00
|
|
|
*/
|
|
|
|
static void setlibpaths(void)
|
|
|
|
{
|
|
|
|
static int init = 0;
|
|
|
|
if (!init) {
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
pm_printf(PM_LOG_DEBUG, "setlibpaths() called\n");
|
2008-02-11 21:15:44 -05:00
|
|
|
/* Configure root path first. If it is set and dbpath/logfile were not
|
|
|
|
* set, then set those as well to reside under the root. */
|
2007-12-02 13:56:57 -05:00
|
|
|
if(config->rootdir) {
|
|
|
|
char path[PATH_MAX];
|
|
|
|
ret = alpm_option_set_root(config->rootdir);
|
|
|
|
if(ret != 0) {
|
|
|
|
pm_printf(PM_LOG_ERROR, _("problem setting rootdir '%s' (%s)\n"),
|
|
|
|
config->rootdir, alpm_strerrorlast());
|
|
|
|
cleanup(ret);
|
|
|
|
}
|
|
|
|
if(!config->dbpath) {
|
2008-09-28 20:33:56 -04:00
|
|
|
/* omit leading slash from our static DBPATH, root handles it */
|
|
|
|
snprintf(path, PATH_MAX, "%s%s", alpm_option_get_root(), DBPATH + 1);
|
2007-12-02 13:56:57 -05:00
|
|
|
config->dbpath = strdup(path);
|
|
|
|
}
|
|
|
|
if(!config->logfile) {
|
2008-09-28 20:33:56 -04:00
|
|
|
/* omit leading slash from our static LOGFILE path, root handles it */
|
|
|
|
snprintf(path, PATH_MAX, "%s%s", alpm_option_get_root(), LOGFILE + 1);
|
2007-12-02 13:56:57 -05:00
|
|
|
config->logfile = strdup(path);
|
|
|
|
}
|
|
|
|
}
|
2008-02-11 21:15:44 -05:00
|
|
|
/* Set other paths if they were configured. Note that unless rootdir
|
|
|
|
* was left undefined, these two paths (dbpath and logfile) will have
|
|
|
|
* been set locally above, so the if cases below will now trigger. */
|
2007-12-02 13:56:57 -05:00
|
|
|
if(config->dbpath) {
|
|
|
|
ret = alpm_option_set_dbpath(config->dbpath);
|
|
|
|
if(ret != 0) {
|
|
|
|
pm_printf(PM_LOG_ERROR, _("problem setting dbpath '%s' (%s)\n"),
|
|
|
|
config->dbpath, alpm_strerrorlast());
|
|
|
|
cleanup(ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(config->logfile) {
|
|
|
|
ret = alpm_option_set_logfile(config->logfile);
|
|
|
|
if(ret != 0) {
|
|
|
|
pm_printf(PM_LOG_ERROR, _("problem setting logfile '%s' (%s)\n"),
|
|
|
|
config->logfile, alpm_strerrorlast());
|
|
|
|
cleanup(ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add a default cachedir if one wasn't specified */
|
|
|
|
if(alpm_option_get_cachedirs() == NULL) {
|
|
|
|
alpm_option_add_cachedir(CACHEDIR);
|
|
|
|
}
|
2007-12-03 23:17:19 -05:00
|
|
|
init = 1;
|
2007-12-02 13:56:57 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-23 16:58:04 -04:00
|
|
|
/** Parse command-line arguments for each operation.
|
2007-03-28 16:14:42 -04:00
|
|
|
* @param argc argc
|
|
|
|
* @param argv argv
|
|
|
|
* @return 0 on success, 1 on error
|
2005-03-14 20:51:43 -05:00
|
|
|
*/
|
2006-03-13 15:34:47 -05:00
|
|
|
static int parseargs(int argc, char *argv[])
|
2005-03-14 20:51:43 -05:00
|
|
|
{
|
|
|
|
int opt;
|
|
|
|
int option_index = 0;
|
|
|
|
static struct option opts[] =
|
|
|
|
{
|
|
|
|
{"query", no_argument, 0, 'Q'},
|
2005-03-25 17:37:13 -05:00
|
|
|
{"remove", no_argument, 0, 'R'},
|
2005-03-14 20:51:43 -05:00
|
|
|
{"sync", no_argument, 0, 'S'},
|
2005-03-25 17:37:13 -05:00
|
|
|
{"deptest", no_argument, 0, 'T'}, /* used by makepkg */
|
|
|
|
{"upgrade", no_argument, 0, 'U'},
|
2005-03-14 20:51:43 -05:00
|
|
|
{"version", no_argument, 0, 'V'},
|
2005-03-25 17:37:13 -05:00
|
|
|
{"dbpath", required_argument, 0, 'b'},
|
|
|
|
{"cascade", no_argument, 0, 'c'},
|
2006-10-15 15:34:52 -04:00
|
|
|
{"changelog", no_argument, 0, 'c'},
|
2005-03-14 20:51:43 -05:00
|
|
|
{"clean", no_argument, 0, 'c'},
|
|
|
|
{"nodeps", no_argument, 0, 'd'},
|
2007-07-14 18:44:06 -04:00
|
|
|
{"deps", no_argument, 0, 'd'},
|
|
|
|
{"explicit", no_argument, 0, 'e'},
|
2005-03-25 17:37:13 -05:00
|
|
|
{"force", no_argument, 0, 'f'},
|
|
|
|
{"groups", no_argument, 0, 'g'},
|
|
|
|
{"help", no_argument, 0, 'h'},
|
|
|
|
{"info", no_argument, 0, 'i'},
|
|
|
|
{"dbonly", no_argument, 0, 'k'},
|
2009-03-30 12:48:15 -04:00
|
|
|
{"check", no_argument, 0, 'k'},
|
2005-03-25 17:37:13 -05:00
|
|
|
{"list", no_argument, 0, 'l'},
|
2005-12-13 21:23:14 -05:00
|
|
|
{"foreign", no_argument, 0, 'm'},
|
2007-11-22 15:01:45 -05:00
|
|
|
{"nosave", no_argument, 0, 'n'},
|
2005-03-14 20:51:43 -05:00
|
|
|
{"owns", no_argument, 0, 'o'},
|
|
|
|
{"file", no_argument, 0, 'p'},
|
2005-04-13 15:16:32 -04:00
|
|
|
{"print-uris", no_argument, 0, 'p'},
|
2007-11-07 02:05:33 -05:00
|
|
|
{"quiet", no_argument, 0, 'q'},
|
2005-03-25 17:37:13 -05:00
|
|
|
{"root", required_argument, 0, 'r'},
|
|
|
|
{"recursive", no_argument, 0, 's'},
|
|
|
|
{"search", no_argument, 0, 's'},
|
2008-01-10 09:59:43 -05:00
|
|
|
{"unrequired", no_argument, 0, 't'},
|
2007-02-04 03:30:13 -05:00
|
|
|
{"upgrades", no_argument, 0, 'u'},
|
2005-03-14 20:51:43 -05:00
|
|
|
{"sysupgrade", no_argument, 0, 'u'},
|
2007-11-18 12:45:46 -05:00
|
|
|
{"unneeded", no_argument, 0, 'u'},
|
2005-03-25 17:37:13 -05:00
|
|
|
{"verbose", no_argument, 0, 'v'},
|
2005-03-14 20:51:43 -05:00
|
|
|
{"downloadonly", no_argument, 0, 'w'},
|
|
|
|
{"refresh", no_argument, 0, 'y'},
|
|
|
|
{"noconfirm", no_argument, 0, 1000},
|
|
|
|
{"config", required_argument, 0, 1001},
|
2005-03-25 17:37:13 -05:00
|
|
|
{"ignore", required_argument, 0, 1002},
|
2007-01-31 01:10:21 -05:00
|
|
|
{"debug", optional_argument, 0, 1003},
|
2007-07-15 12:44:18 -04:00
|
|
|
{"noprogressbar", no_argument, 0, 1004},
|
2006-03-07 13:17:03 -05:00
|
|
|
{"noscriptlet", no_argument, 0, 1005},
|
Re-add the non-user friendly --ask option
This re-implements the --ask option which was removed in commit
1ff8e7f364a9f640ada7526384646d510ac29967.
This option does not have to be exposed to the user (help,doc,etc), but is
very very useful for pactest if we want to have more coverage there.
This was rewritten in a smarter way, without code duplication. And with a
different behavior : this option is now only used to inverse default
behavior to questions.
We still use bit operations based on the following struct :
/* Transaction Conversations (ie, questions) */
typedef enum _pmtransconv_t {
PM_TRANS_CONV_INSTALL_IGNOREPKG = 0x01,
PM_TRANS_CONV_REPLACE_PKG = 0x02,
PM_TRANS_CONV_CONFLICT_PKG = 0x04,
PM_TRANS_CONV_CORRUPTED_PKG = 0x08,
PM_TRANS_CONV_LOCAL_NEWER = 0x10,
PM_TRANS_CONV_REMOVE_PKGS = 0x20,
} pmtransconv_t;
for each conv matched, the default answer is inversed.
--ask 0 : all default answers are preserved
--ask 4 : only conflict question is inversed
--ask 63 : all questions are inversed (63 == 1+2+4+8+16+32)
Signed-off-by: Xavier Chantry <shiningxc@gmail.com>
Signed-off-by: Dan McGee <dan@archlinux.org>
2009-08-31 14:17:05 -04:00
|
|
|
{"ask", required_argument, 0, 1006},
|
2007-02-12 02:03:08 -05:00
|
|
|
{"cachedir", required_argument, 0, 1007},
|
2007-07-15 12:44:18 -04:00
|
|
|
{"asdeps", no_argument, 0, 1008},
|
2007-10-05 10:18:29 -04:00
|
|
|
{"logfile", required_argument, 0, 1009},
|
2007-11-09 20:13:28 -05:00
|
|
|
{"ignoregroup", required_argument, 0, 1010},
|
2007-11-22 15:01:45 -05:00
|
|
|
{"needed", no_argument, 0, 1011},
|
2008-01-13 16:15:10 -05:00
|
|
|
{"asexplicit", no_argument, 0, 1012},
|
2009-07-22 00:03:25 -04:00
|
|
|
{"arch", required_argument, 0, 1013},
|
2005-03-14 20:51:43 -05:00
|
|
|
{0, 0, 0, 0}
|
|
|
|
};
|
|
|
|
|
2007-12-02 15:04:18 -05:00
|
|
|
while((opt = getopt_long(argc, argv, "RUFQSTr:b:vkhscVfmnoldepqituwygz", opts, &option_index))) {
|
2007-11-13 19:32:56 -05:00
|
|
|
alpm_list_t *list = NULL, *item = NULL; /* lists for splitting strings */
|
|
|
|
|
2005-03-14 20:51:43 -05:00
|
|
|
if(opt < 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch(opt) {
|
2006-01-07 05:01:19 -05:00
|
|
|
case 0: break;
|
2005-10-28 08:20:40 -04:00
|
|
|
case 1000: config->noconfirm = 1; break;
|
2005-03-25 17:37:13 -05:00
|
|
|
case 1001:
|
2005-10-28 08:20:40 -04:00
|
|
|
if(config->configfile) {
|
|
|
|
free(config->configfile);
|
2005-04-13 15:16:32 -04:00
|
|
|
}
|
2005-10-28 08:20:40 -04:00
|
|
|
config->configfile = strndup(optarg, PATH_MAX);
|
2007-01-17 00:25:32 -05:00
|
|
|
break;
|
2007-11-13 19:32:56 -05:00
|
|
|
case 1002:
|
|
|
|
list = strsplit(optarg, ',');
|
|
|
|
for(item = list; item; item = alpm_list_next(item)) {
|
|
|
|
alpm_option_add_ignorepkg((char *)alpm_list_getdata(item));
|
|
|
|
}
|
|
|
|
FREELIST(list);
|
|
|
|
break;
|
2007-01-31 01:10:21 -05:00
|
|
|
case 1003:
|
|
|
|
/* debug levels are made more 'human readable' than using a raw logmask
|
2007-06-07 22:20:40 -04:00
|
|
|
* here, error and warning are set in config_new, though perhaps a
|
2007-01-31 01:10:21 -05:00
|
|
|
* --quiet option will remove these later */
|
|
|
|
if(optarg) {
|
|
|
|
unsigned short debug = atoi(optarg);
|
|
|
|
switch(debug) {
|
2007-04-26 16:23:59 -04:00
|
|
|
case 2:
|
2007-06-07 22:20:40 -04:00
|
|
|
config->logmask |= PM_LOG_FUNCTION; /* fall through */
|
2007-04-26 16:23:59 -04:00
|
|
|
case 1:
|
2007-06-07 22:20:40 -04:00
|
|
|
config->logmask |= PM_LOG_DEBUG;
|
2007-04-26 16:23:59 -04:00
|
|
|
break;
|
2007-01-31 01:10:21 -05:00
|
|
|
default:
|
2007-07-23 16:58:04 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("'%s' is not a valid debug level\n"),
|
|
|
|
optarg);
|
2007-01-31 01:10:21 -05:00
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-07 22:20:40 -04:00
|
|
|
config->logmask |= PM_LOG_DEBUG;
|
2007-01-31 01:10:21 -05:00
|
|
|
}
|
|
|
|
/* progress bars get wonky with debug on, shut them off */
|
|
|
|
config->noprogressbar = 1;
|
|
|
|
break;
|
2006-01-28 00:07:50 -05:00
|
|
|
case 1004: config->noprogressbar = 1; break;
|
2006-03-07 13:17:03 -05:00
|
|
|
case 1005: config->flags |= PM_TRANS_FLAG_NOSCRIPTLET; break;
|
Re-add the non-user friendly --ask option
This re-implements the --ask option which was removed in commit
1ff8e7f364a9f640ada7526384646d510ac29967.
This option does not have to be exposed to the user (help,doc,etc), but is
very very useful for pactest if we want to have more coverage there.
This was rewritten in a smarter way, without code duplication. And with a
different behavior : this option is now only used to inverse default
behavior to questions.
We still use bit operations based on the following struct :
/* Transaction Conversations (ie, questions) */
typedef enum _pmtransconv_t {
PM_TRANS_CONV_INSTALL_IGNOREPKG = 0x01,
PM_TRANS_CONV_REPLACE_PKG = 0x02,
PM_TRANS_CONV_CONFLICT_PKG = 0x04,
PM_TRANS_CONV_CORRUPTED_PKG = 0x08,
PM_TRANS_CONV_LOCAL_NEWER = 0x10,
PM_TRANS_CONV_REMOVE_PKGS = 0x20,
} pmtransconv_t;
for each conv matched, the default answer is inversed.
--ask 0 : all default answers are preserved
--ask 4 : only conflict question is inversed
--ask 63 : all questions are inversed (63 == 1+2+4+8+16+32)
Signed-off-by: Xavier Chantry <shiningxc@gmail.com>
Signed-off-by: Dan McGee <dan@archlinux.org>
2009-08-31 14:17:05 -04:00
|
|
|
case 1006: config->noask = 1; config->ask = atoi(optarg); break;
|
2007-02-12 02:03:08 -05:00
|
|
|
case 1007:
|
2007-08-21 21:28:05 -04:00
|
|
|
if(alpm_option_add_cachedir(optarg) != 0) {
|
|
|
|
pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"),
|
2007-09-08 12:41:45 -04:00
|
|
|
optarg, alpm_strerrorlast());
|
2007-02-12 02:03:08 -05:00
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
break;
|
2007-07-15 12:44:18 -04:00
|
|
|
case 1008:
|
|
|
|
config->flags |= PM_TRANS_FLAG_ALLDEPS;
|
|
|
|
break;
|
2007-10-05 10:18:29 -04:00
|
|
|
case 1009:
|
2007-12-02 13:20:55 -05:00
|
|
|
config->logfile = strdup(optarg);
|
2007-10-05 10:18:29 -04:00
|
|
|
break;
|
2007-11-13 19:32:56 -05:00
|
|
|
case 1010:
|
|
|
|
list = strsplit(optarg, ',');
|
|
|
|
for(item = list; item; item = alpm_list_next(item)) {
|
|
|
|
alpm_option_add_ignoregrp((char *)alpm_list_getdata(item));
|
|
|
|
}
|
|
|
|
FREELIST(list);
|
|
|
|
break;
|
2007-11-22 15:01:45 -05:00
|
|
|
case 1011: config->flags |= PM_TRANS_FLAG_NEEDED; break;
|
2008-01-13 16:15:10 -05:00
|
|
|
case 1012:
|
|
|
|
config->flags |= PM_TRANS_FLAG_ALLEXPLICIT;
|
|
|
|
break;
|
2009-07-22 00:03:25 -04:00
|
|
|
case 1013:
|
|
|
|
setarch(optarg);
|
|
|
|
break;
|
2006-01-07 05:01:19 -05:00
|
|
|
case 'Q': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_QUERY); break;
|
|
|
|
case 'R': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_REMOVE); break;
|
|
|
|
case 'S': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_SYNC); break;
|
2005-10-28 08:20:40 -04:00
|
|
|
case 'T': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_DEPTEST); break;
|
|
|
|
case 'U': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_UPGRADE); break;
|
|
|
|
case 'V': config->version = 1; break;
|
2005-03-25 17:37:13 -05:00
|
|
|
case 'b':
|
2007-12-02 13:20:55 -05:00
|
|
|
config->dbpath = strdup(optarg);
|
2007-01-17 00:25:32 -05:00
|
|
|
break;
|
2006-01-07 05:01:19 -05:00
|
|
|
case 'c':
|
2007-01-17 00:25:32 -05:00
|
|
|
(config->op_s_clean)++;
|
2006-01-07 05:01:19 -05:00
|
|
|
config->flags |= PM_TRANS_FLAG_CASCADE;
|
2006-10-15 15:34:52 -04:00
|
|
|
config->op_q_changelog = 1;
|
2007-01-17 00:25:32 -05:00
|
|
|
break;
|
2007-07-14 18:44:06 -04:00
|
|
|
case 'd':
|
|
|
|
config->op_q_deps = 1;
|
|
|
|
config->flags |= PM_TRANS_FLAG_NODEPS;
|
|
|
|
break;
|
2007-01-17 00:25:32 -05:00
|
|
|
case 'e':
|
2007-07-14 18:44:06 -04:00
|
|
|
config->op_q_explicit = 1;
|
2007-01-17 00:25:32 -05:00
|
|
|
break;
|
2005-10-28 08:20:40 -04:00
|
|
|
case 'f': config->flags |= PM_TRANS_FLAG_FORCE; break;
|
2007-01-17 00:25:32 -05:00
|
|
|
case 'g': (config->group)++; break;
|
2005-10-28 08:20:40 -04:00
|
|
|
case 'h': config->help = 1; break;
|
2007-01-17 00:25:32 -05:00
|
|
|
case 'i': (config->op_q_info)++; (config->op_s_info)++; break;
|
2009-03-30 12:48:15 -04:00
|
|
|
case 'k':
|
|
|
|
config->flags |= PM_TRANS_FLAG_DBONLY;
|
|
|
|
config->op_q_check = 1;
|
|
|
|
break;
|
2005-10-28 08:20:40 -04:00
|
|
|
case 'l': config->op_q_list = 1; break;
|
2005-12-13 21:23:14 -05:00
|
|
|
case 'm': config->op_q_foreign = 1; break;
|
2005-10-28 08:20:40 -04:00
|
|
|
case 'n': config->flags |= PM_TRANS_FLAG_NOSAVE; break;
|
|
|
|
case 'o': config->op_q_owns = 1; break;
|
2006-01-07 05:01:19 -05:00
|
|
|
case 'p':
|
|
|
|
config->op_q_isfile = 1;
|
2008-08-17 13:23:12 -04:00
|
|
|
config->op_s_printuris = 1;
|
|
|
|
config->flags |= PM_TRANS_FLAG_NOCONFLICTS;
|
2009-05-16 11:59:45 -04:00
|
|
|
config->flags |= PM_TRANS_FLAG_NOLOCK;
|
2007-01-17 00:25:32 -05:00
|
|
|
break;
|
2007-11-22 15:01:45 -05:00
|
|
|
case 'q':
|
|
|
|
config->quiet = 1;
|
|
|
|
break;
|
2005-03-14 20:51:43 -05:00
|
|
|
case 'r':
|
2007-12-02 13:20:55 -05:00
|
|
|
config->rootdir = strdup(optarg);
|
2007-01-17 00:25:32 -05:00
|
|
|
break;
|
2006-01-07 05:01:19 -05:00
|
|
|
case 's':
|
|
|
|
config->op_s_search = 1;
|
|
|
|
config->op_q_search = 1;
|
2008-03-03 16:09:21 -05:00
|
|
|
if(config->flags & PM_TRANS_FLAG_RECURSE) {
|
|
|
|
config->flags |= PM_TRANS_FLAG_RECURSEALL;
|
|
|
|
} else {
|
|
|
|
config->flags |= PM_TRANS_FLAG_RECURSE;
|
|
|
|
}
|
2007-01-17 00:25:32 -05:00
|
|
|
break;
|
2007-05-31 15:48:16 -04:00
|
|
|
case 't':
|
2008-01-10 09:59:43 -05:00
|
|
|
config->op_q_unrequired = 1;
|
2007-05-31 15:48:16 -04:00
|
|
|
break;
|
2007-02-03 20:36:45 -05:00
|
|
|
case 'u':
|
2009-05-14 12:25:16 -04:00
|
|
|
(config->op_s_upgrade)++;
|
2007-02-04 03:26:52 -05:00
|
|
|
config->op_q_upgrade = 1;
|
2007-11-18 12:45:46 -05:00
|
|
|
config->flags |= PM_TRANS_FLAG_UNNEEDED;
|
2007-02-03 20:36:45 -05:00
|
|
|
break;
|
2007-01-17 00:25:32 -05:00
|
|
|
case 'v': (config->verbose)++; break;
|
2006-03-04 10:33:44 -05:00
|
|
|
case 'w':
|
|
|
|
config->op_s_downloadonly = 1;
|
2006-10-15 15:34:52 -04:00
|
|
|
config->flags |= PM_TRANS_FLAG_DOWNLOADONLY;
|
2006-03-04 10:33:44 -05:00
|
|
|
config->flags |= PM_TRANS_FLAG_NOCONFLICTS;
|
2007-01-17 00:25:32 -05:00
|
|
|
break;
|
|
|
|
case 'y': (config->op_s_sync)++; break;
|
2005-03-14 20:51:43 -05:00
|
|
|
case '?': return(1);
|
2006-01-07 05:01:19 -05:00
|
|
|
default: return(1);
|
2005-03-14 20:51:43 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-13 15:34:47 -05:00
|
|
|
if(config->op == 0) {
|
2007-07-23 16:58:04 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("only one operation may be used at a time\n"));
|
2006-03-13 15:34:47 -05:00
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(config->help) {
|
2007-10-31 12:43:04 -04:00
|
|
|
usage(config->op, mbasename(argv[0]));
|
2006-03-13 15:34:47 -05:00
|
|
|
return(2);
|
|
|
|
}
|
|
|
|
if(config->version) {
|
|
|
|
version();
|
2007-02-12 20:37:48 -05:00
|
|
|
return(2);
|
2006-03-13 15:34:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
while(optind < argc) {
|
|
|
|
/* add the target to our target array */
|
2007-01-19 04:28:44 -05:00
|
|
|
pm_targets = alpm_list_add(pm_targets, strdup(argv[optind]));
|
2006-03-13 15:34:47 -05:00
|
|
|
optind++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
2008-08-24 17:24:53 -04:00
|
|
|
/* helper for being used with setrepeatingoption */
|
|
|
|
static void option_add_holdpkg(const char *name) {
|
|
|
|
config->holdpkg = alpm_list_add(config->holdpkg, strdup(name));
|
|
|
|
}
|
|
|
|
|
2008-01-28 13:49:27 -05:00
|
|
|
/* helper for being used with setrepeatingoption */
|
|
|
|
static void option_add_syncfirst(const char *name) {
|
|
|
|
config->syncfirst = alpm_list_add(config->syncfirst, strdup(name));
|
|
|
|
}
|
|
|
|
|
2007-12-02 16:10:18 -05:00
|
|
|
/** Add repeating options such as NoExtract, NoUpgrade, etc to libalpm
|
|
|
|
* settings. Refactored out of the parseconfig code since all of them did
|
|
|
|
* the exact same thing and duplicated code.
|
|
|
|
* @param ptr a pointer to the start of the multiple options
|
|
|
|
* @param option the string (friendly) name of the option, used for messages
|
|
|
|
* @param optionfunc a function pointer to an alpm_option_add_* function
|
|
|
|
*/
|
|
|
|
static void setrepeatingoption(const char *ptr, const char *option,
|
|
|
|
void (*optionfunc)(const char*))
|
|
|
|
{
|
|
|
|
char *p = (char*)ptr;
|
|
|
|
char *q;
|
|
|
|
|
|
|
|
while((q = strchr(p, ' '))) {
|
|
|
|
*q = '\0';
|
|
|
|
(*optionfunc)(p);
|
|
|
|
pm_printf(PM_LOG_DEBUG, "config: %s: %s\n", option, p);
|
|
|
|
p = q;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
(*optionfunc)(p);
|
|
|
|
pm_printf(PM_LOG_DEBUG, "config: %s: %s\n", option, p);
|
|
|
|
}
|
|
|
|
|
2009-04-04 04:17:30 -04:00
|
|
|
static char *get_filename(const char *url) {
|
|
|
|
char *filename = strrchr(url, '/');
|
|
|
|
if(filename != NULL) {
|
|
|
|
filename++;
|
|
|
|
}
|
|
|
|
return(filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *get_destfile(const char *path, const char *filename) {
|
|
|
|
char *destfile;
|
|
|
|
/* len = localpath len + filename len + null */
|
|
|
|
int len = strlen(path) + strlen(filename) + 1;
|
|
|
|
destfile = calloc(len, sizeof(char));
|
|
|
|
snprintf(destfile, len, "%s%s", path, filename);
|
|
|
|
|
|
|
|
return(destfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *get_tempfile(const char *path, const char *filename) {
|
|
|
|
char *tempfile;
|
|
|
|
/* len = localpath len + filename len + '.part' len + null */
|
|
|
|
int len = strlen(path) + strlen(filename) + 6;
|
|
|
|
tempfile = calloc(len, sizeof(char));
|
|
|
|
snprintf(tempfile, len, "%s%s.part", path, filename);
|
|
|
|
|
|
|
|
return(tempfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** External fetch callback */
|
|
|
|
int download_with_xfercommand(const char *url, const char *localpath,
|
|
|
|
time_t mtimeold, time_t *mtimenew) {
|
|
|
|
int ret = 0;
|
|
|
|
int retval;
|
|
|
|
int usepart = 0;
|
2009-09-06 19:14:09 -04:00
|
|
|
char *parsedcmd,*tempcmd;
|
2009-04-04 04:17:30 -04:00
|
|
|
char cwd[PATH_MAX];
|
|
|
|
char *destfile, *tempfile, *filename;
|
|
|
|
|
|
|
|
if(!config->xfercommand) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
filename = get_filename(url);
|
|
|
|
if(!filename) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
destfile = get_destfile(localpath, filename);
|
|
|
|
tempfile = get_tempfile(localpath, filename);
|
|
|
|
|
2009-09-06 19:14:09 -04:00
|
|
|
tempcmd = strdup(config->xfercommand);
|
2009-04-04 04:17:30 -04:00
|
|
|
/* replace all occurrences of %o with fn.part */
|
2009-09-06 19:14:09 -04:00
|
|
|
if(strstr(tempcmd, "%o")) {
|
2009-04-04 04:17:30 -04:00
|
|
|
usepart = 1;
|
2009-09-06 19:14:09 -04:00
|
|
|
parsedcmd = strreplace(tempcmd, "%o", tempfile);
|
|
|
|
free(tempcmd);
|
|
|
|
tempcmd = parsedcmd;
|
2009-04-04 04:17:30 -04:00
|
|
|
}
|
|
|
|
/* replace all occurrences of %u with the download URL */
|
2009-09-06 19:14:09 -04:00
|
|
|
parsedcmd = strreplace(tempcmd, "%u", url);
|
|
|
|
free(tempcmd);
|
|
|
|
|
2009-04-04 04:17:30 -04:00
|
|
|
/* cwd to the download directory */
|
|
|
|
getcwd(cwd, PATH_MAX);
|
|
|
|
if(chdir(localpath)) {
|
|
|
|
pm_printf(PM_LOG_WARNING, "could not chdir to %s\n", localpath);
|
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
/* execute the parsed command via /bin/sh -c */
|
2009-09-06 19:14:09 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "running command: %s\n", parsedcmd);
|
|
|
|
retval = system(parsedcmd);
|
2009-04-04 04:17:30 -04:00
|
|
|
|
|
|
|
if(retval == -1) {
|
|
|
|
pm_printf(PM_LOG_WARNING, "running XferCommand: fork failed!\n");
|
|
|
|
ret = -1;
|
|
|
|
} else if(retval != 0) {
|
|
|
|
/* download failed */
|
|
|
|
pm_printf(PM_LOG_DEBUG, "XferCommand command returned non-zero status "
|
|
|
|
"code (%d)\n", retval);
|
|
|
|
ret = -1;
|
|
|
|
} else {
|
|
|
|
/* download was successful */
|
|
|
|
if(usepart) {
|
|
|
|
rename(tempfile, destfile);
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
chdir(cwd);
|
|
|
|
if(ret == -1) {
|
|
|
|
/* hack to let an user the time to cancel a download */
|
|
|
|
sleep(2);
|
|
|
|
}
|
|
|
|
free(destfile);
|
|
|
|
free(tempfile);
|
2009-09-06 19:14:09 -04:00
|
|
|
free(parsedcmd);
|
2009-04-04 04:17:30 -04:00
|
|
|
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
2007-06-04 12:01:53 -04:00
|
|
|
/* The real parseconfig. Called with a null section argument by the publicly
|
|
|
|
* visible parseconfig so we can recall from within ourself on an include */
|
2007-06-04 15:39:00 -04:00
|
|
|
static int _parseconfig(const char *file, const char *givensection,
|
|
|
|
pmdb_t * const givendb)
|
2007-06-04 12:01:53 -04:00
|
|
|
{
|
|
|
|
FILE *fp = NULL;
|
|
|
|
char line[PATH_MAX+1];
|
|
|
|
int linenum = 0;
|
|
|
|
char *ptr, *section = NULL;
|
|
|
|
pmdb_t *db = NULL;
|
2008-11-17 11:02:43 -05:00
|
|
|
int ret = 0;
|
2007-06-04 12:01:53 -04:00
|
|
|
|
2007-07-10 14:24:58 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: attempting to read file %s\n", file);
|
2007-06-04 12:01:53 -04:00
|
|
|
fp = fopen(file, "r");
|
|
|
|
if(fp == NULL) {
|
2007-06-07 22:20:40 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("config file %s could not be read.\n"), file);
|
2007-06-04 12:01:53 -04:00
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
2007-06-04 15:39:00 -04:00
|
|
|
/* if we are passed a section, use it as our starting point */
|
2007-06-04 12:01:53 -04:00
|
|
|
if(givensection != NULL) {
|
|
|
|
section = strdup(givensection);
|
|
|
|
}
|
2007-06-04 15:39:00 -04:00
|
|
|
/* if we are passed a db, use it as our starting point */
|
|
|
|
if(givendb != NULL) {
|
|
|
|
db = givendb;
|
|
|
|
}
|
2007-06-04 12:01:53 -04:00
|
|
|
|
|
|
|
while(fgets(line, PATH_MAX, fp)) {
|
|
|
|
linenum++;
|
|
|
|
strtrim(line);
|
|
|
|
|
|
|
|
/* ignore whole line and end of line comments */
|
|
|
|
if(strlen(line) == 0 || line[0] == '#') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if((ptr = strchr(line, '#'))) {
|
|
|
|
*ptr = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
if(line[0] == '[' && line[strlen(line)-1] == ']') {
|
|
|
|
/* new config section, skip the '[' */
|
2007-06-27 22:58:21 -04:00
|
|
|
ptr = line;
|
|
|
|
ptr++;
|
2007-06-04 12:01:53 -04:00
|
|
|
if(section) {
|
|
|
|
free(section);
|
|
|
|
}
|
|
|
|
section = strdup(ptr);
|
|
|
|
section[strlen(section)-1] = '\0';
|
2007-07-10 14:24:58 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: new section '%s'\n", section);
|
2007-06-04 12:01:53 -04:00
|
|
|
if(!strlen(section)) {
|
2007-06-09 13:38:14 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("config file %s, line %d: bad section name.\n"),
|
|
|
|
file, linenum);
|
2008-11-17 11:02:43 -05:00
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
2007-06-04 12:01:53 -04:00
|
|
|
}
|
2007-12-02 13:56:57 -05:00
|
|
|
/* if we are not looking at the options section, register a db and also
|
|
|
|
* ensure we have set all of our library paths as the library is too stupid
|
|
|
|
* at the moment to do lazy opening of the databases */
|
2007-06-04 12:51:23 -04:00
|
|
|
if(strcmp(section, "options") != 0) {
|
2007-12-02 13:56:57 -05:00
|
|
|
setlibpaths();
|
2007-08-26 22:42:17 -04:00
|
|
|
db = alpm_db_register_sync(section);
|
2008-11-17 11:02:43 -05:00
|
|
|
if(db == NULL) {
|
|
|
|
pm_printf(PM_LOG_ERROR, _("could not register '%s' database (%s)\n"),
|
|
|
|
section, alpm_strerrorlast());
|
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2007-06-04 12:51:23 -04:00
|
|
|
}
|
2007-06-04 12:01:53 -04:00
|
|
|
} else {
|
|
|
|
/* directive */
|
2008-03-13 11:36:44 -04:00
|
|
|
char *key;
|
2007-06-04 12:01:53 -04:00
|
|
|
/* strsep modifies the 'line' string: 'key \0 ptr' */
|
|
|
|
key = line;
|
|
|
|
ptr = line;
|
|
|
|
strsep(&ptr, "=");
|
|
|
|
strtrim(key);
|
|
|
|
strtrim(ptr);
|
|
|
|
|
|
|
|
if(key == NULL) {
|
2007-06-09 13:38:14 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("config file %s, line %d: syntax error in config file- missing key.\n"),
|
|
|
|
file, linenum);
|
2008-11-17 11:02:43 -05:00
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
2007-06-04 12:01:53 -04:00
|
|
|
}
|
2008-03-13 11:36:44 -04:00
|
|
|
/* For each directive, compare to the camelcase string. */
|
2008-01-13 15:14:34 -05:00
|
|
|
if(section == NULL) {
|
|
|
|
pm_printf(PM_LOG_ERROR, _("config file %s, line %d: All directives must belong to a section.\n"),
|
2007-06-09 13:38:14 -04:00
|
|
|
file, linenum);
|
2008-11-17 11:02:43 -05:00
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
2007-06-04 12:01:53 -04:00
|
|
|
}
|
2007-06-27 22:58:21 -04:00
|
|
|
if(ptr == NULL && strcmp(section, "options") == 0) {
|
|
|
|
/* directives without settings, all in [options] */
|
2009-08-08 13:59:02 -04:00
|
|
|
if(strcmp(key, "UseSyslog") == 0) {
|
2007-06-04 12:01:53 -04:00
|
|
|
alpm_option_set_usesyslog(1);
|
2007-07-10 14:24:58 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: usesyslog\n");
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "ILoveCandy") == 0) {
|
2007-06-04 12:12:13 -04:00
|
|
|
config->chomp = 1;
|
2007-07-10 14:24:58 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: chomp\n");
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "ShowSize") == 0) {
|
2007-09-27 22:38:47 -04:00
|
|
|
config->showsize = 1;
|
2007-07-10 14:24:58 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: showsize\n");
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "UseDelta") == 0) {
|
2007-10-19 13:17:53 -04:00
|
|
|
alpm_option_set_usedelta(1);
|
|
|
|
pm_printf(PM_LOG_DEBUG, "config: usedelta\n");
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "TotalDownload") == 0) {
|
2007-11-09 19:54:18 -05:00
|
|
|
config->totaldownload = 1;
|
|
|
|
pm_printf(PM_LOG_DEBUG, "config: totaldownload\n");
|
2007-06-04 12:01:53 -04:00
|
|
|
} else {
|
2007-06-09 13:38:14 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"),
|
|
|
|
file, linenum, key);
|
2008-11-17 11:02:43 -05:00
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
2007-06-04 12:01:53 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* directives with settings */
|
2008-03-13 11:36:44 -04:00
|
|
|
if(strcmp(key, "Include") == 0) {
|
2007-07-10 14:24:58 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: including %s\n", ptr);
|
2007-12-14 12:35:46 -05:00
|
|
|
_parseconfig(ptr, section, db);
|
|
|
|
/* Ignore include failures... assume non-critical */
|
2007-06-04 12:01:53 -04:00
|
|
|
} else if(strcmp(section, "options") == 0) {
|
2008-03-13 11:36:44 -04:00
|
|
|
if(strcmp(key, "NoUpgrade") == 0) {
|
2007-12-02 16:10:18 -05:00
|
|
|
setrepeatingoption(ptr, "NoUpgrade", alpm_option_add_noupgrade);
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "NoExtract") == 0) {
|
2007-12-02 16:10:18 -05:00
|
|
|
setrepeatingoption(ptr, "NoExtract", alpm_option_add_noextract);
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "IgnorePkg") == 0) {
|
2007-12-02 16:10:18 -05:00
|
|
|
setrepeatingoption(ptr, "IgnorePkg", alpm_option_add_ignorepkg);
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "IgnoreGroup") == 0) {
|
2007-12-02 16:10:18 -05:00
|
|
|
setrepeatingoption(ptr, "IgnoreGroup", alpm_option_add_ignoregrp);
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "HoldPkg") == 0) {
|
2008-08-24 17:24:53 -04:00
|
|
|
setrepeatingoption(ptr, "HoldPkg", option_add_holdpkg);
|
2008-01-28 13:49:27 -05:00
|
|
|
} else if(strcmp(key, "SyncFirst") == 0) {
|
|
|
|
setrepeatingoption(ptr, "SyncFirst", option_add_syncfirst);
|
2009-07-22 00:03:25 -04:00
|
|
|
} else if(strcmp(key, "Architecture") == 0) {
|
|
|
|
if(!alpm_option_get_arch()) {
|
|
|
|
setarch(ptr);
|
|
|
|
}
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "DBPath") == 0) {
|
2007-07-23 16:58:04 -04:00
|
|
|
/* don't overwrite a path specified on the command line */
|
2007-12-02 13:20:55 -05:00
|
|
|
if(!config->dbpath) {
|
|
|
|
config->dbpath = strdup(ptr);
|
2007-07-10 14:24:58 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: dbpath: %s\n", ptr);
|
2007-06-27 22:58:21 -04:00
|
|
|
}
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "CacheDir") == 0) {
|
2007-08-21 21:28:05 -04:00
|
|
|
if(alpm_option_add_cachedir(ptr) != 0) {
|
|
|
|
pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"),
|
2007-09-08 12:41:45 -04:00
|
|
|
ptr, alpm_strerrorlast());
|
2008-11-17 11:02:43 -05:00
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
2007-07-23 16:58:04 -04:00
|
|
|
}
|
2007-08-21 21:28:05 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: cachedir: %s\n", ptr);
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "RootDir") == 0) {
|
2007-07-23 16:58:04 -04:00
|
|
|
/* don't overwrite a path specified on the command line */
|
2007-12-02 13:20:55 -05:00
|
|
|
if(!config->rootdir) {
|
|
|
|
config->rootdir = strdup(ptr);
|
2007-07-10 14:24:58 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: rootdir: %s\n", ptr);
|
2007-06-27 22:58:21 -04:00
|
|
|
}
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if (strcmp(key, "LogFile") == 0) {
|
2007-12-02 13:20:55 -05:00
|
|
|
if(!config->logfile) {
|
|
|
|
config->logfile = strdup(ptr);
|
2007-07-10 14:24:58 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: logfile: %s\n", ptr);
|
2007-06-27 22:58:21 -04:00
|
|
|
}
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if (strcmp(key, "XferCommand") == 0) {
|
2009-04-04 04:17:30 -04:00
|
|
|
config->xfercommand = strdup(ptr);
|
|
|
|
alpm_option_set_fetchcb(download_with_xfercommand);
|
2007-07-10 14:24:58 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: xfercommand: %s\n", ptr);
|
2008-02-16 10:01:13 -05:00
|
|
|
} else if (strcmp(key, "CleanMethod") == 0) {
|
|
|
|
if (strcmp(ptr, "KeepInstalled") == 0) {
|
|
|
|
config->cleanmethod = PM_CLEAN_KEEPINST;
|
|
|
|
} else if (strcmp(ptr, "KeepCurrent") == 0) {
|
|
|
|
config->cleanmethod = PM_CLEAN_KEEPCUR;
|
|
|
|
} else {
|
|
|
|
pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), ptr);
|
2008-11-17 11:02:43 -05:00
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
2008-02-16 10:01:13 -05:00
|
|
|
}
|
|
|
|
pm_printf(PM_LOG_DEBUG, "config: cleanmethod: %s\n", ptr);
|
2007-06-04 12:01:53 -04:00
|
|
|
} else {
|
2007-06-09 13:38:14 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"),
|
|
|
|
file, linenum, key);
|
2008-11-17 11:02:43 -05:00
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
2007-06-04 12:01:53 -04:00
|
|
|
}
|
2008-03-13 11:36:44 -04:00
|
|
|
} else if(strcmp(key, "Server") == 0) {
|
2007-06-04 15:39:00 -04:00
|
|
|
/* let's attempt a replacement for the current repo */
|
2009-08-19 12:35:32 -04:00
|
|
|
char *temp = strreplace(ptr, "$repo", section);
|
|
|
|
/* let's attempt a replacement for the arch */
|
|
|
|
const char *arch = alpm_option_get_arch();
|
|
|
|
char *server;
|
|
|
|
if(arch) {
|
|
|
|
server = strreplace(temp, "$arch", arch);
|
|
|
|
free(temp);
|
|
|
|
} else {
|
|
|
|
if(strstr(temp, "$arch")) {
|
2009-09-06 19:50:36 -04:00
|
|
|
free(temp);
|
2009-08-19 12:35:32 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("The mirror '%s' contains the $arch"
|
|
|
|
" variable, but no Architecture is defined.\n"), ptr);
|
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
server = temp;
|
|
|
|
}
|
2007-06-04 12:01:53 -04:00
|
|
|
|
2007-06-04 15:39:00 -04:00
|
|
|
if(alpm_db_setserver(db, server) != 0) {
|
|
|
|
/* pm_errno is set by alpm_db_setserver */
|
2008-11-17 11:02:43 -05:00
|
|
|
pm_printf(PM_LOG_ERROR, _("could not add server URL to database '%s': %s (%s)\n"),
|
|
|
|
alpm_db_get_name(db), server, alpm_strerrorlast());
|
|
|
|
free(server);
|
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
2007-06-04 12:01:53 -04:00
|
|
|
}
|
2007-06-04 15:39:00 -04:00
|
|
|
|
|
|
|
free(server);
|
|
|
|
} else {
|
2007-06-09 13:38:14 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"),
|
|
|
|
file, linenum, key);
|
2008-11-17 11:02:43 -05:00
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
2007-06-04 12:01:53 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-11-17 11:02:43 -05:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if(fp) {
|
|
|
|
fclose(fp);
|
|
|
|
}
|
2007-08-21 23:29:10 -04:00
|
|
|
if(section){
|
|
|
|
free(section);
|
|
|
|
}
|
2007-12-02 13:56:57 -05:00
|
|
|
/* call setlibpaths here to ensure we have called it at least once */
|
|
|
|
setlibpaths();
|
2007-06-07 22:20:40 -04:00
|
|
|
pm_printf(PM_LOG_DEBUG, "config: finished parsing %s\n", file);
|
2008-11-17 11:02:43 -05:00
|
|
|
return(ret);
|
2007-06-04 12:01:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Parse a configuration file.
|
|
|
|
* @param file path to the config file.
|
|
|
|
* @return 0 on success, non-zero on error
|
|
|
|
*/
|
2007-12-14 12:35:46 -05:00
|
|
|
static int parseconfig(const char *file)
|
2007-06-04 12:01:53 -04:00
|
|
|
{
|
2007-06-04 15:39:00 -04:00
|
|
|
/* call the real parseconfig function with a null section & db argument */
|
|
|
|
return(_parseconfig(file, NULL, NULL));
|
2007-06-04 12:01:53 -04:00
|
|
|
}
|
|
|
|
|
2008-12-20 00:51:59 -05:00
|
|
|
/** print commandline to logfile
|
|
|
|
*/
|
|
|
|
static void cl_to_log(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
size_t size = 0;
|
|
|
|
int i;
|
|
|
|
for(i = 0; i<argc; i++) {
|
|
|
|
size += strlen(argv[i]) + 1;
|
|
|
|
}
|
|
|
|
char *cl_text = malloc(size);
|
|
|
|
if(!cl_text)
|
|
|
|
return;
|
|
|
|
char *p = cl_text;
|
|
|
|
for(i = 0; i<argc-1; i++) {
|
|
|
|
strcpy(p, argv[i]);
|
|
|
|
p += strlen(argv[i]);
|
|
|
|
*p++ = ' ';
|
|
|
|
}
|
|
|
|
strcpy(p, argv[i]);
|
|
|
|
alpm_logaction("Running '%s'\n", cl_text);
|
|
|
|
free(cl_text);
|
|
|
|
}
|
|
|
|
|
2007-07-23 16:58:04 -04:00
|
|
|
/** Main function.
|
2007-03-28 16:14:42 -04:00
|
|
|
* @param argc argc
|
|
|
|
* @param argv argv
|
|
|
|
* @return A return code indicating success, failure, etc.
|
|
|
|
*/
|
2006-03-13 15:34:47 -05:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int ret = 0;
|
2008-03-09 08:12:32 -04:00
|
|
|
struct sigaction new_action, old_action;
|
2008-04-15 11:10:39 -04:00
|
|
|
#if defined(HAVE_GETEUID) && !defined(CYGWIN)
|
2007-06-07 20:49:31 -04:00
|
|
|
/* geteuid undefined in CYGWIN */
|
|
|
|
uid_t myuid = geteuid();
|
|
|
|
#endif
|
2006-03-13 15:34:47 -05:00
|
|
|
|
2007-10-26 21:31:25 -04:00
|
|
|
#if defined(PACMAN_DEBUG) && defined(HAVE_MCHECK_H)
|
2006-11-14 02:58:42 -05:00
|
|
|
/*setenv("MALLOC_TRACE","pacman.mtrace", 0);*/
|
2006-11-09 14:27:10 -05:00
|
|
|
mtrace();
|
2006-03-13 15:34:47 -05:00
|
|
|
#endif
|
2007-04-25 17:24:23 -04:00
|
|
|
|
2008-03-09 08:12:32 -04:00
|
|
|
/* Set signal handlers */
|
|
|
|
/* Set up the structure to specify the new action. */
|
|
|
|
new_action.sa_handler = handler;
|
|
|
|
sigemptyset(&new_action.sa_mask);
|
|
|
|
new_action.sa_flags = 0;
|
|
|
|
|
|
|
|
sigaction(SIGINT, NULL, &old_action);
|
|
|
|
if(old_action.sa_handler != SIG_IGN) {
|
|
|
|
sigaction(SIGINT, &new_action, NULL);
|
|
|
|
}
|
|
|
|
sigaction(SIGTERM, NULL, &old_action);
|
|
|
|
if(old_action.sa_handler != SIG_IGN) {
|
|
|
|
sigaction(SIGTERM, &new_action, NULL);
|
|
|
|
}
|
|
|
|
sigaction(SIGSEGV, NULL, &old_action);
|
|
|
|
if(old_action.sa_handler != SIG_IGN) {
|
|
|
|
sigaction(SIGSEGV, &new_action, NULL);
|
|
|
|
}
|
2006-03-13 15:34:47 -05:00
|
|
|
|
2006-06-28 01:37:15 -04:00
|
|
|
/* i18n init */
|
2007-10-23 00:52:55 -04:00
|
|
|
#if defined(ENABLE_NLS)
|
2007-03-28 16:14:42 -04:00
|
|
|
localize();
|
2007-10-23 00:52:55 -04:00
|
|
|
#endif
|
2006-06-28 01:37:15 -04:00
|
|
|
|
2007-04-28 04:50:16 -04:00
|
|
|
/* set user agent for downloading */
|
|
|
|
setuseragent();
|
|
|
|
|
2006-03-13 15:34:47 -05:00
|
|
|
/* init config data */
|
|
|
|
config = config_new();
|
2007-04-25 17:24:23 -04:00
|
|
|
|
2006-03-13 15:34:47 -05:00
|
|
|
/* disable progressbar if the output is redirected */
|
|
|
|
if(!isatty(1)) {
|
|
|
|
config->noprogressbar = 1;
|
2005-03-14 20:51:43 -05:00
|
|
|
}
|
|
|
|
|
2007-07-23 16:58:04 -04:00
|
|
|
/* initialize library */
|
2007-01-31 01:10:21 -05:00
|
|
|
if(alpm_initialize() == -1) {
|
2007-07-23 16:58:04 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("failed to initialize alpm library (%s)\n"),
|
2007-09-08 12:41:45 -04:00
|
|
|
alpm_strerrorlast());
|
2007-06-07 20:49:31 -04:00
|
|
|
cleanup(EXIT_FAILURE);
|
2007-01-31 01:10:21 -05:00
|
|
|
}
|
|
|
|
|
2007-06-07 20:49:31 -04:00
|
|
|
/* Setup logging as soon as possible, to print out maximum debugging info */
|
|
|
|
alpm_option_set_logcb(cb_log);
|
|
|
|
alpm_option_set_dlcb(cb_dl_progress);
|
2007-11-04 23:05:44 -05:00
|
|
|
/* define paths to reasonable defaults */
|
2007-08-21 21:28:05 -04:00
|
|
|
alpm_option_set_root(ROOTDIR);
|
|
|
|
alpm_option_set_dbpath(DBPATH);
|
2007-11-04 23:05:44 -05:00
|
|
|
alpm_option_set_logfile(LOGFILE);
|
2007-08-21 21:28:05 -04:00
|
|
|
|
|
|
|
/* Priority of options:
|
|
|
|
* 1. command line
|
|
|
|
* 2. config file
|
|
|
|
* 3. compiled-in defaults
|
|
|
|
* However, we have to parse the command line first because a config file
|
|
|
|
* location can be specified here, so we need to make sure we prefer these
|
|
|
|
* options over the config file coming second.
|
|
|
|
*/
|
2007-06-07 20:49:31 -04:00
|
|
|
|
2006-03-13 15:34:47 -05:00
|
|
|
/* parse the command line */
|
|
|
|
ret = parseargs(argc, argv);
|
|
|
|
if(ret != 0) {
|
2007-06-07 22:20:40 -04:00
|
|
|
cleanup(ret);
|
2005-03-14 20:51:43 -05:00
|
|
|
}
|
|
|
|
|
2007-06-07 20:49:31 -04:00
|
|
|
/* parse the config file */
|
2007-06-07 22:20:40 -04:00
|
|
|
ret = parseconfig(config->configfile);
|
|
|
|
if(ret != 0) {
|
|
|
|
cleanup(ret);
|
2007-06-07 20:49:31 -04:00
|
|
|
}
|
2005-03-14 20:51:43 -05:00
|
|
|
|
2008-06-02 00:10:30 -04:00
|
|
|
/* set TotalDownload callback if option enabled */
|
|
|
|
if(config->totaldownload) {
|
|
|
|
alpm_option_set_totaldlcb(cb_dl_total);
|
|
|
|
}
|
|
|
|
|
Re-add the non-user friendly --ask option
This re-implements the --ask option which was removed in commit
1ff8e7f364a9f640ada7526384646d510ac29967.
This option does not have to be exposed to the user (help,doc,etc), but is
very very useful for pactest if we want to have more coverage there.
This was rewritten in a smarter way, without code duplication. And with a
different behavior : this option is now only used to inverse default
behavior to questions.
We still use bit operations based on the following struct :
/* Transaction Conversations (ie, questions) */
typedef enum _pmtransconv_t {
PM_TRANS_CONV_INSTALL_IGNOREPKG = 0x01,
PM_TRANS_CONV_REPLACE_PKG = 0x02,
PM_TRANS_CONV_CONFLICT_PKG = 0x04,
PM_TRANS_CONV_CORRUPTED_PKG = 0x08,
PM_TRANS_CONV_LOCAL_NEWER = 0x10,
PM_TRANS_CONV_REMOVE_PKGS = 0x20,
} pmtransconv_t;
for each conv matched, the default answer is inversed.
--ask 0 : all default answers are preserved
--ask 4 : only conflict question is inversed
--ask 63 : all questions are inversed (63 == 1+2+4+8+16+32)
Signed-off-by: Xavier Chantry <shiningxc@gmail.com>
Signed-off-by: Dan McGee <dan@archlinux.org>
2009-08-31 14:17:05 -04:00
|
|
|
/* noask is meant to be non-interactive */
|
|
|
|
if(config->noask) {
|
|
|
|
config->noconfirm = 1;
|
|
|
|
}
|
|
|
|
|
2008-04-15 11:10:39 -04:00
|
|
|
#if defined(HAVE_GETEUID) && !defined(CYGWIN)
|
2006-03-13 15:34:47 -05:00
|
|
|
/* check if we have sufficient permission for the requested operation */
|
2009-05-16 11:59:45 -04:00
|
|
|
if(myuid > 0 && needs_root()) {
|
2007-09-28 00:03:35 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("you cannot perform this operation unless you are root.\n"));
|
|
|
|
cleanup(EXIT_FAILURE);
|
2005-03-14 20:51:43 -05:00
|
|
|
}
|
2007-06-07 22:20:40 -04:00
|
|
|
#endif
|
2005-03-14 20:51:43 -05:00
|
|
|
|
2006-03-13 15:34:47 -05:00
|
|
|
if(config->verbose > 0) {
|
2007-06-04 14:50:16 -04:00
|
|
|
alpm_list_t *i;
|
2007-05-31 02:51:28 -04:00
|
|
|
printf("Root : %s\n", alpm_option_get_root());
|
|
|
|
printf("Conf File : %s\n", config->configfile);
|
2007-06-04 14:50:16 -04:00
|
|
|
printf("DB Path : %s\n", alpm_option_get_dbpath());
|
|
|
|
printf("Cache Dirs: ");
|
|
|
|
for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) {
|
|
|
|
printf("%s ", (char*)alpm_list_getdata(i));
|
|
|
|
}
|
|
|
|
printf("\n");
|
2007-06-04 10:37:00 -04:00
|
|
|
printf("Lock File : %s\n", alpm_option_get_lockfile());
|
|
|
|
printf("Log File : %s\n", alpm_option_get_logfile());
|
2007-05-31 02:51:28 -04:00
|
|
|
list_display("Targets :", pm_targets);
|
2006-03-13 15:34:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Opening local database */
|
2007-08-26 22:42:17 -04:00
|
|
|
db_local = alpm_db_register_local();
|
2006-03-13 15:34:47 -05:00
|
|
|
if(db_local == NULL) {
|
2007-07-23 16:58:04 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("could not register 'local' database (%s)\n"),
|
2007-09-08 12:41:45 -04:00
|
|
|
alpm_strerrorlast());
|
2007-06-07 20:49:31 -04:00
|
|
|
cleanup(EXIT_FAILURE);
|
2005-03-14 20:51:43 -05:00
|
|
|
}
|
2006-03-13 15:34:47 -05:00
|
|
|
|
2008-12-20 00:51:59 -05:00
|
|
|
/* Log commandline */
|
|
|
|
if(needs_root()) {
|
|
|
|
cl_to_log(argc, argv);
|
|
|
|
}
|
|
|
|
|
2006-03-13 15:34:47 -05:00
|
|
|
/* start the requested operation */
|
|
|
|
switch(config->op) {
|
2007-04-25 17:24:23 -04:00
|
|
|
case PM_OP_REMOVE:
|
|
|
|
ret = pacman_remove(pm_targets);
|
|
|
|
break;
|
|
|
|
case PM_OP_UPGRADE:
|
|
|
|
ret = pacman_upgrade(pm_targets);
|
|
|
|
break;
|
|
|
|
case PM_OP_QUERY:
|
|
|
|
ret = pacman_query(pm_targets);
|
|
|
|
break;
|
|
|
|
case PM_OP_SYNC:
|
|
|
|
ret = pacman_sync(pm_targets);
|
|
|
|
break;
|
|
|
|
case PM_OP_DEPTEST:
|
|
|
|
ret = pacman_deptest(pm_targets);
|
|
|
|
break;
|
2006-03-13 15:34:47 -05:00
|
|
|
default:
|
2007-07-23 16:58:04 -04:00
|
|
|
pm_printf(PM_LOG_ERROR, _("no operation specified (use -h for help)\n"));
|
2007-06-07 20:49:31 -04:00
|
|
|
ret = EXIT_FAILURE;
|
2005-03-14 20:51:43 -05:00
|
|
|
}
|
|
|
|
|
2006-03-13 15:34:47 -05:00
|
|
|
cleanup(ret);
|
|
|
|
/* not reached */
|
2007-06-07 20:49:31 -04:00
|
|
|
return(EXIT_SUCCESS);
|
2005-03-14 20:51:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* vim: set ts=2 sw=2 noet: */
|