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
00018
00021 static rpmuint32_t addTriggerIndex(Package pkg, const char *file,
00022 const char *script, const char *prog)
00023
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
00055
00056 static const char *name = NULL;
00057
00058 static const char *prog = NULL;
00059
00060 static const char *file = NULL;
00061
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
00070
00071
00072
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
00080
00081
00082
00083
00084
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
00108 name = NULL;
00109 prog = "/bin/sh";
00110 file = NULL;
00111
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
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
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
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 break;
00234 case 'n':
00235 flag = PART_NAME;
00236 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
00251 if (name == NULL)
00252 name = poptGetArg(optCon);
00253
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;
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
00368
00369 if (tag == RPMTAG_TRIGGERSCRIPTS) {
00370
00371 rpmuint32_t index = addTriggerIndex(pkg, file, p, progArgv[0]);
00372
00373
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 }