- default to dbenv with mpool, --rebuilddb with nofsync is much faster.
[tools/librpm-tizen.git] / rpmqv.c
1 #include "system.h"
2
3 #define _AUTOHELP
4
5 #if defined(IAM_RPM) || defined(__LCLINT__)
6 #define IAM_RPMBT
7 #define IAM_RPMDB
8 #define IAM_RPMEIU
9 #define IAM_RPMQV
10 #define IAM_RPMK
11 #endif
12
13 #include <rpmbuild.h>
14 #include <rpmurl.h>
15
16 #ifdef  IAM_RPMBT
17 #include "build.h"
18 #define GETOPT_REBUILD          1003
19 #define GETOPT_RECOMPILE        1004
20 #endif
21
22 #ifdef  IAM_RPMDB
23 #define GETOPT_REBUILDDB        1013
24 #define GETOPT_VERIFYDB         1023
25 static int initdb = 0;
26 #endif
27
28 #ifdef  IAM_RPMEIU
29 #define GETOPT_INSTALL          1014
30 #define GETOPT_RELOCATE         1016
31 #define GETOPT_EXCLUDEPATH      1019
32 static int incldocs = 0;
33 /*@null@*/ static const char * prefix = NULL;
34 #endif  /* IAM_RPMEIU */
35
36 #ifdef  IAM_RPMK
37 #define GETOPT_ADDSIGN          1005
38 #define GETOPT_RESIGN           1006
39 static int noGpg = 0;
40 static int noPgp = 0;
41 #endif  /* IAM_RPMK */
42
43 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
44 #include "signature.h"
45 #endif
46
47 #include "debug.h"
48
49 #define GETOPT_DBPATH           1010
50 #define GETOPT_SHOWRC           1018
51 #define GETOPT_DEFINEMACRO      1020
52 #define GETOPT_EVALMACRO        1021
53 #ifdef  NOTYET
54 #define GETOPT_RCFILE           1022
55 #endif
56
57 enum modes {
58
59     MODE_QUERY          = (1 <<  0),
60     MODE_VERIFY         = (1 <<  3),
61     MODE_QUERYTAGS      = (1 <<  9),
62 #define MODES_QV (MODE_QUERY | MODE_VERIFY)
63
64     MODE_INSTALL        = (1 <<  1),
65     MODE_UNINSTALL      = (1 <<  2),
66 #define MODES_IE (MODE_INSTALL | MODE_UNINSTALL)
67
68     MODE_BUILD          = (1 <<  4),
69     MODE_REBUILD        = (1 <<  5),
70     MODE_RECOMPILE      = (1 <<  8),
71     MODE_TARBUILD       = (1 << 11),
72 #define MODES_BT (MODE_BUILD | MODE_TARBUILD | MODE_REBUILD | MODE_RECOMPILE)
73
74     MODE_CHECKSIG       = (1 <<  6),
75     MODE_RESIGN         = (1 <<  7),
76 #define MODES_K  (MODE_CHECKSIG | MODES_RESIGN)
77
78     MODE_INITDB         = (1 << 10),
79     MODE_REBUILDDB      = (1 << 12),
80     MODE_VERIFYDB       = (1 << 13),
81 #define MODES_DB (MODE_INITDB | MODE_REBUILDDB | MODE_VERIFYDB)
82
83     MODE_UNKNOWN        = 0
84 };
85
86 #define MODES_FOR_DBPATH        (MODES_BT | MODES_IE | MODES_QV | MODES_DB)
87 #define MODES_FOR_NODEPS        (MODES_BT | MODES_IE | MODE_VERIFY)
88 #define MODES_FOR_TEST          (MODES_BT | MODES_IE)
89 #define MODES_FOR_ROOT          (MODES_BT | MODES_IE | MODES_QV | MODES_DB)
90
91 /*@-exportheadervar@*/
92 extern int _ftp_debug;
93 extern int noLibio;
94 extern int _rpmio_debug;
95 extern int _url_debug;
96 extern int _noDirTokens;
97
98 /*@-varuse@*/
99 /*@observer@*/ extern const char * rpmNAME;
100 /*@=varuse@*/
101 /*@observer@*/ extern const char * rpmEVR;
102 /*@-varuse@*/
103 extern int rpmFLAGS;
104 /*@=varuse@*/
105
106 extern struct MacroContext_s rpmCLIMacroContext;
107 /*@=exportheadervar@*/
108
109 /* options for all executables */
110
111 static int help = 0;
112 static int noUsageMsg = 0;
113 /*@observer@*/ /*@null@*/ static const char * pipeOutput = NULL;
114 static int quiet = 0;
115 /*@observer@*/ /*@null@*/ static const char * rcfile = NULL;
116 /*@observer@*/ /*@null@*/ static char * rootdir = "/";
117 static int showrc = 0;
118 static int showVersion = 0;
119
120 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
121 static int signIt = 0;
122 #endif  /* IAM_RPMBT || IAM_RPMK */
123
124 #if defined(IAM_RPMQV) || defined(IAM_RPMK)
125 static int noMd5 = 0;
126 #endif
127
128 #if defined(IAM_RPMEIU)
129 static int noDeps = 0;
130 #endif
131
132 #if defined(IAM_RPMEIU)
133 static int force = 0;
134 #endif
135
136 static struct poptOption rpmAllPoptTable[] = {
137  { "version", '\0', 0, &showVersion, 0,
138         N_("print the version of rpm being used"),
139         NULL },
140  { "quiet", '\0', 0, &quiet, 0,
141         N_("provide less detailed output"), NULL},
142  { "verbose", 'v', 0, 0, 'v',
143         N_("provide more detailed output"), NULL},
144  { "define", '\0', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, 0, GETOPT_DEFINEMACRO,
145         N_("define macro <name> with value <body>"),
146         N_("'<name> <body>'") },
147  { "eval", '\0', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, 0, GETOPT_EVALMACRO,
148         N_("print macro expansion of <expr>+"),
149         N_("<expr>+") },
150  { "pipe", '\0', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &pipeOutput, 0,
151         N_("send stdout to <cmd>"),
152         N_("<cmd>") },
153  { "root", 'r', POPT_ARG_STRING, &rootdir, 0,
154         N_("use <dir> as the top level directory"),
155         N_("<dir>") },
156  { "macros", '\0', POPT_ARG_STRING, &macrofiles, 0,
157         N_("read <file:...> instead of default macro file(s)"),
158         N_("<file:...>") },
159 #if !defined(GETOPT_RCFILE)
160  { "rcfile", '\0', POPT_ARG_STRING, &rcfile, 0,
161         N_("read <file:...> instead of default rpmrc file(s)"),
162         N_("<file:...>") },
163 #else
164  { "rcfile", '\0', 0, 0, GETOPT_RCFILE, 
165         N_("read <file:...> instead of default rpmrc file(s)"),
166         N_("<file:...>") },
167 #endif
168  { "showrc", '\0', 0, &showrc, GETOPT_SHOWRC,
169         N_("display final rpmrc and macro configuration"),
170         NULL },
171
172 #if HAVE_LIBIO_H && defined(_G_IO_IO_FILE_VERSION)
173  { "nolibio", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &noLibio, 1,
174         N_("disable use of libio(3) API"), NULL},
175 #endif
176  { "ftpdebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_ftp_debug, -1,
177         N_("debug protocol data stream"), NULL},
178  { "rpmiodebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmio_debug, -1,
179         N_("debug rpmio I/O"), NULL},
180  { "urldebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_url_debug, -1,
181         N_("debug URL cache handling"), NULL},
182
183    POPT_TABLEEND
184 };
185
186 #ifdef  IAM_RPMDB
187 static struct poptOption rpmDatabasePoptTable[] = {
188  { "initdb", '\0', 0, &initdb, 0,
189         N_("initialize database"), NULL},
190  { "rebuilddb", '\0', 0, 0, GETOPT_REBUILDDB,
191         N_("rebuild database inverted lists from installed package headers"),
192         NULL},
193  { "verifydb", '\0', 0, 0, GETOPT_VERIFYDB,
194         N_("verify database files"),
195         NULL},
196  { "nodirtokens", '\0', POPT_ARG_VAL, &_noDirTokens, 1,
197         N_("generate headers compatible with (legacy) rpm[23] packaging"),
198         NULL},
199  { "dirtokens", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_noDirTokens, 0,
200         N_("generate headers compatible with rpm4 packaging"), NULL},
201
202    POPT_TABLEEND
203 };
204 #endif  /* IAM_RPMDB */
205
206 #ifdef  IAM_RPMK
207 static struct poptOption rpmSignPoptTable[] = {
208  { "addsign", '\0', 0, 0, GETOPT_ADDSIGN,
209         N_("add a signature to a package"), NULL },
210  { "resign", '\0', 0, 0, GETOPT_RESIGN,
211         N_("sign a package (discard current signature)"), NULL },
212  { "sign", '\0', 0, &signIt, 0,
213         N_("generate PGP/GPG signature"), NULL },
214  { "checksig", 'K', 0, 0, 'K',
215         N_("verify package signature"), NULL },
216  { "nogpg", '\0', 0, &noGpg, 0,
217         N_("skip any GPG signatures"), NULL },
218  { "nopgp", '\0', POPT_ARGFLAG_DOC_HIDDEN, &noPgp, 0,
219         N_("skip any PGP signatures"), NULL },
220  { "nomd5", '\0', 0, &noMd5, 0,
221         N_("do not verify file md5 checksums"), NULL },
222
223    POPT_TABLEEND
224 };
225 #endif  /* IAM_RPMK */
226
227 #ifdef  IAM_RPMEIU
228 static rpmtransFlags transFlags = RPMTRANS_FLAG_NONE;
229 static rpmprobFilterFlags probFilter = RPMPROB_FILTER_NONE;
230 static rpmInstallInterfaceFlags installInterfaceFlags = INSTALL_NONE;
231 static rpmEraseInterfaceFlags eraseInterfaceFlags = UNINSTALL_NONE;
232
233 #define _POPT_SET_BIT   (POPT_ARG_VAL|POPT_ARGFLAG_OR)
234
235 static struct poptOption rpmInstallPoptTable[] = {
236  { "allfiles", '\0', _POPT_SET_BIT, &transFlags, RPMTRANS_FLAG_ALLFILES,
237   N_("install all files, even configurations which might otherwise be skipped"),
238         NULL},
239  { "allmatches", '\0', _POPT_SET_BIT, &eraseInterfaceFlags, UNINSTALL_ALLMATCHES,
240         N_("remove all packages which match <package> (normally an error is generated if <package> specified multiple packages)"),
241         NULL},
242
243  { "apply", '\0', _POPT_SET_BIT|POPT_ARGFLAG_DOC_HIDDEN, &transFlags,
244         (_noTransScripts|_noTransTriggers|
245                 RPMTRANS_FLAG_APPLYONLY|RPMTRANS_FLAG_PKGCOMMIT),
246         N_("do not execute package scriptlet(s)"), NULL },
247
248  { "badreloc", '\0', _POPT_SET_BIT, &probFilter, RPMPROB_FILTER_FORCERELOCATE,
249         N_("relocate files in non-relocateable package"), NULL},
250  { "dirstash", '\0', _POPT_SET_BIT|POPT_ARGFLAG_DOC_HIDDEN, &transFlags,
251                 RPMTRANS_FLAG_DIRSTASH,
252         N_("save erased package files by renaming into sub-directory"), NULL},
253  { "erase", 'e', 0, 0, 'e',
254         N_("erase (uninstall) package"), N_("<package>+") },
255  { "excludedocs", '\0', _POPT_SET_BIT, &transFlags, RPMTRANS_FLAG_NODOCS,
256         N_("do not install documentation"), NULL},
257  { "excludepath", '\0', POPT_ARG_STRING, 0, GETOPT_EXCLUDEPATH,
258         N_("skip files with leading component <path> "),
259         N_("<path>") },
260  { "force", '\0', 0, &force, 0,
261         N_("short hand for --replacepkgs --replacefiles"), NULL},
262  { "freshen", 'F', _POPT_SET_BIT, &installInterfaceFlags,
263         (INSTALL_UPGRADE|INSTALL_FRESHEN),
264         N_("upgrade package(s) if already installed"),
265         N_("<packagefile>+") },
266  { "hash", 'h', _POPT_SET_BIT, &installInterfaceFlags, INSTALL_HASH,
267         N_("print hash marks as package installs (good with -v)"), NULL},
268  { "ignorearch", '\0', _POPT_SET_BIT, &probFilter, RPMPROB_FILTER_IGNOREARCH,
269         N_("don't verify package architecture"), NULL},
270  { "ignoreos", '\0', _POPT_SET_BIT, &probFilter, RPMPROB_FILTER_IGNOREOS,
271         N_("don't verify package operating system"), NULL},
272  { "ignoresize", '\0', _POPT_SET_BIT, &probFilter,
273         (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES),
274         N_("don't check disk space before installing"), NULL},
275  { "includedocs", '\0', 0, &incldocs, 0,
276         N_("install documentation"), NULL},
277  { "install", '\0', 0, 0, GETOPT_INSTALL,
278         N_("install package"), N_("<packagefile>+") },
279  { "justdb", '\0', _POPT_SET_BIT, &transFlags, RPMTRANS_FLAG_JUSTDB,
280         N_("update the database, but do not modify the filesystem"), NULL},
281  { "nodeps", '\0', 0, &noDeps, 0,
282         N_("do not verify package dependencies"), NULL },
283  { "noorder", '\0', _POPT_SET_BIT, &installInterfaceFlags, INSTALL_NOORDER,
284         N_("do not reorder package installation to satisfy dependencies"),
285         NULL},
286
287  { "noscripts", '\0', _POPT_SET_BIT, &transFlags,
288         (_noTransScripts|_noTransTriggers),
289         N_("do not execute package scriptlet(s)"), NULL },
290  { "nopre", '\0', _POPT_SET_BIT|POPT_ARGFLAG_DOC_HIDDEN, &transFlags,
291         RPMTRANS_FLAG_NOPRE,
292         N_("do not execute %%pre scriptlet (if any)"), NULL },
293  { "nopost", '\0', _POPT_SET_BIT|POPT_ARGFLAG_DOC_HIDDEN, &transFlags,
294         RPMTRANS_FLAG_NOPOST,
295         N_("do not execute %%post scriptlet (if any)"), NULL },
296  { "nopreun", '\0', _POPT_SET_BIT|POPT_ARGFLAG_DOC_HIDDEN, &transFlags,
297         RPMTRANS_FLAG_NOPREUN,
298         N_("do not execute %%preun scriptlet (if any)"), NULL },
299  { "nopostun", '\0', _POPT_SET_BIT|POPT_ARGFLAG_DOC_HIDDEN, &transFlags,
300         RPMTRANS_FLAG_NOPOSTUN,
301         N_("do not execute %%postun scriptlet (if any)"), NULL },
302
303  { "notriggers", '\0', _POPT_SET_BIT, &transFlags,
304         _noTransTriggers,
305         N_("do not execute any scriptlet(s) triggered by this package"), NULL},
306  { "notriggerprein", '\0', _POPT_SET_BIT|POPT_ARGFLAG_DOC_HIDDEN, &transFlags,
307         RPMTRANS_FLAG_NOTRIGGERPREIN,
308         N_("do not execute any %%triggerprein scriptlet(s)"), NULL},
309  { "notriggerin", '\0', _POPT_SET_BIT|POPT_ARGFLAG_DOC_HIDDEN, &transFlags,
310         RPMTRANS_FLAG_NOTRIGGERIN,
311         N_("do not execute any %%triggerin scriptlet(s)"), NULL},
312  { "notriggerun", '\0', _POPT_SET_BIT|POPT_ARGFLAG_DOC_HIDDEN, &transFlags,
313         RPMTRANS_FLAG_NOTRIGGERUN,
314         N_("do not execute any %%triggerun scriptlet(s)"), NULL},
315  { "notriggerpostun", '\0', _POPT_SET_BIT|POPT_ARGFLAG_DOC_HIDDEN, &transFlags,
316         RPMTRANS_FLAG_NOTRIGGERPOSTUN,
317         N_("do not execute any %%triggerpostun scriptlet(s)"), NULL},
318
319  { "oldpackage", '\0', _POPT_SET_BIT, &probFilter, RPMPROB_FILTER_OLDPACKAGE,
320         N_("upgrade to an old version of the package (--force on upgrades does this automatically)"),
321         NULL},
322  { "percent", '\0', _POPT_SET_BIT, &installInterfaceFlags, INSTALL_PERCENT,
323         N_("print percentages as package installs"), NULL},
324  { "prefix", '\0', POPT_ARG_STRING, &prefix, 0,
325         N_("relocate the package to <dir>, if relocatable"),
326         N_("<dir>") },
327  { "relocate", '\0', POPT_ARG_STRING, 0, GETOPT_RELOCATE,
328         N_("relocate files from path <old> to <new>"),
329         N_("<old>=<new>") },
330  { "repackage", '\0', _POPT_SET_BIT, &transFlags, RPMTRANS_FLAG_REPACKAGE,
331         N_("save erased package files by repackaging"), NULL},
332  { "replacefiles", '\0', _POPT_SET_BIT, &probFilter,
333         (RPMPROB_FILTER_REPLACEOLDFILES | RPMPROB_FILTER_REPLACENEWFILES),
334         N_("install even if the package replaces installed files"), NULL},
335  { "replacepkgs", '\0', _POPT_SET_BIT, &probFilter, RPMPROB_FILTER_REPLACEPKG,
336         N_("reinstall if the package is already present"), NULL},
337  { "test", '\0', _POPT_SET_BIT, &transFlags, RPMTRANS_FLAG_TEST,
338         N_("don't install, but tell if it would work or not"), NULL},
339  { "upgrade", 'U', _POPT_SET_BIT, &installInterfaceFlags, INSTALL_UPGRADE,
340         N_("upgrade package(s)"),
341         N_("<packagefile>+") },
342
343    POPT_TABLEEND
344 };
345 #endif  /* IAM_RPMEIU */
346
347 /* the structure describing the options we take and the defaults */
348 static struct poptOption optionsTable[] = {
349 #if !defined(_AUTOHELP)
350  { "help", '\0', 0, &help, 0,                   NULL, NULL},
351 #endif
352
353  /* XXX colliding options */
354 #if defined(IAM_RPMQV) || defined(IAM_RPMEIU) || defined(IAM_RPMBT)
355  {  NULL, 'i', POPT_ARGFLAG_DOC_HIDDEN, 0, 'i',                 NULL, NULL},
356 #endif
357
358 #ifdef  IAM_RPMQV
359  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmQueryPoptTable, 0,
360         N_("Query options (with -q or --query):"),
361         NULL },
362  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmVerifyPoptTable, 0,
363         N_("Verify options (with -V or --verify):"),
364         NULL },
365 #endif  /* IAM_RPMQV */
366
367 #ifdef  IAM_RPMK
368  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmSignPoptTable, 0,
369         N_("Signature options:"),
370         NULL },
371 #endif  /* IAM_RPMK */
372
373 #ifdef  IAM_RPMDB
374  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmDatabasePoptTable, 0,
375         N_("Database options:"),
376         NULL },
377 #endif  /* IAM_RPMDB */
378
379 #ifdef  IAM_RPMBT
380  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmBuildPoptTable, 0,
381         N_("Build options with [ <specfile> | <tarball> | <source package> ]:"),
382         NULL },
383 #endif  /* IAM_RPMBT */
384
385 #ifdef  IAM_RPMEIU
386  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmInstallPoptTable, 0,
387         N_("Install/Upgrade/Erase options:"),
388         NULL },
389 #endif  /* IAM_RPMEIU */
390
391  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmAllPoptTable, 0,
392         N_("Common options for all rpm modes:"),
393         NULL },
394
395    POPT_AUTOHELP
396    POPT_TABLEEND
397 };
398
399 #ifdef __MINT__
400 /* MiNT cannot dynamically increase the stack.  */
401 long _stksize = 64 * 1024L;
402 #endif
403
404 /*@exits@*/ static void argerror(const char * desc)
405         /*@modifies fileSystem @*/
406 {
407     fprintf(stderr, _("rpm: %s\n"), desc);
408     exit(EXIT_FAILURE);
409 }
410
411 static void printVersion(void)
412         /*@modifies fileSystem @*/
413 {
414     fprintf(stdout, _("RPM version %s\n"), rpmEVR);
415 }
416
417 static void printBanner(void)
418         /*@modifies fileSystem @*/
419 {
420     (void) puts(_("Copyright (C) 1998-2000 - Red Hat, Inc."));
421     (void) puts(_("This program may be freely redistributed under the terms of the GNU GPL"));
422 }
423
424 static void printUsage(void)
425         /*@modifies fileSystem @*/
426 {
427     FILE * fp;
428     printVersion();
429     printBanner();
430     (void) puts("");
431
432     fp = stdout;
433
434     fprintf(fp, _("Usage: %s {--help}\n"), __progname);
435     fprintf(fp,  ("       %s {--version}\n"), __progname);
436
437 #ifdef  IAM_RPMEIU
438 #ifdef  DYING
439 --dbpath        all
440 --ftpproxy etc  all
441 --force         alias for --replacepkgs --replacefiles
442 --includedocs   handle as option in table
443                 --erase forbids many options
444 #endif
445 #endif  /* IAM_RPMEIU */
446
447 #ifdef  IAM_RPMQV
448 #ifdef  DYING   /* XXX popt glue needing --help doco. */
449 --dbpath        all
450 --ftpproxy etc  all
451 -i,--info       Q
452 -R,--requires   Q
453 -P,--provides   Q
454 --scripts       Q
455 --triggeredby   Q
456 --changelog     Q
457 --triggers      Q
458 --querytags     !V
459 --setperms      V
460 --setugids      V
461 #endif  /* DYING */
462 #endif  /* IAM_RPMQV */
463
464 }
465
466 #ifdef  DYING
467 static void printHelpLine(char * prefix, char * help)
468         /*@modifies fileSystem @*/
469 {
470     int indentLength = strlen(prefix) + 3;
471     int lineLength = 79 - indentLength;
472     int helpLength = strlen(help);
473     char * ch;
474     char format[10];
475
476     fprintf(stdout, "%s - ", prefix);
477
478     while (helpLength > lineLength) {
479         ch = help + lineLength - 1;
480         while (ch > help && !isspace(*ch)) ch--;
481         if (ch == help) break;          /* give up */
482         while (ch > (help + 1) && isspace(*ch)) ch--;
483         ch++;
484
485         sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
486         fprintf(stdout, format, help, " ");
487         help = ch;
488         while (isspace(*help) && *help) help++;
489         helpLength = strlen(help);
490     }
491
492     if (helpLength) puts(help);
493 }
494
495 static void printHelp(void) {
496     printVersion();
497     printBanner();
498     puts("");
499
500     puts(         _("Usage:"));
501     printHelpLine(  "   --help                 ", 
502                   _("print this message"));
503     printHelpLine(  "   --version              ",
504                   _("print the version of rpm being used"));
505
506     puts("");
507     puts(         _("  All modes support the following options:"));
508     printHelpLine(_("   --define '<name> <body>'"),
509                   _("define macro <name> with value <body>"));
510     printHelpLine(_("   --eval '<expr>+'       "),
511                   _("print the expansion of macro <expr> to stdout"));
512     printHelpLine(_("   --pipe <cmd>           "),
513                   _("send stdout to <cmd>"));
514     printHelpLine(_("   --rcfile <file:...>    "),
515                   _("use <file:...> instead of default list of macro files"));
516     printHelpLine(  "   --showrc               ",
517                   _("display final rpmrc and macro configuration"));
518 #if defined(IAM_RPMBT) || defined(IAM_RPMDB) || defined(IAM_RPMEIU) || defined(IAM_RPMQV)
519     printHelpLine(_("   --dbpath <dir>         "),
520                   _("use <dir> as the directory for the database"));
521     printHelpLine(_("   --root <dir>           "),
522                   _("use <dir> as the top level directory"));
523 #endif  /* IAM_RPMBT || IAM_RPMDB || IAM_RPMEIU || IAM_RPMQV */
524     printHelpLine(  "   -v                     ",
525                   _("be a little more verbose"));
526     printHelpLine(  "   -vv                    ",
527                   _("be incredibly verbose (for debugging)"));
528
529 #if defined(IAM_RPMEIU) || defined(IAM_RPMQV)
530     puts("");
531     puts(         _("  Install, upgrade and query (with -p) modes allow URL's to be used in place"));
532     puts(         _("  of file names as well as the following options:"));
533     printHelpLine(_("     --ftpproxy <host>    "),
534                   _("hostname or IP of ftp proxy"));
535     printHelpLine(_("     --ftpport <port>     "),
536                   _("port number of ftp server (or proxy)"));
537     printHelpLine(_("     --httpproxy <host>   "),
538                   _("hostname or IP of http proxy"));
539     printHelpLine(_("     --httpport <port>    "),
540                   _("port number of http server (or proxy)"));
541 #endif  /* IAM_RPMEIU || IAM_RPMQV */
542
543 #ifdef IAM_RPMQV
544     puts("");
545     puts(         _("  Package specification options:"));
546     printHelpLine(  "     -a, --all            ",
547                   _("query/verify all packages"));
548     printHelpLine(_("     -f <file>+           "),
549                   _("query/verify package owning <file>"));
550     printHelpLine(_("     -p <packagefile>+    "),
551                   _("query/verify (uninstalled) package <packagefile>"));
552     printHelpLine(_("     --triggeredby <pkg>  "),
553                   _("query/verify packages triggered by <pkg>"));
554     printHelpLine(_("     --whatprovides <cap> "),
555                   _("query/verify packages which provide <cap> capability"));
556     printHelpLine(_("     --whatrequires <cap> "),
557                   _("query/verify packages which require <cap> capability"));
558     puts("");
559     printHelpLine(  "  -q, --query             ",
560                   _("query mode"));
561     printHelpLine(_("     --queryformat <qfmt> "),
562                   _("use <qfmt> as the header format (implies --info)"));
563     puts("");
564     puts(         _("    Information selection options:"));
565     printHelpLine(  "       -i, --info         ",
566                   _("display package information"));
567     printHelpLine(  "       --changelog        ",
568                   _("display the package's change log"));
569     printHelpLine(  "       -l                 ",
570                   _("display package file list"));
571     printHelpLine(  "       -s                 ",
572                   _("show file states (implies -l)"));
573     printHelpLine(  "       -d                 ",
574                   _("list only documentation files (implies -l)"));
575     printHelpLine(  "       -c                 ",
576                   _("list only configuration files (implies -l)"));
577     printHelpLine(  "       --dump             ",
578                   _("show all verifiable information for each file (must be used with -l, -c, or -d)"));
579     printHelpLine(  "       --provides         ",
580                   _("list capabilities provided by package"));
581     printHelpLine(  "       -R, --requires     ",
582                   _("list capabilities required by package"));
583     printHelpLine(  "       --scripts          ",
584                   _("print the various [un]install scriptlets"));
585     printHelpLine(  "       --triggers         ",
586                   _("show the trigger scriptlets contained in the package"));
587     puts("");
588     printHelpLine(  "   -V, -y, --verify       ",
589                   _("verify a package installation using the same same package specification options as -q"));
590     printHelpLine(  "     --nodeps             ",
591                   _("do not verify package dependencies"));
592     printHelpLine(  "     --nofiles            ",
593                   _("do not verify file attributes"));
594     printHelpLine(  "     --nomd5              ",
595                   _("do not verify file md5 checksums"));
596     printHelpLine(  "     --noscripts          ",
597                   _("do not execute scripts (if any)"));
598     puts("");
599     printHelpLine(  "   --querytags            ",
600                   _("list the tags that can be used in a query format"));
601     printHelpLine(  "   --setperms             ",
602                   _("set the file permissions to those in the package database"
603                     " using the same package specification options as -q"));
604     printHelpLine(  "   --setugids             ",
605                   _("set the file owner and group to those in the package "
606                     "database using the same package specification options as "
607                     "-q"));
608 #endif  /* IAM_RPMQV */
609
610 #ifdef  IAM_RPMEIU
611     puts("");
612     puts(         _("   --install <packagefile>"));
613     printHelpLine(_("   -i <packagefile>       "),
614                   _("install package"));
615     printHelpLine(  "     --allfiles           ",
616                   _("install all files, even configurations which might "
617                     "otherwise be skipped"));
618     printHelpLine(  "     --badreloc           ",
619                   _("relocate files in non-relocateable package"));
620     printHelpLine(  "     --excludedocs        ",
621                   _("do not install documentation"));
622     printHelpLine(_("     --excludepath <path> "),
623                   _("skip files with leading component <path> "));
624     printHelpLine(  "     --force              ",
625                   _("short hand for --replacepkgs --replacefiles"));
626     printHelpLine(  "     -h, --hash           ",
627                   _("print hash marks as package installs (good with -v)"));
628     printHelpLine(  "     --ignorearch         ",
629                   _("don't verify package architecture"));
630     printHelpLine(  "     --ignoresize         ",
631                   _("don't check disk space before installing"));
632     printHelpLine(  "     --ignoreos           ",
633                   _("don't verify package operating system"));
634     printHelpLine(  "     --includedocs        ",
635                   _("install documentation"));
636     printHelpLine(  "     --justdb             ",
637                   _("update the database, but do not modify the filesystem"));
638     printHelpLine(  "     --nodeps             ",
639                   _("do not verify package dependencies"));
640     printHelpLine(  "     --noorder            ",
641                   _("do not reorder package installation to satisfy dependencies"));
642     printHelpLine(  "     --noscripts          ",
643                   _("don't execute any installation scriptlets"));
644     printHelpLine(  "     --notriggers         ",
645                   _("don't execute any scriptlets triggered by this package"));
646     printHelpLine(  "     --percent            ",
647                   _("print percentages as package installs"));
648     printHelpLine(_("     --prefix <dir>       "),
649                   _("relocate the package to <dir>, if relocatable"));
650     printHelpLine(_("     --relocate <oldpath>=<newpath>"),
651                   _("relocate files from <oldpath> to <newpath>"));
652     printHelpLine(  "     --replacefiles       ",
653                   _("install even if the package replaces installed files"));
654     printHelpLine(  "     --replacepkgs        ",
655                   _("reinstall if the package is already present"));
656     printHelpLine(  "     --test               ",
657                   _("don't install, but tell if it would work or not"));
658     puts("");
659     puts(         _("   --upgrade <packagefile>"));
660     printHelpLine(_("   -U <packagefile>       "),
661                   _("upgrade package (same options as --install, plus)"));
662     printHelpLine(  "     --oldpackage         ",
663                   _("upgrade to an old version of the package (--force on upgrades does this automatically)"));
664     puts("");
665     puts(         _("   --erase <package>"));
666     printHelpLine(_("   -e <package>           "),
667                   _("erase (uninstall) package"));
668     printHelpLine(  "     --allmatches         ",
669                   _("remove all packages which match <package> (normally an error is generated if <package> specified multiple packages)"));
670     printHelpLine(  "     --justdb             ",
671                   _("update the database, but do not modify the filesystem"));
672     printHelpLine(  "     --nodeps             ",
673                   _("do not verify package dependencies"));
674     printHelpLine(  "     --noorder            ",
675                   _("do not reorder package installation to satisfy dependencies"));
676     printHelpLine(  "     --noscripts          ",
677                   _("do not execute any package specific scripts"));
678     printHelpLine(  "     --notriggers         ",
679                   _("don't execute any scripts triggered by this package"));
680 #endif  /* IAM_RPMEIU */
681
682 #ifdef IAM_RPMK
683     puts("");
684     printHelpLine(_("   --resign <pkg>+        "),
685                   _("sign a package (discard current signature)"));
686     printHelpLine(_("   --addsign <pkg>+       "),
687                   _("add a signature to a package"));
688
689     puts(         _("   --checksig <pkg>+"));
690     printHelpLine(_("   -K <pkg>+             "),
691                   _("verify package signature"));
692     printHelpLine(  "     --nopgp              ",
693                   _("skip any PGP signatures"));
694     printHelpLine(  "     --nogpg              ",
695                   _("skip any GPG signatures"));
696     printHelpLine(  "     --nomd5              ",
697                   _("skip any MD5 signatures"));
698 #endif  /* IAM_RPMK */
699
700 #ifdef  IAM_RPMDB
701     puts("");
702     printHelpLine(  "   --initdb               ",
703                   _("initalize database (unnecessary, legacy use)"));
704     printHelpLine(  "   --rebuilddb            ",
705                   _("rebuild database indices from existing database headers"));
706 #endif
707
708 }
709 #endif
710
711 int main(int argc, const char ** argv)
712 {
713     enum modes bigMode = MODE_UNKNOWN;
714
715 #ifdef  IAM_RPMQV
716     QVA_t qva = &rpmQVArgs;
717 #endif
718
719 #ifdef  IAM_RPMBT
720     BTA_t ba = &rpmBTArgs;
721 #endif
722
723 #ifdef  IAM_RPMEIU
724 /*@only@*/ rpmRelocation * relocations = NULL;
725     int numRelocations = 0;
726 #endif
727
728 #if defined(IAM_RPMK)
729     rpmResignFlags addSign = RESIGN_NEW_SIGNATURE;
730     rpmCheckSigFlags checksigFlags = CHECKSIG_NONE;
731 #endif
732
733 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
734     char * passPhrase = "";
735 #endif
736
737     int arg;
738     int gotDbpath = 0;
739
740     const char * optArg;
741     pid_t pipeChild = 0;
742     poptContext optCon;
743     int ec = 0;
744     int status;
745     int p[2];
746         
747 #if HAVE_MCHECK_H && HAVE_MTRACE
748     mtrace();   /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
749 #endif
750     setprogname(argv[0]);       /* Retrofit glibc __progname */
751
752     /* XXX glibc churn sanity */
753     if (__progname == NULL) {
754         if ((__progname = strrchr(argv[0], '/')) != NULL) __progname++;
755         else __progname = argv[0];
756     }
757
758     /* Set the major mode based on argv[0] */
759     /*@-nullpass@*/
760 #ifdef  IAM_RPMBT
761     if (!strcmp(__progname, "rpmb"))    bigMode = MODE_BUILD;
762     if (!strcmp(__progname, "rpmt"))    bigMode = MODE_TARBUILD;
763     if (!strcmp(__progname, "rpmbuild"))        bigMode = MODE_BUILD;
764 #endif
765 #ifdef  IAM_RPMQV
766     if (!strcmp(__progname, "rpmq"))    bigMode = MODE_QUERY;
767     if (!strcmp(__progname, "rpmv"))    bigMode = MODE_VERIFY;
768     if (!strcmp(__progname, "rpmquery"))        bigMode = MODE_QUERY;
769     if (!strcmp(__progname, "rpmverify"))       bigMode = MODE_VERIFY;
770 #endif
771 #ifdef  RPMEIU
772     if (!strcmp(__progname, "rpme"))    bigMode = MODE_UNINSTALL;
773     if (!strcmp(__progname, "rpmi"))    bigMode = MODE_INSTALL;
774     if (!strcmp(__progname, "rpmu"))    bigMode = MODE_INSTALL;
775 #endif
776     /*@=nullpass@*/
777
778     /* set the defaults for the various command line options */
779     _ftp_debug = 0;
780
781 #if HAVE_LIBIO_H && defined(_G_IO_IO_FILE_VERSION)
782     noLibio = 0;
783 #else
784     noLibio = 1;
785 #endif
786     _rpmio_debug = 0;
787     _url_debug = 0;
788
789     /* XXX Eliminate query linkage loop */
790     specedit = 0;
791     parseSpecVec = parseSpec;
792     freeSpecVec = freeSpec;
793
794     /* set up the correct locale */
795     (void) setlocale(LC_ALL, "" );
796
797 #ifdef  __LCLINT__
798 #define LOCALEDIR       "/usr/share/locale"
799 #endif
800     bindtextdomain(PACKAGE, LOCALEDIR);
801     textdomain(PACKAGE);
802
803     rpmSetVerbosity(RPMMESS_NORMAL);    /* XXX silly use by showrc */
804
805     /* Make a first pass through the arguments, looking for --rcfile */
806     /* We need to handle that before dealing with the rest of the arguments. */
807     /*@-nullpass -temptrans@*/
808     optCon = poptGetContext(__progname, argc, argv, optionsTable, 0);
809     /*@=nullpass =temptrans@*/
810     (void) poptReadConfigFile(optCon, LIBRPMALIAS_FILENAME);
811     (void) poptReadDefaultConfig(optCon, 1);
812     poptSetExecPath(optCon, RPMCONFIGDIR, 1);
813
814     /* reading rcfile early makes it easy to override */
815     /* XXX only --rcfile (and --showrc) need this pre-parse */
816
817     while ((arg = poptGetNextOpt(optCon)) > 0) {
818         switch(arg) {
819         case 'v':
820             rpmIncreaseVerbosity();     /* XXX silly use by showrc */
821             break;
822         default:
823             break;
824       }
825     }
826
827     if (rpmReadConfigFiles(rcfile, NULL))  
828         exit(EXIT_FAILURE);
829
830     if (showrc) {
831         (void) rpmShowRC(stdout);
832         exit(EXIT_SUCCESS);
833     }
834
835     rpmSetVerbosity(RPMMESS_NORMAL);    /* XXX silly use by showrc */
836
837     poptResetContext(optCon);
838
839 #ifdef  IAM_RPMQV
840     if (qva->qva_queryFormat) free((void *)qva->qva_queryFormat);
841     memset(qva, 0, sizeof(*qva));
842     qva->qva_source = RPMQV_PACKAGE;
843     qva->qva_mode = ' ';
844     qva->qva_char = ' ';
845 #endif
846
847 #ifdef  IAM_RPMBT
848     if (ba->buildRootOverride) free((void *)ba->buildRootOverride);
849     if (ba->targets) free(ba->targets);
850     memset(ba, 0, sizeof(*ba));
851     ba->buildMode = ' ';
852     ba->buildChar = ' ';
853 #endif
854
855 #ifdef  IAM_RPMEIU
856     transFlags = RPMTRANS_FLAG_NONE;
857     probFilter = RPMPROB_FILTER_NONE;
858     installInterfaceFlags = INSTALL_NONE;
859     eraseInterfaceFlags = UNINSTALL_NONE;
860 #endif
861
862     while ((arg = poptGetNextOpt(optCon)) > 0) {
863         optArg = poptGetOptArg(optCon);
864
865         switch (arg) {
866             
867         case 'v':
868             rpmIncreaseVerbosity();
869             break;
870
871 #if defined(IAM_RPMQV) || defined(IAM_RPMEIU) || defined(IAM_RPMBT)
872         case 'i':
873 #ifdef  IAM_RPMQV
874             if (bigMode == MODE_QUERY) {
875                 /*@-nullassign -readonlytrans@*/
876                 const char * infoCommand[] = { "--info", NULL };
877                 /*@=nullassign =readonlytrans@*/
878                 (void) poptStuffArgs(optCon, infoCommand);
879             }
880 #endif
881 #ifdef  IAM_RPMEIU
882             if (bigMode == MODE_INSTALL)
883                 /*@-ifempty@*/ ;
884             if (bigMode == MODE_UNKNOWN) {
885                 /*@-nullassign -readonlytrans@*/
886                 const char * installCommand[] = { "--install", NULL };
887                 /*@=nullassign =readonlytrans@*/
888                 (void) poptStuffArgs(optCon, installCommand);
889             }
890 #endif
891             break;
892 #endif  /* IAM_RPMQV || IAM_RPMEIU || IAM_RPMBT */
893
894 #ifdef  IAM_RPMEIU
895         
896         case 'e':
897             if (bigMode != MODE_UNKNOWN && bigMode != MODE_UNINSTALL)
898                 argerror(_("only one major mode may be specified"));
899             bigMode = MODE_UNINSTALL;
900             break;
901         
902         case GETOPT_INSTALL:
903             if (bigMode != MODE_UNKNOWN && bigMode != MODE_INSTALL)
904                 argerror(_("only one major mode may be specified"));
905             bigMode = MODE_INSTALL;
906             break;
907
908 #ifdef  DYING   /* XXX handled by popt */
909         case 'U':
910             if (bigMode != MODE_UNKNOWN && bigMode != MODE_INSTALL)
911                 argerror(_("only one major mode may be specified"));
912             bigMode = MODE_INSTALL;
913             break;
914
915         case 'F':
916             if (bigMode != MODE_UNKNOWN && bigMode != MODE_INSTALL)
917                 argerror(_("only one major mode may be specified"));
918             bigMode = MODE_INSTALL;
919             break;
920 #endif
921
922         case GETOPT_EXCLUDEPATH:
923             if (optArg == NULL || *optArg != '/') 
924                 argerror(_("exclude paths must begin with a /"));
925
926             relocations = xrealloc(relocations, 
927                                   sizeof(*relocations) * (numRelocations + 1));
928             /*@-observertrans -dependenttrans@*/        /* FIX: W2DO? */
929             relocations[numRelocations].oldPath = optArg;
930             relocations[numRelocations++].newPath = NULL;
931             /*@=observertrans =dependenttrans@*/
932             break;
933
934         case GETOPT_RELOCATE:
935           { char * newPath = NULL;
936             if (optArg == NULL || *optArg != '/') 
937                 argerror(_("relocations must begin with a /"));
938             if (!(newPath = strchr(optArg, '=')))
939                 argerror(_("relocations must contain a ="));
940             *newPath++ = '\0';
941             if (*newPath != '/') 
942                 argerror(_("relocations must have a / following the ="));
943             relocations = xrealloc(relocations, 
944                                   sizeof(*relocations) * (numRelocations + 1));
945             /*@-observertrans -kepttrans@*/     /* FIX: W2DO? */
946             relocations[numRelocations].oldPath = optArg;
947             relocations[numRelocations++].newPath = newPath;
948             /*@=observertrans =kepttrans@*/
949           } break;
950 #endif  /* IAM_RPMEIU */
951
952 #ifdef  IAM_RPMDB
953         case GETOPT_REBUILDDB:
954             if (bigMode != MODE_UNKNOWN && bigMode != MODE_REBUILDDB)
955                 argerror(_("only one major mode may be specified"));
956             bigMode = MODE_REBUILDDB;
957             break;
958         case GETOPT_VERIFYDB:
959             if (bigMode != MODE_UNKNOWN && bigMode != MODE_VERIFYDB)
960                 argerror(_("only one major mode may be specified"));
961             bigMode = MODE_VERIFYDB;
962             break;
963 #endif
964
965 #ifdef  IAM_RPMK
966         case 'K':
967             if (bigMode != MODE_UNKNOWN && bigMode != MODE_CHECKSIG)
968                 argerror(_("only one major mode may be specified"));
969             bigMode = MODE_CHECKSIG;
970             break;
971
972         case GETOPT_RESIGN:
973             if (bigMode != MODE_UNKNOWN && bigMode != MODE_RESIGN)
974                 argerror(_("only one major mode may be specified"));
975             bigMode = MODE_RESIGN;
976             addSign = RESIGN_NEW_SIGNATURE;
977             signIt = 1;
978             break;
979
980         case GETOPT_ADDSIGN:
981             if (bigMode != MODE_UNKNOWN && bigMode != MODE_RESIGN)
982                 argerror(_("only one major mode may be specified"));
983             bigMode = MODE_RESIGN;
984             addSign = RESIGN_ADD_SIGNATURE;
985             signIt = 1;
986             break;
987 #endif  /* IAM_RPMK */
988
989         case GETOPT_DEFINEMACRO:
990             if (optArg) {
991                 (void) rpmDefineMacro(NULL, optArg, RMIL_CMDLINE);
992                 (void) rpmDefineMacro(&rpmCLIMacroContext, optArg,RMIL_CMDLINE);
993             }
994             noUsageMsg = 1;
995             break;
996
997         case GETOPT_EVALMACRO:
998             if (optArg) {
999                 const char *val = rpmExpand(optArg, NULL);
1000                 fprintf(stdout, "%s\n", val);
1001                 val = _free(val);
1002             }
1003             noUsageMsg = 1;
1004             break;
1005
1006 #if defined(GETOPT_RCFILE)
1007         case GETOPT_RCFILE:
1008             fprintf(stderr, _("The --rcfile option has been eliminated.\n"));
1009             fprintf(stderr, _("Use \"--macros <file:...>\" instead.\n"));
1010             exit(EXIT_FAILURE);
1011             /*@notreached@*/ break;
1012 #endif
1013
1014         default:
1015             fprintf(stderr, _("Internal error in argument processing (%d) :-(\n"), arg);
1016             exit(EXIT_FAILURE);
1017         }
1018     }
1019
1020     if (quiet)
1021         rpmSetVerbosity(RPMMESS_QUIET);
1022
1023     if (showVersion) printVersion();
1024
1025     if (arg < -1) {
1026         fprintf(stderr, "%s: %s\n", 
1027                 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 
1028                 poptStrerror(arg));
1029         exit(EXIT_FAILURE);
1030     }
1031
1032 #ifdef  IAM_RPMBT
1033     switch (ba->buildMode) {
1034     case 'b':   bigMode = MODE_BUILD;           break;
1035     case 't':   bigMode = MODE_TARBUILD;        break;
1036     case 'B':   bigMode = MODE_REBUILD;         break;
1037     case 'C':   bigMode = MODE_RECOMPILE;       break;
1038     }
1039
1040     if ((ba->buildAmount & RPMBUILD_RMSOURCE) && bigMode == MODE_UNKNOWN)
1041         bigMode = MODE_BUILD;
1042
1043     if ((ba->buildAmount & RPMBUILD_RMSPEC) && bigMode == MODE_UNKNOWN)
1044         bigMode = MODE_BUILD;
1045
1046     if (ba->buildRootOverride && bigMode != MODE_BUILD &&
1047         bigMode != MODE_REBUILD && bigMode != MODE_TARBUILD) {
1048         argerror("--buildroot may only be used during package builds");
1049     }
1050 #endif  /* IAM_RPMBT */
1051     
1052 #ifdef  IAM_RPMDB
1053     if (initdb) {
1054         if (bigMode != MODE_UNKNOWN) 
1055             argerror(_("only one major mode may be specified"));
1056         else
1057             bigMode = MODE_INITDB;
1058     }
1059 #endif  /* IAM_RPMDB */
1060
1061 #ifdef  IAM_RPMQV
1062     switch (qva->qva_mode) {
1063     case 'q':   bigMode = MODE_QUERY;           break;
1064     case 'V':   bigMode = MODE_VERIFY;          break;
1065     case 'Q':   bigMode = MODE_QUERYTAGS;       break;
1066     }
1067
1068     if (qva->qva_sourceCount) {
1069         if (qva->qva_sourceCount > 2)
1070             argerror(_("one type of query/verify may be performed at a "
1071                         "time"));
1072     }
1073     if (qva->qva_flags && (bigMode & ~MODES_QV)) 
1074         argerror(_("unexpected query flags"));
1075
1076     if (qva->qva_queryFormat && (bigMode & ~MODES_QV)) 
1077         argerror(_("unexpected query format"));
1078
1079     if (qva->qva_source != RPMQV_PACKAGE && (bigMode & ~MODES_QV)) 
1080         argerror(_("unexpected query source"));
1081 #endif
1082
1083     if (gotDbpath && (bigMode & ~MODES_FOR_DBPATH))
1084         argerror(_("--dbpath given for operation that does not use a "
1085                         "database"));
1086
1087 #if defined(IAM_RPMEIU)
1088
1089     if (!( bigMode == MODE_INSTALL ) && force)
1090         argerror(_("only installation, upgrading, rmsource and rmspec may be forced"));
1091 #endif  /* IAM_RPMEIU */
1092
1093 #ifdef  IAM_RPMEIU
1094     if (bigMode != MODE_INSTALL && (probFilter & RPMPROB_FILTER_FORCERELOCATE))
1095         argerror(_("files may only be relocated during package installation"));
1096
1097     if (relocations && prefix)
1098         argerror(_("only one of --prefix or --relocate may be used"));
1099
1100     if (bigMode != MODE_INSTALL && relocations)
1101         argerror(_("--relocate and --excludepath may only be used when installing new packages"));
1102
1103     if (bigMode != MODE_INSTALL && prefix)
1104         argerror(_("--prefix may only be used when installing new packages"));
1105
1106     if (prefix && prefix[0] != '/') 
1107         argerror(_("arguments to --prefix must begin with a /"));
1108
1109     if (bigMode != MODE_INSTALL && (installInterfaceFlags & INSTALL_HASH))
1110         argerror(_("--hash (-h) may only be specified during package "
1111                         "installation"));
1112
1113     if (bigMode != MODE_INSTALL && (installInterfaceFlags & INSTALL_PERCENT))
1114         argerror(_("--percent may only be specified during package "
1115                         "installation"));
1116
1117     if (bigMode != MODE_INSTALL &&
1118  (probFilter & (RPMPROB_FILTER_REPLACEOLDFILES|RPMPROB_FILTER_REPLACENEWFILES)))
1119         argerror(_("--replacefiles may only be specified during package "
1120                         "installation"));
1121
1122     if (bigMode != MODE_INSTALL && (probFilter & RPMPROB_FILTER_REPLACEPKG))
1123         argerror(_("--replacepkgs may only be specified during package "
1124                         "installation"));
1125
1126     if (bigMode != MODE_INSTALL && (transFlags & RPMTRANS_FLAG_NODOCS))
1127         argerror(_("--excludedocs may only be specified during package "
1128                    "installation"));
1129
1130     if (bigMode != MODE_INSTALL && incldocs)
1131         argerror(_("--includedocs may only be specified during package "
1132                    "installation"));
1133
1134     if (incldocs && (transFlags & RPMTRANS_FLAG_NODOCS))
1135         argerror(_("only one of --excludedocs and --includedocs may be "
1136                  "specified"));
1137   
1138     if (bigMode != MODE_INSTALL && (probFilter & RPMPROB_FILTER_IGNOREARCH))
1139         argerror(_("--ignorearch may only be specified during package "
1140                    "installation"));
1141
1142     if (bigMode != MODE_INSTALL && (probFilter & RPMPROB_FILTER_IGNOREOS))
1143         argerror(_("--ignoreos may only be specified during package "
1144                    "installation"));
1145
1146     if (bigMode != MODE_INSTALL &&
1147         (probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES)))
1148         argerror(_("--ignoresize may only be specified during package "
1149                    "installation"));
1150
1151     if ((eraseInterfaceFlags & UNINSTALL_ALLMATCHES) && bigMode != MODE_UNINSTALL)
1152         argerror(_("--allmatches may only be specified during package "
1153                    "erasure"));
1154
1155     if ((transFlags & RPMTRANS_FLAG_ALLFILES) && bigMode != MODE_INSTALL)
1156         argerror(_("--allfiles may only be specified during package "
1157                    "installation"));
1158
1159     if ((transFlags & RPMTRANS_FLAG_JUSTDB) &&
1160         bigMode != MODE_INSTALL && bigMode != MODE_UNINSTALL)
1161         argerror(_("--justdb may only be specified during package "
1162                    "installation and erasure"));
1163 #endif  /* IAM_RPMEIU */
1164
1165 #if defined(IAM_RPMEIU)
1166     if (bigMode != MODE_INSTALL && bigMode != MODE_UNINSTALL &&
1167         (transFlags & (RPMTRANS_FLAG_NOSCRIPTS | _noTransScripts | _noTransTriggers)))
1168         argerror(_("script disabling options may only be specified during "
1169                    "package installation and erasure"));
1170
1171     if (bigMode != MODE_INSTALL && bigMode != MODE_UNINSTALL &&
1172         (transFlags & (RPMTRANS_FLAG_NOTRIGGERS | _noTransTriggers)))
1173         argerror(_("trigger disabling options may only be specified during "
1174                    "package installation and erasure"));
1175
1176     if (noDeps & (bigMode & ~MODES_FOR_NODEPS))
1177         argerror(_("--nodeps may only be specified during package "
1178                    "building, rebuilding, recompilation, installation,"
1179                    "erasure, and verification"));
1180
1181     if ((transFlags & RPMTRANS_FLAG_TEST) && (bigMode & ~MODES_FOR_TEST))
1182         argerror(_("--test may only be specified during package installation, "
1183                  "erasure, and building"));
1184 #endif  /* IAM_RPMEIU */
1185
1186     if (rootdir && rootdir[1] && (bigMode & ~MODES_FOR_ROOT))
1187         argerror(_("--root (-r) may only be specified during "
1188                  "installation, erasure, querying, and "
1189                  "database rebuilds"));
1190
1191     if (rootdir) {
1192         switch (urlIsURL(rootdir)) {
1193         default:
1194             if (bigMode & MODES_FOR_ROOT)
1195                 break;
1196             /*@fallthrough@*/
1197         case URL_IS_UNKNOWN:
1198             if (rootdir[0] != '/')
1199                 argerror(_("arguments to --root (-r) must begin with a /"));
1200             break;
1201         }
1202     }
1203
1204 #ifdef  IAM_RPMK
1205     if (noPgp && bigMode != MODE_CHECKSIG)
1206         argerror(_("--nopgp may only be used during signature checking"));
1207
1208     if (noGpg && bigMode != MODE_CHECKSIG)
1209         argerror(_("--nogpg may only be used during signature checking"));
1210 #endif
1211
1212 #if defined(IAM_RPMK) || defined(IAM_RPMQV)
1213     if (noMd5 && bigMode != MODE_CHECKSIG && bigMode != MODE_VERIFY)
1214         argerror(_("--nomd5 may only be used during signature checking and "
1215                    "package verification"));
1216 #endif
1217
1218 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
1219 #if defined(IAM_RPMBT)
1220     signIt = ba->sign;
1221 #endif
1222     if (signIt) {
1223         if (bigMode == MODE_REBUILD || bigMode == MODE_BUILD ||
1224             bigMode == MODE_RESIGN || bigMode == MODE_TARBUILD) {
1225             const char ** av;
1226             struct stat sb;
1227             int errors = 0;
1228
1229             if ((av = poptGetArgs(optCon)) == NULL) {
1230                 fprintf(stderr, _("no files to sign\n"));
1231                 errors++;
1232             } else
1233             while (*av) {
1234                 if (stat(*av, &sb)) {
1235                     fprintf(stderr, _("cannot access file %s\n"), *av);
1236                     errors++;
1237                 }
1238                 av++;
1239             }
1240
1241             if (errors) {
1242                 ec = errors;
1243                 goto exit;
1244             }
1245
1246             if (poptPeekArg(optCon)) {
1247                 int sigTag;
1248                 switch (sigTag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) {
1249                   case 0:
1250                     break;
1251                   case RPMSIGTAG_PGP:
1252                     if ((sigTag == RPMSIGTAG_PGP || sigTag == RPMSIGTAG_PGP5) &&
1253                         !rpmDetectPGPVersion(NULL)) {
1254                         fprintf(stderr, _("pgp not found: "));
1255                         ec = EXIT_FAILURE;
1256                         goto exit;
1257                     }   /*@fallthrough@*/
1258                   case RPMSIGTAG_GPG:
1259                     passPhrase = rpmGetPassPhrase(_("Enter pass phrase: "), sigTag);
1260                     if (passPhrase == NULL) {
1261                         fprintf(stderr, _("Pass phrase check failed\n"));
1262                         ec = EXIT_FAILURE;
1263                         goto exit;
1264                     }
1265                     fprintf(stderr, _("Pass phrase is good.\n"));
1266                     passPhrase = xstrdup(passPhrase);
1267                     break;
1268                   default:
1269                     fprintf(stderr,
1270                             _("Invalid %%_signature spec in macro file.\n"));
1271                     ec = EXIT_FAILURE;
1272                     goto exit;
1273                     /*@notreached@*/ break;
1274                 }
1275             }
1276         } else {
1277             argerror(_("--sign may only be used during package building"));
1278         }
1279     } else {
1280         /* Make rpmLookupSignatureType() return 0 ("none") from now on */
1281         (void) rpmLookupSignatureType(RPMLOOKUPSIG_DISABLE);
1282     }
1283 #endif  /* IAM_RPMBT || IAM_RPMK */
1284
1285     if (pipeOutput) {
1286         (void) pipe(p);
1287
1288         if (!(pipeChild = fork())) {
1289             (void) close(p[1]);
1290             (void) dup2(p[0], STDIN_FILENO);
1291             (void) close(p[0]);
1292             (void) execl("/bin/sh", "/bin/sh", "-c", pipeOutput, NULL);
1293             fprintf(stderr, _("exec failed\n"));
1294         }
1295
1296         (void) close(p[0]);
1297         (void) dup2(p[1], STDOUT_FILENO);
1298         (void) close(p[1]);
1299     }
1300         
1301     switch (bigMode) {
1302 #ifdef  IAM_RPMDB
1303     case MODE_INITDB:
1304         (void) rpmdbInit(rootdir, 0644);
1305         break;
1306
1307     case MODE_REBUILDDB:
1308         ec = rpmdbRebuild(rootdir);
1309         break;
1310     case MODE_VERIFYDB:
1311         ec = rpmdbVerify(rootdir);
1312         break;
1313 #endif  /* IAM_RPMDB */
1314
1315 #ifdef  IAM_RPMBT
1316     case MODE_REBUILD:
1317     case MODE_RECOMPILE:
1318       { const char * pkg;
1319         while (!rpmIsVerbose())
1320             rpmIncreaseVerbosity();
1321
1322         if (!poptPeekArg(optCon))
1323             argerror(_("no packages files given for rebuild"));
1324
1325         ba->buildAmount = RPMBUILD_PREP | RPMBUILD_BUILD | RPMBUILD_INSTALL;
1326         if (bigMode == MODE_REBUILD) {
1327             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
1328             ba->buildAmount |= RPMBUILD_RMSOURCE;
1329             ba->buildAmount |= RPMBUILD_RMSPEC;
1330             ba->buildAmount |= RPMBUILD_CLEAN;
1331             ba->buildAmount |= RPMBUILD_RMBUILD;
1332         }
1333
1334         while ((pkg = poptGetArg(optCon))) {
1335             const char * specFile = NULL;
1336             char * cookie = NULL;
1337
1338             ec = rpmInstallSource("", pkg, &specFile, &cookie);
1339             if (ec)
1340                 /*@loopbreak@*/ break;
1341
1342             ba->rootdir = rootdir;
1343             ec = build(specFile, ba, passPhrase, cookie, rcfile);
1344             free(cookie);
1345             cookie = NULL;
1346             free((void *)specFile);
1347             specFile = NULL;
1348
1349             if (ec)
1350                 /*@loopbreak@*/ break;
1351         }
1352       } break;
1353
1354       case MODE_BUILD:
1355       case MODE_TARBUILD:
1356       { const char * pkg;
1357         while (!rpmIsVerbose())
1358             rpmIncreaseVerbosity();
1359        
1360         switch (ba->buildChar) {
1361         case 'a':
1362             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
1363             /*@fallthrough@*/
1364         case 'b':
1365             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
1366             ba->buildAmount |= RPMBUILD_CLEAN;
1367             /*@fallthrough@*/
1368         case 'i':
1369             ba->buildAmount |= RPMBUILD_INSTALL;
1370             if ((ba->buildChar == 'i') && ba->shortCircuit)
1371                 break;
1372             /*@fallthrough@*/
1373         case 'c':
1374             ba->buildAmount |= RPMBUILD_BUILD;
1375             if ((ba->buildChar == 'c') && ba->shortCircuit)
1376                 break;
1377             /*@fallthrough@*/
1378         case 'p':
1379             ba->buildAmount |= RPMBUILD_PREP;
1380             break;
1381             
1382         case 'l':
1383             ba->buildAmount |= RPMBUILD_FILECHECK;
1384             break;
1385         case 's':
1386             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
1387             break;
1388         }
1389
1390         if (!poptPeekArg(optCon)) {
1391             if (bigMode == MODE_BUILD)
1392                 argerror(_("no spec files given for build"));
1393             else
1394                 argerror(_("no tar files given for build"));
1395         }
1396
1397         while ((pkg = poptGetArg(optCon))) {
1398             ba->rootdir = rootdir;
1399             ec = build(pkg, ba, passPhrase, NULL, rcfile);
1400             if (ec)
1401                 /*@loopbreak@*/ break;
1402             rpmFreeMacros(NULL);
1403             (void) rpmReadConfigFiles(rcfile, NULL);
1404         }
1405       } break;
1406 #endif  /* IAM_RPMBT */
1407
1408 #ifdef  IAM_RPMEIU
1409     case MODE_UNINSTALL:
1410         if (!poptPeekArg(optCon))
1411             argerror(_("no packages given for uninstall"));
1412
1413         if (noDeps) eraseInterfaceFlags |= UNINSTALL_NODEPS;
1414
1415         ec = rpmErase(rootdir, (const char **)poptGetArgs(optCon), 
1416                          transFlags, eraseInterfaceFlags);
1417         break;
1418
1419     case MODE_INSTALL:
1420         if (force) {
1421             probFilter |= RPMPROB_FILTER_REPLACEPKG | 
1422                           RPMPROB_FILTER_REPLACEOLDFILES |
1423                           RPMPROB_FILTER_REPLACENEWFILES |
1424                           RPMPROB_FILTER_OLDPACKAGE;
1425         }
1426
1427         /* RPMTRANS_FLAG_BUILD_PROBS */
1428         /* RPMTRANS_FLAG_KEEPOBSOLETE */
1429
1430         if (!incldocs) {
1431             if (transFlags & RPMTRANS_FLAG_NODOCS)
1432                 ;
1433             else if (rpmExpandNumeric("%{_excludedocs}"))
1434                 transFlags |= RPMTRANS_FLAG_NODOCS;
1435         }
1436
1437         if (noDeps) installInterfaceFlags |= INSTALL_NODEPS;
1438
1439         if (!poptPeekArg(optCon))
1440             argerror(_("no packages given for install"));
1441
1442         /* we've already ensured !(!prefix && !relocations) */
1443         if (prefix) {
1444             relocations = alloca(2 * sizeof(*relocations));
1445             relocations[0].oldPath = NULL;   /* special case magic */
1446             relocations[0].newPath = prefix;
1447             relocations[1].oldPath = relocations[1].newPath = NULL;
1448         } else if (relocations) {
1449             relocations = xrealloc(relocations, 
1450                                   sizeof(*relocations) * (numRelocations + 1));
1451             relocations[numRelocations].oldPath = NULL;
1452             relocations[numRelocations].newPath = NULL;
1453         }
1454
1455         ec += rpmInstall(rootdir, (const char **)poptGetArgs(optCon), 
1456                         transFlags, installInterfaceFlags, probFilter,
1457                         relocations);
1458         break;
1459 #endif  /* IAM_RPMEIU */
1460
1461 #ifdef  IAM_RPMQV
1462     case MODE_QUERY:
1463       { const char * pkg;
1464
1465         qva->qva_prefix = rootdir;
1466         if (qva->qva_source == RPMQV_ALL) {
1467             if (poptPeekArg(optCon))
1468                 argerror(_("extra arguments given for query of all packages"));
1469
1470             ec = rpmQuery(qva, RPMQV_ALL, NULL);
1471         } else {
1472             if (!poptPeekArg(optCon))
1473                 argerror(_("no arguments given for query"));
1474             while ((pkg = poptGetArg(optCon)))
1475                 ec += rpmQuery(qva, qva->qva_source, pkg);
1476         }
1477       } break;
1478
1479     case MODE_VERIFY:
1480       { const char * pkg;
1481         int verifyFlags;
1482
1483         verifyFlags = (VERIFY_FILES|VERIFY_DEPS|VERIFY_SCRIPT|VERIFY_MD5);
1484         verifyFlags &= ~qva->qva_flags;
1485
1486         qva->qva_prefix = rootdir;
1487         qva->qva_flags = verifyFlags;
1488         if (qva->qva_source == RPMQV_ALL) {
1489             if (poptPeekArg(optCon))
1490                 argerror(_("extra arguments given for verify of all packages"));
1491             ec = rpmVerify(qva, RPMQV_ALL, NULL);
1492         } else {
1493             if (!poptPeekArg(optCon))
1494                 argerror(_("no arguments given for verify"));
1495             while ((pkg = poptGetArg(optCon)))
1496                 ec += rpmVerify(qva, qva->qva_source, pkg);
1497         }
1498       } break;
1499
1500     case MODE_QUERYTAGS:
1501         if (argc != 2)
1502             argerror(_("unexpected arguments to --querytags "));
1503
1504         rpmDisplayQueryTags(stdout);
1505         break;
1506 #endif  /* IAM_RPMQV */
1507
1508 #ifdef IAM_RPMK
1509     case MODE_CHECKSIG:
1510         if (!poptPeekArg(optCon))
1511             argerror(_("no packages given for signature check"));
1512         if (!noPgp) checksigFlags |= CHECKSIG_PGP;
1513         if (!noGpg) checksigFlags |= CHECKSIG_GPG;
1514         if (!noMd5) checksigFlags |= CHECKSIG_MD5;
1515         ec = rpmCheckSig(checksigFlags, (const char **)poptGetArgs(optCon));
1516         /* XXX don't overflow single byte exit status */
1517         if (ec > 255) ec = 255;
1518         break;
1519
1520     case MODE_RESIGN:
1521         if (!poptPeekArg(optCon))
1522             argerror(_("no packages given for signing"));
1523         ec = rpmReSign(addSign, passPhrase, (const char **)poptGetArgs(optCon));
1524         /* XXX don't overflow single byte exit status */
1525         if (ec > 255) ec = 255;
1526         break;
1527 #endif  /* IAM_RPMK */
1528         
1529 #if !defined(IAM_RPMQV)
1530     case MODE_QUERY:
1531     case MODE_VERIFY:
1532     case MODE_QUERYTAGS:
1533 #endif
1534 #if !defined(IAM_RPMK)
1535     case MODE_CHECKSIG:
1536     case MODE_RESIGN:
1537 #endif
1538 #if !defined(IAM_RPMDB)
1539     case MODE_INITDB:
1540     case MODE_REBUILDDB:
1541     case MODE_VERIFYDB:
1542 #endif
1543 #if !defined(IAM_RPMBT)
1544     case MODE_BUILD:
1545     case MODE_REBUILD:
1546     case MODE_RECOMPILE:
1547     case MODE_TARBUILD:
1548 #endif
1549 #if !defined(IAM_RPMEIU)
1550     case MODE_INSTALL:
1551     case MODE_UNINSTALL:
1552 #endif
1553     case MODE_UNKNOWN:
1554         if (!showVersion && !help && !noUsageMsg) printUsage();
1555         break;
1556     }
1557
1558 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
1559 exit:
1560 #endif  /* IAM_RPMBT || IAM_RPMK */
1561     optCon = poptFreeContext(optCon);
1562     rpmFreeMacros(NULL);
1563     rpmFreeMacros(&rpmCLIMacroContext);
1564     rpmFreeRpmrc();
1565
1566     if (pipeChild) {
1567         (void) fclose(stdout);
1568         (void) waitpid(pipeChild, &status, 0);
1569     }
1570
1571     /* keeps memory leak checkers quiet */
1572     freeNames();
1573     freeFilesystems();
1574     urlFreeCache();
1575
1576 #ifdef  IAM_RPMQV
1577     qva->qva_queryFormat = _free(qva->qva_queryFormat);
1578 #endif
1579
1580 #ifdef  IAM_RPMBT
1581     ba->buildRootOverride = _free(ba->buildRootOverride);
1582     ba->targets = _free(ba->targets);
1583 #endif
1584
1585 #if HAVE_MCHECK_H && HAVE_MTRACE
1586     muntrace();   /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
1587 #endif
1588     /*@-globstate@*/
1589     return ec;
1590     /*@=globstate@*/
1591 }