build/parseScript.c

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

Generated on Mon Aug 30 09:30:39 2010 for rpm by  doxygen 1.4.7