Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

330 lines (283 sloc) 10.43 kb
/*
* Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
* Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
* Copyright (c) 2011 Will Andrews <will@FreeBSD.org>
* Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/jail.h>
#include <sys/stat.h>
#include <assert.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
#include <jail.h>
#include <pkg.h>
#include "pkgcli.h"
#ifndef GITHASH
#define GITHASH ""
#endif
static void usage(void);
static void usage_help(void);
static int exec_help(int, char **);
bool quiet = false;
static struct commands {
const char * const name;
const char * const desc;
int (*exec)(int argc, char **argv);
void (* const usage)(void);
} cmd[] = {
{ "add", "Registers a package and installs it on the system", exec_add, usage_add},
{ "audit", "Reports vulnerable packages", exec_audit, usage_audit},
{ "autoremove", "Removes orphan packages", exec_autoremove, usage_autoremove},
{ "backup", "Backs-up and restores the local package database", exec_backup, usage_backup},
{ "check", "Checks for missing dependencies and database consistency", exec_check, usage_check},
{ "clean", "Cleans old packages from the cache", exec_clean, usage_clean},
{ "create", "Creates software package distributions", exec_create, usage_create},
{ "delete", "Deletes packages from the database and the system", exec_delete, usage_delete},
{ "fetch", "Fetches packages from a remote repository", exec_fetch, usage_fetch},
{ "help", "Displays help information", exec_help, usage_help},
{ "info", "Displays information about installed packages", exec_info, usage_info},
{ "install", "Installs packages from remote package repositories", exec_install, usage_install},
{ "query", "Queries information about installed packages", exec_query, usage_query},
{ "register", "Registers a package into the local database", exec_register, usage_register},
{ "remove", "Deletes packages from the database and the system", exec_delete, usage_delete},
{ "repo", "Creates a package repository catalogue", exec_repo, usage_repo},
{ "rquery", "Queries information in repository catalogues", exec_rquery, usage_rquery},
{ "search", "Performs a search of package repository catalogues", exec_search, usage_search},
{ "set", "Modifies information about packages in the local database", exec_set, usage_set},
{ "shell", "Opens a debug shell", exec_shell, usage_shell},
{ "shlib", "Displays which packages link against a specific shared library", exec_shlib, usage_shlib},
{ "stats", "Displays package database statistics", exec_stats, usage_stats},
{ "update", "Updates package repository catalogues", exec_update, usage_update},
{ "updating", "Displays UPDATING information for a package", exec_updating, usage_updating},
{ "upgrade", "Performs upgrades of packaged software distributions", exec_upgrade, usage_upgrade},
{ "version", "Displays the versions of installed packages", exec_version, usage_version},
{ "which", "Displays which package installed a specific file", exec_which, usage_which},
};
const unsigned int cmd_len = (sizeof(cmd)/sizeof(cmd[0]));
static void
usage(void)
{
fprintf(stderr, "usage: pkg [-v] [-d] [-j <jail name or id>|-c <chroot path>] <command> [<args>]\n\n");
fprintf(stderr, "Global options supported:\n");
fprintf(stderr, "\t%-15s%s\n", "-d", "Increment debug level");
fprintf(stderr, "\t%-15s%s\n", "-j", "Execute pkg(1) inside a jail(8)");
fprintf(stderr, "\t%-15s%s\n", "-c", "Execute pkg(1) inside a chroot(8)");
fprintf(stderr, "\t%-15s%s\n\n", "-v", "Display pkg(1) version");
fprintf(stderr, "Commands supported:\n");
for (unsigned int i = 0; i < cmd_len; i++)
fprintf(stderr, "\t%-15s%s\n", cmd[i].name, cmd[i].desc);
fprintf(stderr, "\nFor more information on the different commands"
" see 'pkg help <command>'.\n");
exit(EX_USAGE);
}
static void
usage_help(void)
{
fprintf(stderr, "usage: pkg help <command>\n\n");
fprintf(stderr, "Where <command> can be:\n");
for (unsigned int i = 0; i < cmd_len; i++)
fprintf(stderr, "\t%s\n", cmd[i].name);
}
static int
exec_help(int argc, char **argv)
{
char *manpage;
if ((argc != 2) || (strcmp("help", argv[1]) == 0)) {
usage_help();
return(EX_USAGE);
}
for (unsigned int i = 0; i < cmd_len; i++) {
if (strcmp(cmd[i].name, argv[1]) == 0) {
if (asprintf(&manpage, "/usr/bin/man pkg-%s", cmd[i].name) == -1)
errx(1, "cannot allocate memory");
system(manpage);
free(manpage);
return (0);
}
}
if (strcmp(argv[1], "pkg") == 0) {
system("/usr/bin/man 8 pkg");
return (0);
} else if (strcmp(argv[1], "pkg.conf") == 0) {
system("/usr/bin/man 5 pkg.conf");
return (0);
}
/* Command name not found */
warnx("'%s' is not a valid command.\n", argv[1]);
fprintf(stderr, "See 'pkg help' for more information on the commands.\n");
return (EX_USAGE);
}
int
main(int argc, char **argv)
{
unsigned int i;
struct commands *command = NULL;
unsigned int ambiguous = 0;
const char *chroot_path = NULL;
int jid;
const char *jail_str = NULL;
size_t len;
signed char ch;
int debug = 0;
int version = 0;
int ret = EX_OK;
const char *buf = NULL;
bool b;
struct pkg_config_kv *kv = NULL;
/* Set stdout unbuffered */
setvbuf(stdout, NULL, _IONBF, 0);
if (argc < 2)
usage();
while ((ch = getopt(argc, argv, "dj:c:vq")) != -1) {
switch (ch) {
case 'd':
debug++;
break;
case 'c':
chroot_path = optarg;
break;
case 'j':
jail_str = optarg;
break;
case 'v':
version++;
break;
default:
break;
}
}
argc -= optind;
argv += optind;
if (version == 1) {
printf(PKGVERSION""GITHASH"\n");
exit(EX_OK);
}
if (argc == 0 && version == 0)
usage();
umask(022);
pkg_event_register(&event_callback, &debug);
/* reset getopt for the next call */
optreset = 1;
optind = 1;
if (jail_str != NULL && chroot_path != NULL) {
fprintf(stderr, "-j and -c cannot be used at the same time!\n");
usage();
}
if (chroot_path != NULL)
if (chroot(chroot_path) == -1)
errx(EX_SOFTWARE, "chroot failed!");
if (jail_str != NULL) {
jid = jail_getid(jail_str);
if (jid < 0)
errx(1, "%s", jail_errmsg);
if (jail_attach(jid) == -1)
err(1, "jail_attach(%s)", jail_str);
}
if (jail_str != NULL || chroot_path != NULL)
if (chdir("/") == -1)
errx(EX_SOFTWARE, "chdir() failed");
if (pkg_init(NULL) != EPKG_OK)
errx(EX_SOFTWARE, "Cannot parse configuration file!");
if (version > 1) {
printf("version: "PKGVERSION""GITHASH"\n");
pkg_config_string(PKG_CONFIG_ABI, &buf);
printf("abi: %s\n", buf);
pkg_config_string(PKG_CONFIG_DBDIR, &buf);
printf("db dir: %s\n", buf);
pkg_config_string(PKG_CONFIG_CACHEDIR, &buf);
printf("cache dir: %s\n", buf);
pkg_config_string(PKG_CONFIG_PORTSDIR, &buf);
printf("ports dir: %s\n", buf);
pkg_config_bool(PKG_CONFIG_SYSLOG, &b);
printf("Log into syslog: %s\n", b ? "yes": "no");
pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &b);
printf("Assume always yes: %s\n", b ? "yes" : "no");
if (version > 2) {
pkg_config_bool(PKG_CONFIG_HANDLE_RC_SCRIPTS, &b);
printf("Handle rc scripts: %s\n", b ? "yes" : "no");
pkg_config_bool(PKG_CONFIG_SHLIBS, &b);
printf("Track shlibs: %s\n", b ? "yes" : "no");
pkg_config_bool(PKG_CONFIG_AUTODEPS, &b);
printf("Automatic dependency tracking: %s\n", b ? "yes": "no");
pkg_config_string(PKG_CONFIG_PLIST_KEYWORDS_DIR, &buf);
printf("Custom keywords directory: %s\n", buf ? buf : "none");
pkg_config_bool(PKG_CONFIG_DEVELOPER_MODE, &b);
printf("Developer mode: %s\n", b ? "yes" : "no");
}
pkg_config_bool(PKG_CONFIG_MULTIREPOS, &b);
if (b) {
printf("Repositories:\n");
while (pkg_config_list(PKG_CONFIG_REPOS, &kv) == EPKG_OK) {
printf(" - %s: %s\n", pkg_config_kv_get(kv, PKG_CONFIG_KV_KEY),
pkg_config_kv_get(kv, PKG_CONFIG_KV_VALUE));
}
} else {
pkg_config_string(PKG_CONFIG_REPO, &buf);
printf("Repository: %s\n", buf ? buf : "none");
}
pkg_shutdown();
exit(EX_OK);
}
len = strlen(argv[0]);
for (i = 0; i < cmd_len; i++) {
if (strncmp(argv[0], cmd[i].name, len) == 0) {
/* if we have the exact cmd */
if (len == strlen(cmd[i].name)) {
command = &cmd[i];
ambiguous = 0;
break;
}
/*
* we already found a partial match so `argv[0]' is
* an ambiguous shortcut
*/
ambiguous++;
command = &cmd[i];
}
}
if (command == NULL) {
pkg_shutdown();
usage();
return (ret); /* Not reached but makes scanbuild happy */
}
if (ambiguous <= 1) {
assert(command->exec != NULL);
ret = command->exec(argc, argv);
} else {
warnx("'%s' is not a valid command.\n", argv[0]);
fprintf(stderr, "See 'pkg help' for more information on the commands.\n\n");
fprintf(stderr, "Command '%s' could be one of the following:\n", argv[0]);
for (i = 0; i < cmd_len; i++)
if (strncmp(argv[0], cmd[i].name, len) == 0)
fprintf(stderr, "\t%s\n",cmd[i].name);
}
pkg_shutdown();
return (ret);
}
Jump to Line
Something went wrong with that request. Please try again.