build/parseScript.c

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

Generated on Fri May 25 21:18:11 2007 for rpm by  doxygen 1.5.2