rpm 5.2.1

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

- File List
- Globals

build/parseScript.c
Go to the documentation of this file.

    00001
    00006 #include "system.h"
    00007
    00008 #include <rpmio.h>
    00009 #include <rpmiotypes.h>
    00010 #include <rpmlog.h>
    00011 #define _RPMEVR_INTERNAL
    00012 #include "rpmbuild.h"
    00013 #include "debug.h"
    00014
    00015 #include <rpmlua.h>
    00016
    00017 /*@access poptContext @*/       /* compared with NULL */
    00018
    00021 static rpmuint32_t addTriggerIndex(Package pkg, const char *file,
    00022         const char *script, const char *prog)
    00023         /*@modifies pkg->triggerFiles @*/
    00024 {
    00025     struct TriggerFileEntry *tfe;
    00026     struct TriggerFileEntry *list = pkg->triggerFiles;
    00027     struct TriggerFileEntry *last = NULL;
    00028     rpmuint32_t index = 0;
    00029
    00030     while (list) {
    00031         last = list;
    00032         list = list->next;
    00033     }
    00034
    00035     if (last)
    00036         index = last->index + 1;
    00037
    00038     tfe = xcalloc(1, sizeof(*tfe));
    00039
    00040     tfe->fileName = (file) ? xstrdup(file) : NULL;
    00041     tfe->script = (script && *script != '\0') ? xstrdup(script) : NULL;
    00042     tfe->prog = xstrdup(prog);
    00043     tfe->index = index;
    00044     tfe->next = NULL;
    00045
    00046     if (last)
    00047         last->next = tfe;
    00048     else
    00049         pkg->triggerFiles = tfe;
    00050
    00051     return index;
    00052 }
    00053
    00054 /* these have to be global because of stupid compilers */
    00055 /*@unchecked@*/
    00056     /*@observer@*/ /*@null@*/ static const char *name = NULL;
    00057 /*@unchecked@*/
    00058     /*@observer@*/ /*@null@*/ static const char *prog = NULL;
    00059 /*@unchecked@*/
    00060     /*@observer@*/ /*@null@*/ static const char *file = NULL;
    00061 /*@unchecked@*/
    00062     static struct poptOption optionsTable[] = {
    00063         { NULL, 'p', POPT_ARG_STRING, &prog, 'p',       NULL, NULL},
    00064         { NULL, 'n', POPT_ARG_STRING, &name, 'n',       NULL, NULL},
    00065         { NULL, 'f', POPT_ARG_STRING, &file, 'f',       NULL, NULL},
    00066         { 0, 0, 0, 0, 0,        NULL, NULL}
    00067     };
    00068
    00069 /* %trigger is a strange combination of %pre and Requires: behavior */
    00070 /* We can handle it by parsing the args before "--" in parseScript. */
    00071 /* We then pass the remaining arguments to parseRCPOT, along with   */
    00072 /* an index we just determined.                                     */
    00073
    00074 int parseScript(Spec spec, int parsePart)
    00075 {
    00076     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00077     int xx;
    00078
    00079     /* There are a few options to scripts: */
    00080     /*  <pkg>                              */
    00081     /*  -n <pkg>                           */
    00082     /*  -p <sh>                            */
    00083     /*  -p "<sh> <args>..."                */
    00084     /*  -f <file>                          */
    00085
    00086     char *p;
    00087     const char **progArgv = NULL;
    00088     int progArgc;
    00089     char *partname = NULL;
    00090     rpmTag reqtag = 0;
    00091     rpmTag tag = 0;
    00092     rpmsenseFlags tagflags = 0;
    00093     rpmTag progtag = 0;
    00094     int flag = PART_SUBNAME;
    00095     Package pkg;
    00096     rpmiob iob = NULL;
    00097     rpmParseState nextPart;
    00098     char reqargs[BUFSIZ];
    00099
    00100     int argc;
    00101     int arg;
    00102     const char **argv = NULL;
    00103     poptContext optCon = NULL;
    00104     rpmRC rc;
    00105
    00106     reqargs[0] = '\0';
    00107     /*@-mods@*/
    00108     name = NULL;
    00109     prog = "/bin/sh";
    00110     file = NULL;
    00111     /*@=mods@*/
    00112
    00113     switch (parsePart) {
    00114       case PART_PRE:
    00115         tag = RPMTAG_PREIN;
    00116         tagflags = RPMSENSE_SCRIPT_PRE;
    00117         progtag = RPMTAG_PREINPROG;
    00118         partname = "%pre";
    00119         break;
    00120       case PART_POST:
    00121         tag = RPMTAG_POSTIN;
    00122         tagflags = RPMSENSE_SCRIPT_POST;
    00123         progtag = RPMTAG_POSTINPROG;
    00124         partname = "%post";
    00125         break;
    00126       case PART_PREUN:
    00127         tag = RPMTAG_PREUN;
    00128         tagflags = RPMSENSE_SCRIPT_PREUN;
    00129         progtag = RPMTAG_PREUNPROG;
    00130         partname = "%preun";
    00131         break;
    00132       case PART_POSTUN:
    00133         tag = RPMTAG_POSTUN;
    00134         tagflags = RPMSENSE_SCRIPT_POSTUN;
    00135         progtag = RPMTAG_POSTUNPROG;
    00136         partname = "%postun";
    00137         break;
    00138       case PART_PRETRANS:
    00139         tag = RPMTAG_PRETRANS;
    00140         tagflags = 0;
    00141         progtag = RPMTAG_PRETRANSPROG;
    00142         partname = "%pretrans";
    00143         break;
    00144       case PART_POSTTRANS:
    00145         tag = RPMTAG_POSTTRANS;
    00146         tagflags = 0;
    00147         progtag = RPMTAG_POSTTRANSPROG;
    00148         partname = "%posttrans";
    00149         break;
    00150       case PART_VERIFYSCRIPT:
    00151         tag = RPMTAG_VERIFYSCRIPT;
    00152         tagflags = RPMSENSE_SCRIPT_VERIFY;
    00153         progtag = RPMTAG_VERIFYSCRIPTPROG;
    00154         partname = "%verifyscript";
    00155         break;
    00156       case PART_TRIGGERPREIN:
    00157         tag = RPMTAG_TRIGGERSCRIPTS;
    00158         tagflags = 0;
    00159         reqtag = RPMTAG_TRIGGERPREIN;
    00160         progtag = RPMTAG_TRIGGERSCRIPTPROG;
    00161         partname = "%triggerprein";
    00162         break;
    00163       case PART_TRIGGERIN:
    00164         tag = RPMTAG_TRIGGERSCRIPTS;
    00165         tagflags = 0;
    00166         reqtag = RPMTAG_TRIGGERIN;
    00167         progtag = RPMTAG_TRIGGERSCRIPTPROG;
    00168         partname = "%triggerin";
    00169         break;
    00170       case PART_TRIGGERUN:
    00171         tag = RPMTAG_TRIGGERSCRIPTS;
    00172         tagflags = 0;
    00173         reqtag = RPMTAG_TRIGGERUN;
    00174         progtag = RPMTAG_TRIGGERSCRIPTPROG;
    00175         partname = "%triggerun";
    00176         break;
    00177       case PART_TRIGGERPOSTUN:
    00178         tag = RPMTAG_TRIGGERSCRIPTS;
    00179         tagflags = 0;
    00180         reqtag = RPMTAG_TRIGGERPOSTUN;
    00181         progtag = RPMTAG_TRIGGERSCRIPTPROG;
    00182         partname = "%triggerpostun";
    00183         break;
    00184       /* support "%sanitycheck" script/section */
    00185       case PART_SANITYCHECK:
    00186         tag = RPMTAG_SANITYCHECK;
    00187         tagflags = RPMSENSE_SCRIPT_SANITYCHECK;
    00188         progtag = RPMTAG_SANITYCHECKPROG;
    00189         partname = "%sanitycheck";
    00190         break;
    00191     }
    00192
    00193     if (tag == RPMTAG_TRIGGERSCRIPTS) {
    00194         /* break line into two */
    00195         p = strstr(spec->line, "--");
    00196         if (!p) {
    00197             rpmlog(RPMLOG_ERR, _("line %d: triggers must have --: %s\n"),
    00198                      spec->lineNum, spec->line);
    00199             return RPMRC_FAIL;
    00200         }
    00201
    00202         *p = '\0';
    00203         strcpy(reqargs, p + 2);
    00204     }
    00205
    00206     if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
    00207         rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
    00208                  spec->lineNum, partname, poptStrerror(rc));
    00209         return RPMRC_FAIL;
    00210     }
    00211
    00212     optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
    00213     while ((arg = poptGetNextOpt(optCon)) > 0) {
    00214         switch (arg) {
    00215         case 'p':
    00216             if (prog[0] == '<') {
    00217                 if (prog[strlen(prog)-1] != '>') {
    00218                     rpmlog(RPMLOG_ERR,
    00219                              _("line %d: internal script must end "
    00220                              "with \'>\': %s\n"), spec->lineNum, prog);
    00221                     rc = RPMRC_FAIL;
    00222                     goto exit;
    00223                 }
    00224             } else if (prog[0] == '%') {
    00225                 /* XXX check well-formed macro? */
    00226             } else if (prog[0] != '/') {
    00227                 rpmlog(RPMLOG_ERR,
    00228                          _("line %d: script program must begin "
    00229                          "with \'/\': %s\n"), spec->lineNum, prog);
    00230                 rc = RPMRC_FAIL;
    00231                 goto exit;
    00232             }
    00233             /*@switchbreak@*/ break;
    00234         case 'n':
    00235             flag = PART_NAME;
    00236             /*@switchbreak@*/ break;
    00237         }
    00238     }
    00239
    00240     if (arg < -1) {
    00241         rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"),
    00242                  spec->lineNum,
    00243                  poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
    00244                  spec->line);
    00245         rc = RPMRC_FAIL;
    00246         goto exit;
    00247     }
    00248
    00249     if (poptPeekArg(optCon)) {
    00250         /*@-mods@*/
    00251         if (name == NULL)
    00252             name = poptGetArg(optCon);
    00253         /*@=mods@*/
    00254         if (poptPeekArg(optCon)) {
    00255             rpmlog(RPMLOG_ERR, _("line %d: Too many names: %s\n"),
    00256                      spec->lineNum,
    00257                      spec->line);
    00258             rc = RPMRC_FAIL;
    00259             goto exit;
    00260         }
    00261     }
    00262
    00263     if (lookupPackage(spec, name, flag, &pkg) != RPMRC_OK) {
    00264         rpmlog(RPMLOG_ERR, _("line %d: Package does not exist: %s\n"),
    00265                  spec->lineNum, spec->line);
    00266         rc = RPMRC_FAIL;
    00267         goto exit;
    00268     }
    00269
    00270     if (tag != RPMTAG_TRIGGERSCRIPTS) {
    00271         if (headerIsEntry(pkg->header, progtag)) {
    00272             rpmlog(RPMLOG_ERR, _("line %d: Second %s\n"),
    00273                      spec->lineNum, partname);
    00274             rc = RPMRC_FAIL;
    00275             goto exit;
    00276         }
    00277     }
    00278
    00279     if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) {
    00280         rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
    00281                  spec->lineNum, partname, poptStrerror(rc));
    00282         rc = RPMRC_FAIL;
    00283         goto exit;
    00284     }
    00285
    00286     iob = rpmiobNew(0);
    00287     if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
    00288         nextPart = PART_NONE;
    00289     } else {
    00290         if (rc)
    00291             goto exit;
    00292         while ((nextPart = isPart(spec)) == PART_NONE) {
    00293             iob = rpmiobAppend(iob, spec->line, 0);
    00294             if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
    00295                 nextPart = PART_NONE;
    00296                 break;
    00297             }
    00298             if (rc)
    00299                 goto exit;
    00300         }
    00301     }
    00302     iob = rpmiobRTrim(iob);
    00303     p = rpmiobStr(iob);
    00304
    00305 #ifdef WITH_LUA
    00306     if (!strcmp(progArgv[0], "<lua>")) {
    00307         rpmlua lua = NULL; /* Global state. */
    00308         if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) {
    00309             rc = RPMRC_FAIL;
    00310             goto exit;
    00311         }
    00312         (void) rpmlibNeedsFeature(pkg->header,
    00313                                   "BuiltinLuaScripts", "4.2.2-1");
    00314     } else
    00315 #endif
    00316 #ifdef WITH_FICL
    00317     if (!strcmp(progArgv[0], "<ficl>")) {
    00318         (void) rpmlibNeedsFeature(pkg->header,
    00319                                   "BuiltinFiclScripts", "5.2-1");
    00320     } else
    00321 #endif
    00322 #ifdef WITH_JS
    00323     if (!strcmp(progArgv[0], "<js>")) {
    00324         (void) rpmlibNeedsFeature(pkg->header,
    00325                                   "BuiltinJavaScript", "5.2-1");
    00326     } else
    00327 #endif
    00328 #ifdef WITH_PERLEMBED
    00329     if (!strcmp(progArgv[0], "<perl>")) {
    00330         (void) rpmlibNeedsFeature(pkg->header,
    00331                                   "BuiltinPerlScripts", "5.2-1");
    00332     } else
    00333 #endif
    00334 #ifdef WITH_PYTHONEMBED
    00335     if (!strcmp(progArgv[0], "<python>")) {
    00336         (void) rpmlibNeedsFeature(pkg->header,
    00337                                   "BuiltinPythonScripts", "5.2-1");
    00338     } else
    00339 #endif
    00340 #ifdef WITH_RUBYEMBED
    00341     if (!strcmp(progArgv[0], "<ruby>")) {
    00342         (void) rpmlibNeedsFeature(pkg->header,
    00343                                   "BuiltinRubyScripts", "5.2-1");
    00344     } else
    00345 #endif
    00346 #ifdef WITH_TCL
    00347     if (!strcmp(progArgv[0], "<tcl>")) {
    00348         (void) rpmlibNeedsFeature(pkg->header,
    00349                                   "BuiltinTclScripts", "5.2-1");
    00350     } else
    00351 #endif
    00352     if (progArgv[0][0] == '<') {
    00353         rpmlog(RPMLOG_ERR,
    00354                  _("line %d: unsupported internal script: %s\n"),
    00355                  spec->lineNum, progArgv[0]);
    00356         rc = RPMRC_FAIL;
    00357         goto exit;
    00358     } else
    00359     if (!(rpmExpandNumeric("%{?_disable_shell_interpreter_deps}")
    00360      && !strcmp(progArgv[0], "/bin/sh")))
    00361     {
    00362
    00363         (void) addReqProv(spec, pkg->header, RPMTAG_REQUIRENAME,
    00364                 progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0);
    00365     }
    00366
    00367     /* Trigger script insertion is always delayed in order to */
    00368     /* get the index right.                                   */
    00369     if (tag == RPMTAG_TRIGGERSCRIPTS) {
    00370         /* Add file/index/prog triple to the trigger file list */
    00371         rpmuint32_t index = addTriggerIndex(pkg, file, p, progArgv[0]);
    00372
    00373         /* Generate the trigger tags */
    00374         if ((rc = parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags)))
    00375             goto exit;
    00376     } else {
    00377         if (progArgc == 1) {
    00378             he->tag = progtag;
    00379             he->t = RPM_STRING_TYPE;
    00380             he->p.str = *progArgv;
    00381             he->c = progArgc;
    00382             xx = headerPut(pkg->header, he, 0);
    00383         } else {
    00384             (void) rpmlibNeedsFeature(pkg->header,
    00385                         "ScriptletInterpreterArgs", "4.0.3-1");
    00386             he->tag = progtag;
    00387             he->t = RPM_STRING_ARRAY_TYPE;
    00388             he->p.argv = progArgv;
    00389             he->c = progArgc;
    00390             xx = headerPut(pkg->header, he, 0);
    00391         }
    00392
    00393         if (*p != '\0') {
    00394             he->tag = tag;
    00395             he->t = RPM_STRING_TYPE;
    00396             he->p.str = p;
    00397             he->c = 1;
    00398             xx = headerPut(pkg->header, he, 0);
    00399         }
    00400
    00401         if (file) {
    00402             switch (parsePart) {
    00403               case PART_PRE:
    00404                 pkg->preInFile = xstrdup(file);
    00405                 break;
    00406               case PART_POST:
    00407                 pkg->postInFile = xstrdup(file);
    00408                 break;
    00409               case PART_PREUN:
    00410                 pkg->preUnFile = xstrdup(file);
    00411                 break;
    00412               case PART_POSTUN:
    00413                 pkg->postUnFile = xstrdup(file);
    00414                 break;
    00415               case PART_PRETRANS:
    00416                 pkg->preTransFile = xstrdup(file);
    00417                 break;
    00418               case PART_POSTTRANS:
    00419                 pkg->postTransFile = xstrdup(file);
    00420                 break;
    00421               case PART_VERIFYSCRIPT:
    00422                 pkg->verifyFile = xstrdup(file);
    00423                 break;
    00424               case PART_SANITYCHECK:
    00425                 pkg->sanityCheckFile = xstrdup(file);
    00426                 break;
    00427             }
    00428         }
    00429     }
    00430     rc = (rpmRC) nextPart;
    00431
    00432 exit:
    00433     iob = rpmiobFree(iob);
    00434     progArgv = _free(progArgv);
    00435     argv = _free(argv);
    00436     optCon = poptFreeContext(optCon);
    00437
    00438     return rc;
    00439 }