2 * \file build/parseScript.c
3 * Parse install-time script section from spec file.
8 #include <rpm/rpmbuild.h>
9 #include <rpm/rpmlog.h>
12 #include "rpmio/rpmlua.h"
16 static int addTriggerIndex(Package pkg, const char *file,
17 const char *script, const char *prog)
19 struct TriggerFileEntry *tfe;
20 struct TriggerFileEntry *list = pkg->triggerFiles;
21 struct TriggerFileEntry *last = NULL;
30 index = last->index + 1;
32 tfe = xcalloc(1, sizeof(*tfe));
34 tfe->fileName = (file) ? xstrdup(file) : NULL;
35 tfe->script = (script && *script != '\0') ? xstrdup(script) : NULL;
36 tfe->prog = xstrdup(prog);
43 pkg->triggerFiles = tfe;
48 /* these have to be global because of stupid compilers */
49 static const char *name = NULL;
50 static const char *prog = NULL;
51 static const char *file = NULL;
52 static struct poptOption optionsTable[] = {
53 { NULL, 'p', POPT_ARG_STRING, &prog, 'p', NULL, NULL},
54 { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL},
55 { NULL, 'f', POPT_ARG_STRING, &file, 'f', NULL, NULL},
56 { 0, 0, 0, 0, 0, NULL, NULL}
59 /* %trigger is a strange combination of %pre and Requires: behavior */
60 /* We can handle it by parsing the args before "--" in parseScript. */
61 /* We then pass the remaining arguments to parseRCPOT, along with */
62 /* an index we just determined. */
64 int parseScript(rpmSpec spec, int parsePart)
66 /* There are a few options to scripts: */
70 /* -p "<sh> <args>..." */
74 const char **progArgv = NULL;
76 char *partname = NULL;
80 rpm_tag_t progtag = 0;
81 int flag = PART_SUBNAME;
90 const char **argv = NULL;
91 poptContext optCon = NULL;
101 tagflags = RPMSENSE_SCRIPT_PRE;
102 progtag = RPMTAG_PREINPROG;
107 tagflags = RPMSENSE_SCRIPT_POST;
108 progtag = RPMTAG_POSTINPROG;
113 tagflags = RPMSENSE_SCRIPT_PREUN;
114 progtag = RPMTAG_PREUNPROG;
119 tagflags = RPMSENSE_SCRIPT_POSTUN;
120 progtag = RPMTAG_POSTUNPROG;
121 partname = "%postun";
124 tag = RPMTAG_PRETRANS;
126 progtag = RPMTAG_PRETRANSPROG;
127 partname = "%pretrans";
130 tag = RPMTAG_POSTTRANS;
132 progtag = RPMTAG_POSTTRANSPROG;
133 partname = "%posttrans";
135 case PART_VERIFYSCRIPT:
136 tag = RPMTAG_VERIFYSCRIPT;
137 tagflags = RPMSENSE_SCRIPT_VERIFY;
138 progtag = RPMTAG_VERIFYSCRIPTPROG;
139 partname = "%verifyscript";
142 tag = RPMTAG_TRIGGERSCRIPTS;
144 reqtag = RPMTAG_TRIGGERIN;
145 progtag = RPMTAG_TRIGGERSCRIPTPROG;
146 partname = "%triggerin";
149 tag = RPMTAG_TRIGGERSCRIPTS;
151 reqtag = RPMTAG_TRIGGERUN;
152 progtag = RPMTAG_TRIGGERSCRIPTPROG;
153 partname = "%triggerun";
155 case PART_TRIGGERPOSTUN:
156 tag = RPMTAG_TRIGGERSCRIPTS;
158 reqtag = RPMTAG_TRIGGERPOSTUN;
159 progtag = RPMTAG_TRIGGERSCRIPTPROG;
160 partname = "%triggerpostun";
164 if (tag == RPMTAG_TRIGGERSCRIPTS) {
165 /* break line into two */
166 p = strstr(spec->line, "--");
168 rpmlog(RPMLOG_ERR, _("line %d: triggers must have --: %s\n"),
169 spec->lineNum, spec->line);
174 strcpy(reqargs, p + 2);
177 if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
178 rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
179 spec->lineNum, partname, poptStrerror(rc));
183 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
184 while ((arg = poptGetNextOpt(optCon)) > 0) {
187 if (prog[0] == '<') {
188 if (prog[strlen(prog)-1] != '>') {
190 _("line %d: internal script must end "
191 "with \'>\': %s\n"), spec->lineNum, prog);
195 } else if (prog[0] != '/') {
197 _("line %d: script program must begin "
198 "with \'/\': %s\n"), spec->lineNum, prog);
210 rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"),
212 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
218 if (poptPeekArg(optCon)) {
220 name = poptGetArg(optCon);
221 if (poptPeekArg(optCon)) {
222 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);
237 if (tag != RPMTAG_TRIGGERSCRIPTS) {
238 if (headerIsEntry(pkg->header, progtag)) {
239 rpmlog(RPMLOG_ERR, _("line %d: Second %s\n"),
240 spec->lineNum, partname);
246 if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) {
247 rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
248 spec->lineNum, partname, poptStrerror(rc));
254 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
255 nextPart = PART_NONE;
259 while (! (nextPart = isPart(spec->line))) {
260 appendStringBuf(sb, spec->line);
261 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
262 nextPart = PART_NONE;
269 stripTrailingBlanksStringBuf(sb);
270 p = getStringBuf(sb);
273 if (!strcmp(progArgv[0], "<lua>")) {
274 rpmlua lua = NULL; /* Global state. */
275 if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) {
279 (void) rpmlibNeedsFeature(pkg->header,
280 "BuiltinLuaScripts", "4.2.2-1");
283 if (progArgv[0][0] == '<') {
285 _("line %d: unsupported internal script: %s\n"),
286 spec->lineNum, progArgv[0]);
290 (void) addReqProv(spec, pkg->header, RPMTAG_REQUIRENAME,
291 progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0);
294 /* Trigger script insertion is always delayed in order to */
295 /* get the index right. */
296 if (tag == RPMTAG_TRIGGERSCRIPTS) {
297 /* Add file/index/prog triple to the trigger file list */
298 index = addTriggerIndex(pkg, file, p, progArgv[0]);
300 /* Generate the trigger tags */
301 if ((rc = parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags)))
305 (void) headerAddEntry(pkg->header, progtag, RPM_STRING_TYPE,
306 *progArgv, (rpm_count_t) progArgc);
308 (void) rpmlibNeedsFeature(pkg->header,
309 "ScriptletInterpreterArgs", "4.0.3-1");
310 (void) headerAddEntry(pkg->header, progtag, RPM_STRING_ARRAY_TYPE,
311 progArgv, (rpm_count_t) progArgc);
315 (void) headerAddEntry(pkg->header, tag, RPM_STRING_TYPE, p, 1);
320 pkg->preInFile = xstrdup(file);
323 pkg->postInFile = xstrdup(file);
326 pkg->preUnFile = xstrdup(file);
329 pkg->postUnFile = xstrdup(file);
332 pkg->preTransFile = xstrdup(file);
335 pkg->postTransFile = xstrdup(file);
337 case PART_VERIFYSCRIPT:
338 pkg->verifyFile = xstrdup(file);
346 sb = freeStringBuf(sb);
347 progArgv = _free(progArgv);
349 optCon = poptFreeContext(optCon);