- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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