- make --querytags a common option, fix errant regex (#70135).
[platform/upstream/rpm.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:"),
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                 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     /* XXX Eliminate query linkage loop */
269     /*@-type@*/ /* FIX: casts? */
270     parseSpecVec = parseSpec;
271     freeSpecVec = freeSpec;
272     /*@=type@*/
273
274     /* set up the correct locale */
275     (void) setlocale(LC_ALL, "" );
276
277 #ifdef  __LCLINT__
278 #define LOCALEDIR       "/usr/share/locale"
279 #endif
280     bindtextdomain(PACKAGE, LOCALEDIR);
281     textdomain(PACKAGE);
282
283     rpmSetVerbosity(RPMMESS_NORMAL);    /* XXX silly use by showrc */
284
285     /* Make a first pass through the arguments, looking for --rcfile */
286     /* We need to handle that before dealing with the rest of the arguments. */
287     /*@-nullpass -temptrans@*/
288     optCon = poptGetContext(__progname, argc, argv, optionsTable, 0);
289     /*@=nullpass =temptrans@*/
290     (void) poptReadConfigFile(optCon, LIBRPMALIAS_FILENAME);
291     (void) poptReadDefaultConfig(optCon, 1);
292     poptSetExecPath(optCon, RPMCONFIGDIR, 1);
293
294     while ((arg = poptGetNextOpt(optCon)) > 0) {
295         optArg = poptGetOptArg(optCon);
296
297         switch (arg) {
298         default:
299             fprintf(stderr, _("Internal error in argument processing (%d) :-(\n"), arg);
300             exit(EXIT_FAILURE);
301         }
302     }
303
304     if (arg < -1) {
305         fprintf(stderr, "%s: %s\n", 
306                 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 
307                 poptStrerror(arg));
308         exit(EXIT_FAILURE);
309     }
310
311     rpmcliConfigured();
312
313 #ifdef  IAM_RPMBT
314     switch (ba->buildMode) {
315     case 'b':   bigMode = MODE_BUILD;           break;
316     case 't':   bigMode = MODE_TARBUILD;        break;
317     case 'B':   bigMode = MODE_REBUILD;         break;
318     case 'C':   bigMode = MODE_RECOMPILE;       break;
319     }
320
321     if ((ba->buildAmount & RPMBUILD_RMSOURCE) && bigMode == MODE_UNKNOWN)
322         bigMode = MODE_BUILD;
323
324     if ((ba->buildAmount & RPMBUILD_RMSPEC) && bigMode == MODE_UNKNOWN)
325         bigMode = MODE_BUILD;
326
327     if (ba->buildRootOverride && bigMode != MODE_BUILD &&
328         bigMode != MODE_REBUILD && bigMode != MODE_TARBUILD) {
329         argerror("--buildroot may only be used during package builds");
330     }
331 #endif  /* IAM_RPMBT */
332     
333 #ifdef  IAM_RPMDB
334   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_DB)) {
335     if (da->init) {
336         if (bigMode != MODE_UNKNOWN) 
337             argerror(_("only one major mode may be specified"));
338         else
339             bigMode = MODE_INITDB;
340     } else
341     if (da->rebuild) {
342         if (bigMode != MODE_UNKNOWN) 
343             argerror(_("only one major mode may be specified"));
344         else
345             bigMode = MODE_REBUILDDB;
346     } else
347     if (da->verify) {
348         if (bigMode != MODE_UNKNOWN) 
349             argerror(_("only one major mode may be specified"));
350         else
351             bigMode = MODE_VERIFYDB;
352     }
353   }
354 #endif  /* IAM_RPMDB */
355
356 #ifdef  IAM_RPMQV
357   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_QV)) {
358     switch (qva->qva_mode) {
359     case 'q':   bigMode = MODE_QUERY;           break;
360     case 'V':   bigMode = MODE_VERIFY;          break;
361     }
362
363     if (qva->qva_sourceCount) {
364         if (qva->qva_sourceCount > 2)
365             argerror(_("one type of query/verify may be performed at a "
366                         "time"));
367     }
368     if (qva->qva_flags && (bigMode & ~MODES_QV)) 
369         argerror(_("unexpected query flags"));
370
371     if (qva->qva_queryFormat && (bigMode & ~MODES_QV)) 
372         argerror(_("unexpected query format"));
373
374     if (qva->qva_source != RPMQV_PACKAGE && (bigMode & ~MODES_QV)) 
375         argerror(_("unexpected query source"));
376   }
377 #endif  /* IAM_RPMQV */
378
379 #ifdef  IAM_RPMEIU
380   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_IE))
381     {   int iflags = (ia->installInterfaceFlags &
382                 (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL));
383         int eflags = (ia->installInterfaceFlags & INSTALL_ERASE);
384
385         if (iflags & eflags)
386             argerror(_("only one major mode may be specified"));
387         else if (iflags)
388             bigMode = MODE_INSTALL;
389         else if (eflags)
390             bigMode = MODE_ERASE;
391     }
392 #endif  /* IAM_RPMQV */
393
394 #ifdef  IAM_RPMK
395   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_K)) {
396         switch (ka->qva_mode) {
397         case RPMSIGN_NONE:
398             ka->sign = 0;
399             break;
400         case RPMSIGN_IMPORT_PUBKEY:
401         case RPMSIGN_CHK_SIGNATURE:
402             bigMode = MODE_CHECKSIG;
403             ka->sign = 0;
404             break;
405         case RPMSIGN_ADD_SIGNATURE:
406         case RPMSIGN_NEW_SIGNATURE:
407             bigMode = MODE_RESIGN;
408             ka->sign = 1;
409             break;
410         }
411   }
412 #endif  /* IAM_RPMK */
413
414 #if defined(IAM_RPMEIU)
415     if (!( bigMode == MODE_INSTALL ) &&
416 (ia->probFilter & (RPMPROB_FILTER_REPLACEPKG | RPMPROB_FILTER_REPLACEOLDFILES | RPMPROB_FILTER_REPLACENEWFILES | RPMPROB_FILTER_OLDPACKAGE)))
417         argerror(_("only installation, upgrading, rmsource and rmspec may be forced"));
418     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_FORCERELOCATE))
419         argerror(_("files may only be relocated during package installation"));
420
421     if (ia->relocations && ia->prefix)
422         argerror(_("only one of --prefix or --relocate may be used"));
423
424     if (bigMode != MODE_INSTALL && ia->relocations)
425         argerror(_("--relocate and --excludepath may only be used when installing new packages"));
426
427     if (bigMode != MODE_INSTALL && ia->prefix)
428         argerror(_("--prefix may only be used when installing new packages"));
429
430     if (ia->prefix && ia->prefix[0] != '/') 
431         argerror(_("arguments to --prefix must begin with a /"));
432
433     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_HASH))
434         argerror(_("--hash (-h) may only be specified during package "
435                         "installation"));
436
437     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_PERCENT))
438         argerror(_("--percent may only be specified during package "
439                         "installation"));
440
441     if (bigMode != MODE_INSTALL &&
442  (ia->probFilter & (RPMPROB_FILTER_REPLACEOLDFILES|RPMPROB_FILTER_REPLACENEWFILES)))
443         argerror(_("--replacefiles may only be specified during package "
444                         "installation"));
445
446     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_REPLACEPKG))
447         argerror(_("--replacepkgs may only be specified during package "
448                         "installation"));
449
450     if (bigMode != MODE_INSTALL && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
451         argerror(_("--excludedocs may only be specified during package "
452                    "installation"));
453
454     if (bigMode != MODE_INSTALL && ia->incldocs)
455         argerror(_("--includedocs may only be specified during package "
456                    "installation"));
457
458     if (ia->incldocs && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
459         argerror(_("only one of --excludedocs and --includedocs may be "
460                  "specified"));
461   
462     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREARCH))
463         argerror(_("--ignorearch may only be specified during package "
464                    "installation"));
465
466     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREOS))
467         argerror(_("--ignoreos may only be specified during package "
468                    "installation"));
469
470     if (bigMode != MODE_INSTALL &&
471         (ia->probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES)))
472         argerror(_("--ignoresize may only be specified during package "
473                    "installation"));
474
475     if ((ia->eraseInterfaceFlags & UNINSTALL_ALLMATCHES) && bigMode != MODE_ERASE)
476         argerror(_("--allmatches may only be specified during package "
477                    "erasure"));
478
479     if ((ia->transFlags & RPMTRANS_FLAG_ALLFILES) && bigMode != MODE_INSTALL)
480         argerror(_("--allfiles may only be specified during package "
481                    "installation"));
482
483     if ((ia->transFlags & RPMTRANS_FLAG_JUSTDB) &&
484         bigMode != MODE_INSTALL && bigMode != MODE_ERASE)
485         argerror(_("--justdb may only be specified during package "
486                    "installation and erasure"));
487
488     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
489         (ia->transFlags & (RPMTRANS_FLAG_NOSCRIPTS | _noTransScripts | _noTransTriggers)))
490         argerror(_("script disabling options may only be specified during "
491                    "package installation and erasure"));
492
493     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
494         (ia->transFlags & (RPMTRANS_FLAG_NOTRIGGERS | _noTransTriggers)))
495         argerror(_("trigger disabling options may only be specified during "
496                    "package installation and erasure"));
497
498     if (ia->noDeps & (bigMode & ~MODES_FOR_NODEPS))
499         argerror(_("--nodeps may only be specified during package "
500                    "building, rebuilding, recompilation, installation,"
501                    "erasure, and verification"));
502
503     if ((ia->transFlags & RPMTRANS_FLAG_TEST) && (bigMode & ~MODES_FOR_TEST))
504         argerror(_("--test may only be specified during package installation, "
505                  "erasure, and building"));
506 #endif  /* IAM_RPMEIU */
507
508     if (rpmcliRootDir && rpmcliRootDir[1] && (bigMode & ~MODES_FOR_ROOT))
509         argerror(_("--root (-r) may only be specified during "
510                  "installation, erasure, querying, and "
511                  "database rebuilds"));
512
513     if (rpmcliRootDir) {
514         switch (urlIsURL(rpmcliRootDir)) {
515         default:
516             if (bigMode & MODES_FOR_ROOT)
517                 break;
518             /*@fallthrough@*/
519         case URL_IS_UNKNOWN:
520             if (rpmcliRootDir[0] != '/')
521                 argerror(_("arguments to --root (-r) must begin with a /"));
522             break;
523         }
524     }
525
526 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
527     if (0
528 #if defined(IAM_RPMBT)
529     || ba->sign 
530 #endif
531 #if defined(IAM_RPMK)
532     || ka->sign
533 #endif
534     )
535     /*@-branchstate@*/
536     {
537         if (bigMode == MODE_REBUILD || bigMode == MODE_BUILD ||
538             bigMode == MODE_RESIGN || bigMode == MODE_TARBUILD)
539         {
540             const char ** av;
541             struct stat sb;
542             int errors = 0;
543
544             if ((av = poptGetArgs(optCon)) == NULL) {
545                 fprintf(stderr, _("no files to sign\n"));
546                 errors++;
547             } else
548             while (*av) {
549                 if (stat(*av, &sb)) {
550                     fprintf(stderr, _("cannot access file %s\n"), *av);
551                     errors++;
552                 }
553                 av++;
554             }
555
556             if (errors) {
557                 ec = errors;
558                 goto exit;
559             }
560
561             if (poptPeekArg(optCon)) {
562                 int sigTag;
563                 switch (sigTag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) {
564                   case 0:
565                     break;
566                   case RPMSIGTAG_PGP:
567                     if ((sigTag == RPMSIGTAG_PGP || sigTag == RPMSIGTAG_PGP5) &&
568                         !rpmDetectPGPVersion(NULL)) {
569                         fprintf(stderr, _("pgp not found: "));
570                         ec = EXIT_FAILURE;
571                         goto exit;
572                     }   /*@fallthrough@*/
573                   case RPMSIGTAG_GPG:
574                     passPhrase = rpmGetPassPhrase(_("Enter pass phrase: "), sigTag);
575                     if (passPhrase == NULL) {
576                         fprintf(stderr, _("Pass phrase check failed\n"));
577                         ec = EXIT_FAILURE;
578                         goto exit;
579                     }
580                     fprintf(stderr, _("Pass phrase is good.\n"));
581                     passPhrase = xstrdup(passPhrase);
582                     break;
583                   default:
584                     fprintf(stderr,
585                             _("Invalid %%_signature spec in macro file.\n"));
586                     ec = EXIT_FAILURE;
587                     goto exit;
588                     /*@notreached@*/ break;
589                 }
590             }
591         } else {
592             argerror(_("--sign may only be used during package building"));
593         }
594     } else {
595         /* Make rpmLookupSignatureType() return 0 ("none") from now on */
596         (void) rpmLookupSignatureType(RPMLOOKUPSIG_DISABLE);
597     }
598     /*@=branchstate@*/
599 #endif  /* IAM_RPMBT || IAM_RPMK */
600
601     if (rpmcliPipeOutput) {
602         (void) pipe(p);
603
604         if (!(pipeChild = fork())) {
605             (void) close(p[1]);
606             (void) dup2(p[0], STDIN_FILENO);
607             (void) close(p[0]);
608             (void) execl("/bin/sh", "/bin/sh", "-c", rpmcliPipeOutput, NULL);
609             fprintf(stderr, _("exec failed\n"));
610         }
611
612         (void) close(p[0]);
613         (void) dup2(p[1], STDOUT_FILENO);
614         (void) close(p[1]);
615     }
616         
617     ts = rpmtsCreate();
618     (void) rpmtsSetRootDir(ts, rpmcliRootDir);
619     switch (bigMode) {
620 #ifdef  IAM_RPMDB
621     case MODE_INITDB:
622         (void) rpmtsInitDB(ts, 0644);
623         break;
624
625     case MODE_REBUILDDB:
626     {   int vsflags = rpmExpandNumeric("%{_vsflags_rebuilddb}");
627         (void)rpmtsSetVerifySigFlags(ts, (vsflags & ~_RPMTS_VSF_VERIFY_LEGACY));
628         ec = rpmtsRebuildDB(ts);
629     }   break;
630     case MODE_VERIFYDB:
631         ec = rpmtsVerifyDB(ts);
632         break;
633 #endif  /* IAM_RPMDB */
634
635 #ifdef  IAM_RPMBT
636     case MODE_REBUILD:
637     case MODE_RECOMPILE:
638     {   const char * pkg;
639
640         while (!rpmIsVerbose())
641             rpmIncreaseVerbosity();
642
643         if (!poptPeekArg(optCon))
644             argerror(_("no packages files given for rebuild"));
645
646         ba->buildAmount = RPMBUILD_PREP | RPMBUILD_BUILD | RPMBUILD_INSTALL;
647         if (bigMode == MODE_REBUILD) {
648             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
649             ba->buildAmount |= RPMBUILD_RMSOURCE;
650             ba->buildAmount |= RPMBUILD_RMSPEC;
651             ba->buildAmount |= RPMBUILD_CLEAN;
652             ba->buildAmount |= RPMBUILD_RMBUILD;
653         }
654
655         while ((pkg = poptGetArg(optCon))) {
656             const char * specFile = NULL;
657
658             ba->cookie = NULL;
659             ec = rpmInstallSource(ts, pkg, &specFile, &ba->cookie);
660             if (ec == 0) {
661                 ba->rootdir = rpmcliRootDir;
662                 ba->passPhrase = passPhrase;
663                 ec = build(ts, specFile, ba, rpmcliRcfile);
664             }
665             ba->cookie = _free(ba->cookie);
666             specFile = _free(specFile);
667
668             if (ec)
669                 /*@loopbreak@*/ break;
670         }
671
672     }   break;
673
674     case MODE_BUILD:
675     case MODE_TARBUILD:
676     {   const char * pkg;
677         while (!rpmIsVerbose())
678             rpmIncreaseVerbosity();
679        
680         switch (ba->buildChar) {
681         case 'a':
682             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
683             /*@fallthrough@*/
684         case 'b':
685             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
686             ba->buildAmount |= RPMBUILD_CLEAN;
687             /*@fallthrough@*/
688         case 'i':
689             ba->buildAmount |= RPMBUILD_INSTALL;
690             if ((ba->buildChar == 'i') && ba->shortCircuit)
691                 /*@innerbreak@*/ break;
692             /*@fallthrough@*/
693         case 'c':
694             ba->buildAmount |= RPMBUILD_BUILD;
695             if ((ba->buildChar == 'c') && ba->shortCircuit)
696                 /*@innerbreak@*/ break;
697             /*@fallthrough@*/
698         case 'p':
699             ba->buildAmount |= RPMBUILD_PREP;
700             /*@innerbreak@*/ break;
701             
702         case 'l':
703             ba->buildAmount |= RPMBUILD_FILECHECK;
704             /*@innerbreak@*/ break;
705         case 's':
706             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
707             /*@innerbreak@*/ break;
708         }
709
710         if (!poptPeekArg(optCon)) {
711             if (bigMode == MODE_BUILD)
712                 argerror(_("no spec files given for build"));
713             else
714                 argerror(_("no tar files given for build"));
715         }
716
717         while ((pkg = poptGetArg(optCon))) {
718             ba->rootdir = rpmcliRootDir;
719             ba->passPhrase = passPhrase;
720             ba->cookie = NULL;
721             ec = build(ts, pkg, ba, rpmcliRcfile);
722             if (ec)
723                 /*@loopbreak@*/ break;
724             rpmFreeMacros(NULL);
725             (void) rpmReadConfigFiles(rpmcliRcfile, NULL);
726         }
727     }   break;
728 #endif  /* IAM_RPMBT */
729
730 #ifdef  IAM_RPMEIU
731     case MODE_ERASE:
732         if (ia->noDeps) ia->eraseInterfaceFlags |= UNINSTALL_NODEPS;
733
734         if (!poptPeekArg(optCon)) {
735             if (ia->rbtid == 0)
736                 argerror(_("no packages given for erase"));
737 ia->transFlags |= RPMTRANS_FLAG_NOMD5;
738 ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
739             ec += rpmRollback(ts, ia, NULL);
740         } else {
741             ec += rpmErase(ts, ia, (const char **) poptGetArgs(optCon));
742         }
743         break;
744
745     case MODE_INSTALL:
746
747         /* RPMTRANS_FLAG_KEEPOBSOLETE */
748
749         if (!ia->incldocs) {
750             if (ia->transFlags & RPMTRANS_FLAG_NODOCS)
751                 ;
752             else if (rpmExpandNumeric("%{_excludedocs}"))
753                 ia->transFlags |= RPMTRANS_FLAG_NODOCS;
754         }
755
756         if (ia->noDeps) ia->installInterfaceFlags |= INSTALL_NODEPS;
757
758         /* we've already ensured !(!ia->prefix && !ia->relocations) */
759         /*@-branchstate@*/
760         if (ia->prefix) {
761             ia->relocations = xmalloc(2 * sizeof(*ia->relocations));
762             ia->relocations[0].oldPath = NULL;   /* special case magic */
763             ia->relocations[0].newPath = ia->prefix;
764             ia->relocations[1].oldPath = NULL;
765             ia->relocations[1].newPath = NULL;
766         } else if (ia->relocations) {
767             ia->relocations = xrealloc(ia->relocations, 
768                         sizeof(*ia->relocations) * (ia->numRelocations + 1));
769             ia->relocations[ia->numRelocations].oldPath = NULL;
770             ia->relocations[ia->numRelocations].newPath = NULL;
771         }
772         /*@=branchstate@*/
773
774         if (!poptPeekArg(optCon)) {
775             if (ia->rbtid == 0)
776                 argerror(_("no packages given for install"));
777 ia->transFlags |= RPMTRANS_FLAG_NOMD5;
778 ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
779 /*@i@*/     ec += rpmRollback(ts, ia, NULL);
780         } else {
781             /*@-compdef -compmempass@*/ /* FIX: ia->relocations[0].newPath undefined */
782             ec += rpmInstall(ts, ia, (const char **)poptGetArgs(optCon));
783             /*@=compdef =compmempass@*/
784         }
785         break;
786
787 #endif  /* IAM_RPMEIU */
788
789 #ifdef  IAM_RPMQV
790     case MODE_QUERY:
791         if (qva->qva_source != RPMQV_ALL && !poptPeekArg(optCon))
792             argerror(_("no arguments given for query"));
793         ec = rpmcliQuery(ts, qva, (const char **) poptGetArgs(optCon));
794         /* XXX don't overflow single byte exit status */
795         if (ec > 255) ec = 255;
796         break;
797
798     case MODE_VERIFY:
799     {   rpmVerifyFlags verifyFlags = VERIFY_ALL;
800
801         verifyFlags &= ~qva->qva_flags;
802         qva->qva_flags = (rpmQueryFlags) verifyFlags;
803
804         if (qva->qva_source != RPMQV_ALL && !poptPeekArg(optCon))
805             argerror(_("no arguments given for verify"));
806         ec = rpmcliVerify(ts, qva, (const char **) poptGetArgs(optCon));
807         /* XXX don't overflow single byte exit status */
808         if (ec > 255) ec = 255;
809     }   break;
810 #endif  /* IAM_RPMQV */
811
812 #ifdef IAM_RPMK
813     case MODE_CHECKSIG:
814     {   rpmVerifyFlags verifyFlags =
815                 (VERIFY_MD5|VERIFY_DIGEST|VERIFY_SIGNATURE);
816
817         verifyFlags &= ~ka->qva_flags;
818         ka->qva_flags = (rpmQueryFlags) verifyFlags;
819     }   /*@fallthrough@*/
820     case MODE_RESIGN:
821         if (!poptPeekArg(optCon))
822             argerror(_("no arguments given"));
823         ka->passPhrase = passPhrase;
824         ec = rpmcliSign(ts, ka, (const char **)poptGetArgs(optCon));
825         /* XXX don't overflow single byte exit status */
826         if (ec > 255) ec = 255;
827         break;
828 #endif  /* IAM_RPMK */
829         
830 #if !defined(IAM_RPMQV)
831     case MODE_QUERY:
832     case MODE_VERIFY:
833 #endif
834 #if !defined(IAM_RPMK)
835     case MODE_CHECKSIG:
836     case MODE_RESIGN:
837 #endif
838 #if !defined(IAM_RPMDB)
839     case MODE_INITDB:
840     case MODE_REBUILDDB:
841     case MODE_VERIFYDB:
842 #endif
843 #if !defined(IAM_RPMBT)
844     case MODE_BUILD:
845     case MODE_REBUILD:
846     case MODE_RECOMPILE:
847     case MODE_TARBUILD:
848 #endif
849 #if !defined(IAM_RPMEIU)
850     case MODE_INSTALL:
851     case MODE_ERASE:
852 #endif
853     case MODE_UNKNOWN:
854         if (poptPeekArg(optCon) != NULL || argc <= 1 || rpmIsVerbose())
855             printUsage(optCon, stdout, 0);
856         break;
857     }
858
859 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
860 exit:
861 #endif  /* IAM_RPMBT || IAM_RPMK */
862
863     ts = rpmtsFree(ts);
864
865     optCon = poptFreeContext(optCon);
866     rpmFreeMacros(NULL);
867 /*@i@*/ rpmFreeMacros(rpmCLIMacroContext);
868     rpmFreeRpmrc();
869
870     if (pipeChild) {
871         (void) fclose(stdout);
872         (void) waitpid(pipeChild, &status, 0);
873     }
874
875     /* keeps memory leak checkers quiet */
876     freeNames();
877     freeFilesystems();
878 /*@i@*/ urlFreeCache();
879     rpmlogClose();
880     dbiTags = _free(dbiTags);
881
882 #ifdef  IAM_RPMQV
883     qva->qva_queryFormat = _free(qva->qva_queryFormat);
884 #endif
885
886 #ifdef  IAM_RPMBT
887     ba->buildRootOverride = _free(ba->buildRootOverride);
888     ba->targets = _free(ba->targets);
889 #endif
890
891 #ifdef  IAM_RPMEIU
892     if (ia->relocations != NULL)
893     for (i = 0; i < ia->numRelocations; i++)
894         ia->relocations[i].oldPath = _free(ia->relocations[i].oldPath);
895     ia->relocations = _free(ia->relocations);
896 #endif
897
898 #if HAVE_MCHECK_H && HAVE_MTRACE
899     /*@-noeffect@*/
900     muntrace();   /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
901     /*@=noeffect@*/
902 #endif
903     /*@-globstate@*/
904     return ec;
905     /*@=globstate@*/
906 }
907 /*@=mods@*/
908 /*@=bounds@*/