rpm  5.4.14
parseScript.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio.h>
9 #include <rpmiotypes.h>
10 #include <rpmlog.h>
11 #define _RPMEVR_INTERNAL
12 #include "rpmbuild.h"
13 #include "debug.h"
14 
15 #include <rpmlua.h>
16 
17 /*@access poptContext @*/ /* compared with NULL */
18 
21 static rpmuint32_t addTriggerIndex(Package pkg, const char *file,
22  const char *script, const char *prog)
23  /*@modifies pkg->triggerFiles @*/
24 {
25  struct TriggerFileEntry *tfe;
26  struct TriggerFileEntry *list = pkg->triggerFiles;
27  struct TriggerFileEntry *last = NULL;
28  rpmuint32_t index = 0;
29 
30  while (list) {
31  last = list;
32  list = list->next;
33  }
34 
35  if (last)
36  index = last->index + 1;
37 
38  tfe = xcalloc(1, sizeof(*tfe));
39 
40  tfe->fileName = (file) ? xstrdup(file) : NULL;
41  tfe->script = (script && *script != '\0') ? xstrdup(script) : NULL;
42  tfe->prog = xstrdup(prog);
43  tfe->index = index;
44  tfe->next = NULL;
45 
46  if (last)
47  last->next = tfe;
48  else
49  pkg->triggerFiles = tfe;
50 
51  return index;
52 }
53 
54 /* these have to be global because of stupid compilers */
55 /*@unchecked@*/
56  /*@observer@*/ /*@null@*/ static const char *name = NULL;
57 /*@unchecked@*/
58  /*@observer@*/ /*@null@*/ static const char *prog = NULL;
59 /*@unchecked@*/
60  /*@observer@*/ /*@null@*/ static const char *file = NULL;
61 /*@unchecked@*/
62  static struct poptOption optionsTable[] = {
63  { NULL, 'p', POPT_ARG_STRING, &prog, 'p', NULL, NULL},
64  { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL},
65  { NULL, 'f', POPT_ARG_STRING, &file, 'f', NULL, NULL},
66  { 0, 0, 0, 0, 0, NULL, NULL}
67  };
68 
69 /* %trigger is a strange combination of %pre and Requires: behavior */
70 /* We can handle it by parsing the args before "--" in parseScript. */
71 /* We then pass the remaining arguments to parseRCPOT, along with */
72 /* an index we just determined. */
73 
74 int parseScript(Spec spec, int parsePart)
75 {
76  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
77  int xx;
78 
79  /* There are a few options to scripts: */
80  /* <pkg> */
81  /* -n <pkg> */
82  /* -p <sh> */
83  /* -p "<sh> <args>..." */
84  /* -f <file> */
85 
86  char *p;
87  const char **progArgv = NULL;
88  int progArgc;
89  char *partname = NULL;
90  rpmTag reqtag = 0;
91  rpmTag tag = 0;
92  rpmsenseFlags tagflags = 0;
93  rpmTag progtag = 0;
94  int flag = PART_SUBNAME;
95  Package pkg;
96  rpmiob iob = NULL;
97  rpmParseState nextPart;
98  char reqargs[BUFSIZ];
99 
100  int argc;
101  int arg;
102  const char **argv = NULL;
104  rpmRC rc;
105 
106  reqargs[0] = '\0';
107  /*@-mods@*/
108  name = NULL;
109  prog = "/bin/sh";
110  file = NULL;
111  /*@=mods@*/
112 
113  switch (parsePart) {
114  case PART_PRE:
115  tag = RPMTAG_PREIN;
116  tagflags = RPMSENSE_SCRIPT_PRE;
117  progtag = RPMTAG_PREINPROG;
118  partname = "%pre";
119  break;
120  case PART_POST:
121  tag = RPMTAG_POSTIN;
122  tagflags = RPMSENSE_SCRIPT_POST;
123  progtag = RPMTAG_POSTINPROG;
124  partname = "%post";
125  break;
126  case PART_PREUN:
127  tag = RPMTAG_PREUN;
128  tagflags = RPMSENSE_SCRIPT_PREUN;
129  progtag = RPMTAG_PREUNPROG;
130  partname = "%preun";
131  break;
132  case PART_POSTUN:
133  tag = RPMTAG_POSTUN;
134  tagflags = RPMSENSE_SCRIPT_POSTUN;
135  progtag = RPMTAG_POSTUNPROG;
136  partname = "%postun";
137  break;
138  case PART_PRETRANS:
139  tag = RPMTAG_PRETRANS;
140  tagflags = 0;
141  progtag = RPMTAG_PRETRANSPROG;
142  partname = "%pretrans";
143  break;
144  case PART_POSTTRANS:
145  tag = RPMTAG_POSTTRANS;
146  tagflags = 0;
147  progtag = RPMTAG_POSTTRANSPROG;
148  partname = "%posttrans";
149  break;
150  case PART_VERIFYSCRIPT:
151  tag = RPMTAG_VERIFYSCRIPT;
152  tagflags = RPMSENSE_SCRIPT_VERIFY;
153  progtag = RPMTAG_VERIFYSCRIPTPROG;
154  partname = "%verifyscript";
155  break;
156  case PART_TRIGGERPREIN:
157  tag = RPMTAG_TRIGGERSCRIPTS;
158  tagflags = 0;
159  reqtag = RPMTAG_TRIGGERPREIN;
160  progtag = RPMTAG_TRIGGERSCRIPTPROG;
161  partname = "%triggerprein";
162  break;
163  case PART_TRIGGERIN:
164  tag = RPMTAG_TRIGGERSCRIPTS;
165  tagflags = 0;
166  reqtag = RPMTAG_TRIGGERIN;
167  progtag = RPMTAG_TRIGGERSCRIPTPROG;
168  partname = "%triggerin";
169  break;
170  case PART_TRIGGERUN:
171  tag = RPMTAG_TRIGGERSCRIPTS;
172  tagflags = 0;
173  reqtag = RPMTAG_TRIGGERUN;
174  progtag = RPMTAG_TRIGGERSCRIPTPROG;
175  partname = "%triggerun";
176  break;
177  case PART_TRIGGERPOSTUN:
178  tag = RPMTAG_TRIGGERSCRIPTS;
179  tagflags = 0;
180  reqtag = RPMTAG_TRIGGERPOSTUN;
181  progtag = RPMTAG_TRIGGERSCRIPTPROG;
182  partname = "%triggerpostun";
183  break;
184  /* support "%sanitycheck" script/section */
185  case PART_SANITYCHECK:
186  tag = RPMTAG_SANITYCHECK;
187  tagflags = RPMSENSE_SCRIPT_SANITYCHECK;
188  progtag = RPMTAG_SANITYCHECKPROG;
189  partname = "%sanitycheck";
190  break;
191  }
192 
193  if (tag == RPMTAG_TRIGGERSCRIPTS) {
194  /* break line into two */
195  p = strstr(spec->line, "--");
196  if (!p) {
197  rpmlog(RPMLOG_ERR, _("line %d: triggers must have --: %s\n"),
198  spec->lineNum, spec->line);
199  return RPMRC_FAIL;
200  }
201 
202  *p = '\0';
203  strncpy(reqargs, p + 2, sizeof(reqargs)-1);
204  reqargs[sizeof(reqargs)-1] = '\0';
205  }
206 
207  if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
208  rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
209  spec->lineNum, partname, poptStrerror(rc));
210  return RPMRC_FAIL;
211  }
212 
213  optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
214  while ((arg = poptGetNextOpt(optCon)) > 0) {
215  switch (arg) {
216  case 'p':
217  if (prog[0] == '<') {
218  const char * s = prog;
219  while (s && s[1] && s[1] != '>')
220  s++;
221  if (s[1] != '>') {
223  _("line %d: embedded interpreter token must end "
224  "with \'>\': %s\n"), spec->lineNum, prog);
225  rc = RPMRC_FAIL;
226  goto exit;
227  }
228  } else if (prog[0] == '%') {
229  /* XXX check well-formed macro? */
230  } else if (prog[0] != '/') {
232  _("line %d: script program must begin "
233  "with \'/\': %s\n"), spec->lineNum, prog);
234  rc = RPMRC_FAIL;
235  goto exit;
236  }
237  /*@switchbreak@*/ break;
238  case 'n':
239  flag = PART_NAME;
240  /*@switchbreak@*/ break;
241  }
242  }
243 
244  if (arg < -1) {
245  rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"),
246  spec->lineNum,
247  poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
248  spec->line);
249  rc = RPMRC_FAIL;
250  goto exit;
251  }
252 
253  if (poptPeekArg(optCon)) {
254  /*@-mods@*/
255  if (name == NULL)
256  name = poptGetArg(optCon);
257  /*@=mods@*/
258  if (poptPeekArg(optCon)) {
259  rpmlog(RPMLOG_ERR, _("line %d: Too many names: %s\n"),
260  spec->lineNum,
261  spec->line);
262  rc = RPMRC_FAIL;
263  goto exit;
264  }
265  }
266 
267  if (lookupPackage(spec, name, flag, &pkg) != RPMRC_OK) {
268  rpmlog(RPMLOG_ERR, _("line %d: Package does not exist: %s\n"),
269  spec->lineNum, spec->line);
270  rc = RPMRC_FAIL;
271  goto exit;
272  }
273 
274  if (tag != RPMTAG_TRIGGERSCRIPTS) {
275  if (headerIsEntry(pkg->header, progtag)) {
276  rpmlog(RPMLOG_ERR, _("line %d: Second %s\n"),
277  spec->lineNum, partname);
278  rc = RPMRC_FAIL;
279  goto exit;
280  }
281  }
282 
283  if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) {
284  rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
285  spec->lineNum, partname, poptStrerror(rc));
286  rc = RPMRC_FAIL;
287  goto exit;
288  }
289 
290  iob = rpmiobNew(0);
291  if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
292  nextPart = PART_NONE;
293  } else {
294  if (rc)
295  goto exit;
296  while ((nextPart = isPart(spec)) == PART_NONE) {
297  iob = rpmiobAppend(iob, spec->line, 0);
298  if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
299  nextPart = PART_NONE;
300  break;
301  }
302  if (rc)
303  goto exit;
304  }
305  }
306  iob = rpmiobRTrim(iob);
307  p = rpmiobStr(iob);
308 
309 #ifdef WITH_LUA
310  if (!strcmp(progArgv[0], "<lua>")) {
311  rpmlua lua = NULL; /* Global state. */
312  if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) {
313  rc = RPMRC_FAIL;
314  goto exit;
315  }
317  "BuiltinLuaScripts", "4.2.2-1");
318  } else
319 #endif
320 #ifdef WITH_AUGEAS
321  if (!strcmp(progArgv[0], "<augeas>")) {
323  "BuiltinAugeasScripts", "5.3-1");
324  } else
325 #endif
326 #ifdef WITH_FICL
327  if (!strcmp(progArgv[0], "<ficl>")) {
329  "BuiltinFiclScripts", "5.2-1");
330  } else
331 #endif
332 #ifdef WITH_GPSEE
333  if (!strcmp(progArgv[0], "<js>")) {
335  "BuiltinJavaScript", "5.2-1");
336  } else
337 #endif
338 #ifdef WITH_PERLEMBED
339  if (!strcmp(progArgv[0], "<perl>")) {
341  "BuiltinPerlScripts", "5.2-1");
342  } else
343 #endif
344 #ifdef WITH_PYTHONEMBED
345  if (!strcmp(progArgv[0], "<python>")) {
347  "BuiltinPythonScripts", "5.2-1");
348  } else
349 #endif
350 #ifdef WITH_RUBYEMBED
351  if (!strcmp(progArgv[0], "<ruby>")) {
353  "BuiltinRubyScripts", "5.2-1");
354  } else
355 #endif
356 #ifdef WITH_SEMANAGE
357  if (!strcmp(progArgv[0], "<spook>")) {
359  "BuiltinSpookScripts", "5.3-1");
360  } else
361 #endif
362 #ifdef WITH_SQLITE
363  if (!strcmp(progArgv[0], "<sql>")) {
365  "BuiltinSqlScripts", "5.3-1");
366  } else
367 #endif
368 #ifdef WITH_SQUIRREL
369  if (!strcmp(progArgv[0], "<squirrel>")) {
371  "BuiltinSquirrelScripts", "5.2-1");
372  } else
373 #endif
374 #ifdef WITH_TCL
375  if (!strcmp(progArgv[0], "<tcl>")) {
377  "BuiltinTclScripts", "5.2-1");
378  } else
379 #endif
380  if (progArgv[0][0] == '<') {
382  _("line %d: unsupported internal script: %s\n"),
383  spec->lineNum, progArgv[0]);
384  rc = RPMRC_FAIL;
385  goto exit;
386  } else
387  if (!(rpmExpandNumeric("%{?_disable_shell_interpreter_deps}")
388  && !strcmp(progArgv[0], "/bin/sh")))
389  {
390 
392  progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0);
393  }
394 
395  /* Trigger script insertion is always delayed in order to */
396  /* get the index right. */
397  if (tag == RPMTAG_TRIGGERSCRIPTS) {
398  /* Add file/index/prog triple to the trigger file list */
399  rpmuint32_t index = addTriggerIndex(pkg, file, p, progArgv[0]);
400 
401  /* Generate the trigger tags */
402  if ((rc = parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags)))
403  goto exit;
404  } else {
405  if (progArgc == 1) {
406  he->tag = progtag;
407  he->t = RPM_STRING_TYPE;
408  he->p.str = *progArgv;
409  he->c = progArgc;
410  xx = headerPut(pkg->header, he, 0);
411  } else {
413  "ScriptletInterpreterArgs", "4.0.3-1");
414  he->tag = progtag;
415  he->t = RPM_STRING_ARRAY_TYPE;
416  he->p.argv = progArgv;
417  he->c = progArgc;
418  xx = headerPut(pkg->header, he, 0);
419  }
420 
421  if (*p != '\0') {
422  he->tag = tag;
423  he->t = RPM_STRING_TYPE;
424  he->p.str = p;
425  he->c = 1;
426  xx = headerPut(pkg->header, he, 0);
427  }
428 
429  if (file) {
430  switch (parsePart) {
431  case PART_PRE:
432  pkg->preInFile = xstrdup(file);
433  break;
434  case PART_POST:
435  pkg->postInFile = xstrdup(file);
436  break;
437  case PART_PREUN:
438  pkg->preUnFile = xstrdup(file);
439  break;
440  case PART_POSTUN:
441  pkg->postUnFile = xstrdup(file);
442  break;
443  case PART_PRETRANS:
444  pkg->preTransFile = xstrdup(file);
445  break;
446  case PART_POSTTRANS:
447  pkg->postTransFile = xstrdup(file);
448  break;
449  case PART_VERIFYSCRIPT:
450  pkg->verifyFile = xstrdup(file);
451  break;
452  case PART_SANITYCHECK:
453  pkg->sanityCheckFile = xstrdup(file);
454  break;
455  }
456  }
457  }
458  rc = (rpmRC) nextPart;
459 
460 exit:
461  iob = rpmiobFree(iob);
462  progArgv = _free(progArgv);
463  argv = _free(argv);
464  optCon = poptFreeContext(optCon);
465 
466  return rc;
467 }
rpmTagType t
Definition: rpmtag.h:502
char * fileName
Definition: rpmspec.h:31
rpmiob rpmiobRTrim(rpmiob iob)
Trim trailing white space.
Definition: rpmiob.c:67
const char * str
Definition: rpmtag.h:73
int xx
Definition: spec.c:744
rpmTag tag
Definition: rpmtag.h:501
const char ** argv
Definition: rpmtag.h:75
static const char * prog
Definition: parseScript.c:58
int rpmluaCheckScript(rpmlua _lua, const char *script, const char *name)
rpmlog(RPMLOG_ERR,"%s\n", buf)
const char * postInFile
Definition: rpmspec.h:230
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
int rc
Definition: poptALL.c:670
char * prog
Definition: rpmspec.h:35
rpmRC lookupPackage(Spec spec, const char *name, int flag, Package *pkg)
Find sub-package control structure by name.
Definition: spec.c:78
#define PART_NAME
Definition: rpmbuild.h:50
enum rpmTag_e rpmTag
Definition: rpmtag.h:468
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
rpmiob rpmiobAppend(rpmiob iob, const char *s, size_t nl)
Append string to I/O buffer.
Definition: rpmiob.c:77
argv
Definition: rpmmtree.c:3679
int addReqProv(Spec spec, Header h, rpmTag tagN, const char *N, const char *EVR, rpmsenseFlags Flags, rpmuint32_t index)
Add dependency to header, filtering duplicates.
Definition: reqprov.c:14
struct rpmiob_s * rpmiob
Definition: rpmiotypes.h:60
PyObject * list
Definition: rpmts-py.c:521
static rpmuint32_t addTriggerIndex(Package pkg, const char *file, const char *script, const char *prog)
Definition: parseScript.c:21
char * alloca()
enum rpmRC_e rpmRC
RPM return codes.
Definition: signature.c:616
Yet Another syslog(3) API clone.
goto exit
Definition: db3.c:1903
memset(_r, 0, sizeof(*_r))
Header header
Definition: rpmspec.h:217
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
char * p
Definition: macro.c:413
rpmParseState isPart(Spec spec)
Check line for section separator, return next parser state.
Definition: parseSpec.c:64
int headerIsEntry(Header h, rpmTag tag)
Check if tag is in header.
Definition: header.c:1438
char * line
Definition: rpmspec.h:138
#define PART_SUBNAME
Definition: rpmbuild.h:49
enum evrFlags_e rpmsenseFlags
Definition: rpmevr.h:74
he tag
Definition: db3.c:1927
rpmTagData p
Definition: rpmtag.h:504
struct _HE_s * HE_t
Destroy an extension cache.
Definition: rpmtag.h:59
struct TriggerFileEntry * triggerFiles
Definition: rpmspec.h:248
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2293
rpmTagCount c
Definition: rpmtag.h:505
The structure used to store values parsed from a spec file.
Definition: rpmspec.h:113
int parseScript(Spec spec, int parsePart)
Parse %pre et al scriptlets from a spec file.
Definition: parseScript.c:74
const char * preInFile
Definition: rpmspec.h:228
struct TriggerFileEntry * next
Definition: rpmspec.h:37
char * script
Definition: rpmspec.h:33
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
Definition: rpmiob.c:44
optCon
Definition: poptALL.c:604
const char * postUnFile
Definition: rpmspec.h:234
char * rpmiobStr(rpmiob iob)
Return I/O buffer (as string).
Definition: rpmiob.c:112
Definition: rpmtag.h:500
return strcmp(ame->name, bme->name)
const char * s
Definition: poptALL.c:734
This is the only module users of librpmbuild should need to include.
static const char * file
Definition: parseScript.c:60
enum rpmParseState_e rpmParseState
int lineNum
Definition: rpmspec.h:139
return NULL
Definition: poptALL.c:613
const char * verifyFile
Definition: rpmspec.h:240
struct rpmlua_s * rpmlua
Definition: rpmlua.h:53
static void
Print copy of spec file, filling in Group/Description/Summary from specspo.
Definition: spec.c:737
static const char * name
#define _(Text)
Definition: system.h:29
rpmRC parseRCPOT(Spec spec, Package pkg, const char *field, rpmTag tagN, rpmuint32_t index, rpmsenseFlags tagflags)
Parse dependency relations from spec file and/or autogenerated output buffer.
Definition: parseReqs.c:20
The structure used to store values for a package.
Definition: rpmspec.h:214
const char * preUnFile
Definition: rpmspec.h:232
poptContext
Definition: poptALL.c:525
int rpmlibNeedsFeature(Header h, const char *feature, const char *featureEVR)
Add rpmlib feature dependency.
Definition: reqprov.c:212
int readLine(Spec spec, rpmStripFlags strip)
Read next line from spec file.
Definition: parseSpec.c:351
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
strncpy(sbuf, f, flen)
const char * postTransFile
Definition: rpmspec.h:238
int rpmExpandNumeric(const char *arg)
Return macro expansion as a numeric value.
Definition: macro.c:3252
static struct poptOption optionsTable[]
Definition: parseScript.c:62
const char * preTransFile
Definition: rpmspec.h:236
const char * sanityCheckFile
Definition: rpmspec.h:242
Spec spec
Definition: spec-py.c:121