2 * \file build/parseScript.c
3 * Parse install-time script section from spec file.
8 #include <rpm/header.h>
9 #include <rpm/rpmbuild.h>
10 #include <rpm/rpmlog.h>
12 #include "rpmio/rpmlua.h"
19 static int addTriggerIndex(Package pkg, const char *file,
20 const char *script, const char *prog)
22 struct TriggerFileEntry *tfe;
23 struct TriggerFileEntry *list = pkg->triggerFiles;
24 struct TriggerFileEntry *last = NULL;
33 index = last->index + 1;
35 tfe = xcalloc(1, sizeof(*tfe));
37 tfe->fileName = (file) ? xstrdup(file) : NULL;
38 tfe->script = (script && *script != '\0') ? xstrdup(script) : NULL;
39 tfe->prog = xstrdup(prog);
46 pkg->triggerFiles = tfe;
51 /* %trigger is a strange combination of %pre and Requires: behavior */
52 /* We can handle it by parsing the args before "--" in parseScript. */
53 /* We then pass the remaining arguments to parseRCPOT, along with */
54 /* an index we just determined. */
56 int parseScript(rpmSpec spec, int parsePart)
58 /* There are a few options to scripts: */
62 /* -p "<sh> <args>..." */
66 const char **progArgv = NULL;
68 const char *partname = NULL;
71 rpmsenseFlags tagflags = 0;
73 int flag = PART_SUBNAME;
78 char * reqargs = NULL;
80 int res = PART_ERROR; /* assume failure */
83 const char **argv = NULL;
84 poptContext optCon = NULL;
85 const char *name = NULL;
86 const char *prog = "/bin/sh";
87 const char *file = NULL;
88 struct poptOption optionsTable[] = {
89 { NULL, 'p', POPT_ARG_STRING, &prog, 'p', NULL, NULL},
90 { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL},
91 { NULL, 'f', POPT_ARG_STRING, &file, 'f', NULL, NULL},
92 { 0, 0, 0, 0, 0, NULL, NULL}
98 tagflags = RPMSENSE_SCRIPT_PRE;
99 progtag = RPMTAG_PREINPROG;
104 tagflags = RPMSENSE_SCRIPT_POST;
105 progtag = RPMTAG_POSTINPROG;
110 tagflags = RPMSENSE_SCRIPT_PREUN;
111 progtag = RPMTAG_PREUNPROG;
116 tagflags = RPMSENSE_SCRIPT_POSTUN;
117 progtag = RPMTAG_POSTUNPROG;
118 partname = "%postun";
121 tag = RPMTAG_PRETRANS;
123 progtag = RPMTAG_PRETRANSPROG;
124 partname = "%pretrans";
127 tag = RPMTAG_POSTTRANS;
129 progtag = RPMTAG_POSTTRANSPROG;
130 partname = "%posttrans";
132 case PART_VERIFYSCRIPT:
133 tag = RPMTAG_VERIFYSCRIPT;
134 tagflags = RPMSENSE_SCRIPT_VERIFY;
135 progtag = RPMTAG_VERIFYSCRIPTPROG;
136 partname = "%verifyscript";
138 case PART_TRIGGERPREIN:
139 tag = RPMTAG_TRIGGERSCRIPTS;
141 reqtag = RPMTAG_TRIGGERPREIN;
142 progtag = RPMTAG_TRIGGERSCRIPTPROG;
143 partname = "%triggerprein";
146 tag = RPMTAG_TRIGGERSCRIPTS;
148 reqtag = RPMTAG_TRIGGERIN;
149 progtag = RPMTAG_TRIGGERSCRIPTPROG;
150 partname = "%triggerin";
153 tag = RPMTAG_TRIGGERSCRIPTS;
155 reqtag = RPMTAG_TRIGGERUN;
156 progtag = RPMTAG_TRIGGERSCRIPTPROG;
157 partname = "%triggerun";
159 case PART_TRIGGERPOSTUN:
160 tag = RPMTAG_TRIGGERSCRIPTS;
162 reqtag = RPMTAG_TRIGGERPOSTUN;
163 progtag = RPMTAG_TRIGGERSCRIPTPROG;
164 partname = "%triggerpostun";
168 if (tag == RPMTAG_TRIGGERSCRIPTS) {
169 /* break line into two */
170 p = strstr(spec->line, "--");
172 rpmlog(RPMLOG_ERR, _("line %d: triggers must have --: %s\n"),
173 spec->lineNum, spec->line);
178 reqargs = xstrdup(p + 2);
181 if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
182 rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
183 spec->lineNum, partname, poptStrerror(rc));
187 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
188 while ((arg = poptGetNextOpt(optCon)) > 0) {
191 if (prog[0] == '<') {
192 if (prog[strlen(prog)-1] != '>') {
194 _("line %d: internal script must end "
195 "with \'>\': %s\n"), spec->lineNum, prog);
198 } else if (prog[0] != '/') {
200 _("line %d: script program must begin "
201 "with \'/\': %s\n"), spec->lineNum, prog);
212 rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"),
214 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
219 if (poptPeekArg(optCon)) {
221 name = poptGetArg(optCon);
222 if (poptPeekArg(optCon)) {
223 rpmlog(RPMLOG_ERR, _("line %d: Too many names: %s\n"),
230 if (lookupPackage(spec, name, flag, &pkg)) {
231 rpmlog(RPMLOG_ERR, _("line %d: Package does not exist: %s\n"),
232 spec->lineNum, spec->line);
236 if (tag != RPMTAG_TRIGGERSCRIPTS) {
237 if (headerIsEntry(pkg->header, progtag)) {
238 rpmlog(RPMLOG_ERR, _("line %d: Second %s\n"),
239 spec->lineNum, partname);
244 if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) {
245 rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
246 spec->lineNum, partname, poptStrerror(rc));
251 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
252 nextPart = PART_NONE;
256 while (! (nextPart = isPart(spec->line))) {
257 appendStringBuf(sb, spec->line);
258 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
259 nextPart = PART_NONE;
266 stripTrailingBlanksStringBuf(sb);
267 p = getStringBuf(sb);
270 if (rstreq(progArgv[0], "<lua>")) {
271 rpmlua lua = NULL; /* Global state. */
272 if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) {
275 (void) rpmlibNeedsFeature(pkg->header,
276 "BuiltinLuaScripts", "4.2.2-1");
279 if (progArgv[0][0] == '<') {
281 _("line %d: unsupported internal script: %s\n"),
282 spec->lineNum, progArgv[0]);
285 (void) addReqProv(spec, pkg->header, RPMTAG_REQUIRENAME,
286 progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0);
289 /* Trigger script insertion is always delayed in order to */
290 /* get the index right. */
291 if (tag == RPMTAG_TRIGGERSCRIPTS) {
292 /* Add file/index/prog triple to the trigger file list */
293 index = addTriggerIndex(pkg, file, p, progArgv[0]);
295 /* Generate the trigger tags */
296 if ((rc = parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags)))
302 * XXX Ancient rpm uses STRING, not STRING_ARRAY type here. Construct
303 * the td manually and preserve legacy compat for now...
309 td.data = (void *) *progArgv;
310 td.type = RPM_STRING_TYPE;
312 (void) rpmlibNeedsFeature(pkg->header,
313 "ScriptletInterpreterArgs", "4.0.3-1");
315 td.type = RPM_STRING_ARRAY_TYPE;
317 headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
320 headerPutString(pkg->header, tag, p);
326 pkg->preInFile = xstrdup(file);
329 pkg->postInFile = xstrdup(file);
332 pkg->preUnFile = xstrdup(file);
335 pkg->postUnFile = xstrdup(file);
338 pkg->preTransFile = xstrdup(file);
341 pkg->postTransFile = xstrdup(file);
343 case PART_VERIFYSCRIPT:
344 pkg->verifyFile = xstrdup(file);
353 sb = freeStringBuf(sb);
354 progArgv = _free(progArgv);
356 optCon = poptFreeContext(optCon);