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

Generated on Mon Nov 29 2010 05:18:42 for rpm by  doxygen 1.7.2