rpm 5.3.7

rpmqv.c

Go to the documentation of this file.
00001 #include "system.h"
00002 extern const char *__progname;
00003 
00004 /* Copyright (C) 1998-2002 - Red Hat, Inc. */
00005 
00006 #define _AUTOHELP
00007 
00008 #if defined(IAM_RPM) || defined(__LCLINT__)
00009 #define IAM_RPMBT
00010 #define IAM_RPMDB
00011 #define IAM_RPMEIU
00012 #define IAM_RPMQV
00013 #define IAM_RPMK
00014 #endif
00015 
00016 #if defined(RPM_VENDOR_OPENPKG) /* integrity-checking */
00017 #define _RPMIOB_INTERNAL        /* XXX rpmiobSlurp */
00018 #include "rpmio_internal.h"
00019 #endif
00020 
00021 #include <rpmio.h>
00022 #include <rpmiotypes.h>
00023 #include <poptIO.h>
00024 
00025 #include <rpmtypes.h>
00026 #include <rpmtag.h>
00027 #include "rpmdb.h"
00028 
00029 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
00030 #include "signature.h"
00031 #endif
00032 
00033 #if defined(RPM_VENDOR_OPENPKG) /* integrity-checking */
00034 #include "rpmns.h"
00035 #define _RPMLUA_INTERNAL
00036 #include "rpmlua.h"
00037 #include "rpmluaext.h"
00038 #endif
00039 
00040 #include "rpmversion.h"
00041 #include "rpmps.h"
00042 #include "rpmts.h"
00043 
00044 #include "fs.h"         /* XXX for rpmFreeFilesystems() */
00045 
00046 #include <rpmbuild.h>
00047 
00048 #ifdef  IAM_RPMBT
00049 #include "build.h"
00050 #define GETOPT_REBUILD          1003
00051 #define GETOPT_RECOMPILE        1004
00052 #endif
00053 
00054 #include <rpmcli.h>
00055 #include <rpmrollback.h>
00056 
00057 #include "debug.h"
00058 
00059 enum modes {
00060     MODE_UNKNOWN        = 0,
00061 
00062     MODE_QUERY          = (1 <<  0),
00063     MODE_VERIFY         = (1 <<  3),
00064 #define MODES_QV (MODE_QUERY | MODE_VERIFY)
00065 
00066     MODE_INSTALL        = (1 <<  1),
00067     MODE_ERASE          = (1 <<  2),
00068 #define MODES_IE (MODE_INSTALL | MODE_ERASE)
00069 
00070     MODE_BUILD          = (1 <<  4),
00071     MODE_REBUILD        = (1 <<  5),
00072     MODE_RECOMPILE      = (1 <<  8),
00073     MODE_TARBUILD       = (1 << 11),
00074 #define MODES_BT (MODE_BUILD | MODE_TARBUILD | MODE_REBUILD | MODE_RECOMPILE)
00075 
00076     MODE_CHECKSIG       = (1 <<  6),
00077     MODE_RESIGN         = (1 <<  7),
00078 #define MODES_K  (MODE_CHECKSIG | MODE_RESIGN)
00079 
00080     MODE_REBUILDDB      = (1 << 12),
00081 #define MODES_DB (MODE_REBUILDDB)
00082 };
00083 
00084 #define MODES_FOR_DBPATH        (MODES_BT | MODES_IE | MODES_QV | MODES_DB)
00085 #define MODES_FOR_NODEPS        (MODES_BT | MODES_IE | MODE_VERIFY)
00086 #define MODES_FOR_TEST          (MODES_BT | MODES_IE)
00087 #define MODES_FOR_ROOT          (MODES_BT | MODES_IE | MODES_QV | MODES_DB | MODES_K)
00088 
00089 /* the structure describing the options we take and the defaults */
00090 /*@unchecked@*/
00091 static struct poptOption optionsTable[] = {
00092 
00093 #ifdef  IAM_RPMQV
00094  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmQueryPoptTable, 0,
00095         N_("Query options (with -q or --query):"),
00096         NULL },
00097  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmVerifyPoptTable, 0,
00098         N_("Verify options (with -V or --verify):"),
00099         NULL },
00100 #ifdef  NOTYET
00101  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliQVSourcePoptTable, 0,
00102         N_("Source options (with --query or --verify):"),
00103         NULL },
00104 #endif
00105 #endif  /* IAM_RPMQV */
00106 
00107 #if defined(IAM_RPMQV) || defined(IAM_RPMEIU)
00108  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliDepFlagsPoptTable, 0,
00109         N_("Dependency check/order options:"),
00110         NULL },
00111 #endif  /* IAM_RPMQV */
00112 
00113 #ifdef  IAM_RPMQV
00114  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmioFtsPoptTable, 0,
00115         N_("File tree walk options (with --ftswalk):"),
00116         NULL },
00117 #endif  /* IAM_RPMQV */
00118 
00119 #ifdef  IAM_RPMK
00120  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmSignPoptTable, 0,
00121         N_("Signature options:"),
00122         NULL },
00123 #endif  /* IAM_RPMK */
00124 
00125 #ifdef  IAM_RPMDB
00126  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmDatabasePoptTable, 0,
00127         N_("Database options:"),
00128         NULL },
00129 #endif  /* IAM_RPMDB */
00130 
00131 #ifdef  IAM_RPMBT
00132  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmBuildPoptTable, 0,
00133         N_("Build options with [ <specfile> | <tarball> | <source package> ]:"),
00134         NULL },
00135 #endif  /* IAM_RPMBT */
00136 
00137 #ifdef  IAM_RPMEIU
00138  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmInstallPoptTable, 0,
00139         N_("Install/Upgrade/Erase options:"),
00140         NULL },
00141 #endif  /* IAM_RPMEIU */
00142 
00143  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
00144         N_("Common options:"),
00145         NULL },
00146 
00147    POPT_AUTOALIAS
00148    POPT_AUTOHELP
00149    POPT_TABLEEND
00150 };
00151 
00152 #ifdef __MINT__
00153 /* MiNT cannot dynamically increase the stack.  */
00154 long _stksize = 64 * 1024L;
00155 #endif
00156 
00157 /*@exits@*/ static void argerror(const char * desc)
00158         /*@globals __assert_program_name, fileSystem @*/
00159         /*@modifies fileSystem @*/
00160 {
00161     fprintf(stderr, _("%s: %s\n"), __progname, desc);
00162     exit(EXIT_FAILURE);
00163 }
00164 
00165 #ifdef  DYING /* XXX rpmIsVerbose alone stops usage spewage with every --eval */
00166 static void printVersion(FILE * fp)
00167         /*@globals rpmEVR, fileSystem @*/
00168         /*@modifies *fp, fileSystem @*/
00169 {
00170     fprintf(fp, "%s (" RPM_NAME ") %s\n", __progname, rpmEVR);
00171     if (rpmIsVerbose())
00172         fprintf(fp, "rpmlib 0x%08x,0x%08x,0x%08x\n",
00173             rpmlibVersion(), rpmlibTimestamp(), rpmlibVendor());
00174 }
00175 
00176 static void printUsage(poptContext con, FILE * fp, int flags)
00177         /*@globals rpmEVR, fileSystem, internalState @*/
00178         /*@modifies *fp, fileSystem, internalState @*/
00179 {
00180     printVersion(fp);
00181     fprintf(fp, "\n");
00182 
00183     if (rpmIsVerbose())
00184         poptPrintHelp(con, fp, flags);
00185     else
00186         poptPrintUsage(con, fp, flags);
00187 }
00188 #endif
00189 
00190 #if defined(RPM_VENDOR_OPENPKG) /* integrity-checking */
00191 
00192 #if !defined(RPM_INTEGRITY_FP)
00193 #error required RPM_INTEGRITY_FP (fingerprint of public key of integrity authority) not defined!
00194 #endif
00195 
00196 enum {
00197     INTEGRITY_OK      = 0,
00198     INTEGRITY_WARNING = 1,
00199     INTEGRITY_ERROR   = 2
00200 };
00201 
00202 static void integrity_check_message(const char *fmt, ...)
00203 {
00204     va_list ap;
00205 
00206     va_start(ap, fmt);
00207     fprintf(stderr, "rpm: ATTENTION: INTEGRITY CHECKING DETECTED AN ENVIRONMENT ANOMALY!\nrpm: ");
00208     vfprintf(stderr, fmt, ap);
00209     va_end(ap);
00210     return;
00211 }
00212 
00213 static void integrity_check(const char *progname, enum modes progmode_num)
00214 {
00215     rpmts ts = NULL;
00216     rpmlua lua = NULL;
00217     char *spec_fn = NULL;
00218     char *proc_fn = NULL;
00219     char *pkey_fn = NULL;
00220     char *spec = NULL;
00221     char *proc = NULL;
00222     rpmiob spec_iob = NULL;
00223     rpmiob proc_iob = NULL;
00224     const char *result = NULL;
00225     const char *error = NULL;
00226     int xx;
00227     const char *progmode;
00228     int rc = INTEGRITY_ERROR;
00229 
00230     /* determine paths of integrity checking related files */
00231     spec_fn = rpmExpand("%{?_integrity_spec_cfg}%{!?_integrity_spec_cfg:scripts/integrity.cfg}", NULL);
00232     if (spec_fn == NULL || spec_fn[0] == '\0') {
00233         integrity_check_message("ERROR: Integrity Configuration Specification file not configured.\n"
00234             "rpm: HINT: macro %%{_integrity_spec_cfg} not configured correctly.\n");
00235         goto failure;
00236     }
00237     proc_fn = rpmExpand("%{?_integrity_proc_lua}%{!?_integrity_proc_lua:scripts/integrity.lua}", NULL);
00238     if (proc_fn == NULL || proc_fn[0] == '\0') {
00239         integrity_check_message("ERROR: Integrity Validation Processor file not configured.\n"
00240             "rpm: HINT: macro %%{_integrity_proc_lua} not configured correctly.\n");
00241         goto failure;
00242     }
00243     pkey_fn = rpmExpand("%{?_integrity_pkey_pgp}%{!?_integrity_pkey_pgp:scripts/integrity.pgp}", NULL);
00244     if (pkey_fn == NULL || pkey_fn[0] == '\0') {
00245         integrity_check_message("ERROR: Integrity Autority Public-Key file not configured.\n"
00246             "rpm: HINT: macro %%{_integrity_pkey_pgp} not configured correctly.\n");
00247         goto failure;
00248     }
00249 
00250     /* create RPM transaction environment and open RPM database */
00251     ts = rpmtsCreate();
00252     (void)rpmtsOpenDB(ts, O_RDONLY);
00253 
00254     /* check signature on integrity configuration specification file */
00255     if (rpmnsProbeSignature(ts, spec_fn, NULL, pkey_fn, RPM_INTEGRITY_FP, 0) != RPMRC_OK) {
00256         integrity_check_message("ERROR: Integrity Configuration Specification file contains invalid signature.\n"
00257             "rpm: HINT: Check file \"%s\".\n", spec_fn);
00258         goto failure;
00259     }
00260 
00261     /* check signature on integrity validation processor file */
00262     if (rpmnsProbeSignature(ts, proc_fn, NULL, pkey_fn, RPM_INTEGRITY_FP, 0) != RPMRC_OK) {
00263         integrity_check_message("ERROR: Integrity Validation Processor file contains invalid signature.\n"
00264             "rpm: HINT: Check file \"%s\".\n", proc_fn);
00265         goto failure;
00266     }
00267 
00268     /* load integrity configuration specification file */
00269     xx = rpmiobSlurp(spec_fn, &spec_iob);
00270     if (!(xx == 0 && spec_iob != NULL)) {
00271         integrity_check_message("ERROR: Unable to load Integrity Configuration Specification file.\n"
00272             "rpm: HINT: Check file \"%s\".\n", spec_fn);
00273         goto failure;
00274     }
00275     spec = rpmiobStr(spec_iob);
00276 
00277     /* load integrity validation processor file */
00278     xx = rpmiobSlurp(proc_fn, &proc_iob);
00279     if (!(xx == 0 && proc_iob != NULL)) {
00280         integrity_check_message("ERROR: Unable to load Integrity Validation Processor file.\n"
00281             "rpm: HINT: Check file \"%s\".\n", proc_fn);
00282         goto failure;
00283     }
00284     proc = rpmiobStr(proc_iob);
00285 
00286     /* provision program name and mode */
00287     if (progname == NULL || progname[0] == '\0')
00288         progname = "rpm";
00289     switch (progmode_num) {
00290         case MODE_QUERY:     progmode = "query";     break;
00291         case MODE_VERIFY:    progmode = "verify";    break;
00292         case MODE_CHECKSIG:  progmode = "checksig";  break;
00293         case MODE_RESIGN:    progmode = "resign";    break;
00294         case MODE_INSTALL:   progmode = "install";   break;
00295         case MODE_ERASE:     progmode = "erase";     break;
00296         case MODE_BUILD:     progmode = "build";     break;
00297         case MODE_REBUILD:   progmode = "rebuild";   break;
00298         case MODE_RECOMPILE: progmode = "recompile"; break;
00299         case MODE_TARBUILD:  progmode = "tarbuild";  break;
00300         case MODE_REBUILDDB: progmode = "rebuilddb"; break;
00301         case MODE_UNKNOWN:   progmode = "unknown";   break;
00302         default:             progmode = "unknown";   break;
00303     }
00304 
00305     /* execute Integrity Validation Processor via Lua glue code */
00306     lua = rpmluaNew();
00307     rpmluaSetPrintBuffer(lua, 1);
00308     rpmluaextActivate(lua);
00309     lua_getfield(lua->L, LUA_GLOBALSINDEX, "integrity");
00310     lua_getfield(lua->L, -1, "processor");
00311     lua_remove(lua->L, -2);
00312     lua_pushstring(lua->L, progname);
00313     lua_pushstring(lua->L, progmode);
00314     lua_pushstring(lua->L, spec_fn);
00315     lua_pushstring(lua->L, spec);
00316     lua_pushstring(lua->L, proc_fn);
00317     lua_pushstring(lua->L, proc);
00318 #ifdef RPM_INTEGRITY_MV
00319     lua_pushstring(lua->L, RPM_INTEGRITY_MV);
00320 #else
00321     lua_pushstring(lua->L, "0");
00322 #endif
00323     if (lua_pcall(lua->L, 7, 1, 0) != 0) {
00324         error = lua_isstring(lua->L, -1) ? lua_tostring(lua->L, -1) : "unknown error";
00325         lua_pop(lua->L, 1);
00326         integrity_check_message("ERROR: Failed to execute Integrity Validation Processor.\n"
00327             "rpm: ERROR: Lua: %s.\n"
00328             "rpm: HINT: Check file \"%s\".\n", error, proc_fn);
00329         goto failure;
00330     }
00331 
00332     /* check Integrity Validation Processor results */
00333     if (!lua_isstring(lua->L, -1)) {
00334         integrity_check_message("ERROR: Failed to fetch Integrity Validation Processor results.\n"
00335             "rpm: HINT: Check file \"%s\".\n", proc_fn);
00336         goto failure;
00337     }
00338     result = lua_tostring(lua->L, -1);
00339     if (strcmp(result, "OK") == 0)
00340         rc = INTEGRITY_OK;
00341     else if (strncmp(result, "WARNING:", 8) == 0) {
00342         rc = INTEGRITY_WARNING;
00343         integrity_check_message("%s\n", result);
00344     }
00345     else {
00346         rc = INTEGRITY_ERROR;
00347         integrity_check_message("%s\n", result);
00348     }
00349 
00350     /* cleanup processing */
00351     failure:
00352     if (lua != NULL)
00353         rpmluaFree(lua);
00354     if (ts != NULL)
00355         (void)rpmtsFree(ts);
00356     ts = NULL;
00357     if (spec_iob != NULL)
00358         spec_iob = rpmiobFree(spec_iob);
00359     if (proc_iob != NULL)
00360         proc_iob = rpmiobFree(proc_iob);
00361 
00362     /* final result handling */
00363     if (rc != INTEGRITY_OK) {
00364         if (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO))
00365             sleep(4);
00366         if (rc == INTEGRITY_ERROR)
00367             exit(42);
00368     }
00369     return;
00370 }
00371 #endif
00372 
00373 /*@-bounds@*/ /* LCL: segfault */
00374 /*@-mods@*/ /* FIX: shrug */
00375 #if !defined(__GLIBC__) && !defined(__LCLINT__)
00376 int main(int argc, const char ** argv, /*@unused@*/ char ** envp)
00377 #else
00378 int main(int argc, const char ** argv)
00379 #endif
00380         /*@globals rpmEVR, RPMVERSION,
00381                 rpmGlobalMacroContext, rpmCLIMacroContext,
00382                 h_errno, fileSystem, internalState@*/
00383         /*@modifies fileSystem, internalState@*/
00384 {
00385     poptContext optCon = rpmcliInit(argc, (char *const *)argv, optionsTable);
00386 
00387     rpmts ts = NULL;
00388     enum modes bigMode = MODE_UNKNOWN;
00389 
00390 #if defined(IAM_RPMQV)
00391     QVA_t qva = &rpmQVKArgs;
00392 #endif
00393 
00394 #ifdef  IAM_RPMBT
00395     BTA_t ba = &rpmBTArgs;
00396 #endif
00397 
00398 #ifdef  IAM_RPMEIU
00399     QVA_t ia = &rpmIArgs;
00400 #endif
00401 
00402 #if defined(IAM_RPMDB)
00403     QVA_t da = &rpmDBArgs;
00404 #endif
00405 
00406 #if defined(IAM_RPMK)
00407     QVA_t ka = &rpmQVKArgs;
00408 #endif
00409 
00410 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
00411     char * passPhrase = "";
00412 #endif
00413 
00414     pid_t pipeChild = 0;
00415     int ec = 0;
00416     int status;
00417     int p[2];
00418 #ifdef  IAM_RPMEIU
00419     int xx;
00420 #endif
00421         
00422 #if !defined(__GLIBC__) && !defined(__LCLINT__)
00423     environ = envp;
00424 #else
00425 /* XXX limit the fiddle up to linux for now. */
00426 #if !defined(HAVE_SETPROCTITLE) && defined(__linux__)
00427     (void) initproctitle(argc, (char **)argv, environ);
00428 #endif
00429 #endif  
00430 
00431     /* Set the major mode based on argv[0] */
00432     /*@-nullpass@*/
00433 #ifdef  IAM_RPMBT
00434     if (!strcmp(__progname, "rpmb"))    bigMode = MODE_BUILD;
00435     if (!strcmp(__progname, "lt-rpmb")) bigMode = MODE_BUILD;
00436     if (!strcmp(__progname, "rpmt"))    bigMode = MODE_TARBUILD;
00437     if (!strcmp(__progname, "rpmbuild"))        bigMode = MODE_BUILD;
00438 #endif
00439 #ifdef  IAM_RPMQV
00440     if (!strcmp(__progname, "rpmq"))    bigMode = MODE_QUERY;
00441     if (!strcmp(__progname, "lt-rpmq")) bigMode = MODE_QUERY;
00442     if (!strcmp(__progname, "rpmv"))    bigMode = MODE_VERIFY;
00443     if (!strcmp(__progname, "rpmquery"))        bigMode = MODE_QUERY;
00444     if (!strcmp(__progname, "rpmverify"))       bigMode = MODE_VERIFY;
00445 #endif
00446 #ifdef  RPMEIU
00447     if (!strcmp(__progname, "rpme"))    bigMode = MODE_ERASE;
00448     if (!strcmp(__progname, "rpmi"))    bigMode = MODE_INSTALL;
00449     if (!strcmp(__progname, "lt-rpmi")) bigMode = MODE_INSTALL;
00450     if (!strcmp(__progname, "rpmu"))    bigMode = MODE_INSTALL;
00451 #endif
00452     /*@=nullpass@*/
00453 
00454 #if defined(IAM_RPMQV)
00455     /* Jumpstart option from argv[0] if necessary. */
00456     switch (bigMode) {
00457     case MODE_QUERY:    qva->qva_mode = 'q';    break;
00458     case MODE_VERIFY:   qva->qva_mode = 'V';    break;
00459     case MODE_CHECKSIG: qva->qva_mode = 'K';    break;
00460     case MODE_RESIGN:   qva->qva_mode = 'R';    break;
00461     case MODE_INSTALL:
00462     case MODE_ERASE:
00463     case MODE_BUILD:
00464     case MODE_REBUILD:
00465     case MODE_RECOMPILE:
00466     case MODE_TARBUILD:
00467     case MODE_REBUILDDB:
00468     case MODE_UNKNOWN:
00469     default:
00470         break;
00471     }
00472 #endif
00473 
00474     rpmcliConfigured();
00475 
00476 #ifdef  IAM_RPMBT
00477     switch (ba->buildMode) {
00478     case 'b':   bigMode = MODE_BUILD;           break;
00479     case 't':   bigMode = MODE_TARBUILD;        break;
00480     case 'B':   bigMode = MODE_REBUILD;         break;
00481     case 'C':   bigMode = MODE_RECOMPILE;       break;
00482     }
00483 
00484     if ((ba->buildAmount & RPMBUILD_RMSOURCE) && bigMode == MODE_UNKNOWN)
00485         bigMode = MODE_BUILD;
00486 
00487     if ((ba->buildAmount & RPMBUILD_RMSPEC) && bigMode == MODE_UNKNOWN)
00488         bigMode = MODE_BUILD;
00489 #endif  /* IAM_RPMBT */
00490     
00491 #ifdef  IAM_RPMDB
00492   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_DB)) {
00493     if (da->rebuild) {
00494         if (bigMode != MODE_UNKNOWN) 
00495             argerror(_("only one major mode may be specified"));
00496         else
00497             bigMode = MODE_REBUILDDB;
00498     }
00499   }
00500 #endif  /* IAM_RPMDB */
00501 
00502 #ifdef  IAM_RPMQV
00503   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_QV)) {
00504     switch (qva->qva_mode) {
00505     case 'q':   bigMode = MODE_QUERY;           break;
00506     case 'V':   bigMode = MODE_VERIFY;          break;
00507     }
00508 
00509     if (qva->qva_sourceCount) {
00510         if (qva->qva_sourceCount > 2)
00511             argerror(_("one type of query/verify may be performed at a "
00512                         "time"));
00513     }
00514     if (qva->qva_flags && (bigMode & ~MODES_QV)) 
00515         argerror(_("unexpected query flags"));
00516 
00517     if (qva->qva_queryFormat && (bigMode & ~MODES_QV)) 
00518         argerror(_("unexpected query format"));
00519 
00520     if (qva->qva_source != RPMQV_PACKAGE && (bigMode & ~MODES_QV)) 
00521         argerror(_("unexpected query source"));
00522   }
00523 #endif  /* IAM_RPMQV */
00524 
00525 #ifdef  IAM_RPMEIU
00526   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_IE))
00527     {   int iflags = (ia->installInterfaceFlags &
00528                 (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL));
00529         int eflags = (ia->installInterfaceFlags & INSTALL_ERASE);
00530 
00531         if (iflags & eflags)
00532             argerror(_("only one major mode may be specified"));
00533         else if (iflags)
00534             bigMode = MODE_INSTALL;
00535         else if (eflags)
00536             bigMode = MODE_ERASE;
00537     }
00538 #endif  /* IAM_RPMEIU */
00539 
00540 #ifdef  IAM_RPMK
00541   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_K)) {
00542         switch (ka->qva_mode) {
00543         case RPMSIGN_NONE:
00544             ka->sign = 0;
00545             break;
00546         case RPMSIGN_IMPORT_PUBKEY:
00547         case RPMSIGN_CHK_SIGNATURE:
00548             bigMode = MODE_CHECKSIG;
00549             ka->sign = 0;
00550             break;
00551         case RPMSIGN_ADD_SIGNATURE:
00552         case RPMSIGN_NEW_SIGNATURE:
00553         case RPMSIGN_DEL_SIGNATURE:
00554             bigMode = MODE_RESIGN;
00555             ka->sign = (ka->qva_mode != RPMSIGN_DEL_SIGNATURE);
00556             break;
00557         }
00558   }
00559 #endif  /* IAM_RPMK */
00560 
00561 #if defined(IAM_RPMEIU)
00562     if (!( bigMode == MODE_INSTALL ) &&
00563 (ia->probFilter & (RPMPROB_FILTER_REPLACEPKG | RPMPROB_FILTER_OLDPACKAGE)))
00564         argerror(_("only installation, upgrading, rmsource and rmspec may be forced"));
00565     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_FORCERELOCATE))
00566         argerror(_("files may only be relocated during package installation"));
00567 
00568     if (ia->relocations && ia->qva_prefix)
00569         argerror(_("cannot use --prefix with --relocate or --excludepath"));
00570 
00571     if (bigMode != MODE_INSTALL && ia->relocations)
00572         argerror(_("--relocate and --excludepath may only be used when installing new packages"));
00573 
00574     if (bigMode != MODE_INSTALL && ia->qva_prefix)
00575         argerror(_("--prefix may only be used when installing new packages"));
00576 
00577     if (ia->qva_prefix && ia->qva_prefix[0] != '/') 
00578         argerror(_("arguments to --prefix must begin with a /"));
00579 
00580     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_HASH))
00581         argerror(_("--hash (-h) may only be specified during package "
00582                         "installation"));
00583 
00584     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_PERCENT))
00585         argerror(_("--percent may only be specified during package "
00586                         "installation"));
00587 
00588     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_REPLACEPKG))
00589         argerror(_("--replacepkgs may only be specified during package "
00590                         "installation"));
00591 
00592     if (bigMode != MODE_INSTALL && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
00593         argerror(_("--excludedocs may only be specified during package "
00594                    "installation"));
00595 
00596     if (bigMode != MODE_INSTALL && ia->incldocs)
00597         argerror(_("--includedocs may only be specified during package "
00598                    "installation"));
00599 
00600     if (ia->incldocs && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
00601         argerror(_("only one of --excludedocs and --includedocs may be "
00602                  "specified"));
00603   
00604     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREARCH))
00605         argerror(_("--ignorearch may only be specified during package "
00606                    "installation"));
00607 
00608     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREOS))
00609         argerror(_("--ignoreos may only be specified during package "
00610                    "installation"));
00611 
00612     if ((ia->installInterfaceFlags & INSTALL_ALLMATCHES) && bigMode != MODE_ERASE)
00613         argerror(_("--allmatches may only be specified during package "
00614                    "erasure"));
00615 
00616     if ((ia->transFlags & RPMTRANS_FLAG_ALLFILES) && bigMode != MODE_INSTALL)
00617         argerror(_("--allfiles may only be specified during package "
00618                    "installation"));
00619 
00620     if ((ia->transFlags & RPMTRANS_FLAG_JUSTDB) &&
00621         bigMode != MODE_INSTALL && bigMode != MODE_ERASE)
00622         argerror(_("--justdb may only be specified during package "
00623                    "installation and erasure"));
00624 
00625     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
00626         (ia->transFlags & (RPMTRANS_FLAG_NOSCRIPTS | _noTransScripts | _noTransTriggers)))
00627         argerror(_("script disabling options may only be specified during "
00628                    "package installation and erasure"));
00629 
00630     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
00631         (ia->transFlags & (RPMTRANS_FLAG_NOTRIGGERS | _noTransTriggers)))
00632         argerror(_("trigger disabling options may only be specified during "
00633                    "package installation and erasure"));
00634 
00635     if (ia->noDeps & (bigMode & ~MODES_FOR_NODEPS))
00636         argerror(_("--nodeps may only be specified during package "
00637                    "building, rebuilding, recompilation, installation, "
00638                    "erasure, and verification"));
00639 
00640     if ((ia->transFlags & RPMTRANS_FLAG_TEST) && (bigMode & ~MODES_FOR_TEST))
00641         argerror(_("--test may only be specified during package installation, "
00642                  "erasure, and building"));
00643 #endif  /* IAM_RPMEIU */
00644 
00645     if (rpmioRootDir && rpmioRootDir[1] && (bigMode & ~MODES_FOR_ROOT))
00646         argerror(_("--root (-r) may only be specified during "
00647                  "installation, erasure, querying, and "
00648                  "database rebuilds"));
00649 
00650     if (rpmioRootDir) {
00651         switch (urlIsURL(rpmioRootDir)) {
00652         default:
00653             if (bigMode & MODES_FOR_ROOT)
00654                 break;
00655             /*@fallthrough@*/
00656         case URL_IS_UNKNOWN:
00657             if (rpmioRootDir[0] != '/')
00658                 argerror(_("arguments to --root (-r) must begin with a /"));
00659             break;
00660         }
00661     }
00662 
00663 #if defined(RPM_VENDOR_OPENPKG) /* integrity-checking */
00664     integrity_check(__progname, bigMode);
00665 #endif
00666 
00667 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
00668     if (0
00669 #if defined(IAM_RPMBT)
00670     || ba->sign 
00671 #endif
00672 #if defined(IAM_RPMK)
00673     || ka->sign
00674 #endif
00675     )
00676     /*@-branchstate@*/
00677     {
00678         if (bigMode == MODE_REBUILD || bigMode == MODE_BUILD ||
00679             bigMode == MODE_RESIGN || bigMode == MODE_TARBUILD)
00680         {
00681             const char ** av;
00682             struct stat sb;
00683             int errors = 0;
00684 
00685             if ((av = poptGetArgs(optCon)) == NULL) {
00686                 fprintf(stderr, _("no files to sign\n"));
00687                 errors++;
00688             } else
00689             while (*av) {
00690                 if (Stat(*av, &sb)) {
00691                     fprintf(stderr, _("cannot access file %s\n"), *av);
00692                     errors++;
00693                 }
00694                 av++;
00695             }
00696 
00697             if (errors) {
00698                 ec = errors;
00699                 goto exit;
00700             }
00701 
00702         
00703             if (poptPeekArg(optCon)
00704 #if defined(IAM_RPMBT)
00705             && !ba->nopassword 
00706 #endif
00707 #if defined(IAM_RPMK)
00708             && !ka->nopassword
00709 #endif
00710             )
00711             {
00712                 passPhrase = Getpass(_("Enter pass phrase: "));
00713                 if (rpmCheckPassPhrase(passPhrase)) {
00714                     fprintf(stderr, _("Pass phrase check failed\n"));
00715                     ec = EXIT_FAILURE;
00716                     goto exit;
00717                 }
00718                 fprintf(stderr, _("Pass phrase is good.\n"));
00719                 /* XXX Getpass() should realloc instead. */
00720                 passPhrase = xstrdup(passPhrase);
00721             }
00722         }
00723     }
00724     /*@=branchstate@*/
00725 #endif  /* IAM_RPMBT || IAM_RPMK */
00726 
00727     if (rpmioPipeOutput) {
00728         if (pipe(p) < 0) {
00729             fprintf(stderr, _("creating a pipe for --pipe failed: %m\n"));
00730             goto exit;
00731         }
00732 
00733         if (!(pipeChild = fork())) {
00734             (void) close(p[1]);
00735             (void) dup2(p[0], STDIN_FILENO);
00736             (void) close(p[0]);
00737             (void) execl("/bin/sh", "/bin/sh", "-c", rpmioPipeOutput, NULL);
00738             fprintf(stderr, _("exec failed\n"));
00739         }
00740 
00741         (void) close(p[0]);
00742         (void) dup2(p[1], STDOUT_FILENO);
00743         (void) close(p[1]);
00744     }
00745         
00746     ts = rpmtsCreate();
00747     (void) rpmtsSetRootDir(ts, rpmioRootDir);
00748     switch (bigMode) {
00749 #ifdef  IAM_RPMDB
00750     case MODE_REBUILDDB:
00751     {   rpmVSFlags vsflags = rpmExpandNumeric("%{_vsflags_rebuilddb}");
00752         rpmVSFlags ovsflags;
00753         if (rpmcliQueryFlags & VERIFY_DIGEST)
00754             vsflags |= _RPMVSF_NODIGESTS;
00755         if (rpmcliQueryFlags & VERIFY_SIGNATURE)
00756             vsflags |= _RPMVSF_NOSIGNATURES;
00757         ovsflags = rpmtsSetVSFlags(ts, vsflags);
00758         ec = rpmtsRebuildDB(ts);
00759         vsflags = rpmtsSetVSFlags(ts, ovsflags);
00760     }   break;
00761 #endif  /* IAM_RPMDB */
00762 
00763 #ifdef  IAM_RPMBT
00764     case MODE_REBUILD:
00765     case MODE_RECOMPILE:
00766     {   const char * pkg;
00767         int nbuilds = 0;
00768 
00769         while (!rpmIsVerbose())
00770             rpmIncreaseVerbosity();
00771 
00772         if (!poptPeekArg(optCon))
00773             argerror(_("no packages files given for rebuild"));
00774 
00775         ba->buildAmount =
00776             RPMBUILD_PREP | RPMBUILD_BUILD | RPMBUILD_INSTALL | RPMBUILD_CHECK;
00777         if (bigMode == MODE_REBUILD) {
00778             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
00779             ba->buildAmount |= RPMBUILD_RMSOURCE;
00780             ba->buildAmount |= RPMBUILD_RMSPEC;
00781             ba->buildAmount |= RPMBUILD_CLEAN;
00782             ba->buildAmount |= RPMBUILD_RMBUILD;
00783         }
00784 
00785         while ((pkg = poptGetArg(optCon))) {
00786             if (nbuilds++ > 0) {
00787                 rpmFreeMacros(NULL);
00788                 rpmFreeRpmrc();
00789                 (void) rpmReadConfigFiles(NULL, NULL);
00790             }
00791             ba->specFile = NULL;
00792             ba->cookie = NULL;
00793             ec = rpmInstallSource(ts, pkg, &ba->specFile, &ba->cookie);
00794             if (ec == 0) {
00795                 ba->rootdir = rpmioRootDir;
00796                 ba->passPhrase = passPhrase;
00797                 ec = build(ts, ba, NULL);
00798             }
00799             ba->cookie = _free(ba->cookie);
00800             ba->specFile = _free(ba->specFile);
00801 
00802             if (ec)
00803                 /*@loopbreak@*/ break;
00804         }
00805 
00806     }   break;
00807 
00808     case MODE_BUILD:
00809     case MODE_TARBUILD:
00810     {   int nbuilds = 0;
00811 
00812 #if defined(RPM_VENDOR_OPENPKG) /* no-auto-verbose-increase-for-track-and-fetch */
00813         if (ba->buildChar != 't' && ba->buildChar != 'f')
00814 #endif
00815         while (!rpmIsVerbose())
00816             rpmIncreaseVerbosity();
00817        
00818         switch (ba->buildChar) {
00819         case 'a':
00820             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
00821             /*@fallthrough@*/
00822         case 'b':
00823             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
00824             ba->buildAmount |= RPMBUILD_CLEAN;
00825             if ((ba->buildChar == 'b') && ba->shortCircuit)
00826                 /*@innerbreak@*/ break;
00827             /*@fallthrough@*/
00828         case 'i':
00829             ba->buildAmount |= RPMBUILD_INSTALL;
00830             ba->buildAmount |= RPMBUILD_CHECK;
00831             if ((ba->buildChar == 'i') && ba->shortCircuit)
00832                 /*@innerbreak@*/ break;
00833             /*@fallthrough@*/
00834         case 'c':
00835             ba->buildAmount |= RPMBUILD_BUILD;
00836             if ((ba->buildChar == 'c') && ba->shortCircuit)
00837                 /*@innerbreak@*/ break;
00838             /*@fallthrough@*/
00839         case 'p':
00840             ba->buildAmount |= RPMBUILD_PREP;
00841             /*@innerbreak@*/ break;
00842             
00843         case 'l':
00844             ba->buildAmount |= RPMBUILD_FILECHECK;
00845             /*@innerbreak@*/ break;
00846         case 's':
00847             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
00848 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-deps-on-building-srpms */
00849             /* enforce no dependency checking when rolling a source RPM */
00850             ba->noDeps = 1;
00851 #endif
00852             /*@innerbreak@*/ break;
00853         case 't':       /* support extracting the "%track" script/section */
00854             ba->buildAmount |= RPMBUILD_TRACK;
00855             /* enforce no dependency checking and expansion of %setup, %patch and %prep macros */
00856             ba->noDeps = 1;
00857             rpmDefineMacro(NULL, "setup #", RMIL_CMDLINE);
00858             rpmDefineMacro(NULL, "patch #", RMIL_CMDLINE);
00859             rpmDefineMacro(NULL, "prep %%prep", RMIL_CMDLINE);
00860             /*@innerbreak@*/ break;
00861         case 'f':
00862             ba->buildAmount |= RPMBUILD_FETCHSOURCE;
00863             ba->noDeps = 1;
00864             /*@innerbreak@*/ break;
00865         }
00866 
00867         if (!poptPeekArg(optCon)) {
00868             if (bigMode == MODE_BUILD)
00869                 argerror(_("no spec files given for build"));
00870             else
00871                 argerror(_("no tar files given for build"));
00872         }
00873 
00874         while ((ba->specFile = poptGetArg(optCon))) {
00875             if (nbuilds++ > 0) {
00876                 rpmFreeMacros(NULL);
00877                 rpmFreeRpmrc();
00878                 (void) rpmReadConfigFiles(NULL, NULL);
00879             }
00880             ba->rootdir = rpmioRootDir;
00881             ba->passPhrase = passPhrase;
00882             ba->cookie = NULL;
00883             ec = build(ts, ba, NULL);
00884             if (ec)
00885                 /*@loopbreak@*/ break;
00886         }
00887     }   break;
00888 #endif  /* IAM_RPMBT */
00889 
00890 #ifdef  IAM_RPMEIU
00891     case MODE_ERASE:
00892         ia->depFlags = global_depFlags;
00893         if (ia->noDeps) ia->installInterfaceFlags |= INSTALL_NODEPS;
00894 
00895         if (!poptPeekArg(optCon)) {
00896             if (ia->rbtid == 0)
00897                 argerror(_("no packages given for erase"));
00898 ia->transFlags |= RPMTRANS_FLAG_NOFDIGESTS;
00899 ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
00900 ia->rbCheck = rpmcliInstallCheck;
00901 ia->rbOrder = rpmcliInstallOrder;
00902 ia->rbRun = rpmcliInstallRun;
00903             ec += rpmRollback(ts, ia, NULL);
00904         } else {
00905             ec += rpmErase(ts, ia, (const char **) poptGetArgs(optCon));
00906         }
00907         break;
00908 
00909     case MODE_INSTALL:
00910 
00911         /* RPMTRANS_FLAG_KEEPOBSOLETE */
00912 
00913         ia->depFlags = global_depFlags;
00914         if (!ia->incldocs) {
00915             if (ia->transFlags & RPMTRANS_FLAG_NODOCS) {
00916                 ;
00917             } else if (rpmExpandNumeric("%{_excludedocs}"))
00918                 ia->transFlags |= RPMTRANS_FLAG_NODOCS;
00919         }
00920 
00921         if (ia->noDeps) ia->installInterfaceFlags |= INSTALL_NODEPS;
00922 
00923         /* we've already ensured !(!ia->prefix && !ia->relocations) */
00924         /*@-branchstate@*/
00925         if (ia->qva_prefix) {
00926             xx = rpmfiAddRelocation(&ia->relocations, &ia->nrelocations,
00927                         NULL, ia->qva_prefix);
00928             xx = rpmfiAddRelocation(&ia->relocations, &ia->nrelocations,
00929                         NULL, NULL);
00930         } else if (ia->relocations) {
00931             xx = rpmfiAddRelocation(&ia->relocations, &ia->nrelocations,
00932                         NULL, NULL);
00933         }
00934         /*@=branchstate@*/
00935 
00936         if (!poptPeekArg(optCon)) {
00937             if (ia->rbtid == 0)
00938                 argerror(_("no packages given for install"));
00939 ia->transFlags |= RPMTRANS_FLAG_NOFDIGESTS;
00940 ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
00941 ia->rbCheck = rpmcliInstallCheck;
00942 ia->rbOrder = rpmcliInstallOrder;
00943 ia->rbRun = rpmcliInstallRun;
00944 /*@i@*/     ec += rpmRollback(ts, ia, NULL);
00945         } else {
00946             /*@-compdef -compmempass@*/ /* FIX: ia->relocations[0].newPath undefined */
00947             ec += rpmcliInstall(ts, ia, (const char **)poptGetArgs(optCon));
00948             /*@=compdef =compmempass@*/
00949         }
00950         break;
00951 
00952 #endif  /* IAM_RPMEIU */
00953 
00954 #ifdef  IAM_RPMQV
00955     case MODE_QUERY:
00956         if (!poptPeekArg(optCon)
00957          && !(qva->qva_source == RPMQV_ALL || qva->qva_source == RPMQV_HDLIST))
00958             argerror(_("no arguments given for query"));
00959 
00960         qva->depFlags = global_depFlags;
00961         qva->qva_specQuery = rpmspecQuery;
00962         ec = rpmcliQuery(ts, qva, (const char **) poptGetArgs(optCon));
00963         qva->qva_specQuery = NULL;
00964         break;
00965 
00966     case MODE_VERIFY:
00967     {   rpmVerifyFlags verifyFlags = VERIFY_ALL;
00968 
00969         qva->depFlags = global_depFlags;
00970         verifyFlags &= ~qva->qva_flags;
00971         qva->qva_flags = (rpmQueryFlags) verifyFlags;
00972 
00973         if (!poptPeekArg(optCon)
00974          && !(qva->qva_source == RPMQV_ALL || qva->qva_source == RPMQV_HDLIST))
00975             argerror(_("no arguments given for verify"));
00976         ec = rpmcliVerify(ts, qva, (const char **) poptGetArgs(optCon));
00977     }   break;
00978 #endif  /* IAM_RPMQV */
00979 
00980 #ifdef IAM_RPMK
00981     case MODE_CHECKSIG:
00982     {   rpmVerifyFlags verifyFlags =
00983                 (VERIFY_FDIGEST|VERIFY_HDRCHK|VERIFY_DIGEST|VERIFY_SIGNATURE);
00984 
00985         verifyFlags &= ~ka->qva_flags;
00986         ka->qva_flags = (rpmQueryFlags) verifyFlags;
00987     }   /*@fallthrough@*/
00988     case MODE_RESIGN:
00989         if (!poptPeekArg(optCon))
00990             argerror(_("no arguments given"));
00991         ka->passPhrase = passPhrase;
00992         ec = rpmcliSign(ts, ka, (const char **)poptGetArgs(optCon));
00993         break;
00994 #endif  /* IAM_RPMK */
00995         
00996 #if !defined(IAM_RPMQV)
00997     case MODE_QUERY:
00998     case MODE_VERIFY:
00999 #endif
01000 #if !defined(IAM_RPMK)
01001     case MODE_CHECKSIG:
01002     case MODE_RESIGN:
01003 #endif
01004 #if !defined(IAM_RPMDB)
01005     case MODE_REBUILDDB:
01006 #endif
01007 #if !defined(IAM_RPMBT)
01008     case MODE_BUILD:
01009     case MODE_REBUILD:
01010     case MODE_RECOMPILE:
01011     case MODE_TARBUILD:
01012 #endif
01013 #if !defined(IAM_RPMEIU)
01014     case MODE_INSTALL:
01015     case MODE_ERASE:
01016 #endif
01017     case MODE_UNKNOWN:
01018 #ifdef  DYING /* XXX rpmIsVerbose alone stops usage spewage with every --eval */
01019         if (poptPeekArg(optCon) != NULL || argc <= 1 || rpmIsVerbose()) {
01020             printUsage(optCon, stderr, 0);
01021             ec = argc;
01022         }
01023 #endif
01024         break;
01025     }
01026 
01027 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
01028 exit:
01029 #endif  /* IAM_RPMBT || IAM_RPMK */
01030 
01031     (void)rpmtsFree(ts); 
01032     ts = NULL;
01033 
01034     if (pipeChild) {
01035         (void) fclose(stdout);
01036         (void) waitpid(pipeChild, &status, 0);
01037     }
01038 
01039 #ifdef  IAM_RPMQV
01040     qva->qva_queryFormat = _free(qva->qva_queryFormat);
01041 #endif
01042 
01043 #ifdef  IAM_RPMBT
01044     freeNames();
01045     /* XXX _specPool/_pkgPool teardown should be done somewhere else. */
01046     {   extern rpmioPool _pkgPool;
01047         extern rpmioPool _specPool;
01048         _pkgPool = rpmioFreePool(_pkgPool);
01049         _specPool = rpmioFreePool(_specPool);
01050     }
01051 #endif
01052 
01053 #ifdef  IAM_RPMEIU
01054     ia->relocations = rpmfiFreeRelocations(ia->relocations);
01055 #endif
01056 
01057     optCon = rpmcliFini(optCon);
01058 
01059 /* XXX limit the fiddle up to linux for now. */
01060 #if !defined(HAVE_SETPROCTITLE) && defined(__linux__)
01061     (void) finiproctitle();
01062 #endif
01063 
01064     /* XXX don't overflow single byte exit status */
01065     /* XXX status 255 is special to xargs(1) */
01066     if (ec > 254) ec = 254;
01067 
01068     /*@-globstate@*/
01069     return ec;
01070     /*@=globstate@*/
01071 }
01072 /*@=mods@*/
01073 /*@=bounds@*/