- fix: --noscripts is another multimode option.
[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 <rpmcli.h>
14 #include <rpmbuild.h>
15
16 #define POPT_NODEPS             1025
17 #define POPT_FORCE              1026
18 #define POPT_NOMD5              1027
19 #define POPT_NOSCRIPTS          1028
20
21 #ifdef  IAM_RPMBT
22 #include "build.h"
23 #define GETOPT_REBUILD          1003
24 #define GETOPT_RECOMPILE        1004
25 #endif
26
27 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
28 #include "signature.h"
29 #endif
30
31 #include "debug.h"
32
33 #define GETOPT_DBPATH           1010
34 #define GETOPT_SHOWRC           1018
35 #define GETOPT_DEFINEMACRO      1020
36 #define GETOPT_EVALMACRO        1021
37 #ifdef  NOTYET
38 #define GETOPT_RCFILE           1022
39 #endif
40
41 enum modes {
42
43     MODE_QUERY          = (1 <<  0),
44     MODE_VERIFY         = (1 <<  3),
45     MODE_QUERYTAGS      = (1 <<  9),
46 #define MODES_QV (MODE_QUERY | MODE_VERIFY)
47
48     MODE_INSTALL        = (1 <<  1),
49     MODE_ERASE          = (1 <<  2),
50     MODE_ROLLBACK       = (1 << 14),
51 #define MODES_IE (MODE_INSTALL | MODE_ERASE | MODE_ROLLBACK)
52
53     MODE_BUILD          = (1 <<  4),
54     MODE_REBUILD        = (1 <<  5),
55     MODE_RECOMPILE      = (1 <<  8),
56     MODE_TARBUILD       = (1 << 11),
57 #define MODES_BT (MODE_BUILD | MODE_TARBUILD | MODE_REBUILD | MODE_RECOMPILE)
58
59     MODE_CHECKSIG       = (1 <<  6),
60     MODE_RESIGN         = (1 <<  7),
61 #define MODES_K  (MODE_CHECKSIG | MODE_RESIGN)
62
63     MODE_INITDB         = (1 << 10),
64     MODE_REBUILDDB      = (1 << 12),
65     MODE_VERIFYDB       = (1 << 13),
66 #define MODES_DB (MODE_INITDB | MODE_REBUILDDB | MODE_VERIFYDB)
67
68
69     MODE_UNKNOWN        = 0
70 };
71
72 #define MODES_FOR_DBPATH        (MODES_BT | MODES_IE | MODES_QV | MODES_DB)
73 #define MODES_FOR_NODEPS        (MODES_BT | MODES_IE | MODE_VERIFY)
74 #define MODES_FOR_TEST          (MODES_BT | MODES_IE)
75 #define MODES_FOR_ROOT          (MODES_BT | MODES_IE | MODES_QV | MODES_DB)
76
77 /*@-exportheadervar@*/
78 extern int _ftp_debug;
79 extern int noLibio;
80 extern int _rpmio_debug;
81 extern int _url_debug;
82
83 /*@-varuse@*/
84 /*@observer@*/ extern const char * rpmNAME;
85 /*@=varuse@*/
86 /*@observer@*/ extern const char * rpmEVR;
87 /*@-varuse@*/
88 extern int rpmFLAGS;
89 /*@=varuse@*/
90
91 extern struct MacroContext_s rpmCLIMacroContext;
92 /*@=exportheadervar@*/
93
94 /* options for all executables */
95
96 static int help = 0;
97 static int noUsageMsg = 0;
98 /*@observer@*/ /*@null@*/ static const char * pipeOutput = NULL;
99 static int quiet = 0;
100 /*@observer@*/ /*@null@*/ static const char * rcfile = NULL;
101 /*@observer@*/ /*@null@*/ static char * rootdir = "/";
102 static int showrc = 0;
103 static int showVersion = 0;
104
105 static struct poptOption rpmAllPoptTable[] = {
106  { "version", '\0', 0, &showVersion, 0,
107         N_("print the version of rpm being used"),
108         NULL },
109  { "quiet", '\0', 0, &quiet, 0,
110         N_("provide less detailed output"), NULL},
111  { "verbose", 'v', 0, 0, 'v',
112         N_("provide more detailed output"), NULL},
113  { "define", '\0', POPT_ARG_STRING, 0, GETOPT_DEFINEMACRO,
114         N_("define macro <name> with value <body>"),
115         N_("'<name> <body>'") },
116  { "eval", '\0', POPT_ARG_STRING, 0, GETOPT_EVALMACRO,
117         N_("print macro expansion of <expr>+"),
118         N_("<expr>+") },
119  { "pipe", '\0', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &pipeOutput, 0,
120         N_("send stdout to <cmd>"),
121         N_("<cmd>") },
122  { "root", 'r', POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &rootdir, 0,
123         N_("use <dir> as the top level directory"),
124         N_("<dir>") },
125  { "macros", '\0', POPT_ARG_STRING, &macrofiles, 0,
126         N_("read <file:...> instead of default macro file(s)"),
127         N_("<file:...>") },
128 #if !defined(GETOPT_RCFILE)
129  { "rcfile", '\0', POPT_ARG_STRING, &rcfile, 0,
130         N_("read <file:...> instead of default rpmrc file(s)"),
131         N_("<file:...>") },
132 #else
133  { "rcfile", '\0', 0, 0, GETOPT_RCFILE, 
134         N_("read <file:...> instead of default rpmrc file(s)"),
135         N_("<file:...>") },
136 #endif
137  { "showrc", '\0', 0, &showrc, GETOPT_SHOWRC,
138         N_("display final rpmrc and macro configuration"),
139         NULL },
140
141 #if HAVE_LIBIO_H && defined(_G_IO_IO_FILE_VERSION)
142  { "nolibio", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &noLibio, 1,
143         N_("disable use of libio(3) API"), NULL},
144 #endif
145  { "ftpdebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_ftp_debug, -1,
146         N_("debug protocol data stream"), NULL},
147  { "rpmiodebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmio_debug, -1,
148         N_("debug rpmio I/O"), NULL},
149  { "urldebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_url_debug, -1,
150         N_("debug URL cache handling"), NULL},
151
152    POPT_TABLEEND
153 };
154
155 /* the structure describing the options we take and the defaults */
156 static struct poptOption optionsTable[] = {
157
158  /* XXX colliding options */
159 #if defined(IAM_RPMQV) || defined(IAM_RPMEIU) || defined(IAM_RPMBT)
160  {  NULL, 'i', POPT_ARGFLAG_DOC_HIDDEN, 0, 'i',                 NULL, NULL},
161  {  "nodeps", 0, POPT_ARGFLAG_DOC_HIDDEN, 0, POPT_NODEPS,       NULL, NULL},
162  {  "noscripts", 0, POPT_ARGFLAG_DOC_HIDDEN, 0, POPT_NOSCRIPTS, NULL, NULL},
163  {  "nomd5", 0, POPT_ARGFLAG_DOC_HIDDEN, 0, POPT_NOMD5,         NULL, NULL},
164  {  "force", 0, POPT_ARGFLAG_DOC_HIDDEN, 0, POPT_FORCE,         NULL, NULL},
165 #endif
166
167 #ifdef  IAM_RPMQV
168  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmQueryPoptTable, 0,
169         N_("Query options (with -q or --query):"),
170         NULL },
171  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmVerifyPoptTable, 0,
172         N_("Verify options (with -V or --verify):"),
173         NULL },
174 #endif  /* IAM_RPMQV */
175
176 #ifdef  IAM_RPMK
177  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmSignPoptTable, 0,
178         N_("Signature options:"),
179         NULL },
180 #endif  /* IAM_RPMK */
181
182 #ifdef  IAM_RPMDB
183  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmDatabasePoptTable, 0,
184         N_("Database options:"),
185         NULL },
186 #endif  /* IAM_RPMDB */
187
188 #ifdef  IAM_RPMBT
189  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmBuildPoptTable, 0,
190         N_("Build options with [ <specfile> | <tarball> | <source package> ]:"),
191         NULL },
192 #endif  /* IAM_RPMBT */
193
194 #ifdef  IAM_RPMEIU
195  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmInstallPoptTable, 0,
196         N_("Install/Upgrade/Erase options:"),
197         NULL },
198 #endif  /* IAM_RPMEIU */
199
200  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmAllPoptTable, 0,
201         N_("Common options for all rpm modes:"),
202         NULL },
203
204    POPT_AUTOALIAS
205    POPT_AUTOHELP
206    POPT_TABLEEND
207 };
208
209 #ifdef __MINT__
210 /* MiNT cannot dynamically increase the stack.  */
211 long _stksize = 64 * 1024L;
212 #endif
213
214 /*@exits@*/ static void argerror(const char * desc)
215         /*@modifies fileSystem @*/
216 {
217     fprintf(stderr, _("%s: %s\n"), __progname, desc);
218     exit(EXIT_FAILURE);
219 }
220
221 static void printVersion(void)
222         /*@modifies fileSystem @*/
223 {
224     fprintf(stdout, _("RPM version %s\n"), rpmEVR);
225 }
226
227 static void printBanner(void)
228         /*@modifies fileSystem @*/
229 {
230     (void) puts(_("Copyright (C) 1998-2000 - Red Hat, Inc."));
231     (void) puts(_("This program may be freely redistributed under the terms of the GNU GPL"));
232 }
233
234 static void printUsage(void)
235         /*@modifies fileSystem @*/
236 {
237     FILE * fp = stdout;
238     printVersion();
239     printBanner();
240     (void) puts("");
241
242     fprintf(fp, _("Usage: %s {--help}\n"), __progname);
243     fprintf(fp,  ("       %s {--version}\n"), __progname);
244
245 #ifdef  IAM_RPMEIU
246 #ifdef  DYING
247 --dbpath        all
248 --ftpproxy etc  all
249 --force         alias for --replacepkgs --replacefiles
250 --includedocs   handle as option in table
251                 --erase forbids many options
252 #endif  /* DYING */
253 #endif  /* IAM_RPMEIU */
254
255 #ifdef  IAM_RPMQV
256 #ifdef  DYING   /* XXX popt glue needing --help doco. */
257 --dbpath        all
258 --ftpproxy etc  all
259 -i,--info       Q
260 -R,--requires   Q
261 -P,--provides   Q
262 --scripts       Q
263 --triggeredby   Q
264 --changelog     Q
265 --triggers      Q
266 --querytags     !V
267 --setperms      V
268 --setugids      V
269 #endif  /* DYING */
270 #endif  /* IAM_RPMQV */
271
272 }
273
274 int main(int argc, const char ** argv)
275 {
276     enum modes bigMode = MODE_UNKNOWN;
277
278 #ifdef  IAM_RPMQV
279     QVA_t qva = &rpmQVArgs;
280 #endif
281
282 #ifdef  IAM_RPMBT
283     BTA_t ba = &rpmBTArgs;
284 #endif
285
286 #ifdef  IAM_RPMEIU
287    struct rpmInstallArguments_s * ia = &rpmIArgs;
288 #endif
289
290 #if defined(IAM_RPMDB)
291    struct rpmDatabaseArguments_s * da = &rpmDBArgs;
292 #endif
293
294 #if defined(IAM_RPMK)
295    struct rpmSignArguments_s * ka = &rpmKArgs;
296 #endif
297
298 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
299     char * passPhrase = "";
300 #endif
301
302     int arg;
303     int gotDbpath = 0;
304
305     const char * optArg;
306     pid_t pipeChild = 0;
307     poptContext optCon;
308     int ec = 0;
309     int status;
310     int p[2];
311         
312 #if HAVE_MCHECK_H && HAVE_MTRACE
313     mtrace();   /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
314 #endif
315     setprogname(argv[0]);       /* Retrofit glibc __progname */
316
317     /* XXX glibc churn sanity */
318     if (__progname == NULL) {
319         if ((__progname = strrchr(argv[0], '/')) != NULL) __progname++;
320         else __progname = argv[0];
321     }
322
323     /* Set the major mode based on argv[0] */
324     /*@-nullpass@*/
325 #ifdef  IAM_RPMBT
326     if (!strcmp(__progname, "rpmb"))    bigMode = MODE_BUILD;
327     if (!strcmp(__progname, "rpmt"))    bigMode = MODE_TARBUILD;
328     if (!strcmp(__progname, "rpmbuild"))        bigMode = MODE_BUILD;
329 #endif
330 #ifdef  IAM_RPMQV
331     if (!strcmp(__progname, "rpmq"))    bigMode = MODE_QUERY;
332     if (!strcmp(__progname, "rpmv"))    bigMode = MODE_VERIFY;
333     if (!strcmp(__progname, "rpmquery"))        bigMode = MODE_QUERY;
334     if (!strcmp(__progname, "rpmverify"))       bigMode = MODE_VERIFY;
335 #endif
336 #ifdef  RPMEIU
337     if (!strcmp(__progname, "rpme"))    bigMode = MODE_ERASE;
338     if (!strcmp(__progname, "rpmi"))    bigMode = MODE_INSTALL;
339     if (!strcmp(__progname, "rpmu"))    bigMode = MODE_INSTALL;
340 #endif
341     /*@=nullpass@*/
342
343     /* set the defaults for the various command line options */
344     _ftp_debug = 0;
345
346 #if HAVE_LIBIO_H && defined(_G_IO_IO_FILE_VERSION)
347     noLibio = 0;
348 #else
349     noLibio = 1;
350 #endif
351     _rpmio_debug = 0;
352     _url_debug = 0;
353
354     /* XXX Eliminate query linkage loop */
355     specedit = 0;
356     parseSpecVec = parseSpec;
357     freeSpecVec = freeSpec;
358
359     /* set up the correct locale */
360     (void) setlocale(LC_ALL, "" );
361
362 #ifdef  __LCLINT__
363 #define LOCALEDIR       "/usr/share/locale"
364 #endif
365     bindtextdomain(PACKAGE, LOCALEDIR);
366     textdomain(PACKAGE);
367
368     rpmSetVerbosity(RPMMESS_NORMAL);    /* XXX silly use by showrc */
369
370     /* Make a first pass through the arguments, looking for --rcfile */
371     /* We need to handle that before dealing with the rest of the arguments. */
372     /*@-nullpass -temptrans@*/
373     optCon = poptGetContext(__progname, argc, argv, optionsTable, 0);
374     /*@=nullpass =temptrans@*/
375     (void) poptReadConfigFile(optCon, LIBRPMALIAS_FILENAME);
376     (void) poptReadDefaultConfig(optCon, 1);
377     poptSetExecPath(optCon, RPMCONFIGDIR, 1);
378
379     /* reading rcfile early makes it easy to override */
380     /* XXX only --rcfile (and --showrc) need this pre-parse */
381
382     while ((arg = poptGetNextOpt(optCon)) > 0) {
383         switch(arg) {
384         case 'v':
385             rpmIncreaseVerbosity();     /* XXX silly use by showrc */
386             break;
387         default:
388             break;
389       }
390     }
391
392     if (rpmReadConfigFiles(rcfile, NULL))  
393         exit(EXIT_FAILURE);
394
395     if (showrc) {
396         (void) rpmShowRC(stdout);
397         exit(EXIT_SUCCESS);
398     }
399
400     rpmSetVerbosity(RPMMESS_NORMAL);    /* XXX silly use by showrc */
401
402     poptResetContext(optCon);
403
404 #ifdef  IAM_RPMQV
405     qva->qva_queryFormat = _free(qva->qva_queryFormat);
406     memset(qva, 0, sizeof(*qva));
407     qva->qva_source = RPMQV_PACKAGE;
408     qva->qva_fflags = RPMFILE_ALL;
409     qva->qva_mode = ' ';
410     qva->qva_char = ' ';
411 #endif
412
413 #ifdef  IAM_RPMBT
414     ba->buildRootOverride = _free(ba->buildRootOverride);
415     ba->targets = _free(ba->targets);
416     memset(ba, 0, sizeof(*ba));
417     ba->buildMode = ' ';
418     ba->buildChar = ' ';
419 #endif
420
421 #ifdef  IAM_RPMDB
422     memset(da, 0, sizeof(*da));
423 #endif
424
425 #ifdef  IAM_RPMK
426     memset(ka, 0, sizeof(*ka));
427     ka->addSign = RESIGN_NONE;
428     ka->checksigFlags = CHECKSIG_ALL;
429 #endif
430
431 #ifdef  IAM_RPMEIU
432     ia->relocations = _free(ia->relocations);
433     memset(ia, 0, sizeof(*ia));
434     ia->transFlags = RPMTRANS_FLAG_NONE;
435     ia->probFilter = RPMPROB_FILTER_NONE;
436     ia->installInterfaceFlags = INSTALL_NONE;
437     ia->eraseInterfaceFlags = UNINSTALL_NONE;
438 #endif
439
440     while ((arg = poptGetNextOpt(optCon)) > 0) {
441         optArg = poptGetOptArg(optCon);
442
443         switch (arg) {
444             
445         case 'v':
446             rpmIncreaseVerbosity();
447             break;
448
449 /* XXX options used in multiple rpm modes */
450 #if defined(IAM_RPMQV) || defined(IAM_RPMK)
451         case POPT_NOMD5:
452 #ifdef  IAM_RPMQV
453             if (bigMode == MODE_VERIFY || qva->qva_mode == 'V')
454                 qva->qva_flags |= VERIFY_MD5;
455             else
456 #endif
457 #ifdef  IAM_RPMK
458             if (bigMode & MODES_K)
459                 ka->checksigFlags &= ~CHECKSIG_MD5;
460             else
461 #endif
462                 /*@-ifempty@*/ ;
463             break;
464 #endif  /* IAM_RPMQV || IAM_RPMK */
465
466 #if defined(IAM_RPMQV) || defined(IAM_RPMEIU) || defined(IAM_RPMBT)
467         case POPT_NODEPS:
468 #ifdef  IAM_RPMQV
469             if (bigMode == MODE_VERIFY || qva->qva_mode == 'V')
470                 qva->qva_flags |= VERIFY_DEPS;
471             else
472 #endif
473 #ifdef  IAM_RPMEIU
474             if ((bigMode & MODES_IE) ||
475                 (ia->installInterfaceFlags &
476             (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL|INSTALL_ERASE)))
477                 ia->noDeps = 1;
478             else
479 #endif
480 #ifdef  IAM_RPMBT
481             if ((bigMode & MODES_BT) || ba->buildMode != ' ')
482                 ba->noDeps = 1;
483             else
484 #endif
485                 /*@-ifempty@*/ ;
486             break;
487
488         case POPT_FORCE:
489 #ifdef  IAM_RPMEIU
490             if ((bigMode & MODES_IE) ||
491                 (ia->installInterfaceFlags &
492             (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL|INSTALL_ERASE)))
493                 ia->probFilter |=
494                         ( RPMPROB_FILTER_REPLACEPKG
495                         | RPMPROB_FILTER_REPLACEOLDFILES
496                         | RPMPROB_FILTER_REPLACENEWFILES
497                         | RPMPROB_FILTER_OLDPACKAGE);
498             else
499 #endif
500 #ifdef  IAM_RPMBT
501             if ((bigMode & MODES_BT) || ba->buildMode != ' ')
502                 ba->force = 1;
503             else
504 #endif
505                 /*@-ifempty@*/ ;
506             break;
507
508         case 'i':
509 #ifdef  IAM_RPMQV
510             if (bigMode == MODE_QUERY || qva->qva_mode == 'q') {
511                 /*@-nullassign -readonlytrans@*/
512                 const char * infoCommand[] = { "--info", NULL };
513                 /*@=nullassign =readonlytrans@*/
514                 (void) poptStuffArgs(optCon, infoCommand);
515             } else
516 #endif
517 #ifdef  IAM_RPMEIU
518             if (bigMode == MODE_INSTALL ||
519                 (ia->installInterfaceFlags &
520                     (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL)))
521                 /*@-ifempty@*/ ;
522             else if (bigMode == MODE_UNKNOWN) {
523                 /*@-nullassign -readonlytrans@*/
524                 const char * installCommand[] = { "--install", NULL };
525                 /*@=nullassign =readonlytrans@*/
526                 (void) poptStuffArgs(optCon, installCommand);
527             } else
528 #endif
529                 /*@-ifempty@*/ ;
530             break;
531
532         case POPT_NOSCRIPTS:
533 #ifdef  IAM_RPMQV
534             if (bigMode == MODE_VERIFY || qva->qva_mode == 'V')
535                 qva->qva_flags |= VERIFY_SCRIPT;
536             else
537 #endif
538 #ifdef  IAM_RPMEIU
539             if ((bigMode & MODES_IE) ||
540                 (ia->installInterfaceFlags &
541             (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL|INSTALL_ERASE)))
542                 ia->transFlags |= (_noTransScripts | _noTransTriggers);
543             else
544 #endif
545                 /*@-ifempty@*/ ;
546             break;
547
548 #endif  /* IAM_RPMQV || IAM_RPMEIU || IAM_RPMBT */
549
550         case GETOPT_DEFINEMACRO:
551             if (optArg) {
552                 (void) rpmDefineMacro(NULL, optArg, RMIL_CMDLINE);
553                 (void) rpmDefineMacro(&rpmCLIMacroContext, optArg,RMIL_CMDLINE);
554             }
555             noUsageMsg = 1;
556             break;
557
558         case GETOPT_EVALMACRO:
559             if (optArg) {
560                 const char *val = rpmExpand(optArg, NULL);
561                 fprintf(stdout, "%s\n", val);
562                 val = _free(val);
563             }
564             noUsageMsg = 1;
565             break;
566
567 #if defined(GETOPT_RCFILE)
568         case GETOPT_RCFILE:
569             fprintf(stderr, _("The --rcfile option has been eliminated.\n"));
570             fprintf(stderr, _("Use \"--macros <file:...>\" instead.\n"));
571             exit(EXIT_FAILURE);
572             /*@notreached@*/ break;
573 #endif
574
575         default:
576             fprintf(stderr, _("Internal error in argument processing (%d) :-(\n"), arg);
577             exit(EXIT_FAILURE);
578         }
579     }
580
581     if (quiet)
582         rpmSetVerbosity(RPMMESS_QUIET);
583
584     if (showVersion) printVersion();
585
586     if (arg < -1) {
587         fprintf(stderr, "%s: %s\n", 
588                 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 
589                 poptStrerror(arg));
590         exit(EXIT_FAILURE);
591     }
592
593 #ifdef  IAM_RPMBT
594     switch (ba->buildMode) {
595     case 'b':   bigMode = MODE_BUILD;           break;
596     case 't':   bigMode = MODE_TARBUILD;        break;
597     case 'B':   bigMode = MODE_REBUILD;         break;
598     case 'C':   bigMode = MODE_RECOMPILE;       break;
599     }
600
601     if ((ba->buildAmount & RPMBUILD_RMSOURCE) && bigMode == MODE_UNKNOWN)
602         bigMode = MODE_BUILD;
603
604     if ((ba->buildAmount & RPMBUILD_RMSPEC) && bigMode == MODE_UNKNOWN)
605         bigMode = MODE_BUILD;
606
607     if (ba->buildRootOverride && bigMode != MODE_BUILD &&
608         bigMode != MODE_REBUILD && bigMode != MODE_TARBUILD) {
609         argerror("--buildroot may only be used during package builds");
610     }
611 #endif  /* IAM_RPMBT */
612     
613 #ifdef  IAM_RPMDB
614   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_DB)) {
615     if (da->init) {
616         if (bigMode != MODE_UNKNOWN) 
617             argerror(_("only one major mode may be specified"));
618         else
619             bigMode = MODE_INITDB;
620     } else
621     if (da->rebuild) {
622         if (bigMode != MODE_UNKNOWN) 
623             argerror(_("only one major mode may be specified"));
624         else
625             bigMode = MODE_REBUILDDB;
626     } else
627     if (da->verify) {
628         if (bigMode != MODE_UNKNOWN) 
629             argerror(_("only one major mode may be specified"));
630         else
631             bigMode = MODE_VERIFYDB;
632     }
633   }
634 #endif  /* IAM_RPMDB */
635
636 #ifdef  IAM_RPMQV
637   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_QV)) {
638     switch (qva->qva_mode) {
639     case 'q':   bigMode = MODE_QUERY;           break;
640     case 'V':   bigMode = MODE_VERIFY;          break;
641     case 'Q':   bigMode = MODE_QUERYTAGS;       break;
642     }
643
644     if (qva->qva_sourceCount) {
645         if (qva->qva_sourceCount > 2)
646             argerror(_("one type of query/verify may be performed at a "
647                         "time"));
648     }
649     if (qva->qva_flags && (bigMode & ~MODES_QV)) 
650         argerror(_("unexpected query flags"));
651
652     if (qva->qva_queryFormat && (bigMode & ~MODES_QV)) 
653         argerror(_("unexpected query format"));
654
655     if (qva->qva_source != RPMQV_PACKAGE && (bigMode & ~MODES_QV)) 
656         argerror(_("unexpected query source"));
657   }
658 #endif  /* IAM_RPMQV */
659
660 #ifdef  IAM_RPMEIU
661   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_IE))
662     {   int iflags = (ia->installInterfaceFlags &
663                 (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL));
664         int eflags = (ia->installInterfaceFlags & INSTALL_ERASE);
665
666         if (iflags & eflags)
667             argerror(_("only one major mode may be specified"));
668         else if (iflags)
669             bigMode = MODE_INSTALL;
670         else if (eflags)
671             bigMode = MODE_ERASE;
672     }
673 #endif  /* IAM_RPMQV */
674
675 #ifdef  IAM_RPMK
676   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_K)) {
677         switch (ka->addSign) {
678         case RESIGN_NONE:
679             break;
680         case RESIGN_CHK_SIGNATURE:
681             bigMode = MODE_CHECKSIG;
682             break;
683         case RESIGN_ADD_SIGNATURE:
684         case RESIGN_NEW_SIGNATURE:
685             bigMode = MODE_RESIGN;
686             break;
687
688         }
689   }
690 #endif  /* IAM_RPMK */
691
692     /* XXX TODO: never happens. */
693     if (gotDbpath && (bigMode & ~MODES_FOR_DBPATH))
694         argerror(_("--dbpath given for operation that does not use a "
695                         "database"));
696
697 #if defined(IAM_RPMEIU)
698     if (!( bigMode == MODE_INSTALL ) &&
699 (ia->probFilter & (RPMPROB_FILTER_REPLACEPKG | RPMPROB_FILTER_REPLACEOLDFILES | RPMPROB_FILTER_REPLACENEWFILES | RPMPROB_FILTER_OLDPACKAGE)))
700         argerror(_("only installation, upgrading, rmsource and rmspec may be forced"));
701     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_FORCERELOCATE))
702         argerror(_("files may only be relocated during package installation"));
703
704     if (ia->relocations && ia->prefix)
705         argerror(_("only one of --prefix or --relocate may be used"));
706
707     if (bigMode != MODE_INSTALL && ia->relocations)
708         argerror(_("--relocate and --excludepath may only be used when installing new packages"));
709
710     if (bigMode != MODE_INSTALL && ia->prefix)
711         argerror(_("--prefix may only be used when installing new packages"));
712
713     if (ia->prefix && ia->prefix[0] != '/') 
714         argerror(_("arguments to --prefix must begin with a /"));
715
716     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_HASH))
717         argerror(_("--hash (-h) may only be specified during package "
718                         "installation"));
719
720     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_PERCENT))
721         argerror(_("--percent may only be specified during package "
722                         "installation"));
723
724     if (bigMode != MODE_INSTALL &&
725  (ia->probFilter & (RPMPROB_FILTER_REPLACEOLDFILES|RPMPROB_FILTER_REPLACENEWFILES)))
726         argerror(_("--replacefiles may only be specified during package "
727                         "installation"));
728
729     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_REPLACEPKG))
730         argerror(_("--replacepkgs may only be specified during package "
731                         "installation"));
732
733     if (bigMode != MODE_INSTALL && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
734         argerror(_("--excludedocs may only be specified during package "
735                    "installation"));
736
737     if (bigMode != MODE_INSTALL && ia->incldocs)
738         argerror(_("--includedocs may only be specified during package "
739                    "installation"));
740
741     if (ia->incldocs && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
742         argerror(_("only one of --excludedocs and --includedocs may be "
743                  "specified"));
744   
745     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREARCH))
746         argerror(_("--ignorearch may only be specified during package "
747                    "installation"));
748
749     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREOS))
750         argerror(_("--ignoreos may only be specified during package "
751                    "installation"));
752
753     if (bigMode != MODE_INSTALL &&
754         (ia->probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES)))
755         argerror(_("--ignoresize may only be specified during package "
756                    "installation"));
757
758     if ((ia->eraseInterfaceFlags & UNINSTALL_ALLMATCHES) && bigMode != MODE_ERASE)
759         argerror(_("--allmatches may only be specified during package "
760                    "erasure"));
761
762     if ((ia->transFlags & RPMTRANS_FLAG_ALLFILES) && bigMode != MODE_INSTALL)
763         argerror(_("--allfiles may only be specified during package "
764                    "installation"));
765
766     if ((ia->transFlags & RPMTRANS_FLAG_JUSTDB) &&
767         bigMode != MODE_INSTALL && bigMode != MODE_ERASE)
768         argerror(_("--justdb may only be specified during package "
769                    "installation and erasure"));
770
771     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
772         (ia->transFlags & (RPMTRANS_FLAG_NOSCRIPTS | _noTransScripts | _noTransTriggers)))
773         argerror(_("script disabling options may only be specified during "
774                    "package installation and erasure"));
775
776     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
777         (ia->transFlags & (RPMTRANS_FLAG_NOTRIGGERS | _noTransTriggers)))
778         argerror(_("trigger disabling options may only be specified during "
779                    "package installation and erasure"));
780
781     if (ia->noDeps & (bigMode & ~MODES_FOR_NODEPS))
782         argerror(_("--nodeps may only be specified during package "
783                    "building, rebuilding, recompilation, installation,"
784                    "erasure, and verification"));
785
786     if ((ia->transFlags & RPMTRANS_FLAG_TEST) && (bigMode & ~MODES_FOR_TEST))
787         argerror(_("--test may only be specified during package installation, "
788                  "erasure, and building"));
789 #endif  /* IAM_RPMEIU */
790
791     if (rootdir && rootdir[1] && (bigMode & ~MODES_FOR_ROOT))
792         argerror(_("--root (-r) may only be specified during "
793                  "installation, erasure, querying, and "
794                  "database rebuilds"));
795
796     if (rootdir) {
797         switch (urlIsURL(rootdir)) {
798         default:
799             if (bigMode & MODES_FOR_ROOT)
800                 break;
801             /*@fallthrough@*/
802         case URL_IS_UNKNOWN:
803             if (rootdir[0] != '/')
804                 argerror(_("arguments to --root (-r) must begin with a /"));
805             break;
806         }
807     }
808
809 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
810     if (0
811 #if defined(IAM_RPMBT)
812     || ba->sign 
813 #endif
814 #if defined(IAM_RPMK)
815     || ka->sign
816 #endif
817     ) {
818         if (bigMode == MODE_REBUILD || bigMode == MODE_BUILD ||
819             bigMode == MODE_RESIGN || bigMode == MODE_TARBUILD) {
820             const char ** av;
821             struct stat sb;
822             int errors = 0;
823
824             if ((av = poptGetArgs(optCon)) == NULL) {
825                 fprintf(stderr, _("no files to sign\n"));
826                 errors++;
827             } else
828             while (*av) {
829                 if (stat(*av, &sb)) {
830                     fprintf(stderr, _("cannot access file %s\n"), *av);
831                     errors++;
832                 }
833                 av++;
834             }
835
836             if (errors) {
837                 ec = errors;
838                 goto exit;
839             }
840
841             if (poptPeekArg(optCon)) {
842                 int sigTag;
843                 switch (sigTag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) {
844                   case 0:
845                     break;
846                   case RPMSIGTAG_PGP:
847                     if ((sigTag == RPMSIGTAG_PGP || sigTag == RPMSIGTAG_PGP5) &&
848                         !rpmDetectPGPVersion(NULL)) {
849                         fprintf(stderr, _("pgp not found: "));
850                         ec = EXIT_FAILURE;
851                         goto exit;
852                     }   /*@fallthrough@*/
853                   case RPMSIGTAG_GPG:
854                     passPhrase = rpmGetPassPhrase(_("Enter pass phrase: "), sigTag);
855                     if (passPhrase == NULL) {
856                         fprintf(stderr, _("Pass phrase check failed\n"));
857                         ec = EXIT_FAILURE;
858                         goto exit;
859                     }
860                     fprintf(stderr, _("Pass phrase is good.\n"));
861                     passPhrase = xstrdup(passPhrase);
862                     break;
863                   default:
864                     fprintf(stderr,
865                             _("Invalid %%_signature spec in macro file.\n"));
866                     ec = EXIT_FAILURE;
867                     goto exit;
868                     /*@notreached@*/ break;
869                 }
870             }
871         } else {
872             argerror(_("--sign may only be used during package building"));
873         }
874     } else {
875         /* Make rpmLookupSignatureType() return 0 ("none") from now on */
876         (void) rpmLookupSignatureType(RPMLOOKUPSIG_DISABLE);
877     }
878 #endif  /* IAM_RPMBT || IAM_RPMK */
879
880     if (pipeOutput) {
881         (void) pipe(p);
882
883         if (!(pipeChild = fork())) {
884             (void) close(p[1]);
885             (void) dup2(p[0], STDIN_FILENO);
886             (void) close(p[0]);
887             (void) execl("/bin/sh", "/bin/sh", "-c", pipeOutput, NULL);
888             fprintf(stderr, _("exec failed\n"));
889         }
890
891         (void) close(p[0]);
892         (void) dup2(p[1], STDOUT_FILENO);
893         (void) close(p[1]);
894     }
895         
896     switch (bigMode) {
897 #ifdef  IAM_RPMDB
898     case MODE_INITDB:
899         (void) rpmdbInit(rootdir, 0644);
900         break;
901
902     case MODE_REBUILDDB:
903         ec = rpmdbRebuild(rootdir);
904         break;
905     case MODE_VERIFYDB:
906         ec = rpmdbVerify(rootdir);
907         break;
908 #endif  /* IAM_RPMDB */
909
910 #ifdef  IAM_RPMBT
911     case MODE_REBUILD:
912     case MODE_RECOMPILE:
913       { const char * pkg;
914         while (!rpmIsVerbose())
915             rpmIncreaseVerbosity();
916
917         if (!poptPeekArg(optCon))
918             argerror(_("no packages files given for rebuild"));
919
920         ba->buildAmount = RPMBUILD_PREP | RPMBUILD_BUILD | RPMBUILD_INSTALL;
921         if (bigMode == MODE_REBUILD) {
922             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
923             ba->buildAmount |= RPMBUILD_RMSOURCE;
924             ba->buildAmount |= RPMBUILD_RMSPEC;
925             ba->buildAmount |= RPMBUILD_CLEAN;
926             ba->buildAmount |= RPMBUILD_RMBUILD;
927         }
928
929         while ((pkg = poptGetArg(optCon))) {
930             const char * specFile = NULL;
931             char * cookie = NULL;
932
933             ec = rpmInstallSource("", pkg, &specFile, &cookie);
934             if (ec)
935                 /*@loopbreak@*/ break;
936
937             ba->rootdir = rootdir;
938             ec = build(specFile, ba, passPhrase, cookie, rcfile);
939             free(cookie);
940             cookie = NULL;
941             free((void *)specFile);
942             specFile = NULL;
943
944             if (ec)
945                 /*@loopbreak@*/ break;
946         }
947       } break;
948
949       case MODE_BUILD:
950       case MODE_TARBUILD:
951       { const char * pkg;
952         while (!rpmIsVerbose())
953             rpmIncreaseVerbosity();
954        
955         switch (ba->buildChar) {
956         case 'a':
957             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
958             /*@fallthrough@*/
959         case 'b':
960             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
961             ba->buildAmount |= RPMBUILD_CLEAN;
962             /*@fallthrough@*/
963         case 'i':
964             ba->buildAmount |= RPMBUILD_INSTALL;
965             if ((ba->buildChar == 'i') && ba->shortCircuit)
966                 break;
967             /*@fallthrough@*/
968         case 'c':
969             ba->buildAmount |= RPMBUILD_BUILD;
970             if ((ba->buildChar == 'c') && ba->shortCircuit)
971                 break;
972             /*@fallthrough@*/
973         case 'p':
974             ba->buildAmount |= RPMBUILD_PREP;
975             break;
976             
977         case 'l':
978             ba->buildAmount |= RPMBUILD_FILECHECK;
979             break;
980         case 's':
981             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
982             break;
983         }
984
985         if (!poptPeekArg(optCon)) {
986             if (bigMode == MODE_BUILD)
987                 argerror(_("no spec files given for build"));
988             else
989                 argerror(_("no tar files given for build"));
990         }
991
992         while ((pkg = poptGetArg(optCon))) {
993             ba->rootdir = rootdir;
994             ec = build(pkg, ba, passPhrase, NULL, rcfile);
995             if (ec)
996                 /*@loopbreak@*/ break;
997             rpmFreeMacros(NULL);
998             (void) rpmReadConfigFiles(rcfile, NULL);
999         }
1000       } break;
1001 #endif  /* IAM_RPMBT */
1002
1003 #ifdef  IAM_RPMEIU
1004     case MODE_ERASE:
1005         if (!poptPeekArg(optCon))
1006             argerror(_("no packages given for uninstall"));
1007
1008         if (ia->noDeps) ia->eraseInterfaceFlags |= UNINSTALL_NODEPS;
1009
1010         ec = rpmErase(rootdir, (const char **)poptGetArgs(optCon), 
1011                          ia->transFlags, ia->eraseInterfaceFlags);
1012         break;
1013
1014     case MODE_INSTALL:
1015
1016         if (!poptPeekArg(optCon))
1017             argerror(_("no packages given for install"));
1018
1019         /* RPMTRANS_FLAG_BUILD_PROBS */
1020         /* RPMTRANS_FLAG_KEEPOBSOLETE */
1021
1022         if (!ia->incldocs) {
1023             if (ia->transFlags & RPMTRANS_FLAG_NODOCS)
1024                 ;
1025             else if (rpmExpandNumeric("%{_excludedocs}"))
1026                 ia->transFlags |= RPMTRANS_FLAG_NODOCS;
1027         }
1028
1029         if (ia->noDeps) ia->installInterfaceFlags |= INSTALL_NODEPS;
1030
1031         /* we've already ensured !(!ia->prefix && !ia->relocations) */
1032         if (ia->prefix) {
1033             ia->relocations = xmalloc(2 * sizeof(*ia->relocations));
1034             ia->relocations[0].oldPath = NULL;   /* special case magic */
1035             ia->relocations[0].newPath = ia->prefix;
1036             ia->relocations[1].oldPath = ia->relocations[1].newPath = NULL;
1037         } else if (ia->relocations) {
1038             ia->relocations = xrealloc(ia->relocations, 
1039                         sizeof(*ia->relocations) * (ia->numRelocations + 1));
1040             ia->relocations[ia->numRelocations].oldPath = NULL;
1041             ia->relocations[ia->numRelocations].newPath = NULL;
1042         }
1043
1044         ec += rpmInstall(rootdir, (const char **)poptGetArgs(optCon), 
1045                         ia->transFlags, ia->installInterfaceFlags, ia->probFilter,
1046                         ia->relocations);
1047         break;
1048
1049     case MODE_ROLLBACK:
1050         ia->rootdir = rootdir;
1051         ec += rpmRollback(ia, (const char **)poptGetArgs(optCon));
1052         break;
1053
1054 #endif  /* IAM_RPMEIU */
1055
1056 #ifdef  IAM_RPMQV
1057     case MODE_QUERY:
1058       { const char * pkg;
1059
1060         qva->qva_prefix = rootdir;
1061         if (qva->qva_source == RPMQV_ALL) {
1062 #ifdef  DYING
1063             if (poptPeekArg(optCon))
1064                 argerror(_("extra arguments given for query of all packages"));
1065 #else
1066             const char ** av = poptGetArgs(optCon);
1067 #endif
1068             /*@-nullpass@*/     /* FIX: av can be NULL */
1069             ec = rpmQuery(qva, RPMQV_ALL, (const char *) av);
1070             /*@=nullpass@*/
1071         } else {
1072             if (!poptPeekArg(optCon))
1073                 argerror(_("no arguments given for query"));
1074             while ((pkg = poptGetArg(optCon)))
1075                 ec += rpmQuery(qva, qva->qva_source, pkg);
1076         }
1077       } break;
1078
1079     case MODE_VERIFY:
1080       { const char * pkg;
1081         rpmVerifyFlags verifyFlags = VERIFY_ALL;
1082
1083         verifyFlags &= ~qva->qva_flags;
1084         qva->qva_flags = (rpmQueryFlags) verifyFlags;
1085         qva->qva_prefix = rootdir;
1086
1087         if (qva->qva_source == RPMQV_ALL) {
1088             if (poptPeekArg(optCon))
1089                 argerror(_("extra arguments given for verify of all packages"));
1090             ec = rpmVerify(qva, RPMQV_ALL, NULL);
1091         } else {
1092             if (!poptPeekArg(optCon))
1093                 argerror(_("no arguments given for verify"));
1094             while ((pkg = poptGetArg(optCon)))
1095                 ec += rpmVerify(qva, qva->qva_source, pkg);
1096         }
1097       } break;
1098
1099     case MODE_QUERYTAGS:
1100         if (argc != 2)
1101             argerror(_("unexpected arguments to --querytags "));
1102
1103         rpmDisplayQueryTags(stdout);
1104         break;
1105 #endif  /* IAM_RPMQV */
1106
1107 #ifdef IAM_RPMK
1108     case MODE_CHECKSIG:
1109         if (!poptPeekArg(optCon))
1110             argerror(_("no packages given for signature check"));
1111         ec = rpmCheckSig(ka->checksigFlags,
1112                         (const char **)poptGetArgs(optCon));
1113         /* XXX don't overflow single byte exit status */
1114         if (ec > 255) ec = 255;
1115         break;
1116
1117     case MODE_RESIGN:
1118         if (!poptPeekArg(optCon))
1119             argerror(_("no packages given for signing"));
1120         ec = rpmReSign(ka->addSign, passPhrase,
1121                         (const char **)poptGetArgs(optCon));
1122         /* XXX don't overflow single byte exit status */
1123         if (ec > 255) ec = 255;
1124         break;
1125 #endif  /* IAM_RPMK */
1126         
1127 #if !defined(IAM_RPMQV)
1128     case MODE_QUERY:
1129     case MODE_VERIFY:
1130     case MODE_QUERYTAGS:
1131 #endif
1132 #if !defined(IAM_RPMK)
1133     case MODE_CHECKSIG:
1134     case MODE_RESIGN:
1135 #endif
1136 #if !defined(IAM_RPMDB)
1137     case MODE_INITDB:
1138     case MODE_REBUILDDB:
1139     case MODE_VERIFYDB:
1140 #endif
1141 #if !defined(IAM_RPMBT)
1142     case MODE_BUILD:
1143     case MODE_REBUILD:
1144     case MODE_RECOMPILE:
1145     case MODE_TARBUILD:
1146 #endif
1147 #if !defined(IAM_RPMEIU)
1148     case MODE_INSTALL:
1149     case MODE_ERASE:
1150     case MODE_ROLLBACK:
1151 #endif
1152     case MODE_UNKNOWN:
1153         if (!showVersion && !help && !noUsageMsg) printUsage();
1154         break;
1155     }
1156
1157 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
1158 exit:
1159 #endif  /* IAM_RPMBT || IAM_RPMK */
1160     optCon = poptFreeContext(optCon);
1161     rpmFreeMacros(NULL);
1162     rpmFreeMacros(&rpmCLIMacroContext);
1163     rpmFreeRpmrc();
1164
1165     if (pipeChild) {
1166         (void) fclose(stdout);
1167         (void) waitpid(pipeChild, &status, 0);
1168     }
1169
1170     /* keeps memory leak checkers quiet */
1171     freeNames();
1172     freeFilesystems();
1173     urlFreeCache();
1174     rpmlogClose();
1175     dbiTags = _free(dbiTags);
1176
1177 #ifdef  IAM_RPMQV
1178     qva->qva_queryFormat = _free(qva->qva_queryFormat);
1179 #endif
1180
1181 #ifdef  IAM_RPMBT
1182     ba->buildRootOverride = _free(ba->buildRootOverride);
1183     ba->targets = _free(ba->targets);
1184 #endif
1185
1186 #ifdef  IAM_RPMEIU
1187     ia->relocations = _free(ia->relocations);
1188 #endif
1189
1190 #if HAVE_MCHECK_H && HAVE_MTRACE
1191     muntrace();   /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
1192 #endif
1193     /*@-globstate@*/
1194     return ec;
1195     /*@=globstate@*/
1196 }