src/rpm.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Aug 23 11:13:48 2014 +0100 (2014-08-23)
changeset 440 48204dea0b9f
parent 425 0c8bdd8dc942
permissions -rw-r--r--
Remove INTLLIBS from librazor_la_LIBADD.

This partially reverts 611c84a3f4b4538a65d186050608c17adbf17770.
It's not clear what motivated the initial inclusion of INTLLIBS
here since the net effect is only seen in librazor.la and not
in razor.pc and librazor.la is not normally packaged. Certainly
neither the static nor the dynamic versions of librazor currently
use libintl. At best this would cause the linker to search a
static libintl for undefined symbols without finding any; at worse
it causes a static build of plover using librazor.la to fail if
no static version of libintl is installed.
rhughes@241
     1
/*
rhughes@241
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
rhughes@241
     3
 * Copyright (C) 2008  Red Hat, Inc
ali@425
     4
 * Copyright (C) 2009, 2011, 2012  J. Ali Harlow <ali@juiblex.co.uk>
rhughes@241
     5
 *
rhughes@241
     6
 * This program is free software; you can redistribute it and/or modify
rhughes@241
     7
 * it under the terms of the GNU General Public License as published by
rhughes@241
     8
 * the Free Software Foundation; either version 2 of the License, or
rhughes@241
     9
 * (at your option) any later version.
rhughes@241
    10
 *
rhughes@241
    11
 * This program is distributed in the hope that it will be useful,
rhughes@241
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rhughes@241
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rhughes@241
    14
 * GNU General Public License for more details.
rhughes@241
    15
 *
rhughes@241
    16
 * You should have received a copy of the GNU General Public License along
rhughes@241
    17
 * with this program; if not, write to the Free Software Foundation, Inc.,
rhughes@241
    18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
rhughes@241
    19
 */
rhughes@241
    20
jbowes@276
    21
#include "config.h"
jbowes@276
    22
rhughes@241
    23
#include <stdlib.h>
rhughes@241
    24
#include <string.h>
rhughes@241
    25
#include <stdio.h>
krh@247
    26
#include <stdint.h>
rhughes@241
    27
#include <dirent.h>
rhughes@241
    28
#include "razor.h"
rhughes@241
    29
rhughes@241
    30
enum option_type {
rhughes@241
    31
	OPTION_LAST,
rhughes@241
    32
	OPTION_GROUP,
rhughes@241
    33
	OPTION_BOOL,
rhughes@241
    34
	OPTION_STRING
rhughes@241
    35
};
rhughes@241
    36
rhughes@241
    37
struct option {
rhughes@241
    38
	enum option_type type;
rhughes@241
    39
	const char *name;
rhughes@241
    40
	char short_name;
rhughes@241
    41
	const char *arg_name;
rhughes@241
    42
	const char *description;
rhughes@241
    43
	void *data;
rhughes@241
    44
};
rhughes@241
    45
rhughes@241
    46
/* A note about all these options: rpm allows options to mean
rhughes@241
    47
 * different things depending on what other options are present on the
rhughes@241
    48
 * command line.  For example, if -q or --query is present, -i no
rhughes@241
    49
 * longer means install, but info.  The way we handle this is by
rhughes@241
    50
 * setting all the options that may match (ie if -i is given we set
rhughes@241
    51
 * install and info), and then look at the relevent one depending on
rhughes@241
    52
 * what else in on the command line. */
rhughes@241
    53
jbowes@275
    54
static int option_all, option_list, option_whatrequires, option_whatprovides;
jbowes@277
    55
static int option_package, option_file;
rhughes@241
    56
rhughes@241
    57
