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