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