static const struct option query_options[] = {
rhughes@241
    58
	{ OPTION_BOOL, "configfiles", 'c', NULL, "list all configuration files", NULL },
rhughes@241
    59
	{ OPTION_BOOL, "docfiles", 'd', NULL, "list all documentation files", NULL },
rhughes@241
    60
	{ OPTION_BOOL, "dump", 0, NULL, "dump basic file information", NULL },
jbowes@275
    61
	{ OPTION_BOOL, "list", 'l', NULL, "list files in package", &option_list },
rhughes@241
    62
	{ OPTION_STRING, "queryformat", 0, "QUERYFORMAT", "use the following query format", NULL },
rhughes@241
    63
	{ OPTION_BOOL, "state", 's', NULL, "display the states of the listed files", NULL },
rhughes@241
    64
	{ OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
jbowes@277
    65
	{ OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", &option_file },
rhughes@241
    66
	{ OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
rhughes@241
    67
	{ OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
rhughes@241
    68
	{ OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
rhughes@241
    69
	{ OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
rhughes@241
    70
	{ OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
rhughes@241
    71
	{ OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
rhughes@241
    72
	{ OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL, },
rhughes@241
    73
	{ OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
rhughes@241
    74
	{ OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
rhughes@241
    75
	{ OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
rhughes@241
    76
	{ OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
rhughes@241
    77
	{ }
rhughes@241
    78
};
rhughes@241
    79
rhughes@241
    80
static int option_nodeps;
rhughes@241
    81
rhughes@241
    82
static const struct option verify_options[] = {
rhughes@241
    83
	{ OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL },
rhughes@241
    84
	{ OPTION_BOOL, "nofiles", 0, NULL, "don't verify files in package", NULL },
rhughes@241
    85
	{ OPTION_BOOL, "nodeps", 0, NULL, "don't verify package dependencies", &option_nodeps },
rhughes@241
    86
	{ OPTION_BOOL, "noscript", 0, NULL, "don't execute verify script(s)", NULL, },
rhughes@241
    87
	{ OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
jbowes@277
    88
	{ OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", &option_file },
rhughes@241
    89
	{ OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
rhughes@241
    90
	{ OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
rhughes@241
    91
	{ OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
rhughes@241
    92
	{ OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
rhughes@241
    93
	{ OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
rhughes@241
    94
	{ OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
rhughes@241
    95
	{ OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL },
rhughes@241
    96
	{ OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
rhughes@241
    97
	{ OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
rhughes@241
    98
	{ OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
rhughes@241
    99
	{ OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
rhughes@241
   100
	{ }
rhughes@241
   101
};
rhughes@241
   102
rhughes@241
   103
static const struct option ftw_options[] = {
rhughes@241
   104
	{ OPTION_BOOL, "comfollow", 0, NULL, "FTS_COMFOLLOW: follow command line symlinks", NULL },
rhughes@241
   105
	{ OPTION_BOOL, "logical", 0, NULL, "FTS_LOGICAL: logical walk", NULL },
rhughes@241
   106
	{ OPTION_BOOL, "nochdir", 0, NULL, "FTS_NOCHDIR: don't change directories", NULL },
rhughes@241
   107
	{ OPTION_BOOL, "nostat", 0, NULL, "FTS_NOSTAT: don't get stat info", NULL },
rhughes@241
   108
	{ OPTION_BOOL, "physical", 0, NULL, "FTS_PHYSICAL: physical walk", NULL },
rhughes@241
   109
	{ OPTION_BOOL, "seedot", 0, NULL, "FTS_SEEDOT: return dot and dot-dot", NULL },
rhughes@241
   110
	{ OPTION_BOOL, "xdev", 0, NULL, "FTS_XDEV: don't cross devices", NULL },
rhughes@241
   111
	{ OPTION_BOOL, "whiteout", 0, NULL, "FTS_WHITEOUT: return whiteout information", NULL },
rhughes@241
   112
	{ }
rhughes@241
   113
};
rhughes@241
   114
rhughes@241
   115
static const struct option signature_options[] = {
rhughes@241
   116
	{ OPTION_BOOL, "addsign", 0, NULL, "sign package(s) (identical to --resign)", NULL, },
rhughes@241
   117
	{ OPTION_BOOL, "checksig", 'K', NULL, "verify package signature(s)", NULL, },
rhughes@241
   118
	{ OPTION_BOOL, "delsign", 0, NULL, "delete package signatures", NULL, },
rhughes@241
   119
	{ OPTION_BOOL, "import", 0, NULL, "import an armored public key", NULL, },
rhughes@241
   120
	{ OPTION_BOOL, "resign", 0, NULL, "sign package(s) (identical to --addsign)", NULL, },
rhughes@241
   121
	{ OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
rhughes@241
   122
	{ OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL },
rhughes@241
   123
	{ }
rhughes@241
   124
};
rhughes@241
   125
rhughes@241
   126
static int option_initdb;
rhughes@241
   127
rhughes@241
   128
static const struct option database_options[] = {
rhughes@241
   129
	{ OPTION_BOOL, "initdb", 0, NULL, "initialize database", &option_initdb },
rhughes@241
   130
	{ OPTION_BOOL, "rebuilddb", 0, NULL, "rebuild database inverted lists from installed package headers", NULL },
rhughes@241
   131
	{ }
rhughes@241
   132
};
rhughes@241
   133
rhughes@241
   134
static int option_erase, option_install, option_upgrade, option_justdb;
rhughes@241
   135
static int option_test;
rhughes@241
   136
rhughes@241
   137
static const struct option install_options[] = {
rhughes@241
   138
	{ OPTION_BOOL, "aid", 0, NULL, "add suggested packages to transaction", NULL, },
rhughes@241
   139
	{ OPTION_BOOL, "allfiles", 0, NULL, "install all files, even configurations which might otherwise be skipped", NULL, },
rhughes@241
   140
	{ OPTION_BOOL, "allmatches", 0, NULL, "remove all packages which match <package> (normally an error is generated if <package> specified multiple packages)", NULL, },
rhughes@241
   141
	{ OPTION_BOOL, "badreloc", 0, NULL, "relocate files in non-relocatable package", NULL },
rhughes@241
   142
	{ OPTION_BOOL, "erase", 'e', "<package>", "erase (uninstall) package", &option_erase },
rhughes@241
   143
	{ OPTION_BOOL, "excludedocs", 0, NULL, "do not install documentation", NULL, },
rhughes@241
   144
	{ OPTION_BOOL, "excludepath", 0, "<path>", "skip files with leading component <path> ", NULL, },
rhughes@241
   145
	{ OPTION_BOOL, "fileconflicts", 0, NULL, "detect file conflicts between packages", NULL, },
rhughes@241
   146
	{ OPTION_BOOL, "force", 0, NULL, "short hand for --replacepkgs --replacefiles", NULL },
rhughes@241
   147
	{ OPTION_BOOL, "freshen", 'F', "<packagefile>+", "upgrade package(s) if already installed", NULL },
rhughes@241
   148
	{ OPTION_BOOL, "hash", 'h', NULL, "print hash marks as package installs (good with -v)", NULL },
rhughes@241
   149
	{ OPTION_BOOL, "ignorearch", 0, NULL, "don't verify package architecture", NULL, },
rhughes@241
   150
	{ OPTION_BOOL, "ignoreos", 0, NULL, "don't verify package operating system", NULL, },
rhughes@241
   151
	{ OPTION_BOOL, "ignoresize", 0, NULL, "don't check disk space before installing", NULL },
rhughes@241
   152
	{ OPTION_BOOL, "install", 'i', NULL, "install package(s)", &option_install },
rhughes@241
   153
	{ OPTION_BOOL, "justdb", 0, NULL, "update the database, but do not modify the filesystem", &option_justdb, },
rhughes@241
   154
	{ OPTION_BOOL, "nodeps", 0, NULL, "do not verify package dependencies", &option_nodeps, },
rhughes@241
   155
	{ OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL, },
rhughes@241
   156
	{ OPTION_BOOL, "nocontexts", 0, NULL, "don't install file security contexts", NULL, },
rhughes@241
   157
	{ OPTION_BOOL, "noorder", 0, NULL, "do not reorder package installation to satisfy dependencies", NULL, },
rhughes@241
   158
	{ OPTION_BOOL, "nosuggest", 0, NULL, "do not suggest missing dependency resolution(s)", NULL, },
rhughes@241
   159
	{ OPTION_BOOL, "noscripts", 0, NULL, "do not execute package scriptlet(s)", NULL, },
rhughes@241
   160
	{ OPTION_BOOL, "notriggers", 0, NULL, "do not execute any scriptlet(s) triggered by this package", NULL, },
rhughes@241
   161
	{ OPTION_BOOL, "oldpackage", 0, NULL, "upgrade to an old version of the package (--force on upgrades does this automatically)", NULL },
rhughes@241
   162
	{ OPTION_BOOL, "percent", 0, NULL, "print percentages as package installs", NULL, },
rhughes@241
   163
	{ OPTION_STRING, "prefix", 0, "<dir>", "relocate the package to <dir>, if relocatable", NULL, },
rhughes@241
   164
	{ OPTION_STRING, "relocate", 0, "<old>=<new>", "relocate files from path <old> to <new>", NULL, },
rhughes@241
   165
	{ OPTION_BOOL, "repackage", 0, NULL, "save erased package files by repackaging", NULL, },
rhughes@241
   166
	{ OPTION_BOOL, "replacefiles", 0, NULL, "ignore file conflicts between packages", NULL, },
rhughes@241
   167
	{ OPTION_BOOL, "replacepkgs", 0, NULL, "reinstall if the package is already present", NULL, },
rhughes@241
   168
	{ OPTION_BOOL, "test", 0, NULL, "don't install, but tell if it would work or not", &option_test },
rhughes@241
   169
	{ OPTION_BOOL, "upgrade", 'U', "<packagefile>+", "upgrade package(s)", &option_upgrade },
rhughes@241
   170
	{ }
rhughes@241
   171
};
rhughes@241
   172
rhughes@241
   173
static int option_version;
rhughes@241
   174
static const char *option_root = "install";
rhughes@241
   175
rhughes@241
   176
static const struct option common_options[] = {
rhughes@241
   177
	{ OPTION_STRING, "define", 'D', "MACRO EXPR", "define MACRO with value EXPR", NULL, },
rhughes@241
   178
	{ OPTION_STRING, "eval", 'E', "EXPR", "print macro expansion of EXPR", NULL },
rhughes@241
   179
	{ OPTION_STRING, "macros", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
rhughes@241
   180
	{ OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
rhughes@241
   181
	{ OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL, },
rhughes@241
   182
	{ OPTION_STRING, "rcfile", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
rhughes@241
   183
	{ OPTION_STRING, "root", 'r', "ROOT", "use ROOT as top level directory (default: \"/\")", &option_root },
rhughes@241
   184
	{ OPTION_BOOL, "querytags", 0, NULL, "display known query tags", NULL, },
rhughes@241
   185
	{ OPTION_BOOL, "showrc", 0, NULL, "display final rpmrc and macro configuration", NULL, },
rhughes@241
   186
	{ OPTION_BOOL, "quiet", 0, NULL, "provide less detailed output", NULL },
rhughes@241
   187
	{ OPTION_BOOL, "verbose", 'v', NULL, "provide more detailed output", NULL },
rhughes@241
   188
	{ OPTION_BOOL, "version", 0, NULL, "print the version of rpm being used", &option_version },
rhughes@241
   189
	{ }
rhughes@241
   190
};
rhughes@241
   191
rhughes@241
   192
static int option_conflicts, option_obsoletes, option_requires;
rhughes@241
   193
static int option_provides, option_info, option_changelog;
rhughes@241
   194
rhughes@241
   195
static const struct option alias_options[] = {
rhughes@241
   196
	{ OPTION_BOOL, "scripts", 0, NULL, "list install/erase scriptlets from package(s)", NULL, },
rhughes@241
   197
	{ OPTION_BOOL, "setperms", 0, NULL, "set permissions of files in a package", NULL, },
rhughes@241
   198
	{ OPTION_BOOL, "setugids", 0, NULL, "set user/group ownership of files in a package", NULL, },
rhughes@241
   199
	{ OPTION_BOOL, "conflicts", 0, NULL, "list capabilities this package conflicts with", &option_conflicts, },
rhughes@241
   200
	{ OPTION_BOOL, "obsoletes", 0, NULL, "list other packages removed by installing this package", &option_obsoletes, },
rhughes@241
   201
	{ OPTION_BOOL, "provides", 0, NULL, "list capabilities that this package provides", &option_provides, },
jbowes@279
   202
	{ OPTION_BOOL, "requires", 'R', NULL, "list capabilities required by package(s)", &option_requires, },
rhughes@241
   203
	{ OPTION_BOOL, "info", 'i', NULL, "list descriptive information from package(s)", &option_info, },
rhughes@241
   204
	{ OPTION_BOOL, "changelog", 0, NULL, "list change logs for this package", &option_changelog, },
rhughes@241
   205
	{ OPTION_BOOL, "xml", 0, NULL, "list metadata in xml", NULL, },
rhughes@241
   206
	{ OPTION_BOOL, "triggers", 0, NULL, "list trigger scriptlets from package(s)", NULL, },
rhughes@241
   207
	{ OPTION_BOOL, "last", 0, NULL, "list package(s) by install time, most recent first", NULL, },
rhughes@241
   208
	{ OPTION_BOOL, "dupes", 0, NULL, "list duplicated packages", NULL, },
rhughes@241
   209
	{ OPTION_BOOL, "filesbypkg", 0, NULL, "list all files from each package", NULL, },
rhughes@241
   210
	{ OPTION_BOOL, "fileclass", 0, NULL, "list file names with classes", NULL, },
rhughes@241
   211
	{ OPTION_BOOL, "filecolor", 0, NULL, "list file names with colors", NULL, },
rhughes@241
   212
	{ OPTION_BOOL, "filecontext", 0, NULL, "list file names with security context from header", NULL, },
rhughes@241
   213
	{ OPTION_BOOL, "fscontext", 0, NULL, "list file names with security context from file system", NULL, },
rhughes@241
   214
	{ OPTION_BOOL, "recontext", 0, NULL, "list file names with security context from policy RE", NULL, },
rhughes@241
   215
	{ OPTION_BOOL, "fileprovide", 0, NULL, "list file names with provides", NULL, },
rhughes@241
   216
	{ OPTION_BOOL, "filerequire", 0, NULL, "list file names with requires", NULL, },
rhughes@241
   217
	{ OPTION_BOOL, "redhatprovides", 0, NULL, "find package name that contains a provided capability (needs rpmdb-redhat package installed)", NULL, },
rhughes@241
   218
	{ OPTION_BOOL, "redhatrequires", 0, NULL, "find package name that contains a required capability (needs rpmdb-redhat package installed)", NULL, },
rhughes@241
   219
	{ OPTION_STRING, "buildpolicy", 0, "<policy>", "set buildroot <policy> (e.g. compress man pages)", NULL, },
rhughes@241
   220
	{ OPTION_BOOL, "with", 0, "<option>", "enable configure <option> for build", NULL, },
rhughes@241
   221
	{ OPTION_BOOL, "without", 0, "<option>", "disable configure <option> for build", NULL },
rhughes@241
   222
	{ }
rhughes@241
   223
};
rhughes@241
   224
rhughes@241
   225
static int option_help, option_usage;
rhughes@241
   226
rhughes@241
   227
static const struct option help_options[] = {
rhughes@241
   228
	{ OPTION_BOOL, "help", '?', NULL, "Show this help message", &option_help },
rhughes@241
   229
	{ OPTION_BOOL, "usage", 0, NULL, "Display brief usage message", &option_usage},
rhughes@241
   230
	{ }
rhughes@241
   231
};
rhughes@241
   232
rhughes@241
   233
static int option_query, option_verify;
rhughes@241
   234
rhughes@241
   235
static const struct option rpm_options[] = {
rhughes@241
   236
	{ OPTION_BOOL, "query", 'q', NULL, "Query rpm database", &option_query },
rhughes@241
   237
	{ OPTION_BOOL, "verify", 'V', NULL, "Verify rpm database", &option_verify },
rhughes@241
   238
	{ OPTION_GROUP, NULL, 0, NULL, "Query options (with -q or --query):", &query_options },
rhughes@241
   239
	{ OPTION_GROUP, NULL, 0, NULL, "Verify options (with -V or --verify):", &verify_options },
rhughes@241
   240
	{ OPTION_GROUP, NULL, 0, NULL, "File tree walk options (with --ftswalk):", &ftw_options },
rhughes@241
   241
	{ OPTION_GROUP, NULL, 0, NULL, "Signature options:", &signature_options },
rhughes@241
   242
	{ OPTION_GROUP, NULL, 0, NULL, "Database options:", &database_options },
rhughes@241
   243
	{ OPTION_GROUP, NULL, 0, NULL, "Install/Upgrade/Erase options:", &install_options },
rhughes@241
   244
	{ OPTION_GROUP, NULL, 0, NULL, "Common options for all rpm modes and executables:", &common_options },
rhughes@241
   245
	{ OPTION_GROUP, NULL, 0, NULL, "Options implemented via popt alias/exec:", &alias_options },
rhughes@241
   246
	{ OPTION_GROUP, NULL, 0, NULL, "Help options", &help_options },
rhughes@241
   247
	{ }
rhughes@241
   248
};
rhughes@241
   249
richard@310
   250
static const char system_repo_filename[] = "system.rzdb";
rhughes@241
   251
static const char *repo_filename = system_repo_filename;
rhughes@241
   252
rhughes@241
   253
static void
rhughes@241
   254
command_initdb(int argc, const char *argv[])
rhughes@241
   255
{
ali@425
   256
	struct razor_error *error = NULL;
ali@425
   257
ali@425
   258
	if (razor_root_create(option_root, &error)) {
ali@425
   259
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@425
   260
		razor_error_free(error);
ali@425
   261
	} else
ali@425
   262
		printf("Created install root\n");
rhughes@241
   263
}
rhughes@241
   264
rhughes@241
   265
static struct razor_property *
rhughes@241
   266
add_property_packages(struct razor_set *set,
rhughes@241
   267
		      struct razor_package_query *query,
rhughes@241
   268
		      const char *ref_name,
rhughes@241
   269
		      const char *ref_version,
krh@247
   270
		      uint32_t ref_type)
rhughes@241
   271
{
rhughes@241
   272
	struct razor_property *property;
rhughes@241
   273
	struct razor_property_iterator *pi;
rhughes@241
   274
	struct razor_package_iterator *pkgi;
rhughes@241
   275
	const char *name, *version;
krh@247
   276
	uint32_t flags;
rhughes@241
   277
rhughes@241
   278
	pi = razor_property_iterator_create(set, NULL);
rhughes@241
   279
	while (razor_property_iterator_next(pi, &property, &name,
krh@247
   280
					    &flags, &version)) {
rhughes@241
   281
		if (strcmp(ref_name, name) != 0)
rhughes@241
   282
			continue;
krh@247
   283
		if (ref_version &&
krh@247
   284
		    (flags & RAZOR_PROPERTY_RELATION_MASK) == RAZOR_PROPERTY_EQUAL &&
rhughes@241
   285
		    strcmp(ref_version, version) != 0)
rhughes@241
   286
			continue;
krh@247
   287
		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != ref_type)
rhughes@241
   288
			continue;
rhughes@241
   289
rhughes@241
   290
		pkgi = razor_package_iterator_create_for_property(set,
rhughes@241
   291
								  property);
rhughes@241
   292
		razor_package_query_add_iterator(query, pkgi);
rhughes@241
   293
		razor_package_iterator_destroy(pkgi);
rhughes@241
   294
	}
rhughes@241
   295
	razor_property_iterator_destroy(pi);
rhughes@241
   296
rhughes@241
   297
	return property;
rhughes@241
   298
}
rhughes@241
   299
rhughes@241
   300
static int
rhughes@241
   301
strcmpp(const void *p1, const void *p2)
rhughes@241
   302
{
rhughes@241
   303
	return strcmp(*(char * const *) p1, *(char * const *) p2);
rhughes@241
   304
}
rhughes@241
   305
rhughes@241
   306
static void
rhughes@241
   307
add_command_line_packages(struct razor_set *set,
rhughes@241
   308
			  struct razor_package_query *query,
rhughes@241
   309
			  int argc, const char **argv)
rhughes@241
   310
{
rhughes@241
   311
	struct razor_package *package;
rhughes@241
   312
	struct razor_package_iterator *pi;
richard@302
   313
	const char *name;
rhughes@241
   314
	int i, cmp, errors;
rhughes@241
   315
rhughes@241
   316
	qsort(argv, argc, sizeof(*argv), strcmpp);
rhughes@241
   317
	i = 0;
rhughes@241
   318
	errors = 0;
rhughes@241
   319
rhughes@241
   320
	pi = razor_package_iterator_create(set);
rhughes@241
   321
rhughes@241
   322
	while (razor_package_iterator_next(pi, &package,
richard@307
   323
					   RAZOR_DETAIL_NAME, &name,
richard@307
   324
					   RAZOR_DETAIL_LAST)) {
rhughes@241
   325
		while (cmp = strcmp(argv[i], name), cmp < 0 && i < argc) {
rhughes@241
   326
			fprintf(stderr, "error: package %s is not installed\n",
rhughes@241
   327
				argv[i]);
rhughes@241
   328
			errors++;
rhughes@241
   329
			i++;
rhughes@241
   330
		}
rhughes@241
   331
rhughes@241
   332
		if (cmp == 0) {
rhughes@241
   333
			razor_package_query_add_package(query, package);
rhughes@241
   334
			i++;
rhughes@241
   335
		}
rhughes@241
   336
	}
rhughes@241
   337
rhughes@241
   338
	razor_package_iterator_destroy(pi);
rhughes@241
   339
rhughes@241
   340
	if (errors)
rhughes@241
   341
		exit(1);
rhughes@241
   342
}
rhughes@241
   343
rhughes@241
   344
static struct razor_package_iterator *
rhughes@241
   345
get_query_packages(struct razor_set *set, int argc, const char *argv[])
rhughes@241
   346
{
rhughes@241
   347
	struct razor_package_query *query;
rhughes@241
   348
	struct razor_package_iterator *pi;
rhughes@241
   349
	int i;
rhughes@241
   350
jbowes@277
   351
	if (option_all + option_whatprovides + option_whatrequires +
jbowes@277
   352
	    option_file > 1) {
rhughes@241
   353
		printf("only one type of query/verify "
rhughes@241
   354
		       "may be performed at a time\n");
rhughes@241
   355
		exit(1);
rhughes@241
   356
	}
rhughes@241
   357
rhughes@241
   358
	query = razor_package_query_create(set);
rhughes@241
   359
rhughes@241
   360
	if (option_all) {
rhughes@241
   361
		pi = razor_package_iterator_create(set);
rhughes@241
   362
		razor_package_query_add_iterator(query, pi);
rhughes@241
   363
		razor_package_iterator_destroy(pi);
rhughes@241
   364
	} else if (option_whatrequires) {
rhughes@241
   365
		for (i = 0; i < argc; i++)
rhughes@241
   366
			add_property_packages(set, query,
rhughes@241
   367
					      argv[i], NULL,
rhughes@241
   368
					      RAZOR_PROPERTY_REQUIRES);
rhughes@241
   369
	} else if (option_whatprovides) {
rhughes@241
   370
		for (i = 0; i < argc; i++)
rhughes@241
   371
			add_property_packages(set, query,
rhughes@241
   372
					      argv[i], NULL,
rhughes@241
   373
					      RAZOR_PROPERTY_PROVIDES);
jbowes@277
   374
	} else if (option_file) {
jbowes@277
   375
		for (i = 0; i < argc; i++) {
jbowes@277
   376
			pi = razor_package_iterator_create_for_file(set,
jbowes@277
   377
								    argv[i]);
jbowes@277
   378
			razor_package_query_add_iterator(query, pi);
jbowes@277
   379
			razor_package_iterator_destroy(pi);
jbowes@277
   380
		}
rhughes@241
   381
	} else if (argc > 0) {
rhughes@241
   382
		add_command_line_packages(set, query, argc, argv);
rhughes@241
   383
	} else {
rhughes@241
   384
		printf("no arguments given for query/verify\n");
rhughes@241
   385
		exit(1);
rhughes@241
   386
	}
rhughes@241
   387
rhughes@241
   388
	return razor_package_query_finish(query);
rhughes@241
   389
}
rhughes@241
   390
rhughes@241
   391
static void
rhughes@241
   392
print_package_properties(struct razor_set *set,
rhughes@241
   393
			 struct razor_package *package,
krh@247
   394
			 uint32_t ref_type)
rhughes@241
   395
{
rhughes@241
   396
	struct razor_property *property;
rhughes@241
   397
	struct razor_property_iterator *pi;
rhughes@241
   398
	const char *name, *version;
krh@247
   399
	uint32_t flags;
rhughes@241
   400
rhughes@241
   401
	pi = razor_property_iterator_create(set, package);
rhughes@241
   402
	while (razor_property_iterator_next(pi, &property,
krh@247
   403
					    &name, &flags, &version)) {
krh@247
   404
		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != ref_type)
rhughes@241
   405
			continue;
rhughes@241
   406
		if (version[0] == '\0')
rhughes@241
   407
			printf("%s\n", name);
rhughes@241
   408
		else
rhughes@241
   409
			printf("%s %s %s\n", name,
krh@247
   410
			       razor_property_relation_to_string(property),
krh@247
   411
			       version);
rhughes@241
   412
	}
rhughes@241
   413
	razor_property_iterator_destroy(pi);
rhughes@241
   414
}
rhughes@241
   415
rhughes@241
   416
static void
krh@266
   417
print_package_info(struct razor_set *set, struct razor_package *package,
krh@266
   418
		   const char *name, const char *version, const char *arch)
rhughes@241
   419
{
krh@266
   420
	const char *summary, *description, *url, *license;
krh@266
   421
richard@302
   422
	razor_package_get_details (set, package,
richard@302
   423
				   RAZOR_DETAIL_SUMMARY, &summary,
richard@302
   424
				   RAZOR_DETAIL_DESCRIPTION, &description,
richard@302
   425
				   RAZOR_DETAIL_URL, &url,
richard@302
   426
				   RAZOR_DETAIL_LICENSE, &license,
richard@307
   427
				   RAZOR_DETAIL_LAST);
krh@266
   428
krh@266
   429
	printf("Name:        %s\n", name);
krh@266
   430
	printf("Arch:        %s\n", arch);
krh@266
   431
	printf("Version:     %s\n", version);
krh@266
   432
	printf("URL:         %s\n", url);
krh@266
   433
	printf("License:     %s\n", license);
krh@266
   434
	printf("Summary:     %s\n", summary);
krh@266
   435
	printf("Description:\n");
krh@266
   436
	printf("%s\n", description);
krh@266
   437
	printf("\n");
rhughes@241
   438
}
rhughes@241
   439
rhughes@241
   440
static void
rhughes@241
   441
print_package_changelog(struct razor_set *set, struct razor_package *package)
rhughes@241
   442
{
rhughes@241
   443
	printf("FIXME: Package changelog not tracked.\n");
rhughes@241
   444
}
rhughes@241
   445
rhughes@241
   446
static struct razor_set *
rhughes@241
   447
create_set_from_command_line(int argc, const char *argv[])
rhughes@241
   448
{
rhughes@241
   449
	struct razor_importer *importer;
rhughes@241
   450
	struct razor_rpm *rpm;
rhughes@241
   451
	int i;
rhughes@241
   452
krh@249
   453
	importer = razor_importer_create();
rhughes@241
   454
rhughes@241
   455
	for (i = 0; i < argc; i++) {
ali@426
   456
		rpm = razor_rpm_open(argv[i], NULL);
rhughes@241
   457
		if (rpm == NULL)
rhughes@241
   458
			continue;
rhughes@241
   459
		if (razor_importer_add_rpm(importer, rpm))
rhughes@241
   460
			printf("couldn't import %s\n", argv[i]);
rhughes@241
   461
rhughes@241
   462
		razor_rpm_close(rpm);
rhughes@241
   463
	}
rhughes@241
   464
rhughes@241
   465
	return razor_importer_finish(importer);
rhughes@241
   466
}
rhughes@241
   467
rhughes@241
   468
static void
rhughes@241
   469
command_query(int argc, const char *argv[])
rhughes@241
   470
{
ali@424
   471
	struct razor_error *error = NULL;
rhughes@241
   472
	struct razor_set *set;
rhughes@241
   473
	struct razor_package_iterator *pi;
rhughes@241
   474
	struct razor_package *package;
krh@373
   475
	const char *name, *version, *arch;
rhughes@241
   476
rhughes@241
   477
	if (option_package) {
rhughes@241
   478
		set = create_set_from_command_line(argc, argv);
rhughes@241
   479
		argc = 0;
rhughes@241
   480
		option_all = 1;
rhughes@241
   481
	} else {
ali@424
   482
		set = razor_root_open_read_only(option_root, &error);
ali@403
   483
		if (!set) {
ali@424
   484
			fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   485
			razor_error_free(error);
ali@403
   486
			return;
ali@403
   487
		}
rhughes@241
   488
	}
rhughes@241
   489
rhughes@241
   490
	pi = get_query_packages(set, argc, argv);
rhughes@241
   491
rhughes@241
   492
	while (razor_package_iterator_next(pi, &package,
richard@302
   493
					   RAZOR_DETAIL_NAME, &name,
richard@302
   494
					   RAZOR_DETAIL_VERSION, &version,
richard@307
   495
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
   496
					   RAZOR_DETAIL_LAST)) {
rhughes@241
   497
		if (option_conflicts)
rhughes@241
   498
			print_package_properties(set, package,
rhughes@241
   499
						 RAZOR_PROPERTY_CONFLICTS);
rhughes@241
   500
		if (option_obsoletes)
rhughes@241
   501
			print_package_properties(set, package,
rhughes@241
   502
						 RAZOR_PROPERTY_OBSOLETES);
rhughes@241
   503
		if (option_requires)
rhughes@241
   504
			print_package_properties(set, package,
rhughes@241
   505
						 RAZOR_PROPERTY_REQUIRES);
rhughes@241
   506
		if (option_provides)
rhughes@241
   507
			print_package_properties(set, package,
rhughes@241
   508
						 RAZOR_PROPERTY_PROVIDES);
rhughes@241
   509
		if (option_info)
krh@266
   510
			print_package_info(set, package, name, version, arch);
rhughes@241
   511
		if (option_changelog)
rhughes@241
   512
			print_package_changelog(set, package);
jbowes@275
   513
		if (option_list)
krh@306
   514
			razor_set_list_package_files(set, package);
rhughes@241
   515
rhughes@241
   516
		if (option_conflicts + option_obsoletes +
rhughes@241
   517
		    option_requires + option_provides +
jbowes@275
   518
		    option_info + option_changelog + option_list == 0)
rhughes@241
   519
			printf("%s-%s.%s\n", name, version, arch);
rhughes@241
   520
	}
rhughes@241
   521
rhughes@241
   522
	razor_package_iterator_destroy(pi);
rhughes@241
   523
ali@403
   524
	razor_set_unref(set);
rhughes@241
   525
}
rhughes@241
   526
rhughes@241
   527
static void
rhughes@241
   528
command_verify(int argc, const char *argv[])
rhughes@241
   529
{
ali@424
   530
	struct razor_error *error = NULL;
rhughes@241
   531
	struct razor_set *set;
rhughes@241
   532
	struct razor_package_iterator *pi;
rhughes@241
   533
	struct razor_package *package;
rhughes@241
   534
	const char *name, *version, *arch;
rhughes@241
   535
rhughes@241
   536
	if (option_package) {
rhughes@241
   537
		set = create_set_from_command_line(argc, argv);
rhughes@241
   538
		argc = 0;
rhughes@241
   539
		option_all = 1;
rhughes@241
   540
	} else {
ali@424
   541
		set = razor_root_open_read_only(option_root, &error);
ali@403
   542
		if (!set) {
ali@424
   543
			fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   544
			razor_error_free(error);
ali@403
   545
			return;
ali@403
   546
		}
rhughes@241
   547
	}
rhughes@241
   548
rhughes@241
   549
	pi = get_query_packages(set, argc, argv);
rhughes@241
   550
rhughes@241
   551
	while (razor_package_iterator_next(pi, &package,
richard@302
   552
					   RAZOR_DETAIL_NAME, &name,
richard@302
   553
					   RAZOR_DETAIL_VERSION, &version,
richard@307
   554
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
   555
					   RAZOR_DETAIL_LAST)) {
rhughes@241
   556
		printf("verify %s-%s.%s - not implemented\n",
rhughes@241
   557
		       name, version, arch);
rhughes@241
   558
	}
rhughes@241
   559
rhughes@241
   560
	razor_package_iterator_destroy(pi);
rhughes@241
   561
}
rhughes@241
   562
rhughes@241
   563
static void
krh@253
   564
update_package(enum razor_diff_action action,
krh@253
   565
	       struct razor_package *package,
krh@253
   566
	       const char *name,
krh@253
   567
	       const char *version,
krh@253
   568
	       const char *arch,
krh@253
   569
	       void *data)
rhughes@241
   570
{
krh@253
   571
	if (action == RAZOR_DIFF_ACTION_ADD)
krh@253
   572
		printf("install %s-%s.%s\n", name, version, arch);
krh@253
   573
	if (action == RAZOR_DIFF_ACTION_REMOVE)
krh@253
   574
		printf("remove %s-%s.%s\n", name, version, arch);
rhughes@241
   575
}
rhughes@241
   576
rhughes@241
   577
static void
rhughes@241
   578
command_erase(int argc, const char *argv[])
rhughes@241
   579
{
ali@424
   580
	struct razor_error *error = NULL;
rhughes@241
   581
	struct razor_set *set, *upstream, *next;
rhughes@241
   582
	struct razor_transaction *trans;
rhughes@241
   583
	struct razor_package_query *query;
rhughes@241
   584
	struct razor_package_iterator *pi;
rhughes@241
   585
	struct razor_package *package;
rhughes@241
   586
rhughes@241
   587
	if (argc == 0) {
rhughes@241
   588
		printf("no packages given for erase\n");
rhughes@241
   589
		exit(1);
rhughes@241
   590
	}
rhughes@241
   591
ali@424
   592
	set = razor_set_open(repo_filename, RAZOR_SET_PRIVATE, &error);
ali@424
   593
	if (!set) {
ali@424
   594
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   595
		razor_error_free(error);
ali@403
   596
		exit(1);
ali@403
   597
	}
rhughes@241
   598
	upstream = razor_set_create();
rhughes@241
   599
rhughes@241
   600
	trans = razor_transaction_create(set, upstream);
rhughes@241
   601
rhughes@241
   602
	query = razor_package_query_create(set);
rhughes@241
   603
	add_command_line_packages(set, query, argc, argv);
rhughes@241
   604
rhughes@241
   605
	pi = razor_package_query_finish(query);
richard@307
   606
	while (razor_package_iterator_next(pi, &package, RAZOR_DETAIL_LAST))
rhughes@241
   607
		razor_transaction_remove_package(trans, package);
rhughes@241
   608
	razor_package_iterator_destroy(pi);
rhughes@241
   609
rhughes@241
   610
	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
rhughes@241
   611
		printf("unsatisfied dependencies.\n");
ali@369
   612
		razor_transaction_destroy(trans);
rhughes@241
   613
		exit(1);
rhughes@241
   614
	}
rhughes@241
   615
ali@369
   616
	if (option_test) {
ali@369
   617
		razor_transaction_destroy(trans);
rhughes@241
   618
		exit(0);
ali@369
   619
	}
rhughes@241
   620
ali@369
   621
	next = razor_transaction_commit(trans);
rhughes@241
   622
rhughes@241
   623
	if (!option_justdb)
krh@253
   624
		razor_set_diff(set, next, update_package, NULL);
rhughes@241
   625
ali@369
   626
	razor_transaction_destroy(trans);
ali@403
   627
	razor_set_unref(set);
ali@403
   628
	razor_set_unref(upstream);
rhughes@241
   629
ali@403
   630
	razor_set_unref(next);
rhughes@241
   631
}
rhughes@241
   632
rhughes@241
   633
static void
rhughes@241
   634
command_install(int argc, const char *argv[])
rhughes@241
   635
{
ali@424
   636
	struct razor_error *error = NULL;
rhughes@241
   637
	struct razor_set *set, *upstream, *next;
rhughes@241
   638
	struct razor_transaction *trans;
rhughes@241
   639
	struct razor_package_iterator *pi;
rhughes@241
   640
	struct razor_package *package;
rhughes@241
   641
rhughes@241
   642
	if (argc == 0) {
rhughes@241
   643
		printf("no packages given for install\n");
rhughes@241
   644
		exit(1);
rhughes@241
   645
	}
rhughes@241
   646
ali@424
   647
	set = razor_set_open(repo_filename, RAZOR_SET_PRIVATE, &error);
ali@424
   648
	if (!set) {
ali@424
   649
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   650
		razor_error_free(error);
ali@403
   651
	}
rhughes@241
   652
	upstream = create_set_from_command_line(argc, argv);
rhughes@241
   653
rhughes@241
   654
	trans = razor_transaction_create(set, upstream);
rhughes@241
   655
rhughes@241
   656
	pi = razor_package_iterator_create(upstream);
richard@307
   657
	while (razor_package_iterator_next(pi, &package, RAZOR_DETAIL_LAST))
rhughes@241
   658
		razor_transaction_install_package(trans, package);
rhughes@241
   659
	razor_package_iterator_destroy(pi);
rhughes@241
   660
rhughes@241
   661
	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
rhughes@241
   662
		printf("unsatisfied dependencies.\n");
ali@369
   663
		razor_transaction_destroy(trans);
rhughes@241
   664
		exit(1);
rhughes@241
   665
	}
rhughes@241
   666
ali@369
   667
	if (option_test) {
ali@369
   668
		razor_transaction_destroy(trans);
rhughes@241
   669
		exit(0);
ali@369
   670
	}
rhughes@241
   671
ali@369
   672
	next = razor_transaction_commit(trans);
rhughes@241
   673
rhughes@241
   674
	if (!option_justdb)
krh@253
   675
		razor_set_diff(set, next, update_package, NULL);
rhughes@241
   676
ali@369
   677
	razor_transaction_destroy(trans);
ali@403
   678
	razor_set_unref(set);
ali@403
   679
	razor_set_unref(upstream);
rhughes@241
   680
ali@403
   681
	razor_set_unref(next);
rhughes@241
   682
}
rhughes@241
   683
rhughes@241
   684
static void
rhughes@241
   685
command_update(int argc, const char *argv[])
rhughes@241
   686
{
ali@424
   687
	struct razor_error *error = NULL;
rhughes@241
   688
	struct razor_set *set, *upstream, *next;
rhughes@241
   689
	struct razor_transaction *trans;
rhughes@241
   690
	struct razor_package_iterator *pi;
rhughes@241
   691
	struct razor_package *package;
rhughes@241
   692
rhughes@241
   693
	if (argc == 0) {
rhughes@241
   694
		printf("no packages given for update\n");
rhughes@241
   695
		exit(1);
rhughes@241
   696
	}
rhughes@241
   697
ali@424
   698
	set = razor_set_open(repo_filename, RAZOR_SET_PRIVATE, &error);
ali@424
   699
	if (!set) {
ali@424
   700
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   701
		razor_error_free(error);
ali@403
   702
	}
rhughes@241
   703
	upstream = create_set_from_command_line(argc, argv);
rhughes@241
   704
rhughes@241
   705
	trans = razor_transaction_create(set, upstream);
rhughes@241
   706
rhughes@241
   707
	pi = razor_package_iterator_create(upstream);
richard@307
   708
	while (razor_package_iterator_next(pi, &package, RAZOR_DETAIL_LAST))
rhughes@241
   709
		razor_transaction_update_package(trans, package);
rhughes@241
   710
	razor_package_iterator_destroy(pi);
rhughes@241
   711
rhughes@241
   712
	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
rhughes@241
   713
		printf("unsatisfied dependencies.\n");
ali@369
   714
		razor_transaction_destroy(trans);
rhughes@241
   715
		exit(1);
rhughes@241
   716
	}
rhughes@241
   717
ali@369
   718
	if (option_test) {
ali@369
   719
		razor_transaction_destroy(trans);
rhughes@241
   720
		exit(0);
ali@369
   721
	}
rhughes@241
   722
ali@369
   723
	next = razor_transaction_commit(trans);
rhughes@241
   724
rhughes@241
   725
	if (!option_justdb)
rhughes@241
   726
		razor_set_diff(set, next, update_package, NULL);
rhughes@241
   727
ali@369
   728
	razor_transaction_destroy(trans);
ali@403
   729
	razor_set_unref(set);
ali@403
   730
	razor_set_unref(upstream);
rhughes@241
   731
ali@403
   732
	razor_set_unref(next);
rhughes@241
   733
}
rhughes@241
   734
rhughes@241
   735
static int
rhughes@241
   736
for_each_option(const struct option *options,
rhughes@241
   737
		const char *name, char short_name,
rhughes@241
   738
		void (*fn)(const struct option *o,
rhughes@241
   739
			   const char *name, char short_name,
rhughes@241
   740
			   void *data), void *data)
rhughes@241
   741
{
rhughes@241
   742
	int i, count = 0;
rhughes@241
   743
rhughes@241
   744
	for (i = 0; options[i].type != OPTION_LAST; i++) {
rhughes@241
   745
		switch (options[i].type) {
rhughes@241
   746
		case OPTION_GROUP:
rhughes@241
   747
			count += for_each_option(options[i].data,
rhughes@241
   748
						 name, short_name, fn, data);
rhughes@241
   749
			break;
rhughes@241
   750
rhughes@241
   751
		case OPTION_BOOL:
rhughes@241
   752
		case OPTION_STRING:
rhughes@241
   753
			if (name && strcmp(options[i].name, name) == 0) {
rhughes@241
   754
				fn(&options[i], name, 0, data);
rhughes@241
   755
				count++;
rhughes@241
   756
				break;
rhughes@241
   757
			}
rhughes@241
   758
rhughes@241
   759
			if (short_name &&
rhughes@241
   760
			    short_name == options[i].short_name) {
rhughes@241
   761
				fn(&options[i], NULL, short_name, data);
rhughes@241
   762
				count++;
rhughes@241
   763
				break;
rhughes@241
   764
			}
rhughes@241
   765
			break;
rhughes@241
   766
rhughes@241
   767
		case OPTION_LAST:
rhughes@241
   768
			break;
rhughes@241
   769
		}
rhughes@241
   770
	}
rhughes@241
   771
rhughes@241
   772
	return count;
rhughes@241
   773
}
rhughes@241
   774
rhughes@241
   775
static void
rhughes@241
   776
handle_option(const struct option *o,
rhughes@241
   777
	      const char *name, char short_name, void *data)
rhughes@241
   778
{
rhughes@241
   779
	if (o->data == NULL) {
rhughes@241
   780
		if (name)
rhughes@241
   781
			printf("option --%s not supported\n", name);
rhughes@241
   782
		else
rhughes@241
   783
			printf("option -%c not supported\n", short_name);
rhughes@241
   784
		return;
rhughes@241
   785
	}
rhughes@241
   786
rhughes@241
   787
	switch (o->type) {
rhughes@241
   788
	case OPTION_BOOL:
rhughes@241
   789
		*(int *) o->data = 1;
rhughes@241
   790
		break;
rhughes@241
   791
rhughes@241
   792
	case OPTION_STRING:
rhughes@241
   793
		*(const char **) o->data = name + strlen(o->name) + 1;
rhughes@241
   794
		break;
rhughes@241
   795
rhughes@241
   796
	case OPTION_LAST:
rhughes@241
   797
	case OPTION_GROUP:
rhughes@241
   798
		/* Shouldn't happen. */
rhughes@241
   799
		break;
rhughes@241
   800
	}
rhughes@241
   801
}
rhughes@241
   802
rhughes@241
   803
static int
rhughes@241
   804
parse_options(const struct option *options, int argc, const char **argv)
rhughes@241
   805
{
rhughes@241
   806
	int i, j, k;
rhughes@241
   807
rhughes@241
   808
	for (i = 1, j = 0; i < argc; i++) {
rhughes@241
   809
		if (argv[i][0] != '-') {
rhughes@241
   810
			argv[j++] = argv[i];
rhughes@241
   811
			continue;
rhughes@241
   812
		}
rhughes@241
   813
rhughes@241
   814
		if (argv[i][1] == '-') {
rhughes@241
   815
			if (for_each_option(options, &argv[i][2], 0,
rhughes@241
   816
					    handle_option, NULL) == 0) {
rhughes@241
   817
				printf("unknown option: %s\n", argv[i]);
rhughes@241
   818
				exit(1);
rhughes@241
   819
			}
rhughes@241
   820
			continue;
rhughes@241
   821
		}
rhughes@241
   822
rhughes@241
   823
		for (k = 1; argv[i][k]; k++) {
rhughes@241
   824
			if (for_each_option(options, NULL, argv[i][k],
rhughes@241
   825
					    handle_option, NULL) == 0) {
rhughes@241
   826
				printf("unknown option: -%c\n", argv[i][k]);
rhughes@241
   827
				exit(1);
rhughes@241
   828
			}
rhughes@241
   829
		}
rhughes@241
   830
	}
rhughes@241
   831
rhughes@241
   832
	return j;
rhughes@241
   833
}
rhughes@241
   834
rhughes@241
   835
static void
rhughes@241
   836
print_options_help(const struct option *options)
rhughes@241
   837
{
rhughes@241
   838
	int i;
rhughes@241
   839
rhughes@241
   840
	for (i = 0; options[i].type != OPTION_LAST; i++) {
rhughes@241
   841
		switch (options[i].type) {
rhughes@241
   842
		case OPTION_GROUP:
rhughes@241
   843
			printf("%s\n", options[i].description);
rhughes@241
   844
			print_options_help(options[i].data);
rhughes@241
   845
			printf("\n");
rhughes@241
   846
			break;
rhughes@241
   847
rhughes@241
   848
		case OPTION_BOOL:
rhughes@241
   849
		case OPTION_STRING:
rhughes@241
   850
			printf("  ");
rhughes@241
   851
			if (options[i].short_name)
rhughes@241
   852
				printf("-%c", options[i].short_name);
rhughes@241
   853
			if (options[i].short_name && options[i].name)
rhughes@241
   854
				printf(", ");
rhughes@241
   855
			if (options[i].name)
rhughes@241
   856
				printf("--%s", options[i].name);
rhughes@241
   857
			if (options[i].arg_name)
rhughes@241
   858
				printf("=%s", options[i].arg_name);
rhughes@241
   859
			if (options[i].description)
rhughes@241
   860
				printf("\t\t%s", options[i].description);
rhughes@241
   861
			printf("\n");
rhughes@241
   862
			break;
rhughes@241
   863
rhughes@241
   864
		case OPTION_LAST:
rhughes@241
   865
			break;
rhughes@241
   866
		}
rhughes@241
   867
	}
rhughes@241
   868
}
rhughes@241
   869
rhughes@241
   870
static void
rhughes@241
   871
print_options_usage(const struct option *options)
rhughes@241
   872
{
rhughes@241
   873
	int i;
rhughes@241
   874
rhughes@241
   875
	for (i = 0; options[i].type != OPTION_LAST; i++) {
rhughes@241
   876
		switch (options[i].type) {
rhughes@241
   877
		case OPTION_GROUP:
rhughes@241
   878
			print_options_usage(options[i].data);
rhughes@241
   879
			break;
rhughes@241
   880
rhughes@241
   881
		case OPTION_BOOL:
rhughes@241
   882
			printf("[");
rhughes@241
   883
			if (options[i].short_name)
rhughes@241
   884
				printf("-%c", options[i].short_name);
rhughes@241
   885
			if (options[i].short_name && options[i].name)
rhughes@241
   886
				printf("|");
rhughes@241
   887
			if (options[i].name)
rhughes@241
   888
				printf("--%s", options[i].name);
rhughes@241
   889
			printf("] ");
rhughes@241
   890
			break;
rhughes@241
   891
rhughes@241
   892
		case OPTION_STRING:
rhughes@241
   893
			printf("[");
rhughes@241
   894
			if (options[i].short_name)
rhughes@241
   895
				printf("-%c", options[i].short_name);
rhughes@241
   896
			if (options[i].short_name && options[i].name)
rhughes@241
   897
				printf("|");
rhughes@241
   898
			if (options[i].name)
rhughes@241
   899
				printf("--%s", options[i].name);
rhughes@241
   900
			if (options[i].arg_name)
rhughes@241
   901
				printf("=%s", options[i].arg_name);
rhughes@241
   902
			printf("] ");
rhughes@241
   903
			break;
rhughes@241
   904
rhughes@241
   905
rhughes@241
   906
			break;
rhughes@241
   907
rhughes@241
   908
		case OPTION_LAST:
rhughes@241
   909
			break;
rhughes@241
   910
		}
rhughes@241
   911
	}
rhughes@241
   912
}
rhughes@241
   913
rhughes@241
   914
int
rhughes@241
   915
main(int argc, const char *argv[])
rhughes@241
   916
{
rhughes@241
   917
	argc = parse_options(rpm_options, argc, argv);
rhughes@241
   918
rhughes@241
   919
	if (option_version) {
jbowes@276
   920
		printf("razor rpm version " VERSION "\n");
rhughes@241
   921
		exit(0);
rhughes@241
   922
	}
rhughes@241
   923
rhughes@241
   924
	if (option_help) {
rhughes@241
   925
		printf("Usage: rpm [OPTION...]\n");
rhughes@241
   926
		print_options_help(rpm_options);
rhughes@241
   927
		exit(0);
rhughes@241
   928
	}
rhughes@241
   929
rhughes@241
   930
	if (option_usage) {
rhughes@241
   931
		printf("Usage: rpm [OPTION...]\n");
rhughes@241
   932
		print_options_usage(rpm_options);
rhughes@241
   933
		printf("\n");
rhughes@241
   934
		exit(0);
rhughes@241
   935
	}
rhughes@241
   936
rhughes@241
   937
	if (option_initdb) {
rhughes@241
   938
		command_initdb(argc, argv);
rhughes@241
   939
	} else if (option_verify) {
rhughes@241
   940
		command_verify(argc, argv);
rhughes@241
   941
	} else if (option_query) {
rhughes@241
   942
		command_query(argc, argv);
rhughes@241
   943
	} else if (option_install) {
rhughes@241
   944
		command_install(argc, argv);
rhughes@241
   945
	} else if (option_upgrade) {
rhughes@241
   946
		command_update(argc, argv);
rhughes@241
   947
	} else if (option_erase) {
rhughes@241
   948
		command_erase(argc, argv);
rhughes@241
   949
	} else {
rhughes@241
   950
		print_options_usage(rpm_options);
rhughes@241
   951
		printf("\n");
rhughes@241
   952
		exit(0);
rhughes@241
   953
	}
rhughes@241
   954
rhughes@241
   955
	return 0;
rhughes@241
   956
}