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