rpm  5.4.10
rpmsquirrel.c
Go to the documentation of this file.
1 #include "system.h"
2 #include <stdarg.h>
3 
4 #include <argv.h>
5 
6 #if defined(MODULE_EMBED)
7 #include <squirrel.h>
8 #undef WITH_SQUIRREL
9 #endif
10 
11 #if defined(WITH_SQUIRREL)
12 #include <dlfcn.h>
13 #include <rpmlog.h>
14 #endif
15 
16 #define _RPMSQUIRREL_INTERNAL
17 #include "rpmsquirrel.h"
18 
19 #include "debug.h"
20 
21 /*@unchecked@*/
23 
24 /*@unchecked@*/ /*@relnull@*/
26 
27 #if defined(WITH_SQUIRREL)
28 static int dlopened = 0;
29 static rpmsquirrel (*rpmsquirrelNew_p) (char ** av, uint32_t flags);
30 static rpmRC (*rpmsquirrelRunFile_p) (rpmsquirrel squirrel, const char * fn, const char ** resultp);
31 static rpmRC (*rpmsquirrelRun_p) (rpmsquirrel squirrel, const char * str, const char ** resultp);
32 #endif
33 
34 static void rpmsquirrelFini(void * _squirrel)
35  /*@globals fileSystem @*/
36  /*@modifies *_squirrel, fileSystem @*/
37 {
38  rpmsquirrel squirrel = (rpmsquirrel) _squirrel;
39 
40 #if defined(MODULE_EMBED)
41  sq_close((HSQUIRRELVM)squirrel->I);
42 #endif
43  squirrel->I = NULL;
44  (void)rpmiobFree(squirrel->iob);
45  squirrel->iob = NULL;
46 }
47 
48 /*@unchecked@*/ /*@only@*/ /*@null@*/
50 
51 static rpmsquirrel rpmsquirrelGetPool(/*@null@*/ rpmioPool pool)
52  /*@globals _rpmsquirrelPool, fileSystem @*/
53  /*@modifies pool, _rpmsquirrelPool, fileSystem @*/
54 {
55  rpmsquirrel squirrel;
56 
57  if (_rpmsquirrelPool == NULL) {
58  _rpmsquirrelPool = rpmioNewPool("squirrel", sizeof(*squirrel), -1, _rpmsquirrel_debug,
59  NULL, NULL, rpmsquirrelFini);
60  pool = _rpmsquirrelPool;
61  }
62  return (rpmsquirrel) rpmioGetPool(pool, sizeof(*squirrel));
63 }
64 
65 #if defined(MODULE_EMBED)
66 static void rpmsquirrelPrint(HSQUIRRELVM v, const SQChar *s, ...)
67 {
68  rpmsquirrel squirrel = sq_getforeignptr(v);
69  size_t nb = 1024;
70  char * b = xmalloc(nb);
71  va_list va;
72 
73  va_start(va, s);
74  while(1) {
75  int nw = vsnprintf(b, nb, s, va);
76  if (nw > -1 && (size_t)nw < nb)
77  break;
78  if (nw > -1) /* glibc 2.1 (and later) */
79  nb = nw+1;
80  else /* glibc 2.0 */
81  nb *= 2;
82  b = xrealloc(b, nb);
83  }
84  va_end(va);
85 
86  (void) rpmiobAppend(squirrel->iob, b, 0);
87  b = _free(b);
88 }
89 
90 #if defined(SQUIRREL_VERSION_NUMBER) && SQUIRREL_VERSION_NUMBER >= 300
91 static void rpmsquirrelStderr(HSQUIRRELVM v, const SQChar *s,...)
92 {
93  va_list vl;
94  va_start(vl, s);
95  vfprintf(stderr, s, vl);
96  va_end(vl);
97 }
98 #endif
99 #endif
100 
101 /* XXX FIXME: honor 0x8000000 in flags to use global interpreter */
103  /*@globals _rpmsquirrelI @*/
104  /*@modifies _rpmsquirrelI @*/
105 {
106  if (_rpmsquirrelI == NULL)
107  _rpmsquirrelI = rpmsquirrelNew(NULL, 0);
108  return _rpmsquirrelI;
109 }
110 
111 #if defined(WITH_SQUIRREL)
112 static void loadModule(void) {
113  const char librpmsquirrel[] = "rpmsquirrel.so";
114  void *h;
115 
116  h = dlopen (librpmsquirrel, RTLD_NOW|RTLD_GLOBAL);
117  if (!h)
118  {
119  rpmlog(RPMLOG_WARNING, D_("Unable to open \"%s\" (%s), "
120  "embedded squirrel will not be available\n"),
121  librpmsquirrel, dlerror());
122  }
123  else if(!((rpmsquirrelNew_p = dlsym(h, "rpmsquirrelNew"))
124  && (rpmsquirrelRunFile_p = dlsym(h, "rpmsquirrelRunFile"))
125  && (rpmsquirrelRun_p = dlsym(h, "rpmsquirrelRun")))) {
126  rpmlog(RPMLOG_WARNING, D_("Opened library \"%s\" is incompatible (%s), "
127  "embedded squirrel will not be available\n"),
128  librpmsquirrel, dlerror());
129  if (dlclose (h))
130  rpmlog(RPMLOG_WARNING, "Error closing library \"%s\": %s", librpmsquirrel,
131  dlerror());
132  } else
133  dlopened = 1;
134 }
135 #endif
136 
137 rpmsquirrel rpmsquirrelNew(char ** av, uint32_t flags)
138 {
139 #if defined(WITH_SQUIRREL)
140  if (!dlopened) loadModule();
141  if (dlopened) return rpmsquirrelNew_p(av, flags);
142 #endif
143  rpmsquirrel squirrel = (flags & 0x80000000)
144  ? rpmsquirrelI() : rpmsquirrelGetPool(_rpmsquirrelPool);
145 
146 #if defined(MODULE_EMBED)
147  static const char * _av[] = { "rpmsquirrel", NULL };
148  SQInteger stacksize = 1024;
149  HSQUIRRELVM v = sq_open(stacksize);
150  int ac;
151 
152  if (av == NULL) av = _av;
153  ac = argvCount(av);
154 
155  squirrel->I = v;
156  sq_setforeignptr(v, squirrel);
157 #if defined(SQUIRREL_VERSION_NUMBER) && SQUIRREL_VERSION_NUMBER >= 300
158  sq_setprintfunc(v, rpmsquirrelPrint, rpmsquirrelStderr);
159 #else
160  sq_setprintfunc(v, rpmsquirrelPrint);
161 #endif
162 
163 #ifdef NOTYET
164  { int i;
165  sq_pushroottable(v);
166  sc_pushstring(v, "ARGS", -1);
167  sq_newarray(v, 0);
168  for (i = 0, i < ac; i++) {
169  sq_pushstring(v, av[i], -1);
170  sq_arrayappend(v, -2);
171  }
172  sq_createslot(v, -3);
173  sq_pop(v, 1);
174  }
175 #endif
176 #endif
177 #if !defined(WITH_SQUIRREL)
178  squirrel->iob = rpmiobNew(0);
179 #endif
180 
181  return rpmsquirrelLink(squirrel);
182 }
183 
184 rpmRC rpmsquirrelRunFile(rpmsquirrel squirrel, const char * fn, const char ** resultp)
185 {
186 #if defined(WITH_SQUIRREL)
187  if (dlopened) return rpmsquirrelRunFile_p(squirrel, fn, resultp);
188 #endif
189  rpmRC rc = RPMRC_FAIL;
190 
192 fprintf(stderr, "==> %s(%p,%s)\n", __FUNCTION__, squirrel, fn);
193 
194  if (squirrel == NULL) squirrel = rpmsquirrelI();
195 
196 #if defined(NOTYET)
197  if (fn != NULL && Tcl_EvalFile((Tcl_Interp *)squirrel->I, fn) == SQUIRREL_OK) {
198  rc = RPMRC_OK;
199  if (resultp)
200  *resultp = rpmiobStr(squirrel->iob);
201  }
202 #endif
203  return rc;
204 }
205 
206 rpmRC rpmsquirrelRun(rpmsquirrel squirrel, const char * str, const char ** resultp)
207 {
208 #if defined(WITH_SQUIRREL)
209  if (dlopened) return rpmsquirrelRun_p(squirrel, str, resultp);
210 #endif
211 
212  rpmRC rc = RPMRC_FAIL;
213 
215 fprintf(stderr, "==> %s(%p,%s)\n", __FUNCTION__, squirrel, str);
216 
217  if (squirrel == NULL) squirrel = rpmsquirrelI();
218 
219 #if defined(MODULE_EMBED)
220  if (str != NULL) {
221  size_t ns = strlen(str);
222  if (ns > 0) {
223  HSQUIRRELVM v = squirrel->I;
224  SQBool raise = SQFalse;
225  SQInteger oldtop = sq_gettop(v);
226  SQRESULT res = sq_compilebuffer(v, str, ns, __FUNCTION__, raise);
227 
228  if (SQ_SUCCEEDED(res)) {
229  SQInteger retval = 0;
230  sq_pushroottable(v);
231  res = sq_call(v, 1, retval, raise);
232  }
233 
234  sq_settop(v, oldtop);
235  }
236  rc = RPMRC_OK;
237  if (resultp)
238  *resultp = rpmiobStr(squirrel->iob);
239  }
240 #endif
241  return rc;
242 }
rpmsquirrel rpmsquirrelLink(rpmsquirrel squirrel)
Reference a squirrel interpreter instance.
rpmsquirrel _rpmsquirrelI
Definition: rpmsquirrel.c:25
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
static rpmsquirrel rpmsquirrelGetPool(rpmioPool pool)
Definition: rpmsquirrel.c:51
rpmiob rpmiobAppend(rpmiob iob, const char *s, size_t nl)
Append string to I/O buffer.
Definition: rpmiob.c:78
int _rpmsquirrel_debug
Definition: rpmsquirrel.c:22
Yet Another syslog(3) API clone.
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:221
int argvCount(const ARGV_t argv)
Return no.
Definition: argv.c:71
rpmRC rpmsquirrelRunFile(rpmsquirrel squirrel, const char *fn, const char **resultp)
Execute squirrel from a file.
Definition: rpmsquirrel.c:184
static void rpmsquirrelFini(void *_squirrel)
Definition: rpmsquirrel.c:34
rpmRC rpmsquirrelRun(rpmsquirrel squirrel, const char *str, const char **resultp)
Execute squirrel string.
Definition: rpmsquirrel.c:206
static rpmsquirrel rpmsquirrelI(void)
Definition: rpmsquirrel.c:102
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
Definition: rpmiob.c:44
struct rpmsquirrel_s * rpmsquirrel
Definition: rpmsquirrel.h:11
enum rpmRC_e rpmRC
RPM return codes.
char * rpmiobStr(rpmiob iob)
Return I/O buffer (as string).
Definition: rpmiob.c:113
rpmioPool _rpmsquirrelPool
Definition: rpmsquirrel.c:49
static int vsnprintf(char *buf, int nb, const char *fmt, va_list ap)
Definition: rpmps.c:212
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:110
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
#define xmalloc
Definition: system.h:33
#define D_(Text)
Definition: system.h:485
rpmsquirrel rpmsquirrelNew(char **av, uint32_t flags)
Create and load a squirrel interpreter.
Definition: rpmsquirrel.c:137
#define xrealloc
Definition: system.h:36