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