rpm 5.2.1
|
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 }