src/rpm.c
author Kristian H?gsberg <krh@redhat.com>
Fri Jun 20 21:56:43 2008 -0400 (2008-06-20)
changeset 254 ccb1c11968ab
parent 249 061a5b815727
child 266 9b652c3617d9
permissions -rw-r--r--
Introduce install/remove iterators.

These iterator constructors lets you pass in two sets and creates
an iterator for the packages to remove or the packages to install.
The iterators will step through the packages in a sequence that respects
the pre, post, preun and postun modifiers.

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