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