rpm  5.4.10
rpmruby.c
Go to the documentation of this file.
1 #include "system.h"
2 #include <argv.h>
3 
4 #if defined(MODULE_EMBED)
5 
6 /* Make sure Ruby's fun stuff has its own xmalloc & Co functions available */
7 #undef xmalloc
8 #undef xcalloc
9 #undef xrealloc
10 
11 /* XXX avoid conflicting definitions in ruby.h */
12 #define HAVE_SETPROCTITLE 1
13 
14 #include <ruby.h>
15 #undef WITH_RUBYEMBED
16 
17 #endif
18 
19 #if defined(WITH_RUBYEMBED)
20 #include <dlfcn.h>
21 #include <rpmlog.h>
22 #endif
23 
24 #define _RPMRUBY_INTERNAL 1
25 #include "rpmruby.h"
26 
27 #include "debug.h"
28 
29 /*@unchecked@*/
31 
32 /*@unchecked@*/ /*@relnull@*/
34 
38 static void rpmrubyFini(void *_ruby)
39  /*@globals fileSystem @*/
40  /*@modifies *_ruby, fileSystem @*/
41 {
42  rpmruby ruby = (rpmruby) _ruby;
43 
44 # if defined(MODULE_EMBED)
45  ruby_cleanup(0);
46 #endif
47  ruby->I = NULL;
48 }
49 
54 /*@unchecked@*/ /*@only@*/ /*@null@*/
56 
67 static rpmruby rpmrubyGetPool(/*@null@*/ rpmioPool pool)
68  /*@globals _rpmrubyPool, fileSystem @*/
69  /*@modifies pool, _rpmrubyPool, fileSystem @*/
70 {
71  rpmruby ruby;
72 
73  if (_rpmrubyPool == NULL) {
74  _rpmrubyPool = rpmioNewPool("ruby", sizeof(*ruby), -1, _rpmruby_debug,
75  NULL, NULL, rpmrubyFini);
76  pool = _rpmrubyPool;
77  }
78 
79  return (rpmruby) rpmioGetPool(pool, sizeof(*ruby));
80 }
81 
82 #if defined(WITH_RUBYEMBED)
83 
84 /*@unchecked@*/
85 static const char * rpmrubyInitStringIO = "\
86 require 'stringio'\n\
87 $stdout = StringIO.new($result, \"w+\")\n\
88 ";
89 #endif
90 
91 static rpmruby rpmrubyI()
92  /*@globals _rpmrubyI @*/
93  /*@modifies _rpmrubyI @*/
94 {
95  if (_rpmrubyI == NULL)
96  _rpmrubyI = rpmrubyNew(NULL, 0);
97  return _rpmrubyI;
98 }
99 
100 #if defined(WITH_RUBYEMBED)
101 static void loadModule(void) {
102  const char librpmruby[] = "rpmruby.so";
103  void *h;
104 
105  h = dlopen (librpmruby, RTLD_NOW|RTLD_GLOBAL);
106  if (!h)
107  {
108  rpmlog(RPMLOG_WARNING, D_("Unable to open \"%s\" (%s), "
109  "embedded ruby will not be available\n"),
110  librpmruby, dlerror());
111  }
112  else if(!((rpmrubyNew_p = dlsym(h, "rpmrubyNew"))
113  && (rpmrubyRun_p = dlsym(h, "rpmrubyRun")))) {
114  rpmlog(RPMLOG_WARNING, D_("Opened library \"%s\" is incompatible (%s), "
115  "embedded ruby will not be available\n"),
116  librpmruby, dlerror());
117  if (dlclose (h))
118  rpmlog(RPMLOG_WARNING, "Error closing library \"%s\": %s", librpmruby,
119  dlerror());
120  } else
121  dlopened = 1;
122 }
123 #endif
124 
125 rpmruby rpmrubyNew(char **av, uint32_t flags)
126 {
127 #if defined(WITH_RUBYEMBED)
128  if (!dlopened) loadModule();
129  if (dlopened) return rpmrubyNew_p(av, flags);
130 #endif
131 
132  static const char *_av[] = { "rpmruby", NULL };
133 
134  /* XXX FIXME: recurse like every other embedded interpreter. */
135  if (_rpmrubyI)
136  return _rpmrubyI;
137 
138  rpmruby ruby = (flags & 0x80000000)
139  ? rpmrubyI() : rpmrubyGetPool(_rpmrubyPool);
140 
141  if (av == NULL)
142  av = (char **) _av;
143 
144 # if defined(MODULE_EMBED)
145  RUBY_INIT_STACK;
146  ruby_init();
147  ruby_init_loadpath();
148 
149  ruby_script((char *)av[0]);
150  rb_gv_set("$result", rb_str_new2(""));
151  (void) rpmrubyRun(ruby, rpmrubyInitStringIO, NULL);
152 #endif
153 
154  return rpmrubyLink(ruby);
155 }
156 
157 #if defined(WITH_RUBYEMBED)
158 static int dlopened = 0;
159 static rpmruby (*rpmrubyNew_p) (char ** av, uint32_t flags);
160 static rpmRC (*rpmrubyRun_p) (rpmruby ruby, const char * str, const char ** resultp);
161 #endif
162 
163 rpmRC rpmrubyRun(rpmruby ruby, const char *str, const char **resultp)
164 {
165 #if defined(WITH_RUBYEMBED)
166  if (dlopened) return rpmrubyRun_p(ruby, str, resultp);
167 #endif
168 
169  rpmRC rc = RPMRC_FAIL;
170 
171 if (_rpmruby_debug)
172 fprintf(stderr, "==> %s(%p,%s,%p)\n", __FUNCTION__, ruby, str, resultp);
173 
174  if (ruby == NULL)
175  ruby = rpmrubyI();
176 
177 #if defined(MODULE_EMBED)
178  if (str) {
179  int state = -1;
180  ruby->state = rb_eval_string_protect(str, &state);
181 
182  /* Check whether the evaluation was successful or not */
183 
184  if (state == 0) {
185  rc = RPMRC_OK;
186  if (resultp)
187  *resultp = RSTRING_PTR(rb_gv_get("$result"));
188  }
189  }
190 #endif
191 
192  return rc;
193 }
194