X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=rpmbuild.c;h=4fb4289f834359b64d81a3340844c6e13f98be03;hb=505aac517c1319c6b5c122a4e2cf34b6c0089d34;hp=63f1e330748eba6f4770a3489ce0d45e74c6de21;hpb=66ce5dc19c4662fb4e7870c5a55166435fbad083;p=platform%2Fupstream%2Frpm.git diff --git a/rpmbuild.c b/rpmbuild.c index 63f1e33..4fb4289 100644 --- a/rpmbuild.c +++ b/rpmbuild.c @@ -1,12 +1,9 @@ #include "system.h" const char *__progname; -#define _AUTOHELP - -#include -#if HAVE_MCHECK_H -#include -#endif +#include +#include +#include #include #include /* RPMSIGTAG, rpmReadPackageFile .. */ @@ -17,25 +14,200 @@ const char *__progname; #include #include #include "lib/signature.h" -#include "build.h" +#include "cliutils.h" #include "debug.h" +static struct rpmBuildArguments_s rpmBTArgs; + +#define POPT_NOLANG -1012 +#define POPT_RMSOURCE -1013 +#define POPT_RMBUILD -1014 +#define POPT_BUILDROOT -1015 +#define POPT_TARGETPLATFORM -1016 +#define POPT_NOBUILD -1017 +#define POPT_RMSPEC -1019 +#define POPT_NODIRTOKENS -1020 + +#define POPT_REBUILD 0x4220 +#define POPT_RECOMPILE 0x4320 +#define POPT_BA 0x6261 +#define POPT_BB 0x6262 +#define POPT_BC 0x6263 +#define POPT_BI 0x6269 +#define POPT_BL 0x626c +#define POPT_BP 0x6270 +#define POPT_BS 0x6273 +#define POPT_TA 0x7461 +#define POPT_TB 0x7462 +#define POPT_TC 0x7463 +#define POPT_TI 0x7469 +#define POPT_TL 0x746c +#define POPT_TP 0x7470 +#define POPT_TS 0x7473 + +extern int _fsm_debug; + +static rpmSpecFlags spec_flags = 0; /*!< Bit(s) to control spec parsing. */ +static int noDeps = 0; /*!< from --nodeps */ +static int shortCircuit = 0; /*!< from --short-circuit */ +static char buildMode = 0; /*!< Build mode (one of "btBC") */ +static char buildChar = 0; /*!< Build stage (one of "abcilps ") */ +static rpmBuildFlags nobuildAmount = 0; /*!< Build stage disablers */ +static ARGV_t build_targets = NULL; /*!< Target platform(s) */ + +static void buildArgCallback( poptContext con, + enum poptCallbackReason reason, + const struct poptOption * opt, const char * arg, + const void * data) +{ + BTA_t rba = &rpmBTArgs; + + switch (opt->val) { + case POPT_REBUILD: + case POPT_RECOMPILE: + case POPT_BA: + case POPT_BB: + case POPT_BC: + case POPT_BI: + case POPT_BL: + case POPT_BP: + case POPT_BS: + case POPT_TA: + case POPT_TB: + case POPT_TC: + case POPT_TI: + case POPT_TL: + case POPT_TP: + case POPT_TS: + if (opt->val == POPT_BS || opt->val == POPT_TS) + noDeps = 1; + if (buildMode == '\0' && buildChar == '\0') { + buildMode = (((unsigned)opt->val) >> 8) & 0xff; + buildChar = (opt->val ) & 0xff; + } + break; + + case POPT_NODIRTOKENS: rba->pkgFlags |= RPMBUILD_PKG_NODIRTOKENS; break; + case POPT_NOBUILD: rba->buildAmount |= RPMBUILD_NOBUILD; break; + case POPT_NOLANG: spec_flags |= RPMSPEC_NOLANG; break; + case POPT_RMSOURCE: rba->buildAmount |= RPMBUILD_RMSOURCE; break; + case POPT_RMSPEC: rba->buildAmount |= RPMBUILD_RMSPEC; break; + case POPT_RMBUILD: rba->buildAmount |= RPMBUILD_RMBUILD; break; + case POPT_BUILDROOT: + if (rba->buildRootOverride) { + rpmlog(RPMLOG_ERR, _("buildroot already specified, ignoring %s\n"), arg); + break; + } + rba->buildRootOverride = xstrdup(arg); + break; + case POPT_TARGETPLATFORM: + argvSplit(&build_targets, arg, ","); + break; + + case RPMCLI_POPT_FORCE: + spec_flags |= RPMSPEC_FORCE; + break; + + } +} + +static struct poptOption rpmBuildPoptTable[] = { + { NULL, '\0', POPT_ARG_CALLBACK | POPT_CBFLAG_INC_DATA | POPT_CBFLAG_CONTINUE, + buildArgCallback, 0, NULL, NULL }, + + { "bp", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_BP, + N_("build through %prep (unpack sources and apply patches) from "), + N_("") }, + { "bc", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_BC, + N_("build through %build (%prep, then compile) from "), + N_("") }, + { "bi", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_BI, + N_("build through %install (%prep, %build, then install) from "), + N_("") }, + { "bl", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_BL, + N_("verify %files section from "), + N_("") }, + { "ba", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_BA, + N_("build source and binary packages from "), + N_("") }, + { "bb", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_BB, + N_("build binary package only from "), + N_("") }, + { "bs", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_BS, + N_("build source package only from "), + N_("") }, + + { "tp", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_TP, + N_("build through %prep (unpack sources and apply patches) from "), + N_("") }, + { "tc", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_TC, + N_("build through %build (%prep, then compile) from "), + N_("") }, + { "ti", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_TI, + N_("build through %install (%prep, %build, then install) from "), + N_("") }, + { "tl", 0, POPT_ARGFLAG_ONEDASH|POPT_ARGFLAG_DOC_HIDDEN, 0, POPT_TL, + N_("verify %files section from "), + N_("") }, + { "ta", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_TA, + N_("build source and binary packages from "), + N_("") }, + { "tb", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_TB, + N_("build binary package only from "), + N_("") }, + { "ts", 0, POPT_ARGFLAG_ONEDASH, 0, POPT_TS, + N_("build source package only from "), + N_("") }, + + { "rebuild", '\0', 0, 0, POPT_REBUILD, + N_("build binary package from "), + N_("") }, + { "recompile", '\0', 0, 0, POPT_RECOMPILE, + N_("build through %install (%prep, %build, then install) from "), + N_("") }, + + { "buildroot", '\0', POPT_ARG_STRING, 0, POPT_BUILDROOT, + N_("override build root"), "DIRECTORY" }, + { "clean", '\0', 0, 0, POPT_RMBUILD, + N_("remove build tree when done"), NULL}, + { "force", '\0', POPT_ARGFLAG_DOC_HIDDEN, 0, RPMCLI_POPT_FORCE, + N_("ignore ExcludeArch: directives from spec file"), NULL}, + { "fsmdebug", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN), &_fsm_debug, -1, + N_("debug file state machine"), NULL}, + { "nobuild", '\0', 0, 0, POPT_NOBUILD, + N_("do not execute any stages of the build"), NULL }, + { "nodeps", '\0', POPT_ARG_VAL, &noDeps, 1, + N_("do not verify build dependencies"), NULL }, + { "nodirtokens", '\0', 0, 0, POPT_NODIRTOKENS, + N_("generate package header(s) compatible with (legacy) rpm v3 packaging"), + NULL}, + + { "noclean", '\0', POPT_BIT_SET, &nobuildAmount, RPMBUILD_CLEAN, + N_("do not execute %clean stage of the build"), NULL }, + { "nocheck", '\0', POPT_BIT_SET, &nobuildAmount, RPMBUILD_CHECK, + N_("do not execute %check stage of the build"), NULL }, + + { "nolang", '\0', POPT_ARGFLAG_DOC_HIDDEN, 0, POPT_NOLANG, + N_("do not accept i18N msgstr's from specfile"), NULL}, + { "rmsource", '\0', 0, 0, POPT_RMSOURCE, + N_("remove sources when done"), NULL}, + { "rmspec", '\0', 0, 0, POPT_RMSPEC, + N_("remove specfile when done"), NULL}, + { "short-circuit", '\0', POPT_ARG_VAL, &shortCircuit, 1, + N_("skip straight to specified stage (only for c,i)"), NULL }, + { "target", '\0', POPT_ARG_STRING, 0, POPT_TARGETPLATFORM, + N_("override target platform"), "CPU-VENDOR-OS" }, + POPT_TABLEEND +}; + enum modes { MODE_BUILD = (1 << 4), MODE_REBUILD = (1 << 5), MODE_RECOMPILE = (1 << 8), MODE_TARBUILD = (1 << 11), -#define MODES_BT (MODE_BUILD | MODE_TARBUILD | MODE_REBUILD | MODE_RECOMPILE) - - MODE_UNKNOWN = 0 }; -#define MODES_FOR_DBPATH (MODES_BT) -#define MODES_FOR_NODEPS (MODES_BT) -#define MODES_FOR_TEST (MODES_BT) -#define MODES_FOR_ROOT (MODES_BT) - static int quiet; /* the structure describing the options we take and the defaults */ @@ -45,7 +217,7 @@ static struct poptOption optionsTable[] = { N_("Build options with [ | | ]:"), NULL }, - { "quiet", '\0', 0, &quiet, 0, NULL, NULL}, + { "quiet", '\0', POPT_ARGFLAG_DOC_HIDDEN, &quiet, 0, NULL, NULL}, { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0, N_("Common options for all rpm modes and executables:"), @@ -56,244 +228,338 @@ static struct poptOption optionsTable[] = { POPT_TABLEEND }; -#ifdef __MINT__ -/* MiNT cannot dynamically increase the stack. */ -long _stksize = 64 * 1024L; -#endif - -RPM_GNUC_NORETURN -static void argerror(const char * desc) +static int checkSpec(rpmts ts, rpmSpec spec) { - fprintf(stderr, _("%s: %s\n"), __progname, desc); - exit(EXIT_FAILURE); -} - -static void printVersion(FILE * fp) -{ - fprintf(fp, _("RPM version %s\n"), rpmEVR); -} + int rc; + rpmps ps = rpmSpecCheckDeps(ts, spec); -static void printBanner(FILE * fp) -{ - fprintf(fp, _("Copyright (C) 1998-2002 - Red Hat, Inc.\n")); - fprintf(fp, _("This program may be freely redistributed under the terms of the GNU GPL\n")); + if (ps) { + rpmlog(RPMLOG_ERR, _("Failed build dependencies:\n")); + rpmpsPrint(NULL, ps); + } + rc = (ps != NULL); + rpmpsFree(ps); + return rc; } -static void printUsage(poptContext con, FILE * fp, int flags) +static int isSpecFile(const char * specfile) { - printVersion(fp); - printBanner(fp); - fprintf(fp, "\n"); - - if (rpmIsVerbose()) - poptPrintHelp(con, fp, flags); - else - poptPrintUsage(con, fp, flags); + char buf[256]; + const char * s; + FILE * f; + int count; + int checking; + + f = fopen(specfile, "r"); + if (f == NULL) { + rpmlog(RPMLOG_ERR, _("Unable to open spec file %s: %s\n"), + specfile, strerror(errno)); + return 0; + } + count = fread(buf, sizeof(buf[0]), sizeof(buf), f); + (void) fclose(f); + + if (count == 0) + return 0; + + checking = 1; + for (s = buf; count--; s++) { + switch (*s) { + case '\r': + case '\n': + checking = 1; + break; + case ':': + checking = 0; + break; + default: +#if 0 + if (checking && !(isprint(*s) || isspace(*s))) return 0; + break; +#else + if (checking && !(isprint(*s) || isspace(*s)) && *(unsigned char *)s < 32) return 0; + break; +#endif + } + } + return 1; } -int main(int argc, char *argv[]) +/* + * Try to find a spec from a tarball pointed to by arg. + * Return absolute path to spec name on success, otherwise NULL. + */ +static char * getTarSpec(const char *arg) { - rpmts ts = NULL; - enum modes bigMode = MODE_UNKNOWN; - BTA_t ba = &rpmBTArgs; - char * passPhrase = ""; - - int arg; - const char *optArg, *poptCtx; - pid_t pipeChild = 0; - poptContext optCon; - int ec = 0; - int status; - int p[2]; - -#if HAVE_MCHECK_H && HAVE_MTRACE - mtrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */ -#endif - setprogname(argv[0]); /* Retrofit glibc __progname */ + char *specFile = NULL; + char *specDir; + char *specBase; + char *tmpSpecFile; + const char **spec; + char tarbuf[BUFSIZ]; + int gotspec = 0, res; + static const char *tryspec[] = { "Specfile", "\\*.spec", NULL }; + + specDir = rpmGetPath("%{_specdir}", NULL); + tmpSpecFile = rpmGetPath("%{_specdir}/", "rpm-spec.XXXXXX", NULL); + + (void) close(mkstemp(tmpSpecFile)); + + for (spec = tryspec; *spec != NULL; spec++) { + FILE *fp; + char *cmd; + + cmd = rpmExpand("%{uncompress: ", arg, "} | ", + "%{__tar} xOvf - --wildcards ", *spec, + " 2>&1 > ", tmpSpecFile, NULL); + + if (!(fp = popen(cmd, "r"))) { + rpmlog(RPMLOG_ERR, _("Failed to open tar pipe: %m\n")); + } else { + char *fok; + for (;;) { + fok = fgets(tarbuf, sizeof(tarbuf) - 1, fp); + /* tar sometimes prints "tar: Record size = 16" messages */ + if (!fok || strncmp(fok, "tar: ", 5) != 0) + break; + } + pclose(fp); + gotspec = (fok != NULL) && isSpecFile(tmpSpecFile); + } - /* XXX glibc churn sanity */ - if (__progname == NULL) { - if ((__progname = strrchr(argv[0], '/')) != NULL) __progname++; - else __progname = argv[0]; + if (!gotspec) + unlink(tmpSpecFile); + free(cmd); } - /* Set the major mode based on argv[0] */ - if (rstreq(__progname, "rpmbuild")) bigMode = MODE_BUILD; + if (!gotspec) { + rpmlog(RPMLOG_ERR, _("Failed to read spec file from %s\n"), arg); + goto exit; + } -#if defined(ENABLE_NLS) - /* set up the correct locale */ - (void) setlocale(LC_ALL, "" ); + specBase = basename(tarbuf); + /* remove trailing \n */ + specBase[strlen(specBase)-1] = '\0'; - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); -#endif + rasprintf(&specFile, "%s/%s", specDir, specBase); + res = rename(tmpSpecFile, specFile); - rpmSetVerbosity(RPMLOG_NOTICE); /* XXX silly use by showrc */ + if (res) { + rpmlog(RPMLOG_ERR, _("Failed to rename %s to %s: %m\n"), + tmpSpecFile, specFile); + free(specFile); + specFile = NULL; + } else { + /* mkstemp() can give unnecessarily strict permissions, fixup */ + mode_t mask; + umask(mask = umask(0)); + (void) chmod(specFile, 0666 & ~mask); + } - /* Only build has it's own set of aliases, everything else uses rpm */ - poptCtx = "rpmbuild"; +exit: + (void) unlink(tmpSpecFile); + free(tmpSpecFile); + free(specDir); + return specFile; +} - /* Make a first pass through the arguments, looking for --rcfile */ - /* We need to handle that before dealing with the rest of the arguments. */ - /* XXX popt argv definition should be fixed instead of casting... */ - optCon = poptGetContext(poptCtx, argc, (const char **)argv, optionsTable, 0); - { - char *poptfile = rpmGenPath(rpmConfigDir(), LIBRPMALIAS_FILENAME, NULL); - (void) poptReadConfigFile(optCon, poptfile); - free(poptfile); +static int buildForTarget(rpmts ts, const char * arg, BTA_t ba) +{ + int buildAmount = ba->buildAmount; + char * buildRootURL = NULL; + char * specFile = NULL; + rpmSpec spec = NULL; + int rc = 1; /* assume failure */ + int justRm = ((buildAmount & ~(RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)) == 0); + rpmSpecFlags specFlags = spec_flags; + + if (ba->buildRootOverride) + buildRootURL = rpmGenPath(NULL, ba->buildRootOverride, NULL); + + /* Create build tree if necessary */ + const char * buildtree = "%{_topdir}:%{_specdir}:%{_sourcedir}:%{_builddir}:%{_rpmdir}:%{_srcrpmdir}:%{_buildrootdir}"; + const char * rootdir = rpmtsRootDir(ts); + if (rpmMkdirs(!rstreq(rootdir, "/") ? rootdir : NULL , buildtree)) { + goto exit; } - (void) poptReadDefaultConfig(optCon, 1); - poptSetExecPath(optCon, rpmConfigDir(), 1); - while ((arg = poptGetNextOpt(optCon)) > 0) { - optArg = poptGetOptArg(optCon); + if (buildMode == 't') { + char *srcdir = NULL, *dir; - switch (arg) { - default: - fprintf(stderr, _("Internal error in argument processing (%d) :-(\n"), arg); - exit(EXIT_FAILURE); + specFile = getTarSpec(arg); + if (!specFile) + goto exit; + + /* Make the directory of the tarball %_sourcedir for this run */ + /* dirname() may modify contents so extra hoops needed. */ + if (*arg != '/') { + dir = rpmGetCwd(); + rstrscat(&dir, "/", arg, NULL); + } else { + dir = xstrdup(arg); } + srcdir = dirname(dir); + addMacro(NULL, "_sourcedir", NULL, srcdir, RMIL_TARBALL); + free(dir); + } else { + specFile = xstrdup(arg); } - if (arg < -1) { - fprintf(stderr, "%s: %s\n", - poptBadOption(optCon, POPT_BADOPTION_NOALIAS), - poptStrerror(arg)); - exit(EXIT_FAILURE); + if (*specFile != '/') { + char *cwd = rpmGetCwd(); + char *s = NULL; + rasprintf(&s, "%s/%s", cwd, specFile); + free(cwd); + free(specFile); + specFile = s; } - rpmcliConfigured(); + struct stat st; + if (stat(specFile, &st) < 0) { + rpmlog(RPMLOG_ERR, _("failed to stat %s: %m\n"), specFile); + goto exit; + } + if (! S_ISREG(st.st_mode)) { + rpmlog(RPMLOG_ERR, _("File %s is not a regular file.\n"), specFile); + goto exit; + } - switch (ba->buildMode) { - case 'b': bigMode = MODE_BUILD; break; - case 't': bigMode = MODE_TARBUILD; break; - case 'B': bigMode = MODE_REBUILD; break; - case 'C': bigMode = MODE_RECOMPILE; break; + /* Try to verify that the file is actually a specfile */ + if (!isSpecFile(specFile)) { + rpmlog(RPMLOG_ERR, + _("File %s does not appear to be a specfile.\n"), specFile); + goto exit; + } + + /* Don't parse spec if only its removal is requested */ + if (ba->buildAmount == RPMBUILD_RMSPEC) { + rc = unlink(specFile); + goto exit; } - if ((ba->buildAmount & RPMBUILD_RMSOURCE) && bigMode == MODE_UNKNOWN) - bigMode = MODE_BUILD; + /* Parse the spec file */ +#define _anyarch(_f) \ +(((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0) + if (_anyarch(buildAmount)) + specFlags |= RPMSPEC_ANYARCH; +#undef _anyarch + + spec = rpmSpecParse(specFile, specFlags, buildRootURL); + if (spec == NULL) { + goto exit; + } - if ((ba->buildAmount & RPMBUILD_RMSPEC) && bigMode == MODE_UNKNOWN) - bigMode = MODE_BUILD; + /* Check build prerequisites if necessary, unless disabled */ + if (!justRm && !noDeps && checkSpec(ts, spec)) { + goto exit; + } - if (ba->buildRootOverride && bigMode != MODE_BUILD && - bigMode != MODE_REBUILD && bigMode != MODE_TARBUILD) { - argerror("--buildroot may only be used during package builds"); + if (rpmSpecBuild(spec, ba)) { + goto exit; } - if (rpmcliRootDir && rpmcliRootDir[1] && (bigMode & ~MODES_FOR_ROOT)) - argerror(_("--root (-r) may only be specified during " - "installation, erasure, querying, and " - "database rebuilds")); + if (buildMode == 't') + (void) unlink(specFile); + rc = 0; - if (rpmcliRootDir) { - switch (urlIsURL(rpmcliRootDir)) { - default: - if (bigMode & MODES_FOR_ROOT) - break; - case URL_IS_UNKNOWN: - if (rpmcliRootDir[0] != '/') - argerror(_("arguments to --root (-r) must begin with a /")); - break; - } +exit: + free(specFile); + rpmSpecFree(spec); + free(buildRootURL); + return rc; +} + +static int build(rpmts ts, const char * arg, BTA_t ba, const char * rcfile) +{ + int rc = 0; + char * targets = argvJoin(build_targets, ","); +#define buildCleanMask (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC) + int cleanFlags = ba->buildAmount & buildCleanMask; + rpmVSFlags vsflags, ovsflags; + + vsflags = rpmExpandNumeric("%{_vsflags_build}"); + if (rpmcliQueryFlags & VERIFY_DIGEST) + vsflags |= _RPMVSF_NODIGESTS; + if (rpmcliQueryFlags & VERIFY_SIGNATURE) + vsflags |= _RPMVSF_NOSIGNATURES; + if (rpmcliQueryFlags & VERIFY_HDRCHK) + vsflags |= RPMVSF_NOHDRCHK; + ovsflags = rpmtsSetVSFlags(ts, vsflags); + + if (build_targets == NULL) { + rc = buildForTarget(ts, arg, ba); + goto exit; } - if (quiet) - rpmSetVerbosity(RPMLOG_WARNING); - - if (ba->sign) { - if (bigMode == MODE_REBUILD || bigMode == MODE_BUILD || - bigMode == MODE_TARBUILD) - { - const char ** av; - struct stat sb; - int errors = 0; - - if ((av = poptGetArgs(optCon)) == NULL) { - fprintf(stderr, _("no files to sign\n")); - errors++; - } else - while (*av) { - if (stat(*av, &sb)) { - fprintf(stderr, _("cannot access file %s\n"), *av); - errors++; - } - av++; - } + /* parse up the build operators */ - if (errors) { - ec = errors; - goto exit; - } + printf(_("Building target platforms: %s\n"), targets); - if (poptPeekArg(optCon)) { - int sigTag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY); - switch (sigTag) { - case 0: - break; - case RPMSIGTAG_PGP: - case RPMSIGTAG_GPG: - case RPMSIGTAG_DSA: - case RPMSIGTAG_RSA: - passPhrase = rpmGetPassPhrase(_("Enter pass phrase: "), sigTag); - if (passPhrase == NULL) { - fprintf(stderr, _("Pass phrase check failed\n")); - ec = EXIT_FAILURE; - goto exit; - } - fprintf(stderr, _("Pass phrase is good.\n")); - passPhrase = xstrdup(passPhrase); - break; - default: - fprintf(stderr, - _("Invalid %%_signature spec in macro file.\n")); - ec = EXIT_FAILURE; - goto exit; - break; - } - } - } else { - argerror(_("--sign may only be used during package building")); - } - } else { - /* Make rpmLookupSignatureType() return 0 ("none") from now on */ - (void) rpmLookupSignatureType(RPMLOOKUPSIG_DISABLE); + ba->buildAmount &= ~buildCleanMask; + for (ARGV_const_t target = build_targets; target && *target; target++) { + /* Perform clean-up after last target build. */ + if (*(target + 1) == NULL) + ba->buildAmount |= cleanFlags; + + printf(_("Building for target %s\n"), *target); + + /* Read in configuration for target. */ + rpmFreeMacros(NULL); + rpmFreeRpmrc(); + (void) rpmReadConfigFiles(rcfile, *target); + rc = buildForTarget(ts, arg, ba); + if (rc) + break; } - if (rpmcliPipeOutput) { - if (pipe(p) < 0) { - fprintf(stderr, _("creating a pipe for --pipe failed: %m\n")); - goto exit; - } +exit: + rpmtsSetVSFlags(ts, ovsflags); + /* Restore original configuration. */ + rpmFreeMacros(NULL); + rpmFreeRpmrc(); + (void) rpmReadConfigFiles(rcfile, NULL); + free(targets); - if (!(pipeChild = fork())) { - (void) signal(SIGPIPE, SIG_DFL); - (void) close(p[1]); - (void) dup2(p[0], STDIN_FILENO); - (void) close(p[0]); - (void) execl("/bin/sh", "/bin/sh", "-c", rpmcliPipeOutput, NULL); - fprintf(stderr, _("exec failed\n")); - } + return rc; +} + +int main(int argc, char *argv[]) +{ + rpmts ts = NULL; + enum modes bigMode = MODE_BUILD; + BTA_t ba = &rpmBTArgs; - (void) close(p[0]); - (void) dup2(p[1], STDOUT_FILENO); - (void) close(p[1]); + const char *pkg = NULL; + int ec = 0; + poptContext optCon = rpmcliInit(argc, argv, optionsTable); + + if (argc <= 1 || poptPeekArg(optCon) == NULL) { + printUsage(optCon, stderr, 0); + exit(EXIT_FAILURE); + } + + switch (buildMode) { + case 'b': bigMode = MODE_BUILD; break; + case 't': bigMode = MODE_TARBUILD; break; + case 'B': bigMode = MODE_REBUILD; break; + case 'C': bigMode = MODE_RECOMPILE; break; } + + if (rpmcliRootDir && rpmcliRootDir[0] != '/') { + argerror(_("arguments to --root (-r) must begin with a /")); + } + + /* rpmbuild is rather chatty by default */ + rpmSetVerbosity(quiet ? RPMLOG_WARNING : RPMLOG_INFO); + + if (rpmcliPipeOutput && initPipe()) + exit(EXIT_FAILURE); ts = rpmtsCreate(); (void) rpmtsSetRootDir(ts, rpmcliRootDir); switch (bigMode) { case MODE_REBUILD: case MODE_RECOMPILE: - { const char * pkg; - - while (!rpmIsVerbose()) - rpmIncreaseVerbosity(); - - if (!poptPeekArg(optCon)) - argerror(_("no packages files given for rebuild")); - ba->buildAmount = RPMBUILD_PREP | RPMBUILD_BUILD | RPMBUILD_INSTALL | RPMBUILD_CHECK; if (bigMode == MODE_REBUILD) { @@ -303,6 +569,7 @@ int main(int argc, char *argv[]) ba->buildAmount |= RPMBUILD_CLEAN; ba->buildAmount |= RPMBUILD_RMBUILD; } + ba->buildAmount &= ~(nobuildAmount); while ((pkg = poptGetArg(optCon))) { char * specFile = NULL; @@ -311,7 +578,6 @@ int main(int argc, char *argv[]) ec = rpmInstallSource(ts, pkg, &specFile, &ba->cookie); if (ec == 0) { ba->rootdir = rpmcliRootDir; - ba->passPhrase = passPhrase; ec = build(ts, specFile, ba, rpmcliRcfile); } ba->cookie = _free(ba->cookie); @@ -320,31 +586,25 @@ int main(int argc, char *argv[]) if (ec) break; } - - } break; - + break; case MODE_BUILD: case MODE_TARBUILD: - { const char * pkg; - if (!quiet) while (!rpmIsVerbose()) - rpmIncreaseVerbosity(); - - switch (ba->buildChar) { + switch (buildChar) { case 'a': ba->buildAmount |= RPMBUILD_PACKAGESOURCE; case 'b': ba->buildAmount |= RPMBUILD_PACKAGEBINARY; ba->buildAmount |= RPMBUILD_CLEAN; - if ((ba->buildChar == 'b') && ba->shortCircuit) + if ((buildChar == 'b') && shortCircuit) break; case 'i': ba->buildAmount |= RPMBUILD_INSTALL; ba->buildAmount |= RPMBUILD_CHECK; - if ((ba->buildChar == 'i') && ba->shortCircuit) + if ((buildChar == 'i') && shortCircuit) break; case 'c': ba->buildAmount |= RPMBUILD_BUILD; - if ((ba->buildChar == 'c') && ba->shortCircuit) + if ((buildChar == 'c') && shortCircuit) break; case 'p': ba->buildAmount |= RPMBUILD_PREP; @@ -357,17 +617,10 @@ int main(int argc, char *argv[]) ba->buildAmount |= RPMBUILD_PACKAGESOURCE; break; } - - if (!poptPeekArg(optCon)) { - if (bigMode == MODE_BUILD) - argerror(_("no spec files given for build")); - else - argerror(_("no tar files given for build")); - } + ba->buildAmount &= ~(nobuildAmount); while ((pkg = poptGetArg(optCon))) { ba->rootdir = rpmcliRootDir; - ba->passPhrase = passPhrase; ba->cookie = NULL; ec = build(ts, pkg, ba, rpmcliRcfile); if (ec) @@ -375,43 +628,16 @@ int main(int argc, char *argv[]) rpmFreeMacros(NULL); (void) rpmReadConfigFiles(rpmcliRcfile, NULL); } - } break; - - case MODE_UNKNOWN: - if (poptPeekArg(optCon) != NULL || argc <= 1 || rpmIsVerbose()) { - printUsage(optCon, stderr, 0); - ec = argc; - } break; } -exit: - - ts = rpmtsFree(ts); - - optCon = poptFreeContext(optCon); - rpmFreeMacros(NULL); - rpmFreeMacros(rpmCLIMacroContext); - rpmFreeRpmrc(); - - if (pipeChild) { - (void) fclose(stdout); - (void) waitpid(pipeChild, &status, 0); - } - - /* keeps memory leak checkers quiet */ - rpmlogClose(); - - freeNames(); - ba->buildRootOverride = _free(ba->buildRootOverride); - ba->targets = _free(ba->targets); - -#if HAVE_MCHECK_H && HAVE_MTRACE - muntrace(); /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */ -#endif + rpmtsFree(ts); + if (finishPipe()) + ec = EXIT_FAILURE; + free(ba->buildRootOverride); + argvFree(build_targets); - /* XXX Avoid exit status overflow. Status 255 is special to xargs(1) */ - if (ec > 254) ec = 254; + rpmcliFini(optCon); - return ec; + return RETVAL(ec); }