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 #endif
90 
91 /* XXX FIXME: honor 0x8000000 in flags to use global interpreter */
93  /*@globals _rpmsquirrelI @*/
94  /*@modifies _rpmsquirrelI @*/
95 {
96  if (_rpmsquirrelI == NULL)
97  _rpmsquirrelI = rpmsquirrelNew(NULL, 0);
98  return _rpmsquirrelI;
99 }
100 
101 #if defined(WITH_SQUIRREL)
102 static void loadModule(void) {
103  const char librpmsquirrel[] = "rpmsquirrel.so";
104  void *h;
105 
106  h = dlopen (librpmsquirrel, RTLD_NOW|RTLD_GLOBAL);
107  if (!h)
108  {
109  rpmlog(RPMLOG_WARNING, D_("Unable to open \"%s\" (%s), "
110  "embedded squirrel will not be available\n"),
111  librpmsquirrel, dlerror());
112  }
113  else if(!((rpmsquirrelNew_p = dlsym(h, "rpmsquirrelNew"))
114  && (rpmsquirrelRunFile_p = dlsym(h, "rpmsquirrelRunFile"))
115  && (rpmsquirrelRun_p = dlsym(h, "rpmsquirrelRun")))) {
116  rpmlog(RPMLOG_WARNING, D_("Opened library \"%s\" is incompatible (%s), "
117  "embedded squirrel will not be available\n"),
118  librpmsquirrel, dlerror());
119  if (dlclose (h))
120  rpmlog(RPMLOG_WARNING, "Error closing library \"%s\": %s", librpmsquirrel,
121  dlerror());
122  } else
123  dlopened = 1;
124 }
125 #endif
126 
127 rpmsquirrel rpmsquirrelNew(char ** av, uint32_t flags)
128 {
129 #if defined(WITH_SQUIRREL)
130  if (!dlopened) loadModule();
131  if (dlopened) return rpmsquirrelNew_p(av, flags);
132 #endif
133  rpmsquirrel squirrel = (flags & 0x80000000)
134  ? rpmsquirrelI() : rpmsquirrelGetPool(_rpmsquirrelPool);
135 
136 #if defined(MODULE_EMBED)
137  static const char * _av[] = { "rpmsquirrel", NULL };
138  SQInteger stacksize = 1024;
139  HSQUIRRELVM v = sq_open(stacksize);
140  int ac;
141 
142  if (av == NULL) av = _av;
143  ac = argvCount(av);
144 
145  squirrel->I = v;
146  sq_setforeignptr(v, squirrel);
147  sq_setprintfunc(v, rpmsquirrelPrint);
148 
149 #ifdef NOTYET
150  { int i;
151  sq_pushroottable(v);
152  sc_pushstring(v, "ARGS", -1);
153  sq_newarray(v, 0);
154  for (i = 0, i < ac; i++) {
155  sq_pushstring(v, av[i], -1);
156  sq_arrayappend(v, -2);
157  }
158  sq_createslot(v, -3);
159  sq_pop(v, 1);
160  }
161 #endif
162 #endif
163 #if !defined(WITH_SQUIRREL)
164  squirrel->iob = rpmiobNew(0);
165 #endif
166 
167  return rpmsquirrelLink(squirrel);
168 }
169 
170 rpmRC rpmsquirrelRunFile(rpmsquirrel squirrel, const char * fn, const char ** resultp)
171 {
172 #if defined(WITH_SQUIRREL)
173  if (dlopened) return rpmsquirrelRunFile_p(squirrel, fn, resultp);
174 #endif
175  rpmRC rc = RPMRC_FAIL;
176 
178 fprintf(stderr, "==> %s(%p,%s)\n", __FUNCTION__, squirrel, fn);
179 
180  if (squirrel == NULL) squirrel = rpmsquirrelI();
181 
182 #if defined(NOTYET)
183  if (fn != NULL && Tcl_EvalFile((Tcl_Interp *)squirrel->I, fn) == SQUIRREL_OK) {
184  rc = RPMRC_OK;
185  if (resultp)
186  *resultp = rpmiobStr(squirrel->iob);
187  }
188 #endif
189  return rc;
190 }
191 
192 rpmRC rpmsquirrelRun(rpmsquirrel squirrel, const char * str, const char ** resultp)
193 {
194 #if defined(WITH_SQUIRREL)
195  if (dlopened) return rpmsquirrelRun_p(squirrel, str, resultp);
196 #endif
197 
198  rpmRC rc = RPMRC_FAIL;
199 
201 fprintf(stderr, "==> %s(%p,%s)\n", __FUNCTION__, squirrel, str);
202 
203  if (squirrel == NULL) squirrel = rpmsquirrelI();
204 
205 #if defined(MODULE_EMBED)
206  if (str != NULL) {
207  size_t ns = strlen(str);
208  if (ns > 0) {
209  HSQUIRRELVM v = squirrel->I;
210  SQBool raise = SQFalse;
211  SQInteger oldtop = sq_gettop(v);
212  SQRESULT res = sq_compilebuffer(v, str, ns, __FUNCTION__, raise);
213 
214  if (SQ_SUCCEEDED(res)) {
215  SQInteger retval = 0;
216  sq_pushroottable(v);
217  res = sq_call(v, 1, retval, raise);
218  }
219 
220  sq_settop(v, oldtop);
221  }
222  rc = RPMRC_OK;
223  if (resultp)
224  *resultp = rpmiobStr(squirrel->iob);
225  }
226 #endif
227  return rc;
228 }