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