rpm 5.3.12
|
00001 #include "system.h" 00002 00003 #if defined(WITH_RUBYEMBED) 00004 /* XXX ruby-1.8.6 grrr, ruby.h includes its own config.h too. */ 00005 #ifdef HAVE_CONFIG_H 00006 #include "config.h" 00007 #endif 00008 #undef PACKAGE_NAME 00009 #undef PACKAGE_TARNAME 00010 #undef PACKAGE_VERSION 00011 #undef PACKAGE_STRING 00012 #undef PACKAGE_BUGREPORT 00013 00014 #undef xmalloc 00015 #undef xcalloc 00016 #undef xrealloc 00017 #pragma GCC diagnostic ignored "-Wstrict-prototypes" 00018 #include <ruby.h> 00019 #pragma GCC diagnostic warning "-Wstrict-prototypes" 00020 00021 #if !defined(RSTRING_PTR) 00022 /* XXX retrofit for ruby-1.8.5 in CentOS5 */ 00023 #define RSTRING_PTR(s) (RSTRING(s)->ptr) 00024 #define RSTRING_LEN(s) (RSTRING(s)->len) 00025 #endif 00026 00027 #endif 00028 00029 #define _RPMRUBY_INTERNAL 00030 #include "rpmruby.h" 00031 00032 #include "debug.h" 00033 00034 /*@unchecked@*/ 00035 int _rpmruby_debug = 0; 00036 00037 /*@unchecked@*/ /*@relnull@*/ 00038 rpmruby _rpmrubyI = NULL; 00039 00040 /*==============================================================*/ 00041 #if defined(HAVE_RUBY_DEFINES_H) /* XXX ruby-1.9.2p0 */ 00042 /* puts the Ruby coroutine in control */ 00043 static void _rpmruby_main_to_ruby(rpmruby ruby) 00044 { 00045 rpmzLog zlog = ruby->zlog; 00046 00047 yarnRelease(ruby->ruby_coroutine_lock); 00048 yarnPossess(ruby->main_coroutine_lock); 00049 if (_rpmruby_debug < 0) Trace((zlog, "-> %s", __FUNCTION__)); 00050 } 00051 00052 /* puts the main C program in control */ 00053 static unsigned long _rpmruby_ruby_to_main(rpmruby ruby, unsigned long self) 00054 { 00055 rpmzLog zlog = ruby->zlog; 00056 00057 yarnRelease(ruby->main_coroutine_lock); 00058 yarnPossess(ruby->ruby_coroutine_lock); 00059 if (_rpmruby_debug < 0) Trace((zlog, "<- %s", __FUNCTION__)); 00060 return Qnil; 00061 } 00062 00063 /* Using _rpmrubyI, puts the main C program in control */ 00064 static VALUE relay_from_ruby_to_main(VALUE self) 00065 { 00066 /* XXX FIXME: _rpmrubyI is global */ 00067 return _rpmruby_ruby_to_main(_rpmrubyI, self); 00068 } 00069 00070 static rpmRC rpmrubyRunThreadFile(rpmruby ruby, const char * fn, 00071 const char **resultp) 00072 { 00073 int error; 00074 VALUE result; 00075 rpmRC rc = RPMRC_FAIL; /* assume failure */ 00076 00077 result = rb_protect((VALUE (*)(VALUE))rb_require, (VALUE)fn, &error); 00078 if (error) { 00079 fprintf(stderr, "rb_require('%s') failed with status=%d\n", 00080 fn, error); 00081 00082 VALUE exception = rb_gv_get("$!"); 00083 if (RTEST(exception)) { 00084 fprintf(stderr, "... because an exception was raised:\n"); 00085 00086 VALUE inspect = rb_inspect(exception); 00087 rb_io_puts(1, &inspect, rb_stderr); 00088 00089 VALUE backtrace = rb_funcall( 00090 exception, rb_intern("backtrace"), 0); 00091 rb_io_puts(1, &backtrace, rb_stderr); 00092 } 00093 } else { 00094 /* XXX FIXME: check result */ 00095 rc = RPMRC_OK; 00096 } 00097 00098 return rc; 00099 } 00100 00101 static void * rpmrubyThread(void * _ruby) 00102 { 00103 rpmruby ruby = _ruby; 00104 rpmzLog zlog = ruby->zlog; 00105 int i; 00106 00107 Trace((zlog, "-- %s: running", __FUNCTION__)); 00108 00109 _rpmruby_ruby_to_main(ruby, Qnil); 00110 00111 for (i = 0; i < 2; i++) 00112 _rpmruby_ruby_to_main(ruby, Qnil); 00113 00114 { 00115 VALUE variable_in_this_stack_frame; 00116 uint8_t * b = ruby->stack; 00117 uint8_t * e = b + ruby->nstack; 00118 00119 /* Start up the ruby interpreter. */ 00120 Trace((zlog, "-- %s: interpreter starting", __FUNCTION__)); 00121 ruby_sysinit(&ruby->ac, (char ***) &ruby->av); 00122 00123 ruby_bind_stack((VALUE *)b, (VALUE *)e); 00124 00125 ruby_init_stack(&variable_in_this_stack_frame); 00126 ruby_init(); 00127 ruby_init_loadpath(); 00128 00129 /* allow Ruby script to relay */ 00130 rb_define_module_function(rb_mKernel, "relay_from_ruby_to_main", 00131 relay_from_ruby_to_main, 0); 00132 Trace((zlog, "-- %s: interpreter started", __FUNCTION__)); 00133 00134 /* Run file.rb arguments. */ 00135 for (i = 1; i < ruby->ac; i++) { 00136 if (*ruby->av[i] == '-') /* XXX FIXME: skip options. */ 00137 continue; 00138 Trace((zlog, "-- %s: require '%s' begin", __FUNCTION__, ruby->av[i])); 00139 rpmrubyRunThreadFile(ruby, ruby->av[i], NULL); 00140 Trace((zlog, "-- %s: require '%s' end", __FUNCTION__, ruby->av[i])); 00141 } 00142 00143 /* Terminate the ruby interpreter. */ 00144 Trace((zlog, "-- %s: interpreter terminating", __FUNCTION__)); 00145 ruby_finalize(); 00146 ruby_cleanup(0); 00147 Trace((zlog, "-- %s: interpreter terminated", __FUNCTION__)); 00148 } 00149 00150 /* Report interpreter end to main. */ 00151 ruby->more = 0; 00152 /* Permit main thread to run without blocking. */ 00153 yarnRelease(ruby->main_coroutine_lock); 00154 00155 Trace((zlog, "-- %s: ended", __FUNCTION__)); 00156 return NULL; 00157 } 00158 #endif /* HAVE_RUBY_DEFINES_H */ 00159 00160 int rpmrubyRunThread(rpmruby ruby) 00161 { 00162 int ec = 0; 00163 00164 #if defined(HAVE_RUBY_DEFINES_H) /* XXX ruby-1.9.2p0 */ 00165 yarnPossess(ruby->ruby_coroutine_lock); 00166 yarnPossess(ruby->main_coroutine_lock); 00167 00168 /* create a thread to house Ruby */ 00169 ruby->thread = yarnLaunchStack((void (*)(void *))rpmrubyThread, ruby, 00170 ruby->stack, ruby->nstack); 00171 assert(ruby->thread != NULL); 00172 00173 /* Relay control to ruby until nothing more to do. */ 00174 ruby->more = (ruby->ac > 1); 00175 while (ruby->more) 00176 _rpmruby_main_to_ruby(ruby); 00177 00178 /* Permit ruby thread to run without blocking. */ 00179 yarnRelease(ruby->ruby_coroutine_lock); 00180 /* Reap the ruby thread. */ 00181 ruby->thread = yarnJoin(ruby->thread); 00182 ec = 0; 00183 #endif /* HAVE_RUBY_DEFINES_H */ 00184 00185 return ec; 00186 } 00187 00188 /*==============================================================*/ 00189 00190 static void rpmrubyFini(void * _ruby) 00191 /*@globals fileSystem @*/ 00192 /*@modifies *_ruby, fileSystem @*/ 00193 { 00194 rpmruby ruby = _ruby; 00195 00196 /* XXX FIXME: 0x40000000 => xruby.c wrapper without interpreter. */ 00197 if (ruby->flags & 0x40000000) { 00198 ruby->main_coroutine_lock = yarnFreeLock(ruby->main_coroutine_lock); 00199 ruby->ruby_coroutine_lock = yarnFreeLock(ruby->ruby_coroutine_lock); 00200 ruby->zlog = rpmzLogDump(ruby->zlog, NULL); 00201 ruby->stack = _free(ruby->stack); 00202 ruby->nstack = 0; 00203 _rpmrubyI = NULL; 00204 } else { 00205 #if defined(WITH_RUBYEMBED) 00206 ruby_finalize(); 00207 ruby_cleanup(0); 00208 #endif 00209 } 00210 ruby->I = NULL; 00211 ruby->flags = 0; 00212 ruby->av = argvFree(ruby->av); 00213 ruby->ac = 0; 00214 } 00215 00216 /*@unchecked@*/ /*@only@*/ /*@null@*/ 00217 rpmioPool _rpmrubyPool; 00218 00219 static rpmruby rpmrubyGetPool(/*@null@*/ rpmioPool pool) 00220 /*@globals _rpmrubyPool, fileSystem @*/ 00221 /*@modifies pool, _rpmrubyPool, fileSystem @*/ 00222 { 00223 rpmruby ruby; 00224 00225 if (_rpmrubyPool == NULL) { 00226 _rpmrubyPool = rpmioNewPool("ruby", sizeof(*ruby), -1, _rpmruby_debug, 00227 NULL, NULL, rpmrubyFini); 00228 pool = _rpmrubyPool; 00229 } 00230 return (rpmruby) rpmioGetPool(pool, sizeof(*ruby)); 00231 } 00232 00233 /*@unchecked@*/ 00234 #if defined(WITH_RUBYEMBED) && !defined(HAVE_RUBY_DEFINES_H)/* XXX ruby-1.8.6 */ 00235 static const char * rpmrubyInitStringIO = "\ 00236 require 'stringio'\n\ 00237 $stdout = StringIO.new($result, \"w+\")\n\ 00238 "; 00239 #endif 00240 00241 static rpmruby rpmrubyI(void) 00242 /*@globals _rpmrubyI @*/ 00243 /*@modifies _rpmrubyI @*/ 00244 { 00245 /* XXX FIXME: pass 0x40000000 for wrapper without interpreter? */ 00246 if (_rpmrubyI == NULL) 00247 _rpmrubyI = rpmrubyNew(NULL, 0); 00248 RUBYDBG((stderr, "<-- %s() I %p\n", __FUNCTION__, _rpmrubyI)); 00249 return _rpmrubyI; 00250 } 00251 00252 rpmruby rpmrubyNew(char ** av, uint32_t flags) 00253 { 00254 static char * _av[] = { "rpmruby", NULL }; 00255 rpmruby ruby = (flags & 0x80000000) 00256 ? rpmrubyI() : rpmrubyGetPool(_rpmrubyPool); 00257 int xx; 00258 00259 RUBYDBG((stderr, "--> %s(%p,0x%x) ruby %p\n", __FUNCTION__, av, flags, ruby)); 00260 00261 /* If failure, or retrieving already initialized _rpmrubyI, just exit. */ 00262 if (ruby == NULL || ruby == _rpmrubyI) 00263 goto exit; 00264 00265 if (av == NULL) av = _av; 00266 00267 ruby->flags = flags; 00268 xx = argvAppend(&ruby->av, (ARGV_t)av); 00269 ruby->ac = argvCount(ruby->av); 00270 00271 /* XXX FIXME: 0x40000000 => xruby.c wrapper without interpreter. */ 00272 if (ruby->flags & 0x40000000) { 00273 static size_t _rpmrubyStackSize = 4 * 1024 * 1024; 00274 00275 /* XXX save as global interpreter. */ 00276 _rpmrubyI = ruby; 00277 00278 ruby->nstack = _rpmrubyStackSize; 00279 ruby->stack = malloc(ruby->nstack); 00280 assert(ruby->stack != NULL); 00281 00282 gettimeofday(&ruby->start, NULL); /* starting time for log entries */ 00283 if (_rpmruby_debug) 00284 ruby->zlog = rpmzLogNew(&ruby->start); /* initialize logging */ 00285 00286 /* initialize the relay mechanism */ 00287 ruby->ruby_coroutine_lock = yarnNewLock(0); 00288 ruby->main_coroutine_lock = yarnNewLock(0); 00289 00290 } else { 00291 00292 #if defined(WITH_RUBYEMBED) 00293 VALUE variable_in_this_stack_frame; /* RUBY_INIT_STSCK */ 00294 00295 #if defined(HAVE_RUBY_DEFINES_H) /* XXX ruby-1.9.2 */ 00296 ruby_sysinit(&ruby->ac, (char ***) &ruby->av); 00297 /* XXX ruby-1.9.2p0 ruby_bind_stack() patch needed */ 00298 { 00299 uint8_t * b = ruby->stack; 00300 uint8_t * e = b + ruby->nstack; 00301 ruby_bind_stack((VALUE *)b, (VALUE *) e); 00302 } 00303 #endif /* NOTYET */ 00304 00305 ruby_init_stack(&variable_in_this_stack_frame); /* RUBY_INIT_STACK */ 00306 00307 ruby_init(); 00308 ruby_init_loadpath(); 00309 00310 ruby_script((char *)av[0]); 00311 if (av[1]) 00312 ruby_set_argv(argvCount((ARGV_t)av)-1, av+1); 00313 00314 rb_gv_set("$result", rb_str_new2("")); 00315 #if !defined(HAVE_RUBY_DEFINES_H) /* XXX ruby-1.8.6 */ 00316 (void) rpmrubyRun(ruby, rpmrubyInitStringIO, NULL); 00317 #endif 00318 #endif /* WITH_RUBYEMBED */ 00319 } 00320 00321 exit: 00322 return rpmrubyLink(ruby); 00323 } 00324 00325 rpmRC rpmrubyRunFile(rpmruby ruby, const char * fn, const char ** resultp) 00326 { 00327 rpmRC rc = RPMRC_FAIL; 00328 00329 RUBYDBG((stderr, "--> %s(%p,%s,%p)\n", __FUNCTION__, ruby, fn, resultp)); 00330 00331 if (ruby == NULL) ruby = rpmrubyI(); 00332 00333 if (fn == NULL) 00334 goto exit; 00335 00336 #if defined(WITH_RUBYEMBED) 00337 #if !defined(HAVE_RUBY_DEFINES_H) /* XXX ruby-1.8.6 */ 00338 rb_load_file(fn); 00339 ruby->state = ruby_exec(); 00340 #else 00341 ruby->state = ruby_exec_node(rb_load_file(fn)); 00342 #endif 00343 if (resultp != NULL) 00344 *resultp = RSTRING_PTR(rb_gv_get("$result")); 00345 rc = RPMRC_OK; 00346 #endif /* WITH_RUBYEMBED */ 00347 00348 exit: 00349 RUBYDBG((stderr, "<-- %s(%p,%s,%p) rc %d\n", __FUNCTION__, ruby, fn, resultp, rc)); 00350 return rc; 00351 } 00352 00353 rpmRC rpmrubyRun(rpmruby ruby, const char * str, const char ** resultp) 00354 { 00355 rpmRC rc = RPMRC_FAIL; 00356 00357 RUBYDBG((stderr, "--> %s(%p,%s,%p)\n", __FUNCTION__, ruby, str, resultp)); 00358 00359 if (ruby == NULL) ruby = rpmrubyI(); 00360 00361 if (str == NULL) 00362 goto exit; 00363 00364 #if defined(WITH_RUBYEMBED) 00365 ruby->state = rb_eval_string(str); 00366 if (resultp != NULL) 00367 *resultp = RSTRING_PTR(rb_gv_get("$result")); 00368 rc = RPMRC_OK; 00369 #endif 00370 00371 exit: 00372 RUBYDBG((stderr, "<-- %s(%p,%s,%p) rc %d\n", __FUNCTION__, ruby, str, resultp, rc)); 00373 return rc; 00374 }