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_TRIGGERIN:
00153 tag = RPMTAG_TRIGGERSCRIPTS;
00154 tagflags = 0;
00155 reqtag = RPMTAG_TRIGGERIN;
00156 progtag = RPMTAG_TRIGGERSCRIPTPROG;
00157 partname = "%triggerin";
00158 break;
00159 case PART_TRIGGERUN:
00160 tag = RPMTAG_TRIGGERSCRIPTS;
00161 tagflags = 0;
00162 reqtag = RPMTAG_TRIGGERUN;
00163 progtag = RPMTAG_TRIGGERSCRIPTPROG;
00164 partname = "%triggerun";
00165 break;
00166 case PART_TRIGGERPOSTUN:
00167 tag = RPMTAG_TRIGGERSCRIPTS;
00168 tagflags = 0;
00169 reqtag = RPMTAG_TRIGGERPOSTUN;
00170 progtag = RPMTAG_TRIGGERSCRIPTPROG;
00171 partname = "%triggerpostun";
00172 break;
00173 }
00174
00175
00176 if (tag == RPMTAG_TRIGGERSCRIPTS) {
00177
00178 p = strstr(spec->line, "--");
00179 if (!p) {
00180 rpmError(RPMERR_BADSPEC, _("line %d: triggers must have --: %s\n"),
00181 spec->lineNum, spec->line);
00182 return RPMERR_BADSPEC;
00183 }
00184
00185 *p = '\0';
00186 strcpy(reqargs, p + 2);
00187 }
00188
00189 if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
00190 rpmError(RPMERR_BADSPEC, _("line %d: Error parsing %s: %s\n"),
00191 spec->lineNum, partname, poptStrerror(rc));
00192 return RPMERR_BADSPEC;
00193 }
00194
00195 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
00196 while ((arg = poptGetNextOpt(optCon)) > 0) {
00197 switch (arg) {
00198 case 'p':
00199 if (prog[0] == '<') {
00200 if (prog[strlen(prog)-1] != '>') {
00201 rpmError(RPMERR_BADSPEC,
00202 _("line %d: internal script must end "
00203 "with \'>\': %s\n"), spec->lineNum, prog);
00204 rc = RPMERR_BADSPEC;
00205 goto exit;
00206 }
00207 } else if (prog[0] != '/') {
00208 rpmError(RPMERR_BADSPEC,
00209 _("line %d: script program must begin "
00210 "with \'/\': %s\n"), spec->lineNum, prog);
00211 rc = RPMERR_BADSPEC;
00212 goto exit;
00213 }
00214 break;
00215 case 'n':
00216 flag = PART_NAME;
00217 break;
00218 }
00219 }
00220
00221 if (arg < -1) {
00222 rpmError(RPMERR_BADSPEC, _("line %d: Bad option %s: %s\n"),
00223 spec->lineNum,
00224 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
00225 spec->line);
00226 rc = RPMERR_BADSPEC;
00227 goto exit;
00228 }
00229
00230 if (poptPeekArg(optCon)) {
00231
00232 if (name == NULL)
00233 name = poptGetArg(optCon);
00234
00235 if (poptPeekArg(optCon)) {
00236 rpmError(RPMERR_BADSPEC, _("line %d: Too many names: %s\n"),
00237 spec->lineNum,
00238 spec->line);
00239 rc = RPMERR_BADSPEC;
00240 goto exit;
00241 }
00242 }
00243
00244 if (lookupPackage(spec, name, flag, &pkg)) {
00245 rpmError(RPMERR_BADSPEC, _("line %d: Package does not exist: %s\n"),
00246 spec->lineNum, spec->line);
00247 rc = RPMERR_BADSPEC;
00248 goto exit;
00249 }
00250
00251 if (tag != RPMTAG_TRIGGERSCRIPTS) {
00252 if (headerIsEntry(pkg->header, progtag)) {
00253 rpmError(RPMERR_BADSPEC, _("line %d: Second %s\n"),
00254 spec->lineNum, partname);
00255 rc = RPMERR_BADSPEC;
00256 goto exit;
00257 }
00258 }
00259
00260 if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) {
00261 rpmError(RPMERR_BADSPEC, _("line %d: Error parsing %s: %s\n"),
00262 spec->lineNum, partname, poptStrerror(rc));
00263 rc = RPMERR_BADSPEC;
00264 goto exit;
00265 }
00266
00267 sb = newStringBuf();
00268 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
00269 nextPart = PART_NONE;
00270 } else {
00271 if (rc)
00272 goto exit;
00273 while (! (nextPart = isPart(spec->line))) {
00274 appendStringBuf(sb, spec->line);
00275 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
00276 nextPart = PART_NONE;
00277 break;
00278 }
00279 if (rc)
00280 goto exit;
00281 }
00282 }
00283 stripTrailingBlanksStringBuf(sb);
00284 p = getStringBuf(sb);
00285
00286 #ifdef WITH_LUA
00287 if (!strcmp(progArgv[0], "<lua>")) {
00288 rpmlua lua = NULL;
00289 if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) {
00290 rc = RPMERR_BADSPEC;
00291 goto exit;
00292 }
00293 (void) rpmlibNeedsFeature(pkg->header,
00294 "BuiltinLuaScripts", "4.2.2-1");
00295 } else
00296 #endif
00297 if (progArgv[0][0] == '<') {
00298 rpmError(RPMERR_BADSPEC,
00299 _("line %d: unsupported internal script: %s\n"),
00300 spec->lineNum, progArgv[0]);
00301 rc = RPMERR_BADSPEC;
00302 goto exit;
00303 } else {
00304 (void) addReqProv(spec, pkg->header, RPMTAG_REQUIRENAME,
00305 progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0);
00306 }
00307
00308
00309
00310 if (tag == RPMTAG_TRIGGERSCRIPTS) {
00311
00312 index = addTriggerIndex(pkg, file, p, progArgv[0]);
00313
00314
00315 if ((rc = parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags)))
00316 goto exit;
00317 } else {
00318 if (progArgc == 1)
00319 (void) headerAddEntry(pkg->header, progtag, RPM_STRING_TYPE,
00320 *progArgv, progArgc);
00321 else {
00322 (void) rpmlibNeedsFeature(pkg->header,
00323 "ScriptletInterpreterArgs", "4.0.3-1");
00324 (void) headerAddEntry(pkg->header, progtag, RPM_STRING_ARRAY_TYPE,
00325 progArgv, progArgc);
00326 }
00327
00328 if (*p != '\0')
00329 (void) headerAddEntry(pkg->header, tag, RPM_STRING_TYPE, p, 1);
00330
00331 if (file) {
00332 switch (parsePart) {
00333 case PART_PRE:
00334 pkg->preInFile = xstrdup(file);
00335 break;
00336 case PART_POST:
00337 pkg->postInFile = xstrdup(file);
00338 break;
00339 case PART_PREUN:
00340 pkg->preUnFile = xstrdup(file);
00341 break;
00342 case PART_POSTUN:
00343 pkg->postUnFile = xstrdup(file);
00344 break;
00345 case PART_PRETRANS:
00346 pkg->preTransFile = xstrdup(file);
00347 break;
00348 case PART_POSTTRANS:
00349 pkg->postTransFile = xstrdup(file);
00350 break;
00351 case PART_VERIFYSCRIPT:
00352 pkg->verifyFile = xstrdup(file);
00353 break;
00354 }
00355 }
00356 }
00357 rc = nextPart;
00358
00359 exit:
00360 sb = freeStringBuf(sb);
00361 progArgv = _free(progArgv);
00362 argv = _free(argv);
00363 optCon = poptFreeContext(optCon);
00364
00365 return rc;
00366 }
00367