rpm 5.3.12
|
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 const char * s = prog; 00218 while (s && s[1] && s[1] != '>') 00219 s++; 00220 if (s[1] != '>') { 00221 rpmlog(RPMLOG_ERR, 00222 _("line %d: embedded interpreter token must end " 00223 "with \'>\': %s\n"), spec->lineNum, prog); 00224 rc = RPMRC_FAIL; 00225 goto exit; 00226 } 00227 } else if (prog[0] == '%') { 00228 /* XXX check well-formed macro? */ 00229 } else if (prog[0] != '/') { 00230 rpmlog(RPMLOG_ERR, 00231 _("line %d: script program must begin " 00232 "with \'/\': %s\n"), spec->lineNum, prog); 00233 rc = RPMRC_FAIL; 00234 goto exit; 00235 } 00236 /*@switchbreak@*/ break; 00237 case 'n': 00238 flag = PART_NAME; 00239 /*@switchbreak@*/ break; 00240 } 00241 } 00242 00243 if (arg < -1) { 00244 rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"), 00245 spec->lineNum, 00246 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 00247 spec->line); 00248 rc = RPMRC_FAIL; 00249 goto exit; 00250 } 00251 00252 if (poptPeekArg(optCon)) { 00253 /*@-mods@*/ 00254 if (name == NULL) 00255 name = poptGetArg(optCon); 00256 /*@=mods@*/ 00257 if (poptPeekArg(optCon)) { 00258 rpmlog(RPMLOG_ERR, _("line %d: Too many names: %s\n"), 00259 spec->lineNum, 00260 spec->line); 00261 rc = RPMRC_FAIL; 00262 goto exit; 00263 } 00264 } 00265 00266 if (lookupPackage(spec, name, flag, &pkg) != RPMRC_OK) { 00267 rpmlog(RPMLOG_ERR, _("line %d: Package does not exist: %s\n"), 00268 spec->lineNum, spec->line); 00269 rc = RPMRC_FAIL; 00270 goto exit; 00271 } 00272 00273 if (tag != RPMTAG_TRIGGERSCRIPTS) { 00274 if (headerIsEntry(pkg->header, progtag)) { 00275 rpmlog(RPMLOG_ERR, _("line %d: Second %s\n"), 00276 spec->lineNum, partname); 00277 rc = RPMRC_FAIL; 00278 goto exit; 00279 } 00280 } 00281 00282 if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) { 00283 rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"), 00284 spec->lineNum, partname, poptStrerror(rc)); 00285 rc = RPMRC_FAIL; 00286 goto exit; 00287 } 00288 00289 iob = rpmiobNew(0); 00290 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { 00291 nextPart = PART_NONE; 00292 } else { 00293 if (rc) 00294 goto exit; 00295 while ((nextPart = isPart(spec)) == PART_NONE) { 00296 iob = rpmiobAppend(iob, spec->line, 0); 00297 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { 00298 nextPart = PART_NONE; 00299 break; 00300 } 00301 if (rc) 00302 goto exit; 00303 } 00304 } 00305 iob = rpmiobRTrim(iob); 00306 p = rpmiobStr(iob); 00307 00308 #ifdef WITH_LUA 00309 if (!strcmp(progArgv[0], "<lua>")) { 00310 rpmlua lua = NULL; /* Global state. */ 00311 if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) { 00312 rc = RPMRC_FAIL; 00313 goto exit; 00314 } 00315 (void) rpmlibNeedsFeature(pkg->header, 00316 "BuiltinLuaScripts", "4.2.2-1"); 00317 } else 00318 #endif 00319 #ifdef WITH_AUGEAS 00320 if (!strcmp(progArgv[0], "<augeas>")) { 00321 (void) rpmlibNeedsFeature(pkg->header, 00322 "BuiltinAugeasScripts", "5.3-1"); 00323 } else 00324 #endif 00325 #ifdef WITH_FICL 00326 if (!strcmp(progArgv[0], "<ficl>")) { 00327 (void) rpmlibNeedsFeature(pkg->header, 00328 "BuiltinFiclScripts", "5.2-1"); 00329 } else 00330 #endif 00331 #ifdef WITH_GPSEE 00332 if (!strcmp(progArgv[0], "<js>")) { 00333 (void) rpmlibNeedsFeature(pkg->header, 00334 "BuiltinJavaScript", "5.2-1"); 00335 } else 00336 #endif 00337 #ifdef WITH_PERLEMBED 00338 if (!strcmp(progArgv[0], "<perl>")) { 00339 (void) rpmlibNeedsFeature(pkg->header, 00340 "BuiltinPerlScripts", "5.2-1"); 00341 } else 00342 #endif 00343 #ifdef WITH_PYTHONEMBED 00344 if (!strcmp(progArgv[0], "<python>")) { 00345 (void) rpmlibNeedsFeature(pkg->header, 00346 "BuiltinPythonScripts", "5.2-1"); 00347 } else 00348 #endif 00349 #ifdef WITH_RUBYEMBED 00350 if (!strcmp(progArgv[0], "<ruby>")) { 00351 (void) rpmlibNeedsFeature(pkg->header, 00352 "BuiltinRubyScripts", "5.2-1"); 00353 } else 00354 #endif 00355 #ifdef WITH_SEMANAGE 00356 if (!strcmp(progArgv[0], "<spook>")) { 00357 (void) rpmlibNeedsFeature(pkg->header, 00358 "BuiltinSpookScripts", "5.3-1"); 00359 } else 00360 #endif 00361 #ifdef WITH_SQLITE 00362 if (!strcmp(progArgv[0], "<sql>")) { 00363 (void) rpmlibNeedsFeature(pkg->header, 00364 "BuiltinSqlScripts", "5.3-1"); 00365 } else 00366 #endif 00367 #ifdef WITH_SQUIRREL 00368 if (!strcmp(progArgv[0], "<squirrel>")) { 00369 (void) rpmlibNeedsFeature(pkg->header, 00370 "BuiltinSquirrelScripts", "5.2-1"); 00371 } else 00372 #endif 00373 #ifdef WITH_TCL 00374 if (!strcmp(progArgv[0], "<tcl>")) { 00375 (void) rpmlibNeedsFeature(pkg->header, 00376 "BuiltinTclScripts", "5.2-1"); 00377 } else 00378 #endif 00379 if (progArgv[0][0] == '<') { 00380 rpmlog(RPMLOG_ERR, 00381 _("line %d: unsupported internal script: %s\n"), 00382 spec->lineNum, progArgv[0]); 00383 rc = RPMRC_FAIL; 00384 goto exit; 00385 } else 00386 if (!(rpmExpandNumeric("%{?_disable_shell_interpreter_deps}") 00387 && !strcmp(progArgv[0], "/bin/sh"))) 00388 { 00389 00390 (void) addReqProv(spec, pkg->header, RPMTAG_REQUIRENAME, 00391 progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0); 00392 } 00393 00394 /* Trigger script insertion is always delayed in order to */ 00395 /* get the index right. */ 00396 if (tag == RPMTAG_TRIGGERSCRIPTS) { 00397 /* Add file/index/prog triple to the trigger file list */ 00398 rpmuint32_t index = addTriggerIndex(pkg, file, p, progArgv[0]); 00399 00400 /* Generate the trigger tags */ 00401 if ((rc = parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags))) 00402 goto exit; 00403 } else { 00404 if (progArgc == 1) { 00405 he->tag = progtag; 00406 he->t = RPM_STRING_TYPE; 00407 he->p.str = *progArgv; 00408 he->c = progArgc; 00409 xx = headerPut(pkg->header, he, 0); 00410 } else { 00411 (void) rpmlibNeedsFeature(pkg->header, 00412 "ScriptletInterpreterArgs", "4.0.3-1"); 00413 he->tag = progtag; 00414 he->t = RPM_STRING_ARRAY_TYPE; 00415 he->p.argv = progArgv; 00416 he->c = progArgc; 00417 xx = headerPut(pkg->header, he, 0); 00418 } 00419 00420 if (*p != '\0') { 00421 he->tag = tag; 00422 he->t = RPM_STRING_TYPE; 00423 he->p.str = p; 00424 he->c = 1; 00425 xx = headerPut(pkg->header, he, 0); 00426 } 00427 00428 if (file) { 00429 switch (parsePart) { 00430 case PART_PRE: 00431 pkg->preInFile = xstrdup(file); 00432 break; 00433 case PART_POST: 00434 pkg->postInFile = xstrdup(file); 00435 break; 00436 case PART_PREUN: 00437 pkg->preUnFile = xstrdup(file); 00438 break; 00439 case PART_POSTUN: 00440 pkg->postUnFile = xstrdup(file); 00441 break; 00442 case PART_PRETRANS: 00443 pkg->preTransFile = xstrdup(file); 00444 break; 00445 case PART_POSTTRANS: 00446 pkg->postTransFile = xstrdup(file); 00447 break; 00448 case PART_VERIFYSCRIPT: 00449 pkg->verifyFile = xstrdup(file); 00450 break; 00451 case PART_SANITYCHECK: 00452 pkg->sanityCheckFile = xstrdup(file); 00453 break; 00454 } 00455 } 00456 } 00457 rc = (rpmRC) nextPart; 00458 00459 exit: 00460 iob = rpmiobFree(iob); 00461 progArgv = _free(progArgv); 00462 argv = _free(argv); 00463 optCon = poptFreeContext(optCon); 00464 00465 return rc; 00466 }