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