Splint fiddles.
[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 #include "rpmdb.h"
17 #include "rpmps.h"
18 #include "rpmts.h"
19
20 #ifdef  IAM_RPMBT
21 #include "build.h"
22 #define GETOPT_REBUILD          1003
23 #define GETOPT_RECOMPILE        1004
24 #endif
25
26 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
27 #include "signature.h"
28 #endif
29
30 #include "debug.h"
31
32 enum modes {
33
34     MODE_QUERY          = (1 <<  0),
35     MODE_VERIFY         = (1 <<  3),
36 #define MODES_QV (MODE_QUERY | MODE_VERIFY)
37
38     MODE_INSTALL        = (1 <<  1),
39     MODE_ERASE          = (1 <<  2),
40 #define MODES_IE (MODE_INSTALL | MODE_ERASE)
41
42     MODE_BUILD          = (1 <<  4),
43     MODE_REBUILD        = (1 <<  5),
44     MODE_RECOMPILE      = (1 <<  8),
45     MODE_TARBUILD       = (1 << 11),
46 #define MODES_BT (MODE_BUILD | MODE_TARBUILD | MODE_REBUILD | MODE_RECOMPILE)
47
48     MODE_CHECKSIG       = (1 <<  6),
49     MODE_RESIGN         = (1 <<  7),
50 #define MODES_K  (MODE_CHECKSIG | MODE_RESIGN)
51
52     MODE_INITDB         = (1 << 10),
53     MODE_REBUILDDB      = (1 << 12),
54     MODE_VERIFYDB       = (1 << 13),
55 #define MODES_DB (MODE_INITDB | MODE_REBUILDDB | MODE_VERIFYDB)
56
57
58     MODE_UNKNOWN        = 0
59 };
60
61 #define MODES_FOR_DBPATH        (MODES_BT | MODES_IE | MODES_QV | MODES_DB)
62 #define MODES_FOR_NODEPS        (MODES_BT | MODES_IE | MODE_VERIFY)
63 #define MODES_FOR_TEST          (MODES_BT | MODES_IE)
64 #define MODES_FOR_ROOT          (MODES_BT | MODES_IE | MODES_QV | MODES_DB | MODES_K)
65
66 /* the structure describing the options we take and the defaults */
67 /*@unchecked@*/
68 static struct poptOption optionsTable[] = {
69
70 #ifdef  IAM_RPMQV
71  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmQueryPoptTable, 0,
72         N_("Query options (with -q or --query):"),
73         NULL },
74  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmVerifyPoptTable, 0,
75         N_("Verify options (with -V or --verify):"),
76         NULL },
77 #endif  /* IAM_RPMQV */
78
79 #ifdef  IAM_RPMK
80  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmSignPoptTable, 0,
81         N_("Signature options:"),
82         NULL },
83 #endif  /* IAM_RPMK */
84
85 #ifdef  IAM_RPMDB
86  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmDatabasePoptTable, 0,
87         N_("Database options:"),
88         NULL },
89 #endif  /* IAM_RPMDB */
90
91 #ifdef  IAM_RPMBT
92  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmBuildPoptTable, 0,
93         N_("Build options with [ <specfile> | <tarball> | <source package> ]:"),
94         NULL },
95 #endif  /* IAM_RPMBT */
96
97 #ifdef  IAM_RPMEIU
98  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmInstallPoptTable, 0,
99         N_("Install/Upgrade/Erase options:"),
100         NULL },
101 #endif  /* IAM_RPMEIU */
102
103  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
104         N_("Common options for all rpm modes and executables:"),
105         NULL },
106
107    POPT_AUTOALIAS
108    POPT_AUTOHELP
109    POPT_TABLEEND
110 };
111
112 #ifdef __MINT__
113 /* MiNT cannot dynamically increase the stack.  */
114 long _stksize = 64 * 1024L;
115 #endif
116
117 /*@exits@*/ static void argerror(const char * desc)
118         /*@globals __assert_program_name, fileSystem @*/
119         /*@modifies fileSystem @*/
120 {
121     fprintf(stderr, _("%s: %s\n"), __progname, desc);
122     exit(EXIT_FAILURE);
123 }
124
125 static void printVersion(FILE * fp)
126         /*@globals rpmEVR, fileSystem @*/
127         /*@modifies *fp, fileSystem @*/
128 {
129     fprintf(fp, _("RPM version %s\n"), rpmEVR);
130 }
131
132 static void printBanner(FILE * fp)
133         /*@globals fileSystem @*/
134         /*@modifies *fp, fileSystem @*/
135 {
136     fprintf(fp, _("Copyright (C) 1998-2002 - Red Hat, Inc.\n"));
137     fprintf(fp, _("This program may be freely redistributed under the terms of the GNU GPL\n"));
138 }
139
140 static void printUsage(poptContext con, FILE * fp, int flags)
141         /*@globals rpmEVR, fileSystem, internalState @*/
142         /*@modifies *fp, fileSystem, internalState @*/
143 {
144     printVersion(fp);
145     printBanner(fp);
146     fprintf(fp, "\n");
147
148     if (rpmIsVerbose())
149         poptPrintHelp(con, fp, flags);
150     else
151         poptPrintUsage(con, fp, flags);
152 }
153
154 /*@-bounds@*/ /* LCL: segfault */
155 /*@-mods@*/ /* FIX: shrug */
156 #if !defined(__GLIBC__) && !defined(__LCLINT__)
157 int main(int argc, const char ** argv, /*@unused@*/ char ** envp)
158 #else
159 int main(int argc, const char ** argv)
160 #endif
161         /*@globals __assert_program_name, rpmEVR, RPMVERSION,
162                 rpmGlobalMacroContext, rpmCLIMacroContext,
163                 h_errno, fileSystem, internalState@*/
164         /*@modifies __assert_program_name,
165                 fileSystem, internalState@*/
166 {
167     rpmts ts = NULL;
168     enum modes bigMode = MODE_UNKNOWN;
169
170 #if defined(IAM_RPMQV)
171     QVA_t qva = &rpmQVKArgs;
172 #endif
173
174 #ifdef  IAM_RPMBT
175     BTA_t ba = &rpmBTArgs;
176 #endif
177
178 #ifdef  IAM_RPMEIU
179    struct rpmInstallArguments_s * ia = &rpmIArgs;
180 #endif
181
182 #if defined(IAM_RPMDB)
183    struct rpmDatabaseArguments_s * da = &rpmDBArgs;
184 #endif
185
186 #if defined(IAM_RPMK)
187    QVA_t ka = &rpmQVKArgs;
188 #endif
189
190 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
191     char * passPhrase = "";
192 #endif
193
194     int arg;
195
196     const char * optArg;
197     pid_t pipeChild = 0;
198     poptContext optCon;
199     int ec = 0;
200     int status;
201     int p[2];
202 #ifdef  IAM_RPMEIU
203     int i;
204 #endif
205         
206 #if HAVE_MCHECK_H && HAVE_MTRACE
207     /*@-noeffect@*/
208     mtrace();   /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
209     /*@=noeffect@*/
210 #endif
211     setprogname(argv[0]);       /* Retrofit glibc __progname */
212
213 #if !defined(__GLIBC__) && !defined(__LCLINT__)
214     environ = envp;
215 #endif  
216
217     /* XXX glibc churn sanity */
218     if (__progname == NULL) {
219         if ((__progname = strrchr(argv[0], '/')) != NULL) __progname++;
220         else __progname = argv[0];
221     }
222
223     /* Set the major mode based on argv[0] */
224     /*@-nullpass@*/
225 #ifdef  IAM_RPMBT
226     if (!strcmp(__progname, "rpmb"))    bigMode = MODE_BUILD;
227     if (!strcmp(__progname, "lt-rpmb")) bigMode = MODE_BUILD;
228     if (!strcmp(__progname, "rpmt"))    bigMode = MODE_TARBUILD;
229     if (!strcmp(__progname, "rpmbuild"))        bigMode = MODE_BUILD;
230 #endif
231 #ifdef  IAM_RPMQV
232     if (!strcmp(__progname, "rpmq"))    bigMode = MODE_QUERY;
233     if (!strcmp(__progname, "lt-rpmq")) bigMode = MODE_QUERY;
234     if (!strcmp(__progname, "rpmv"))    bigMode = MODE_VERIFY;
235     if (!strcmp(__progname, "rpmquery"))        bigMode = MODE_QUERY;
236     if (!strcmp(__progname, "rpmverify"))       bigMode = MODE_VERIFY;
237 #endif
238 #ifdef  RPMEIU
239     if (!strcmp(__progname, "rpme"))    bigMode = MODE_ERASE;
240     if (!strcmp(__progname, "rpmi"))    bigMode = MODE_INSTALL;
241     if (!strcmp(__progname, "lt-rpmi")) bigMode = MODE_INSTALL;
242     if (!strcmp(__progname, "rpmu"))    bigMode = MODE_INSTALL;
243 #endif
244     /*@=nullpass@*/
245
246 #if defined(IAM_RPMQV)
247     /* Jumpstart option from argv[0] if necessary. */
248     switch (bigMode) {
249     case MODE_QUERY:    qva->qva_mode = 'q';    break;
250     case MODE_VERIFY:   qva->qva_mode = 'V';    break;
251     case MODE_CHECKSIG: qva->qva_mode = 'K';    break;
252     case MODE_RESIGN:   qva->qva_mode = 'R';    break;
253     case MODE_INSTALL:
254     case MODE_ERASE:
255     case MODE_BUILD:
256     case MODE_REBUILD:
257     case MODE_RECOMPILE:
258     case MODE_TARBUILD:
259     case MODE_INITDB:
260     case MODE_REBUILDDB:
261     case MODE_VERIFYDB:
262     case MODE_UNKNOWN:
263     default:
264         break;
265     }
266 #endif
267
268 #if defined(ENABLE_NLS)
269     /* set up the correct locale */
270     (void) setlocale(LC_ALL, "" );
271
272 #ifdef  __LCLINT__
273 #define LOCALEDIR       "/usr/share/locale"
274 #endif
275     bindtextdomain(PACKAGE, LOCALEDIR);
276     textdomain(PACKAGE);
277 #endif
278
279     rpmSetVerbosity(RPMMESS_NORMAL);    /* XXX silly use by showrc */
280
281     /* Make a first pass through the arguments, looking for --rcfile */
282     /* We need to handle that before dealing with the rest of the arguments. */
283     /*@-nullpass -temptrans@*/
284     optCon = poptGetContext(__progname, argc, argv, optionsTable, 0);
285     /*@=nullpass =temptrans@*/
286     (void) poptReadConfigFile(optCon, LIBRPMALIAS_FILENAME);
287     (void) poptReadDefaultConfig(optCon, 1);
288     poptSetExecPath(optCon, RPMCONFIGDIR, 1);
289
290     while ((arg = poptGetNextOpt(optCon)) > 0) {
291         optArg = poptGetOptArg(optCon);
292
293         switch (arg) {
294         default:
295             fprintf(stderr, _("Internal error in argument processing (%d) :-(\n"), arg);
296             exit(EXIT_FAILURE);
297         }
298     }
299
300     if (arg < -1) {
301         fprintf(stderr, "%s: %s\n", 
302                 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 
303                 poptStrerror(arg));
304         exit(EXIT_FAILURE);
305     }
306
307     rpmcliConfigured();
308
309 #ifdef  IAM_RPMBT
310     switch (ba->buildMode) {
311     case 'b':   bigMode = MODE_BUILD;           break;
312     case 't':   bigMode = MODE_TARBUILD;        break;
313     case 'B':   bigMode = MODE_REBUILD;         break;
314     case 'C':   bigMode = MODE_RECOMPILE;       break;
315     }
316
317     if ((ba->buildAmount & RPMBUILD_RMSOURCE) && bigMode == MODE_UNKNOWN)
318         bigMode = MODE_BUILD;
319
320     if ((ba->buildAmount & RPMBUILD_RMSPEC) && bigMode == MODE_UNKNOWN)
321         bigMode = MODE_BUILD;
322
323     if (ba->buildRootOverride && bigMode != MODE_BUILD &&
324         bigMode != MODE_REBUILD && bigMode != MODE_TARBUILD) {
325         argerror("--buildroot may only be used during package builds");
326     }
327 #endif  /* IAM_RPMBT */
328     
329 #ifdef  IAM_RPMDB
330   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_DB)) {
331     if (da->init) {
332         if (bigMode != MODE_UNKNOWN) 
333             argerror(_("only one major mode may be specified"));
334         else
335             bigMode = MODE_INITDB;
336     } else
337     if (da->rebuild) {
338         if (bigMode != MODE_UNKNOWN) 
339             argerror(_("only one major mode may be specified"));
340         else
341             bigMode = MODE_REBUILDDB;
342     } else
343     if (da->verify) {
344         if (bigMode != MODE_UNKNOWN) 
345             argerror(_("only one major mode may be specified"));
346         else
347             bigMode = MODE_VERIFYDB;
348     }
349   }
350 #endif  /* IAM_RPMDB */
351
352 #ifdef  IAM_RPMQV
353   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_QV)) {
354     switch (qva->qva_mode) {
355     case 'q':   bigMode = MODE_QUERY;           break;
356     case 'V':   bigMode = MODE_VERIFY;          break;
357     }
358
359     if (qva->qva_sourceCount) {
360         if (qva->qva_sourceCount > 2)
361             argerror(_("one type of query/verify may be performed at a "
362                         "time"));
363     }
364     if (qva->qva_flags && (bigMode & ~MODES_QV)) 
365         argerror(_("unexpected query flags"));
366
367     if (qva->qva_queryFormat && (bigMode & ~MODES_QV)) 
368         argerror(_("unexpected query format"));
369
370     if (qva->qva_source != RPMQV_PACKAGE && (bigMode & ~MODES_QV)) 
371         argerror(_("unexpected query source"));
372   }
373 #endif  /* IAM_RPMQV */
374
375 #ifdef  IAM_RPMEIU
376   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_IE))
377     {   int iflags = (ia->installInterfaceFlags &
378                 (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL));
379         int eflags = (ia->installInterfaceFlags & INSTALL_ERASE);
380
381         if (iflags & eflags)
382             argerror(_("only one major mode may be specified"));
383         else if (iflags)
384             bigMode = MODE_INSTALL;
385         else if (eflags)
386             bigMode = MODE_ERASE;
387     }
388 #endif  /* IAM_RPMEIU */
389
390 #ifdef  IAM_RPMK
391   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_K)) {
392         switch (ka->qva_mode) {
393         case RPMSIGN_NONE:
394             ka->sign = 0;
395             break;
396         case RPMSIGN_IMPORT_PUBKEY:
397         case RPMSIGN_CHK_SIGNATURE:
398             bigMode = MODE_CHECKSIG;
399             ka->sign = 0;
400             break;
401         case RPMSIGN_ADD_SIGNATURE:
402         case RPMSIGN_NEW_SIGNATURE:
403             bigMode = MODE_RESIGN;
404             ka->sign = 1;
405             break;
406         }
407   }
408 #endif  /* IAM_RPMK */
409
410 #if defined(IAM_RPMEIU)
411     if (!( bigMode == MODE_INSTALL ) &&
412 (ia->probFilter & (RPMPROB_FILTER_REPLACEPKG | RPMPROB_FILTER_OLDPACKAGE)))
413         argerror(_("only installation, upgrading, rmsource and rmspec may be forced"));
414     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_FORCERELOCATE))
415         argerror(_("files may only be relocated during package installation"));
416
417     if (ia->relocations && ia->prefix)
418         argerror(_("cannot use --prefix with --relocate or --excludepath"));
419
420     if (bigMode != MODE_INSTALL && ia->relocations)
421         argerror(_("--relocate and --excludepath may only be used when installing new packages"));
422
423     if (bigMode != MODE_INSTALL && ia->prefix)
424         argerror(_("--prefix may only be used when installing new packages"));
425
426     if (ia->prefix && ia->prefix[0] != '/') 
427         argerror(_("arguments to --prefix must begin with a /"));
428
429     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_HASH))
430         argerror(_("--hash (-h) may only be specified during package "
431                         "installation"));
432
433     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_PERCENT))
434         argerror(_("--percent may only be specified during package "
435                         "installation"));
436
437     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_REPLACEPKG))
438         argerror(_("--replacepkgs may only be specified during package "
439                         "installation"));
440
441     if (bigMode != MODE_INSTALL && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
442         argerror(_("--excludedocs may only be specified during package "
443                    "installation"));
444
445     if (bigMode != MODE_INSTALL && ia->incldocs)
446         argerror(_("--includedocs may only be specified during package "
447                    "installation"));
448
449     if (ia->incldocs && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
450         argerror(_("only one of --excludedocs and --includedocs may be "
451                  "specified"));
452   
453     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREARCH))
454         argerror(_("--ignorearch may only be specified during package "
455                    "installation"));
456
457     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREOS))
458         argerror(_("--ignoreos may only be specified during package "
459                    "installation"));
460
461     if (bigMode != MODE_INSTALL &&
462         (ia->probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES)))
463         argerror(_("--ignoresize may only be specified during package "
464                    "installation"));
465
466     if ((ia->eraseInterfaceFlags & UNINSTALL_ALLMATCHES) && bigMode != MODE_ERASE)
467         argerror(_("--allmatches may only be specified during package "
468                    "erasure"));
469
470     if ((ia->transFlags & RPMTRANS_FLAG_ALLFILES) && bigMode != MODE_INSTALL)
471         argerror(_("--allfiles may only be specified during package "
472                    "installation"));
473
474     if ((ia->transFlags & RPMTRANS_FLAG_JUSTDB) &&
475         bigMode != MODE_INSTALL && bigMode != MODE_ERASE)
476         argerror(_("--justdb may only be specified during package "
477                    "installation and erasure"));
478
479     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
480         (ia->transFlags & (RPMTRANS_FLAG_NOSCRIPTS | _noTransScripts | _noTransTriggers)))
481         argerror(_("script disabling options may only be specified during "
482                    "package installation and erasure"));
483
484     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
485         (ia->transFlags & (RPMTRANS_FLAG_NOTRIGGERS | _noTransTriggers)))
486         argerror(_("trigger disabling options may only be specified during "
487                    "package installation and erasure"));
488
489     if (ia->noDeps & (bigMode & ~MODES_FOR_NODEPS))
490         argerror(_("--nodeps may only be specified during package "
491                    "building, rebuilding, recompilation, installation,"
492                    "erasure, and verification"));
493
494     if ((ia->transFlags & RPMTRANS_FLAG_TEST) && (bigMode & ~MODES_FOR_TEST))
495         argerror(_("--test may only be specified during package installation, "
496                  "erasure, and building"));
497 #endif  /* IAM_RPMEIU */
498
499     if (rpmcliRootDir && rpmcliRootDir[1] && (bigMode & ~MODES_FOR_ROOT))
500         argerror(_("--root (-r) may only be specified during "
501                  "installation, erasure, querying, and "
502                  "database rebuilds"));
503
504     if (rpmcliRootDir) {
505         switch (urlIsURL(rpmcliRootDir)) {
506         default:
507             if (bigMode & MODES_FOR_ROOT)
508                 break;
509             /*@fallthrough@*/
510         case URL_IS_UNKNOWN:
511             if (rpmcliRootDir[0] != '/')
512                 argerror(_("arguments to --root (-r) must begin with a /"));
513             break;
514         }
515     }
516
517 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
518     if (0
519 #if defined(IAM_RPMBT)
520     || ba->sign 
521 #endif
522 #if defined(IAM_RPMK)
523     || ka->sign
524 #endif
525     )
526     /*@-branchstate@*/
527     {
528         if (bigMode == MODE_REBUILD || bigMode == MODE_BUILD ||
529             bigMode == MODE_RESIGN || bigMode == MODE_TARBUILD)
530         {
531             const char ** av;
532             struct stat sb;
533             int errors = 0;
534
535             if ((av = poptGetArgs(optCon)) == NULL) {
536                 fprintf(stderr, _("no files to sign\n"));
537                 errors++;
538             } else
539             while (*av) {
540                 if (stat(*av, &sb)) {
541                     fprintf(stderr, _("cannot access file %s\n"), *av);
542                     errors++;
543                 }
544                 av++;
545             }
546
547             if (errors) {
548                 ec = errors;
549                 goto exit;
550             }
551
552             if (poptPeekArg(optCon)) {
553                 int sigTag;
554                 switch (sigTag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) {
555                   case 0:
556                     break;
557                   case RPMSIGTAG_PGP:
558                     if ((sigTag == RPMSIGTAG_PGP || sigTag == RPMSIGTAG_PGP5) &&
559                         !rpmDetectPGPVersion(NULL)) {
560                         fprintf(stderr, _("pgp not found: "));
561                         ec = EXIT_FAILURE;
562                         goto exit;
563                     }   /*@fallthrough@*/
564                   case RPMSIGTAG_GPG:
565                     passPhrase = rpmGetPassPhrase(_("Enter pass phrase: "), sigTag);
566                     if (passPhrase == NULL) {
567                         fprintf(stderr, _("Pass phrase check failed\n"));
568                         ec = EXIT_FAILURE;
569                         goto exit;
570                     }
571                     fprintf(stderr, _("Pass phrase is good.\n"));
572                     passPhrase = xstrdup(passPhrase);
573                     break;
574                   default:
575                     fprintf(stderr,
576                             _("Invalid %%_signature spec in macro file.\n"));
577                     ec = EXIT_FAILURE;
578                     goto exit;
579                     /*@notreached@*/ break;
580                 }
581             }
582         } else {
583             argerror(_("--sign may only be used during package building"));
584         }
585     } else {
586         /* Make rpmLookupSignatureType() return 0 ("none") from now on */
587         (void) rpmLookupSignatureType(RPMLOOKUPSIG_DISABLE);
588     }
589     /*@=branchstate@*/
590 #endif  /* IAM_RPMBT || IAM_RPMK */
591
592     if (rpmcliPipeOutput) {
593         (void) pipe(p);
594
595         if (!(pipeChild = fork())) {
596             (void) close(p[1]);
597             (void) dup2(p[0], STDIN_FILENO);
598             (void) close(p[0]);
599             (void) execl("/bin/sh", "/bin/sh", "-c", rpmcliPipeOutput, NULL);
600             fprintf(stderr, _("exec failed\n"));
601         }
602
603         (void) close(p[0]);
604         (void) dup2(p[1], STDOUT_FILENO);
605         (void) close(p[1]);
606     }
607         
608     ts = rpmtsCreate();
609     (void) rpmtsSetRootDir(ts, rpmcliRootDir);
610     switch (bigMode) {
611 #ifdef  IAM_RPMDB
612     case MODE_INITDB:
613         (void) rpmtsInitDB(ts, 0644);
614         break;
615
616     case MODE_REBUILDDB:
617     {   rpmVSFlags vsflags = rpmExpandNumeric("%{_vsflags_rebuilddb}");
618         rpmVSFlags ovsflags = rpmtsSetVSFlags(ts, vsflags);
619         ec = rpmtsRebuildDB(ts);
620         vsflags = rpmtsSetVSFlags(ts, ovsflags);
621     }   break;
622     case MODE_VERIFYDB:
623         ec = rpmtsVerifyDB(ts);
624         break;
625 #endif  /* IAM_RPMDB */
626
627 #ifdef  IAM_RPMBT
628     case MODE_REBUILD:
629     case MODE_RECOMPILE:
630     {   const char * pkg;
631
632         while (!rpmIsVerbose())
633             rpmIncreaseVerbosity();
634
635         if (!poptPeekArg(optCon))
636             argerror(_("no packages files given for rebuild"));
637
638         ba->buildAmount =
639             RPMBUILD_PREP | RPMBUILD_BUILD | RPMBUILD_INSTALL | RPMBUILD_CHECK;
640         if (bigMode == MODE_REBUILD) {
641             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
642             ba->buildAmount |= RPMBUILD_RMSOURCE;
643             ba->buildAmount |= RPMBUILD_RMSPEC;
644             ba->buildAmount |= RPMBUILD_CLEAN;
645             ba->buildAmount |= RPMBUILD_RMBUILD;
646         }
647
648         while ((pkg = poptGetArg(optCon))) {
649             const char * specFile = NULL;
650
651             ba->cookie = NULL;
652             ec = rpmInstallSource(ts, pkg, &specFile, &ba->cookie);
653             if (ec == 0) {
654                 ba->rootdir = rpmcliRootDir;
655                 ba->passPhrase = passPhrase;
656                 ec = build(ts, specFile, ba, rpmcliRcfile);
657             }
658             ba->cookie = _free(ba->cookie);
659             specFile = _free(specFile);
660
661             if (ec)
662                 /*@loopbreak@*/ break;
663         }
664
665     }   break;
666
667     case MODE_BUILD:
668     case MODE_TARBUILD:
669     {   const char * pkg;
670         while (!rpmIsVerbose())
671             rpmIncreaseVerbosity();
672        
673         switch (ba->buildChar) {
674         case 'a':
675             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
676             /*@fallthrough@*/
677         case 'b':
678             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
679             ba->buildAmount |= RPMBUILD_CLEAN;
680             /*@fallthrough@*/
681         case 'i':
682             ba->buildAmount |= RPMBUILD_INSTALL;
683             ba->buildAmount |= RPMBUILD_CHECK;
684             if ((ba->buildChar == 'i') && ba->shortCircuit)
685                 /*@innerbreak@*/ break;
686             /*@fallthrough@*/
687         case 'c':
688             ba->buildAmount |= RPMBUILD_BUILD;
689             if ((ba->buildChar == 'c') && ba->shortCircuit)
690                 /*@innerbreak@*/ break;
691             /*@fallthrough@*/
692         case 'p':
693             ba->buildAmount |= RPMBUILD_PREP;
694             /*@innerbreak@*/ break;
695             
696         case 'l':
697             ba->buildAmount |= RPMBUILD_FILECHECK;
698             /*@innerbreak@*/ break;
699         case 's':
700             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
701             /*@innerbreak@*/ break;
702         }
703
704         if (!poptPeekArg(optCon)) {
705             if (bigMode == MODE_BUILD)
706                 argerror(_("no spec files given for build"));
707             else
708                 argerror(_("no tar files given for build"));
709         }
710
711         while ((pkg = poptGetArg(optCon))) {
712             ba->rootdir = rpmcliRootDir;
713             ba->passPhrase = passPhrase;
714             ba->cookie = NULL;
715             ec = build(ts, pkg, ba, rpmcliRcfile);
716             if (ec)
717                 /*@loopbreak@*/ break;
718             rpmFreeMacros(NULL);
719             (void) rpmReadConfigFiles(rpmcliRcfile, NULL);
720         }
721     }   break;
722 #endif  /* IAM_RPMBT */
723
724 #ifdef  IAM_RPMEIU
725     case MODE_ERASE:
726         if (ia->noDeps) ia->eraseInterfaceFlags |= UNINSTALL_NODEPS;
727
728         if (!poptPeekArg(optCon)) {
729             if (ia->rbtid == 0)
730                 argerror(_("no packages given for erase"));
731 ia->transFlags |= RPMTRANS_FLAG_NOMD5;
732 ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
733             ec += rpmRollback(ts, ia, NULL);
734         } else {
735             ec += rpmErase(ts, ia, (const char **) poptGetArgs(optCon));
736         }
737         break;
738
739     case MODE_INSTALL:
740
741         /* RPMTRANS_FLAG_KEEPOBSOLETE */
742
743         if (!ia->incldocs) {
744             if (ia->transFlags & RPMTRANS_FLAG_NODOCS) {
745                 ;
746             } else if (rpmExpandNumeric("%{_excludedocs}"))
747                 ia->transFlags |= RPMTRANS_FLAG_NODOCS;
748         }
749
750         if (ia->noDeps) ia->installInterfaceFlags |= INSTALL_NODEPS;
751
752         /* we've already ensured !(!ia->prefix && !ia->relocations) */
753         /*@-branchstate@*/
754         if (ia->prefix) {
755             ia->relocations = xmalloc(2 * sizeof(*ia->relocations));
756             ia->relocations[0].oldPath = NULL;   /* special case magic */
757             ia->relocations[0].newPath = ia->prefix;
758             ia->relocations[1].oldPath = NULL;
759             ia->relocations[1].newPath = NULL;
760         } else if (ia->relocations) {
761             ia->relocations = xrealloc(ia->relocations, 
762                         sizeof(*ia->relocations) * (ia->numRelocations + 1));
763             ia->relocations[ia->numRelocations].oldPath = NULL;
764             ia->relocations[ia->numRelocations].newPath = NULL;
765         }
766         /*@=branchstate@*/
767
768         if (!poptPeekArg(optCon)) {
769             if (ia->rbtid == 0)
770                 argerror(_("no packages given for install"));
771 ia->transFlags |= RPMTRANS_FLAG_NOMD5;
772 ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
773 /*@i@*/     ec += rpmRollback(ts, ia, NULL);
774         } else {
775             /*@-compdef -compmempass@*/ /* FIX: ia->relocations[0].newPath undefined */
776             ec += rpmInstall(ts, ia, (const char **)poptGetArgs(optCon));
777             /*@=compdef =compmempass@*/
778         }
779         break;
780
781 #endif  /* IAM_RPMEIU */
782
783 #ifdef  IAM_RPMQV
784     case MODE_QUERY:
785         if (qva->qva_source != RPMQV_ALL && !poptPeekArg(optCon))
786             argerror(_("no arguments given for query"));
787
788         qva->qva_specQuery = rpmspecQuery;
789         ec = rpmcliQuery(ts, qva, (const char **) poptGetArgs(optCon));
790         qva->qva_specQuery = NULL;
791         break;
792
793     case MODE_VERIFY:
794     {   rpmVerifyFlags verifyFlags = VERIFY_ALL;
795
796         verifyFlags &= ~qva->qva_flags;
797         qva->qva_flags = (rpmQueryFlags) verifyFlags;
798
799         if (qva->qva_source != RPMQV_ALL && !poptPeekArg(optCon))
800             argerror(_("no arguments given for verify"));
801         ec = rpmcliVerify(ts, qva, (const char **) poptGetArgs(optCon));
802     }   break;
803 #endif  /* IAM_RPMQV */
804
805 #ifdef IAM_RPMK
806     case MODE_CHECKSIG:
807     {   rpmVerifyFlags verifyFlags =
808                 (VERIFY_MD5|VERIFY_DIGEST|VERIFY_SIGNATURE);
809
810         verifyFlags &= ~ka->qva_flags;
811         ka->qva_flags = (rpmQueryFlags) verifyFlags;
812     }   /*@fallthrough@*/
813     case MODE_RESIGN:
814         if (!poptPeekArg(optCon))
815             argerror(_("no arguments given"));
816         ka->passPhrase = passPhrase;
817         ec = rpmcliSign(ts, ka, (const char **)poptGetArgs(optCon));
818         break;
819 #endif  /* IAM_RPMK */
820         
821 #if !defined(IAM_RPMQV)
822     case MODE_QUERY:
823     case MODE_VERIFY:
824 #endif
825 #if !defined(IAM_RPMK)
826     case MODE_CHECKSIG:
827     case MODE_RESIGN:
828 #endif
829 #if !defined(IAM_RPMDB)
830     case MODE_INITDB:
831     case MODE_REBUILDDB:
832     case MODE_VERIFYDB:
833 #endif
834 #if !defined(IAM_RPMBT)
835     case MODE_BUILD:
836     case MODE_REBUILD:
837     case MODE_RECOMPILE:
838     case MODE_TARBUILD:
839 #endif
840 #if !defined(IAM_RPMEIU)
841     case MODE_INSTALL:
842     case MODE_ERASE:
843 #endif
844     case MODE_UNKNOWN:
845         if (poptPeekArg(optCon) != NULL || argc <= 1 || rpmIsVerbose()) {
846             printUsage(optCon, stdout, 0);
847             ec = argc;
848         }
849         break;
850     }
851
852 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
853 exit:
854 #endif  /* IAM_RPMBT || IAM_RPMK */
855
856     ts = rpmtsFree(ts);
857
858     optCon = poptFreeContext(optCon);
859     rpmFreeMacros(NULL);
860 /*@i@*/ rpmFreeMacros(rpmCLIMacroContext);
861     rpmFreeRpmrc();
862
863     if (pipeChild) {
864         (void) fclose(stdout);
865         (void) waitpid(pipeChild, &status, 0);
866     }
867
868     /* keeps memory leak checkers quiet */
869     freeFilesystems();
870 /*@i@*/ urlFreeCache();
871     rpmlogClose();
872     dbiTags = _free(dbiTags);
873
874 #ifdef  IAM_RPMQV
875     qva->qva_queryFormat = _free(qva->qva_queryFormat);
876 #endif
877
878 #ifdef  IAM_RPMBT
879     freeNames();
880     ba->buildRootOverride = _free(ba->buildRootOverride);
881     ba->targets = _free(ba->targets);
882 #endif
883
884 #ifdef  IAM_RPMEIU
885     if (ia->relocations != NULL)
886     for (i = 0; i < ia->numRelocations; i++)
887         ia->relocations[i].oldPath = _free(ia->relocations[i].oldPath);
888     ia->relocations = _free(ia->relocations);
889 #endif
890
891 #if HAVE_MCHECK_H && HAVE_MTRACE
892     /*@-noeffect@*/
893     muntrace();   /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
894     /*@=noeffect@*/
895 #endif
896
897     /* XXX don't overflow single byte exit status */
898     if (ec > 255) ec = 255;
899
900     /*@-globstate@*/
901     return ec;
902     /*@=globstate@*/
903 }
904 /*@=mods@*/
905 /*@=bounds@*/