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