00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifdef __CYGWIN__
00015 #include <windows.h>
00016 #include <sys/cygwin.h>
00017 #endif
00018 #include "ruby/ruby.h"
00019 #include "ruby/encoding.h"
00020 #include "internal.h"
00021 #include "eval_intern.h"
00022 #include "dln.h"
00023 #include <stdio.h>
00024 #include <sys/types.h>
00025 #include <ctype.h>
00026
00027 #ifdef __hpux
00028 #include <sys/pstat.h>
00029 #endif
00030 #if defined(LOAD_RELATIVE) && defined(HAVE_DLADDR)
00031 #include <dlfcn.h>
00032 #endif
00033
00034 #ifdef HAVE_UNISTD_H
00035 #include <unistd.h>
00036 #endif
00037 #if defined(HAVE_FCNTL_H)
00038 #include <fcntl.h>
00039 #elif defined(HAVE_SYS_FCNTL_H)
00040 #include <sys/fcntl.h>
00041 #endif
00042 #ifdef HAVE_SYS_PARAM_H
00043 # include <sys/param.h>
00044 #endif
00045 #ifndef MAXPATHLEN
00046 # define MAXPATHLEN 1024
00047 #endif
00048
00049 #include "ruby/util.h"
00050
00051 #ifndef HAVE_STDLIB_H
00052 char *getenv();
00053 #endif
00054
00055 #define DISABLE_BIT(bit) (1U << disable_##bit)
00056 enum disable_flag_bits {
00057 disable_gems,
00058 disable_rubyopt,
00059 disable_flag_count
00060 };
00061
00062 #define DUMP_BIT(bit) (1U << dump_##bit)
00063 enum dump_flag_bits {
00064 dump_version,
00065 dump_copyright,
00066 dump_usage,
00067 dump_yydebug,
00068 dump_syntax,
00069 dump_parsetree,
00070 dump_parsetree_with_comment,
00071 dump_insns,
00072 dump_flag_count
00073 };
00074
00075 struct cmdline_options {
00076 int sflag, xflag;
00077 int do_loop, do_print;
00078 int do_line, do_split;
00079 int do_search;
00080 unsigned int disable;
00081 int verbose;
00082 int safe_level;
00083 unsigned int setids;
00084 unsigned int dump;
00085 const char *script;
00086 VALUE script_name;
00087 VALUE e_script;
00088 struct {
00089 struct {
00090 VALUE name;
00091 int index;
00092 } enc;
00093 } src, ext, intern;
00094 VALUE req_list;
00095 };
00096
00097 static void init_ids(struct cmdline_options *);
00098
00099 #define src_encoding_index GET_VM()->src_encoding_index
00100
00101 static struct cmdline_options *
00102 cmdline_options_init(struct cmdline_options *opt)
00103 {
00104 MEMZERO(opt, *opt, 1);
00105 init_ids(opt);
00106 opt->src.enc.index = src_encoding_index;
00107 opt->ext.enc.index = -1;
00108 opt->intern.enc.index = -1;
00109 #if defined DISABLE_RUBYGEMS && DISABLE_RUBYGEMS
00110 opt->disable |= DISABLE_BIT(gems);
00111 #endif
00112 return opt;
00113 }
00114
00115 static NODE *load_file(VALUE, const char *, int, struct cmdline_options *);
00116 static void forbid_setid(const char *, struct cmdline_options *);
00117 #define forbid_setid(s) forbid_setid((s), opt)
00118
00119 static struct {
00120 int argc;
00121 char **argv;
00122 } origarg;
00123
00124 static void
00125 usage(const char *name)
00126 {
00127
00128
00129
00130 static const char *const usage_msg[] = {
00131 "-0[octal] specify record separator (\\0, if no argument)",
00132 "-a autosplit mode with -n or -p (splits $_ into $F)",
00133 "-c check syntax only",
00134 "-Cdirectory cd to directory, before executing your script",
00135 "-d set debugging flags (set $DEBUG to true)",
00136 "-e 'command' one line of script. Several -e's allowed. Omit [programfile]",
00137 "-Eex[:in] specify the default external and internal character encodings",
00138 "-Fpattern split() pattern for autosplit (-a)",
00139 "-i[extension] edit ARGV files in place (make backup if extension supplied)",
00140 "-Idirectory specify $LOAD_PATH directory (may be used more than once)",
00141 "-l enable line ending processing",
00142 "-n assume 'while gets(); ... end' loop around your script",
00143 "-p assume loop like -n but print line also like sed",
00144 "-rlibrary require the library, before executing your script",
00145 "-s enable some switch parsing for switches after script name",
00146 "-S look for the script using PATH environment variable",
00147 "-T[level=1] turn on tainting checks",
00148 "-v print version number, then turn on verbose mode",
00149 "-w turn warnings on for your script",
00150 "-W[level=2] set warning level; 0=silence, 1=medium, 2=verbose",
00151 "-x[directory] strip off text before #!ruby line and perhaps cd to directory",
00152 "--copyright print the copyright",
00153 "--version print the version",
00154 NULL
00155 };
00156 const char *const *p = usage_msg;
00157
00158 printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name);
00159 while (*p)
00160 printf(" %s\n", *p++);
00161 }
00162
00163 #ifdef MANGLED_PATH
00164 static VALUE
00165 rubylib_mangled_path(const char *s, unsigned int l)
00166 {
00167 static char *newp, *oldp;
00168 static int newl, oldl, notfound;
00169 char *ptr;
00170 VALUE ret;
00171
00172 if (!newp && !notfound) {
00173 newp = getenv("RUBYLIB_PREFIX");
00174 if (newp) {
00175 oldp = newp = strdup(newp);
00176 while (*newp && !ISSPACE(*newp) && *newp != ';') {
00177 newp = CharNext(newp);
00178 }
00179 oldl = newp - oldp;
00180 while (*newp && (ISSPACE(*newp) || *newp == ';')) {
00181 newp = CharNext(newp);
00182 }
00183 newl = strlen(newp);
00184 if (newl == 0 || oldl == 0) {
00185 rb_fatal("malformed RUBYLIB_PREFIX");
00186 }
00187 translit_char(newp, '\\', '/');
00188 }
00189 else {
00190 notfound = 1;
00191 }
00192 }
00193 if (!newp || l < oldl || STRNCASECMP(oldp, s, oldl) != 0) {
00194 return rb_str_new(s, l);
00195 }
00196 ret = rb_str_new(0, l + newl - oldl);
00197 ptr = RSTRING_PTR(ret);
00198 memcpy(ptr, newp, newl);
00199 memcpy(ptr + newl, s + oldl, l - oldl);
00200 ptr[l + newl - oldl] = 0;
00201 return ret;
00202 }
00203 #else
00204 #define rubylib_mangled_path rb_str_new
00205 #endif
00206
00207 static void
00208 push_include(const char *path, VALUE (*filter)(VALUE))
00209 {
00210 const char sep = PATH_SEP_CHAR;
00211 const char *p, *s;
00212 VALUE load_path = GET_VM()->load_path;
00213
00214 p = path;
00215 while (*p) {
00216 while (*p == sep)
00217 p++;
00218 if (!*p) break;
00219 for (s = p; *s && *s != sep; s = CharNext(s));
00220 rb_ary_push(load_path, (*filter)(rubylib_mangled_path(p, s - p)));
00221 p = s;
00222 }
00223 }
00224
00225 #ifdef __CYGWIN__
00226 static void
00227 push_include_cygwin(const char *path, VALUE (*filter)(VALUE))
00228 {
00229 const char *p, *s;
00230 char rubylib[FILENAME_MAX];
00231 VALUE buf = 0;
00232
00233 p = path;
00234 while (*p) {
00235 unsigned int len;
00236 while (*p == ';')
00237 p++;
00238 if (!*p) break;
00239 for (s = p; *s && *s != ';'; s = CharNext(s));
00240 len = s - p;
00241 if (*s) {
00242 if (!buf) {
00243 buf = rb_str_new(p, len);
00244 p = RSTRING_PTR(buf);
00245 }
00246 else {
00247 rb_str_resize(buf, len);
00248 p = strncpy(RSTRING_PTR(buf), p, len);
00249 }
00250 }
00251 #ifdef HAVE_CYGWIN_CONV_PATH
00252 #define CONV_TO_POSIX_PATH(p, lib) \
00253 cygwin_conv_path(CCP_WIN_A_TO_POSIX|CCP_RELATIVE, (p), (lib), sizeof(lib))
00254 #else
00255 #define CONV_TO_POSIX_PATH(p, lib) \
00256 cygwin_conv_to_posix_path((p), (lib))
00257 #endif
00258 if (CONV_TO_POSIX_PATH(p, rubylib) == 0)
00259 p = rubylib;
00260 push_include(p, filter);
00261 if (!*s) break;
00262 p = s + 1;
00263 }
00264 }
00265
00266 #define push_include push_include_cygwin
00267 #endif
00268
00269 void
00270 ruby_push_include(const char *path, VALUE (*filter)(VALUE))
00271 {
00272 if (path == 0)
00273 return;
00274 push_include(path, filter);
00275 }
00276
00277 static VALUE
00278 identical_path(VALUE path)
00279 {
00280 return path;
00281 }
00282 static VALUE
00283 locale_path(VALUE path)
00284 {
00285 rb_enc_associate(path, rb_locale_encoding());
00286 return path;
00287 }
00288
00289 void
00290 ruby_incpush(const char *path)
00291 {
00292 ruby_push_include(path, locale_path);
00293 }
00294
00295 static VALUE
00296 expand_include_path(VALUE path)
00297 {
00298 char *p = RSTRING_PTR(path);
00299 if (!p)
00300 return path;
00301 if (*p == '.' && p[1] == '/')
00302 return path;
00303 return rb_file_expand_path(path, Qnil);
00304 }
00305
00306 void
00307 ruby_incpush_expand(const char *path)
00308 {
00309 ruby_push_include(path, expand_include_path);
00310 }
00311
00312 #if defined _WIN32 || defined __CYGWIN__
00313 static HMODULE libruby;
00314
00315 BOOL WINAPI
00316 DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
00317 {
00318 if (reason == DLL_PROCESS_ATTACH)
00319 libruby = dll;
00320 return TRUE;
00321 }
00322
00323 HANDLE
00324 rb_libruby_handle(void)
00325 {
00326 return libruby;
00327 }
00328 #endif
00329
00330 void ruby_init_loadpath_safe(int safe_level);
00331
00332 void
00333 ruby_init_loadpath(void)
00334 {
00335 ruby_init_loadpath_safe(0);
00336 }
00337
00338 void
00339 ruby_init_loadpath_safe(int safe_level)
00340 {
00341 VALUE load_path;
00342 ID id_initial_load_path_mark;
00343 extern const char ruby_initial_load_paths[];
00344 const char *paths = ruby_initial_load_paths;
00345 #if defined LOAD_RELATIVE
00346 # if defined HAVE_DLADDR || defined HAVE_CYGWIN_CONV_PATH
00347 # define VARIABLE_LIBPATH 1
00348 # else
00349 # define VARIABLE_LIBPATH 0
00350 # endif
00351 # if VARIABLE_LIBPATH
00352 char *libpath;
00353 VALUE sopath;
00354 # else
00355 char libpath[MAXPATHLEN + 1];
00356 # endif
00357 size_t baselen;
00358 char *p;
00359
00360 #if defined _WIN32 || defined __CYGWIN__
00361 # if VARIABLE_LIBPATH
00362 sopath = rb_str_new(0, MAXPATHLEN);
00363 libpath = RSTRING_PTR(sopath);
00364 GetModuleFileName(libruby, libpath, MAXPATHLEN);
00365 # else
00366 GetModuleFileName(libruby, libpath, sizeof libpath);
00367 # endif
00368 #elif defined(__EMX__)
00369 _execname(libpath, sizeof(libpath) - 1);
00370 #elif defined(HAVE_DLADDR)
00371 Dl_info dli;
00372 if (dladdr((void *)(VALUE)expand_include_path, &dli)) {
00373 char fbuf[MAXPATHLEN];
00374 char *f = dln_find_file_r(dli.dli_fname, getenv(PATH_ENV), fbuf, sizeof(fbuf));
00375 VALUE fname = rb_str_new_cstr(f ? f : dli.dli_fname);
00376 rb_str_freeze(fname);
00377 sopath = rb_realpath_internal(Qnil, fname, 1);
00378 }
00379 else {
00380 sopath = rb_str_new(0, 0);
00381 }
00382 libpath = RSTRING_PTR(sopath);
00383 #endif
00384
00385 #if !VARIABLE_LIBPATH
00386 libpath[sizeof(libpath) - 1] = '\0';
00387 #endif
00388 #if defined DOSISH
00389 translit_char(libpath, '\\', '/');
00390 #elif defined __CYGWIN__
00391 {
00392 # if VARIABLE_LIBPATH
00393 const int win_to_posix = CCP_WIN_A_TO_POSIX | CCP_RELATIVE;
00394 size_t newsize = cygwin_conv_path(win_to_posix, libpath, 0, 0);
00395 if (newsize > 0) {
00396 VALUE rubylib = rb_str_new(0, newsize);
00397 p = RSTRING_PTR(rubylib);
00398 if (cygwin_conv_path(win_to_posix, libpath, p, newsize) == 0) {
00399 rb_str_resize(sopath, 0);
00400 sopath = rubylib;
00401 libpath = p;
00402 }
00403 }
00404 # else
00405 char rubylib[FILENAME_MAX];
00406 cygwin_conv_to_posix_path(libpath, rubylib);
00407 strncpy(libpath, rubylib, sizeof(libpath));
00408 # endif
00409 }
00410 #endif
00411 p = strrchr(libpath, '/');
00412 if (p) {
00413 *p = 0;
00414 if (p - libpath > 3 && !(STRCASECMP(p - 4, "/bin") && strcmp(p - 4, "/lib"))) {
00415 p -= 4;
00416 *p = 0;
00417 }
00418 }
00419 #if !VARIABLE_LIBPATH
00420 else {
00421 strlcpy(libpath, ".", sizeof(libpath));
00422 p = libpath + 1;
00423 }
00424 baselen = p - libpath;
00425 #define PREFIX_PATH() rb_str_new(libpath, baselen)
00426 #else
00427 baselen = p - libpath;
00428 rb_str_resize(sopath, baselen);
00429 libpath = RSTRING_PTR(sopath);
00430 #define PREFIX_PATH() sopath
00431 #endif
00432
00433 #define BASEPATH() rb_str_buf_cat(rb_str_buf_new(baselen+len), libpath, baselen)
00434
00435 #define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), (path), (len))
00436 #else
00437 static const char exec_prefix[] = RUBY_EXEC_PREFIX;
00438 #define RUBY_RELATIVE(path, len) rubylib_mangled_path((path), (len))
00439 #define PREFIX_PATH() RUBY_RELATIVE(exec_prefix, sizeof(exec_prefix)-1)
00440 #endif
00441 load_path = GET_VM()->load_path;
00442
00443 if (safe_level == 0) {
00444 #ifdef MANGLED_PATH
00445 rubylib_mangled_path("", 0);
00446 #endif
00447 ruby_push_include(getenv("RUBYLIB"), identical_path);
00448 }
00449
00450 id_initial_load_path_mark = rb_intern_const("@gem_prelude_index");
00451 while (*paths) {
00452 size_t len = strlen(paths);
00453 VALUE path = RUBY_RELATIVE(paths, len);
00454 rb_ivar_set(path, id_initial_load_path_mark, path);
00455 rb_ary_push(load_path, path);
00456 paths += len + 1;
00457 }
00458
00459 rb_const_set(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"), rb_obj_freeze(PREFIX_PATH()));
00460 }
00461
00462
00463 static void
00464 add_modules(VALUE *req_list, const char *mod)
00465 {
00466 VALUE list = *req_list;
00467
00468 if (!list) {
00469 *req_list = list = rb_ary_new();
00470 RBASIC(list)->klass = 0;
00471 }
00472 rb_ary_push(list, rb_obj_freeze(rb_str_new2(mod)));
00473 }
00474
00475 static void
00476 require_libraries(VALUE *req_list)
00477 {
00478 VALUE list = *req_list;
00479 VALUE self = rb_vm_top_self();
00480 ID require;
00481 rb_thread_t *th = GET_THREAD();
00482 rb_block_t *prev_base_block = th->base_block;
00483 int prev_parse_in_eval = th->parse_in_eval;
00484 th->base_block = 0;
00485 th->parse_in_eval = 0;
00486
00487 Init_ext();
00488 CONST_ID(require, "require");
00489 while (list && RARRAY_LEN(list) > 0) {
00490 VALUE feature = rb_ary_shift(list);
00491 rb_funcall2(self, require, 1, &feature);
00492 }
00493 *req_list = 0;
00494
00495 th->parse_in_eval = prev_parse_in_eval;
00496 th->base_block = prev_base_block;
00497 }
00498
00499 static void
00500 process_sflag(int *sflag)
00501 {
00502 if (*sflag > 0) {
00503 long n;
00504 VALUE *args;
00505 VALUE argv = rb_argv;
00506
00507 n = RARRAY_LEN(argv);
00508 args = RARRAY_PTR(argv);
00509 while (n > 0) {
00510 VALUE v = *args++;
00511 char *s = StringValuePtr(v);
00512 char *p;
00513 int hyphen = FALSE;
00514
00515 if (s[0] != '-')
00516 break;
00517 n--;
00518 if (s[1] == '-' && s[2] == '\0')
00519 break;
00520
00521 v = Qtrue;
00522
00523 for (p = s + 1; *p; p++) {
00524 if (*p == '=') {
00525 *p++ = '\0';
00526 v = rb_str_new2(p);
00527 break;
00528 }
00529 if (*p == '-') {
00530 hyphen = TRUE;
00531 }
00532 else if (*p != '_' && !ISALNUM(*p)) {
00533 VALUE name_error[2];
00534 name_error[0] =
00535 rb_str_new2("invalid name for global variable - ");
00536 if (!(p = strchr(p, '='))) {
00537 rb_str_cat2(name_error[0], s);
00538 }
00539 else {
00540 rb_str_cat(name_error[0], s, p - s);
00541 }
00542 name_error[1] = args[-1];
00543 rb_exc_raise(rb_class_new_instance(2, name_error, rb_eNameError));
00544 }
00545 }
00546 s[0] = '$';
00547 if (hyphen) {
00548 for (p = s + 1; *p; ++p) {
00549 if (*p == '-')
00550 *p = '_';
00551 }
00552 }
00553 rb_gv_set(s, v);
00554 }
00555 n = RARRAY_LEN(argv) - n;
00556 while (n--) {
00557 rb_ary_shift(argv);
00558 }
00559 *sflag = -1;
00560 }
00561 }
00562
00563 static long proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt);
00564
00565 static void
00566 moreswitches(const char *s, struct cmdline_options *opt, int envopt)
00567 {
00568 long argc, i, len;
00569 char **argv, *p;
00570 const char *ap = 0;
00571 VALUE argstr, argary;
00572
00573 while (ISSPACE(*s)) s++;
00574 if (!*s) return;
00575 argstr = rb_str_tmp_new((len = strlen(s)) + 2);
00576 argary = rb_str_tmp_new(0);
00577
00578 p = RSTRING_PTR(argstr);
00579 *p++ = ' ';
00580 memcpy(p, s, len + 1);
00581 ap = 0;
00582 rb_str_cat(argary, (char *)&ap, sizeof(ap));
00583 while (*p) {
00584 ap = p;
00585 rb_str_cat(argary, (char *)&ap, sizeof(ap));
00586 while (*p && !ISSPACE(*p)) ++p;
00587 if (!*p) break;
00588 *p++ = '\0';
00589 while (ISSPACE(*p)) ++p;
00590 }
00591 argc = RSTRING_LEN(argary) / sizeof(ap);
00592 ap = 0;
00593 rb_str_cat(argary, (char *)&ap, sizeof(ap));
00594 argv = (char **)RSTRING_PTR(argary);
00595
00596 while ((i = proc_options(argc, argv, opt, envopt)) > 1 && (argc -= i) > 0) {
00597 argv += i;
00598 if (**argv != '-') {
00599 *--*argv = '-';
00600 }
00601 if ((*argv)[1]) {
00602 ++argc;
00603 --argv;
00604 }
00605 }
00606
00607
00608 rb_str_resize(argary, 0);
00609 rb_str_resize(argstr, 0);
00610 }
00611
00612 #define NAME_MATCH_P(name, str, len) \
00613 ((len) < (int)sizeof(name) && strncmp((str), (name), (len)) == 0)
00614
00615 #define UNSET_WHEN(name, bit, str, len) \
00616 if (NAME_MATCH_P((name), (str), (len))) { \
00617 *(unsigned int *)arg &= ~(bit); \
00618 return; \
00619 }
00620
00621 #define SET_WHEN(name, bit, str, len) \
00622 if (NAME_MATCH_P((name), (str), (len))) { \
00623 *(unsigned int *)arg |= (bit); \
00624 return; \
00625 }
00626
00627 static void
00628 enable_option(const char *str, int len, void *arg)
00629 {
00630 #define UNSET_WHEN_DISABLE(bit) UNSET_WHEN(#bit, DISABLE_BIT(bit), str, len)
00631 UNSET_WHEN_DISABLE(gems);
00632 UNSET_WHEN_DISABLE(rubyopt);
00633 if (NAME_MATCH_P("all", str, len)) {
00634 *(unsigned int *)arg = 0U;
00635 return;
00636 }
00637 rb_warn("unknown argument for --enable: `%.*s'", len, str);
00638 }
00639
00640 static void
00641 disable_option(const char *str, int len, void *arg)
00642 {
00643 #define SET_WHEN_DISABLE(bit) SET_WHEN(#bit, DISABLE_BIT(bit), str, len)
00644 SET_WHEN_DISABLE(gems);
00645 SET_WHEN_DISABLE(rubyopt);
00646 if (NAME_MATCH_P("all", str, len)) {
00647 *(unsigned int *)arg = ~0U;
00648 return;
00649 }
00650 rb_warn("unknown argument for --disable: `%.*s'", len, str);
00651 }
00652
00653 static void
00654 dump_option(const char *str, int len, void *arg)
00655 {
00656 #define SET_WHEN_DUMP(bit) SET_WHEN(#bit, DUMP_BIT(bit), str, len)
00657 SET_WHEN_DUMP(version);
00658 SET_WHEN_DUMP(copyright);
00659 SET_WHEN_DUMP(usage);
00660 SET_WHEN_DUMP(yydebug);
00661 SET_WHEN_DUMP(syntax);
00662 SET_WHEN_DUMP(parsetree);
00663 SET_WHEN_DUMP(parsetree_with_comment);
00664 SET_WHEN_DUMP(insns);
00665 rb_warn("don't know how to dump `%.*s',", len, str);
00666 rb_warn("but only [version, copyright, usage, yydebug, syntax, parsetree, parsetree_with_comment, insns].");
00667 }
00668
00669 static void
00670 set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen)
00671 {
00672 VALUE ename;
00673
00674 if (!elen) elen = strlen(e);
00675 ename = rb_str_new(e, elen);
00676
00677 if (*name &&
00678 rb_funcall(ename, rb_intern("casecmp"), 1, *name) != INT2FIX(0)) {
00679 rb_raise(rb_eRuntimeError,
00680 "%s already set to %s", type, RSTRING_PTR(*name));
00681 }
00682 *name = ename;
00683 }
00684
00685 #define set_internal_encoding_once(opt, e, elen) \
00686 set_option_encoding_once("default_internal", &(opt)->intern.enc.name, (e), (elen))
00687 #define set_external_encoding_once(opt, e, elen) \
00688 set_option_encoding_once("default_external", &(opt)->ext.enc.name, (e), (elen))
00689 #define set_source_encoding_once(opt, e, elen) \
00690 set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen))
00691
00692 static long
00693 proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt)
00694 {
00695 long n, argc0 = argc;
00696 const char *s;
00697
00698 if (argc == 0)
00699 return 0;
00700
00701 for (argc--, argv++; argc > 0; argc--, argv++) {
00702 const char *const arg = argv[0];
00703 if (arg[0] != '-' || !arg[1])
00704 break;
00705
00706 s = arg + 1;
00707 reswitch:
00708 switch (*s) {
00709 case 'a':
00710 if (envopt) goto noenvopt;
00711 opt->do_split = TRUE;
00712 s++;
00713 goto reswitch;
00714
00715 case 'p':
00716 if (envopt) goto noenvopt;
00717 opt->do_print = TRUE;
00718
00719 case 'n':
00720 if (envopt) goto noenvopt;
00721 opt->do_loop = TRUE;
00722 s++;
00723 goto reswitch;
00724
00725 case 'd':
00726 ruby_debug = Qtrue;
00727 ruby_verbose = Qtrue;
00728 s++;
00729 goto reswitch;
00730
00731 case 'y':
00732 if (envopt) goto noenvopt;
00733 opt->dump |= DUMP_BIT(yydebug);
00734 s++;
00735 goto reswitch;
00736
00737 case 'v':
00738 if (opt->verbose) {
00739 s++;
00740 goto reswitch;
00741 }
00742 ruby_show_version();
00743 opt->verbose = 1;
00744 case 'w':
00745 ruby_verbose = Qtrue;
00746 s++;
00747 goto reswitch;
00748
00749 case 'W':
00750 {
00751 size_t numlen;
00752 int v = 2;
00753
00754 if (*++s) {
00755 v = scan_oct(s, 1, &numlen);
00756 if (numlen == 0)
00757 v = 1;
00758 s += numlen;
00759 }
00760 switch (v) {
00761 case 0:
00762 ruby_verbose = Qnil;
00763 break;
00764 case 1:
00765 ruby_verbose = Qfalse;
00766 break;
00767 default:
00768 ruby_verbose = Qtrue;
00769 break;
00770 }
00771 }
00772 goto reswitch;
00773
00774 case 'c':
00775 if (envopt) goto noenvopt;
00776 opt->dump |= DUMP_BIT(syntax);
00777 s++;
00778 goto reswitch;
00779
00780 case 's':
00781 if (envopt) goto noenvopt;
00782 forbid_setid("-s");
00783 if (!opt->sflag) opt->sflag = 1;
00784 s++;
00785 goto reswitch;
00786
00787 case 'h':
00788 if (envopt) goto noenvopt;
00789 opt->dump |= DUMP_BIT(usage);
00790 goto switch_end;
00791
00792 case 'l':
00793 if (envopt) goto noenvopt;
00794 opt->do_line = TRUE;
00795 rb_output_rs = rb_rs;
00796 s++;
00797 goto reswitch;
00798
00799 case 'S':
00800 if (envopt) goto noenvopt;
00801 forbid_setid("-S");
00802 opt->do_search = TRUE;
00803 s++;
00804 goto reswitch;
00805
00806 case 'e':
00807 if (envopt) goto noenvopt;
00808 forbid_setid("-e");
00809 if (!*++s) {
00810 s = argv[1];
00811 argc--, argv++;
00812 }
00813 if (!s) {
00814 rb_raise(rb_eRuntimeError, "no code specified for -e");
00815 }
00816 if (!opt->e_script) {
00817 opt->e_script = rb_str_new(0, 0);
00818 if (opt->script == 0)
00819 opt->script = "-e";
00820 }
00821 rb_str_cat2(opt->e_script, s);
00822 rb_str_cat2(opt->e_script, "\n");
00823 break;
00824
00825 case 'r':
00826 forbid_setid("-r");
00827 if (*++s) {
00828 add_modules(&opt->req_list, s);
00829 }
00830 else if (argv[1]) {
00831 add_modules(&opt->req_list, argv[1]);
00832 argc--, argv++;
00833 }
00834 break;
00835
00836 case 'i':
00837 if (envopt) goto noenvopt;
00838 forbid_setid("-i");
00839 ruby_set_inplace_mode(s + 1);
00840 break;
00841
00842 case 'x':
00843 if (envopt) goto noenvopt;
00844 opt->xflag = TRUE;
00845 s++;
00846 if (*s && chdir(s) < 0) {
00847 rb_fatal("Can't chdir to %s", s);
00848 }
00849 break;
00850
00851 case 'C':
00852 case 'X':
00853 if (envopt) goto noenvopt;
00854 s++;
00855 if (!*s) {
00856 s = argv[1];
00857 argc--, argv++;
00858 }
00859 if (!s || !*s) {
00860 rb_fatal("Can't chdir");
00861 }
00862 if (chdir(s) < 0) {
00863 rb_fatal("Can't chdir to %s", s);
00864 }
00865 break;
00866
00867 case 'F':
00868 if (envopt) goto noenvopt;
00869 if (*++s) {
00870 rb_fs = rb_reg_new(s, strlen(s), 0);
00871 }
00872 break;
00873
00874 case 'E':
00875 if (!*++s && (!--argc || !(s = *++argv))) {
00876 rb_raise(rb_eRuntimeError, "missing argument for -E");
00877 }
00878 goto encoding;
00879
00880 case 'U':
00881 set_internal_encoding_once(opt, "UTF-8", 0);
00882 ++s;
00883 goto reswitch;
00884
00885 case 'K':
00886 if (*++s) {
00887 const char *enc_name = 0;
00888 switch (*s) {
00889 case 'E': case 'e':
00890 enc_name = "EUC-JP";
00891 break;
00892 case 'S': case 's':
00893 enc_name = "Windows-31J";
00894 break;
00895 case 'U': case 'u':
00896 enc_name = "UTF-8";
00897 break;
00898 case 'N': case 'n': case 'A': case 'a':
00899 enc_name = "ASCII-8BIT";
00900 break;
00901 }
00902 if (enc_name) {
00903 opt->src.enc.name = rb_str_new2(enc_name);
00904 if (!opt->ext.enc.name)
00905 opt->ext.enc.name = opt->src.enc.name;
00906 }
00907 s++;
00908 }
00909 goto reswitch;
00910
00911 case 'T':
00912 {
00913 size_t numlen;
00914 int v = 1;
00915
00916 if (*++s) {
00917 v = scan_oct(s, 2, &numlen);
00918 if (numlen == 0)
00919 v = 1;
00920 s += numlen;
00921 }
00922 if (v > opt->safe_level) opt->safe_level = v;
00923 }
00924 goto reswitch;
00925
00926 case 'I':
00927 forbid_setid("-I");
00928 if (*++s)
00929 ruby_incpush_expand(s);
00930 else if (argv[1]) {
00931 ruby_incpush_expand(argv[1]);
00932 argc--, argv++;
00933 }
00934 break;
00935
00936 case '0':
00937 if (envopt) goto noenvopt;
00938 {
00939 size_t numlen;
00940 int v;
00941 char c;
00942
00943 v = scan_oct(s, 4, &numlen);
00944 s += numlen;
00945 if (v > 0377)
00946 rb_rs = Qnil;
00947 else if (v == 0 && numlen >= 2) {
00948 rb_rs = rb_str_new2("\n\n");
00949 }
00950 else {
00951 c = v & 0xff;
00952 rb_rs = rb_str_new(&c, 1);
00953 }
00954 }
00955 goto reswitch;
00956
00957 case '-':
00958 if (!s[1] || (s[1] == '\r' && !s[2])) {
00959 argc--, argv++;
00960 goto switch_end;
00961 }
00962 s++;
00963
00964 # define is_option_end(c, allow_hyphen) \
00965 (!(c) || ((allow_hyphen) && (c) == '-') || (c) == '=')
00966 # define check_envopt(name, allow_envopt) \
00967 (((allow_envopt) || !envopt) ? (void)0 : \
00968 rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name))
00969 # define need_argument(name, s) \
00970 ((*(s)++ ? !*(s) : (!--argc || !((s) = *++argv))) ? \
00971 rb_raise(rb_eRuntimeError, "missing argument for --" name) \
00972 : (void)0)
00973 # define is_option_with_arg(name, allow_hyphen, allow_envopt) \
00974 (strncmp((name), s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], (allow_hyphen)) ? \
00975 (check_envopt(name, (allow_envopt)), s += n, need_argument(name, s), 1) : 0)
00976
00977 if (strcmp("copyright", s) == 0) {
00978 if (envopt) goto noenvopt_long;
00979 opt->dump |= DUMP_BIT(copyright);
00980 }
00981 else if (strcmp("debug", s) == 0) {
00982 ruby_debug = Qtrue;
00983 ruby_verbose = Qtrue;
00984 }
00985 else if (is_option_with_arg("enable", Qtrue, Qtrue)) {
00986 ruby_each_words(s, enable_option, &opt->disable);
00987 }
00988 else if (is_option_with_arg("disable", Qtrue, Qtrue)) {
00989 ruby_each_words(s, disable_option, &opt->disable);
00990 }
00991 else if (is_option_with_arg("encoding", Qfalse, Qtrue)) {
00992 char *p;
00993 encoding:
00994 do {
00995 # define set_encoding_part(type) \
00996 if (!(p = strchr(s, ':'))) { \
00997 set_##type##_encoding_once(opt, s, 0); \
00998 break; \
00999 } \
01000 else if (p > s) { \
01001 set_##type##_encoding_once(opt, s, p-s); \
01002 }
01003 set_encoding_part(external);
01004 if (!*(s = ++p)) break;
01005 set_encoding_part(internal);
01006 if (!*(s = ++p)) break;
01007 #if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
01008 set_encoding_part(source);
01009 if (!*(s = ++p)) break;
01010 #endif
01011 rb_raise(rb_eRuntimeError, "extra argument for %s: %s",
01012 (arg[1] == '-' ? "--encoding" : "-E"), s);
01013 # undef set_encoding_part
01014 } while (0);
01015 }
01016 else if (is_option_with_arg("internal-encoding", Qfalse, Qtrue)) {
01017 set_internal_encoding_once(opt, s, 0);
01018 }
01019 else if (is_option_with_arg("external-encoding", Qfalse, Qtrue)) {
01020 set_external_encoding_once(opt, s, 0);
01021 }
01022 #if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
01023 else if (is_option_with_arg("source-encoding", Qfalse, Qtrue)) {
01024 set_source_encoding_once(opt, s, 0);
01025 }
01026 #endif
01027 else if (strcmp("version", s) == 0) {
01028 if (envopt) goto noenvopt_long;
01029 opt->dump |= DUMP_BIT(version);
01030 }
01031 else if (strcmp("verbose", s) == 0) {
01032 opt->verbose = 1;
01033 ruby_verbose = Qtrue;
01034 }
01035 else if (strcmp("yydebug", s) == 0) {
01036 if (envopt) goto noenvopt_long;
01037 opt->dump |= DUMP_BIT(yydebug);
01038 }
01039 else if (is_option_with_arg("dump", Qfalse, Qfalse)) {
01040 ruby_each_words(s, dump_option, &opt->dump);
01041 }
01042 else if (strcmp("help", s) == 0) {
01043 if (envopt) goto noenvopt_long;
01044 opt->dump |= DUMP_BIT(usage);
01045 goto switch_end;
01046 }
01047 else {
01048 rb_raise(rb_eRuntimeError,
01049 "invalid option --%s (-h will show valid options)", s);
01050 }
01051 break;
01052
01053 case '\r':
01054 if (!s[1])
01055 break;
01056
01057 default:
01058 {
01059 if (ISPRINT(*s)) {
01060 rb_raise(rb_eRuntimeError,
01061 "invalid option -%c (-h will show valid options)",
01062 (int)(unsigned char)*s);
01063 }
01064 else {
01065 rb_raise(rb_eRuntimeError,
01066 "invalid option -\\x%02X (-h will show valid options)",
01067 (int)(unsigned char)*s);
01068 }
01069 }
01070 goto switch_end;
01071
01072 noenvopt:
01073
01074 rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: -%c", *s);
01075 break;
01076
01077 noenvopt_long:
01078 rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --%s", s);
01079 break;
01080
01081 case 0:
01082 break;
01083 # undef is_option_end
01084 # undef check_envopt
01085 # undef need_argument
01086 # undef is_option_with_arg
01087 }
01088 }
01089
01090 switch_end:
01091 return argc0 - argc;
01092 }
01093
01094 static void
01095 ruby_init_prelude(void)
01096 {
01097 Init_prelude();
01098 rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"));
01099 }
01100
01101 static int
01102 opt_enc_index(VALUE enc_name)
01103 {
01104 const char *s = RSTRING_PTR(enc_name);
01105 int i = rb_enc_find_index(s);
01106
01107 if (i < 0) {
01108 rb_raise(rb_eRuntimeError, "unknown encoding name - %s", s);
01109 }
01110 else if (rb_enc_dummy_p(rb_enc_from_index(i))) {
01111 rb_raise(rb_eRuntimeError, "dummy encoding is not acceptable - %s ", s);
01112 }
01113 return i;
01114 }
01115
01116 #define rb_progname (GET_VM()->progname)
01117 VALUE rb_argv0;
01118
01119 static VALUE
01120 false_value(void)
01121 {
01122 return Qfalse;
01123 }
01124
01125 static VALUE
01126 true_value(void)
01127 {
01128 return Qtrue;
01129 }
01130
01131 #define rb_define_readonly_boolean(name, val) \
01132 rb_define_virtual_variable((name), (val) ? true_value : false_value, 0)
01133
01134 static VALUE
01135 uscore_get(void)
01136 {
01137 VALUE line;
01138
01139 line = rb_lastline_get();
01140 if (TYPE(line) != T_STRING) {
01141 rb_raise(rb_eTypeError, "$_ value need to be String (%s given)",
01142 NIL_P(line) ? "nil" : rb_obj_classname(line));
01143 }
01144 return line;
01145 }
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157 static VALUE
01158 rb_f_sub(argc, argv)
01159 int argc;
01160 VALUE *argv;
01161 {
01162 VALUE str = rb_funcall3(uscore_get(), rb_intern("sub"), argc, argv);
01163 rb_lastline_set(str);
01164 return str;
01165 }
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178 static VALUE
01179 rb_f_gsub(argc, argv)
01180 int argc;
01181 VALUE *argv;
01182 {
01183 VALUE str = rb_funcall3(uscore_get(), rb_intern("gsub"), argc, argv);
01184 rb_lastline_set(str);
01185 return str;
01186 }
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198 static VALUE
01199 rb_f_chop(void)
01200 {
01201 VALUE str = rb_funcall3(uscore_get(), rb_intern("chop"), 0, 0);
01202 rb_lastline_set(str);
01203 return str;
01204 }
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218 static VALUE
01219 rb_f_chomp(argc, argv)
01220 int argc;
01221 VALUE *argv;
01222 {
01223 VALUE str = rb_funcall3(uscore_get(), rb_intern("chomp"), argc, argv);
01224 rb_lastline_set(str);
01225 return str;
01226 }
01227
01228 static VALUE
01229 process_options(int argc, char **argv, struct cmdline_options *opt)
01230 {
01231 NODE *tree = 0;
01232 VALUE parser;
01233 VALUE iseq;
01234 rb_encoding *enc, *lenc;
01235 const char *s;
01236 char fbuf[MAXPATHLEN];
01237 int i = (int)proc_options(argc, argv, opt, 0);
01238 rb_thread_t *th = GET_THREAD();
01239 rb_env_t *env = 0;
01240
01241 argc -= i;
01242 argv += i;
01243
01244 if (opt->dump & DUMP_BIT(usage)) {
01245 usage(origarg.argv[0]);
01246 return Qtrue;
01247 }
01248
01249 if (!(opt->disable & DISABLE_BIT(rubyopt)) &&
01250 opt->safe_level == 0 && (s = getenv("RUBYOPT"))) {
01251 VALUE src_enc_name = opt->src.enc.name;
01252 VALUE ext_enc_name = opt->ext.enc.name;
01253 VALUE int_enc_name = opt->intern.enc.name;
01254
01255 opt->src.enc.name = opt->ext.enc.name = opt->intern.enc.name = 0;
01256 moreswitches(s, opt, 1);
01257 if (src_enc_name)
01258 opt->src.enc.name = src_enc_name;
01259 if (ext_enc_name)
01260 opt->ext.enc.name = ext_enc_name;
01261 if (int_enc_name)
01262 opt->intern.enc.name = int_enc_name;
01263 }
01264
01265 if (opt->dump & DUMP_BIT(version)) {
01266 ruby_show_version();
01267 return Qtrue;
01268 }
01269 if (opt->dump & DUMP_BIT(copyright)) {
01270 ruby_show_copyright();
01271 }
01272
01273 if (opt->safe_level >= 4) {
01274 OBJ_TAINT(rb_argv);
01275 OBJ_TAINT(GET_VM()->load_path);
01276 }
01277
01278 if (!opt->e_script) {
01279 if (argc == 0) {
01280 if (opt->verbose)
01281 return Qtrue;
01282 opt->script = "-";
01283 }
01284 else {
01285 opt->script = argv[0];
01286 if (opt->script[0] == '\0') {
01287 opt->script = "-";
01288 }
01289 else if (opt->do_search) {
01290 char *path = getenv("RUBYPATH");
01291
01292 opt->script = 0;
01293 if (path) {
01294 opt->script = dln_find_file_r(argv[0], path, fbuf, sizeof(fbuf));
01295 }
01296 if (!opt->script) {
01297 opt->script = dln_find_file_r(argv[0], getenv(PATH_ENV), fbuf, sizeof(fbuf));
01298 }
01299 if (!opt->script)
01300 opt->script = argv[0];
01301 }
01302 argc--;
01303 argv++;
01304 }
01305 }
01306
01307 opt->script_name = rb_str_new_cstr(opt->script);
01308 opt->script = RSTRING_PTR(opt->script_name);
01309 #if defined DOSISH || defined __CYGWIN__
01310 translit_char(RSTRING_PTR(opt->script_name), '\\', '/');
01311 #endif
01312
01313 ruby_init_loadpath_safe(opt->safe_level);
01314 rb_enc_find_index("encdb");
01315 lenc = rb_locale_encoding();
01316 rb_enc_associate(rb_progname, lenc);
01317 rb_obj_freeze(rb_progname);
01318 parser = rb_parser_new();
01319 if (opt->dump & DUMP_BIT(yydebug)) {
01320 rb_parser_set_yydebug(parser, Qtrue);
01321 }
01322 if (opt->ext.enc.name != 0) {
01323 opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
01324 }
01325 if (opt->intern.enc.name != 0) {
01326 opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
01327 }
01328 if (opt->src.enc.name != 0) {
01329 opt->src.enc.index = opt_enc_index(opt->src.enc.name);
01330 src_encoding_index = opt->src.enc.index;
01331 }
01332 if (opt->ext.enc.index >= 0) {
01333 enc = rb_enc_from_index(opt->ext.enc.index);
01334 }
01335 else {
01336 enc = lenc;
01337 }
01338 rb_enc_set_default_external(rb_enc_from_encoding(enc));
01339 if (opt->intern.enc.index >= 0) {
01340 enc = rb_enc_from_index(opt->intern.enc.index);
01341 rb_enc_set_default_internal(rb_enc_from_encoding(enc));
01342 opt->intern.enc.index = -1;
01343 }
01344 rb_enc_associate(opt->script_name, lenc);
01345 rb_obj_freeze(opt->script_name);
01346 {
01347 long i;
01348 VALUE load_path = GET_VM()->load_path;
01349 for (i = 0; i < RARRAY_LEN(load_path); ++i) {
01350 rb_enc_associate(RARRAY_PTR(load_path)[i], lenc);
01351 }
01352 }
01353 if (!(opt->disable & DISABLE_BIT(gems))) {
01354 #if defined DISABLE_RUBYGEMS && DISABLE_RUBYGEMS
01355 rb_require("rubygems");
01356 #else
01357 rb_define_module("Gem");
01358 #endif
01359 }
01360 ruby_init_prelude();
01361 ruby_set_argv(argc, argv);
01362 process_sflag(&opt->sflag);
01363
01364 {
01365
01366 VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING"));
01367 rb_binding_t *bind;
01368
01369 GetBindingPtr(toplevel_binding, bind);
01370 GetEnvPtr(bind->env, env);
01371 }
01372
01373 #define PREPARE_PARSE_MAIN(expr) do { \
01374 th->parse_in_eval--; \
01375 th->base_block = &env->block; \
01376 expr; \
01377 th->parse_in_eval++; \
01378 th->base_block = 0; \
01379 } while (0)
01380
01381 if (opt->e_script) {
01382 VALUE progname = rb_progname;
01383 rb_encoding *eenc;
01384 if (opt->src.enc.index >= 0) {
01385 eenc = rb_enc_from_index(opt->src.enc.index);
01386 }
01387 else {
01388 eenc = lenc;
01389 }
01390 rb_enc_associate(opt->e_script, eenc);
01391 rb_vm_set_progname(rb_progname = opt->script_name);
01392 require_libraries(&opt->req_list);
01393 rb_vm_set_progname(rb_progname = progname);
01394
01395 PREPARE_PARSE_MAIN({
01396 tree = rb_parser_compile_string(parser, opt->script, opt->e_script, 1);
01397 });
01398 }
01399 else {
01400 if (opt->script[0] == '-' && !opt->script[1]) {
01401 forbid_setid("program input from stdin");
01402 }
01403
01404 PREPARE_PARSE_MAIN({
01405 tree = load_file(parser, opt->script, 1, opt);
01406 });
01407 }
01408 rb_progname = opt->script_name;
01409 rb_vm_set_progname(rb_progname);
01410 if (opt->dump & DUMP_BIT(yydebug)) return Qtrue;
01411
01412 if (opt->ext.enc.index >= 0) {
01413 enc = rb_enc_from_index(opt->ext.enc.index);
01414 }
01415 else {
01416 enc = lenc;
01417 }
01418 rb_enc_set_default_external(rb_enc_from_encoding(enc));
01419 if (opt->intern.enc.index >= 0) {
01420
01421 enc = rb_enc_from_index(opt->intern.enc.index);
01422 rb_enc_set_default_internal(rb_enc_from_encoding(enc));
01423 }
01424 else if (!rb_default_internal_encoding())
01425
01426 rb_enc_set_default_internal(Qnil);
01427 rb_stdio_set_default_encoding();
01428
01429 if (!tree) return Qfalse;
01430
01431 process_sflag(&opt->sflag);
01432 opt->xflag = 0;
01433
01434 if (opt->safe_level >= 4) {
01435 FL_UNSET(rb_argv, FL_TAINT);
01436 FL_UNSET(GET_VM()->load_path, FL_TAINT);
01437 }
01438
01439 if (opt->dump & DUMP_BIT(syntax)) {
01440 printf("Syntax OK\n");
01441 return Qtrue;
01442 }
01443
01444 if (opt->do_print) {
01445 PREPARE_PARSE_MAIN({
01446 tree = rb_parser_append_print(parser, tree);
01447 });
01448 }
01449 if (opt->do_loop) {
01450 PREPARE_PARSE_MAIN({
01451 tree = rb_parser_while_loop(parser, tree, opt->do_line, opt->do_split);
01452 });
01453 rb_define_global_function("sub", rb_f_sub, -1);
01454 rb_define_global_function("gsub", rb_f_gsub, -1);
01455 rb_define_global_function("chop", rb_f_chop, 0);
01456 rb_define_global_function("chomp", rb_f_chomp, -1);
01457 }
01458
01459 if (opt->dump & DUMP_BIT(parsetree) || opt->dump & DUMP_BIT(parsetree_with_comment)) {
01460 rb_io_write(rb_stdout, rb_parser_dump_tree(tree, opt->dump & DUMP_BIT(parsetree_with_comment)));
01461 rb_io_flush(rb_stdout);
01462 return Qtrue;
01463 }
01464
01465 PREPARE_PARSE_MAIN({
01466 VALUE path = Qnil;
01467 if (!opt->e_script && strcmp(opt->script, "-"))
01468 path = rb_realpath_internal(Qnil, opt->script_name, 1);
01469 iseq = rb_iseq_new_main(tree, opt->script_name, path);
01470 });
01471
01472 if (opt->dump & DUMP_BIT(insns)) {
01473 rb_io_write(rb_stdout, rb_iseq_disasm(iseq));
01474 rb_io_flush(rb_stdout);
01475 return Qtrue;
01476 }
01477
01478 rb_define_readonly_boolean("$-p", opt->do_print);
01479 rb_define_readonly_boolean("$-l", opt->do_line);
01480 rb_define_readonly_boolean("$-a", opt->do_split);
01481
01482 rb_set_safe_level(opt->safe_level);
01483 rb_gc_set_params();
01484
01485 return iseq;
01486 }
01487
01488 struct load_file_arg {
01489 VALUE parser;
01490 const char *fname;
01491 int script;
01492 struct cmdline_options *opt;
01493 };
01494
01495 static VALUE
01496 load_file_internal(VALUE arg)
01497 {
01498 extern VALUE rb_stdin;
01499 struct load_file_arg *argp = (struct load_file_arg *)arg;
01500 VALUE parser = argp->parser;
01501 const char *fname = argp->fname;
01502 int script = argp->script;
01503 struct cmdline_options *opt = argp->opt;
01504 VALUE f;
01505 int line_start = 1;
01506 NODE *tree = 0;
01507 rb_encoding *enc;
01508 ID set_encoding;
01509 int xflag = 0;
01510
01511 if (!fname)
01512 rb_load_fail(fname);
01513 if (strcmp(fname, "-") == 0) {
01514 f = rb_stdin;
01515 }
01516 else {
01517 int fd, mode = O_RDONLY;
01518 #if defined DOSISH || defined __CYGWIN__
01519 {
01520 const char *ext = strrchr(fname, '.');
01521 if (ext && STRCASECMP(ext, ".exe") == 0) {
01522 mode |= O_BINARY;
01523 xflag = 1;
01524 }
01525 }
01526 #endif
01527 if ((fd = open(fname, mode)) < 0) {
01528 rb_load_fail(fname);
01529 }
01530 rb_update_max_fd(fd);
01531
01532 f = rb_io_fdopen(fd, mode, fname);
01533 }
01534
01535 CONST_ID(set_encoding, "set_encoding");
01536 if (script) {
01537 VALUE c = 1;
01538 VALUE line;
01539 char *p;
01540 int no_src_enc = !opt->src.enc.name;
01541 int no_ext_enc = !opt->ext.enc.name;
01542 int no_int_enc = !opt->intern.enc.name;
01543
01544 enc = rb_ascii8bit_encoding();
01545 rb_funcall(f, set_encoding, 1, rb_enc_from_encoding(enc));
01546
01547 if (xflag || opt->xflag) {
01548 line_start--;
01549 search_shebang:
01550 forbid_setid("-x");
01551 opt->xflag = FALSE;
01552 while (!NIL_P(line = rb_io_gets(f))) {
01553 line_start++;
01554 if (RSTRING_LEN(line) > 2
01555 && RSTRING_PTR(line)[0] == '#'
01556 && RSTRING_PTR(line)[1] == '!') {
01557 if ((p = strstr(RSTRING_PTR(line), "ruby")) != 0) {
01558 goto start_read;
01559 }
01560 }
01561 }
01562 rb_raise(rb_eLoadError, "no Ruby script found in input");
01563 }
01564
01565 c = rb_io_getbyte(f);
01566 if (c == INT2FIX('#')) {
01567 c = rb_io_getbyte(f);
01568 if (c == INT2FIX('!')) {
01569 line = rb_io_gets(f);
01570 if (NIL_P(line))
01571 return 0;
01572
01573 if ((p = strstr(RSTRING_PTR(line), "ruby")) == 0) {
01574
01575 goto search_shebang;
01576 }
01577
01578 start_read:
01579 p += 4;
01580 RSTRING_PTR(line)[RSTRING_LEN(line) - 1] = '\0';
01581 if (RSTRING_PTR(line)[RSTRING_LEN(line) - 2] == '\r')
01582 RSTRING_PTR(line)[RSTRING_LEN(line) - 2] = '\0';
01583 if ((p = strstr(p, " -")) != 0) {
01584 moreswitches(p + 1, opt, 0);
01585 }
01586
01587
01588 rb_io_ungetbyte(f, rb_str_new2("!\n"));
01589 }
01590 else if (!NIL_P(c)) {
01591 rb_io_ungetbyte(f, c);
01592 }
01593 rb_io_ungetbyte(f, INT2FIX('#'));
01594 if (no_src_enc && opt->src.enc.name) {
01595 opt->src.enc.index = opt_enc_index(opt->src.enc.name);
01596 src_encoding_index = opt->src.enc.index;
01597 }
01598 if (no_ext_enc && opt->ext.enc.name) {
01599 opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
01600 }
01601 if (no_int_enc && opt->intern.enc.name) {
01602 opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
01603 }
01604 }
01605 else if (!NIL_P(c)) {
01606 rb_io_ungetbyte(f, c);
01607 }
01608 else {
01609 if (f != rb_stdin) rb_io_close(f);
01610 f = Qnil;
01611 }
01612 rb_vm_set_progname(rb_progname = opt->script_name);
01613 require_libraries(&opt->req_list);
01614 }
01615 if (opt->src.enc.index >= 0) {
01616 enc = rb_enc_from_index(opt->src.enc.index);
01617 }
01618 else if (f == rb_stdin) {
01619 enc = rb_locale_encoding();
01620 }
01621 else {
01622 enc = rb_usascii_encoding();
01623 }
01624 if (NIL_P(f)) {
01625 f = rb_str_new(0, 0);
01626 rb_enc_associate(f, enc);
01627 return (VALUE)rb_parser_compile_string(parser, fname, f, line_start);
01628 }
01629 rb_funcall(f, set_encoding, 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
01630 tree = rb_parser_compile_file(parser, fname, f, line_start);
01631 rb_funcall(f, set_encoding, 1, rb_parser_encoding(parser));
01632 if (script && tree && rb_parser_end_seen_p(parser)) {
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645 rb_define_global_const("DATA", f);
01646 }
01647 else if (f != rb_stdin) {
01648 rb_io_close(f);
01649 }
01650 return (VALUE)tree;
01651 }
01652
01653 static VALUE
01654 restore_lineno(VALUE lineno)
01655 {
01656 return rb_gv_set("$.", lineno);
01657 }
01658
01659 static NODE *
01660 load_file(VALUE parser, const char *fname, int script, struct cmdline_options *opt)
01661 {
01662 struct load_file_arg arg;
01663 arg.parser = parser;
01664 arg.fname = fname;
01665 arg.script = script;
01666 arg.opt = opt;
01667 return (NODE *)rb_ensure(load_file_internal, (VALUE)&arg, restore_lineno, rb_gv_get("$."));
01668 }
01669
01670 void *
01671 rb_load_file(const char *fname)
01672 {
01673 struct cmdline_options opt;
01674
01675 return load_file(rb_parser_new(), fname, 0, cmdline_options_init(&opt));
01676 }
01677
01678 static void
01679 set_arg0(VALUE val, ID id)
01680 {
01681 char *s;
01682 long i;
01683
01684 if (origarg.argv == 0)
01685 rb_raise(rb_eRuntimeError, "$0 not initialized");
01686 StringValue(val);
01687 s = RSTRING_PTR(val);
01688 i = RSTRING_LEN(val);
01689
01690 setproctitle("%.*s", (int)i, s);
01691
01692 rb_progname = rb_obj_freeze(rb_external_str_new(s, i));
01693 }
01694
01695 void
01696 ruby_script(const char *name)
01697 {
01698 if (name) {
01699 rb_progname = rb_external_str_new(name, strlen(name));
01700 rb_vm_set_progname(rb_progname);
01701 }
01702 }
01703
01704 static void
01705 init_ids(struct cmdline_options *opt)
01706 {
01707 rb_uid_t uid = getuid();
01708 rb_uid_t euid = geteuid();
01709 rb_gid_t gid = getgid();
01710 rb_gid_t egid = getegid();
01711
01712 if (uid != euid) opt->setids |= 1;
01713 if (egid != gid) opt->setids |= 2;
01714 if (uid && opt->setids) {
01715 if (opt->safe_level < 1) opt->safe_level = 1;
01716 }
01717 }
01718
01719 #undef forbid_setid
01720 static void
01721 forbid_setid(const char *s, struct cmdline_options *opt)
01722 {
01723 if (opt->setids & 1)
01724 rb_raise(rb_eSecurityError, "no %s allowed while running setuid", s);
01725 if (opt->setids & 2)
01726 rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s);
01727 if (opt->safe_level > 0)
01728 rb_raise(rb_eSecurityError, "no %s allowed in tainted mode", s);
01729 }
01730
01731 static void
01732 verbose_setter(VALUE val, ID id, void *data)
01733 {
01734 VALUE *variable = data;
01735 *variable = RTEST(val) ? Qtrue : val;
01736 }
01737
01738 static VALUE
01739 opt_W_getter(ID id, void *data)
01740 {
01741 VALUE *variable = data;
01742 switch (*variable) {
01743 case Qnil:
01744 return INT2FIX(0);
01745 case Qfalse:
01746 return INT2FIX(1);
01747 case Qtrue:
01748 return INT2FIX(2);
01749 }
01750 return Qnil;
01751 }
01752
01753 void
01754 ruby_prog_init(void)
01755 {
01756 rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter);
01757 rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter);
01758 rb_define_hooked_variable("$-w", &ruby_verbose, 0, verbose_setter);
01759 rb_define_hooked_variable("$-W", &ruby_verbose, opt_W_getter, rb_gvar_readonly_setter);
01760 rb_define_variable("$DEBUG", &ruby_debug);
01761 rb_define_variable("$-d", &ruby_debug);
01762
01763 rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0);
01764 rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);
01765
01766
01767
01768
01769
01770
01771
01772
01773 rb_define_global_const("ARGV", rb_argv);
01774 }
01775
01776 void
01777 ruby_set_argv(int argc, char **argv)
01778 {
01779 int i;
01780 VALUE av = rb_argv;
01781
01782 #if defined(USE_DLN_A_OUT)
01783 if (origarg.argv)
01784 dln_argv0 = origarg.argv[0];
01785 else
01786 dln_argv0 = argv[0];
01787 #endif
01788 rb_ary_clear(av);
01789 for (i = 0; i < argc; i++) {
01790 VALUE arg = rb_external_str_new_cstr(argv[i]);
01791
01792 OBJ_FREEZE(arg);
01793 rb_ary_push(av, arg);
01794 }
01795 }
01796
01797 void *
01798 ruby_process_options(int argc, char **argv)
01799 {
01800 struct cmdline_options opt;
01801 VALUE iseq;
01802
01803 ruby_script(argv[0]);
01804 rb_argv0 = rb_str_new4(rb_progname);
01805 rb_gc_register_mark_object(rb_argv0);
01806 iseq = process_options(argc, argv, cmdline_options_init(&opt));
01807
01808 #ifndef HAVE_SETPROCTITLE
01809 {
01810 extern void ruby_init_setproctitle(int argc, char *argv[]);
01811 ruby_init_setproctitle(argc, argv);
01812 }
01813 #endif
01814
01815 return (void*)(struct RData*)iseq;
01816 }
01817
01818 static void
01819 fill_standard_fds(void)
01820 {
01821 int f0, f1, f2, fds[2];
01822 struct stat buf;
01823 f0 = fstat(0, &buf) == -1 && errno == EBADF;
01824 f1 = fstat(1, &buf) == -1 && errno == EBADF;
01825 f2 = fstat(2, &buf) == -1 && errno == EBADF;
01826 if (f0) {
01827 if (pipe(fds) == 0) {
01828 close(fds[1]);
01829 if (fds[0] != 0) {
01830 dup2(fds[0], 0);
01831 close(fds[0]);
01832 }
01833 }
01834 }
01835 if (f1 || f2) {
01836 if (pipe(fds) == 0) {
01837 close(fds[0]);
01838 if (f1 && fds[1] != 1)
01839 dup2(fds[1], 1);
01840 if (f2 && fds[1] != 2)
01841 dup2(fds[1], 2);
01842 if (fds[1] != 1 && fds[1] != 2)
01843 close(fds[1]);
01844 }
01845 }
01846 }
01847
01848 void
01849 ruby_sysinit(int *argc, char ***argv)
01850 {
01851 #if defined(_WIN32)
01852 void rb_w32_sysinit(int *argc, char ***argv);
01853 rb_w32_sysinit(argc, argv);
01854 #endif
01855 origarg.argc = *argc;
01856 origarg.argv = *argv;
01857 #if defined(USE_DLN_A_OUT)
01858 dln_argv0 = origarg.argv[0];
01859 #endif
01860 fill_standard_fds();
01861 }
01862