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 static const char bindir[] = "/bin";
00414 #ifdef LIBDIR_BASENAME
00415 static const char libdir[] = "/"LIBDIR_BASENAME;
00416 #else
00417 static const char libdir[] = "/lib";
00418 #endif
00419 const ptrdiff_t bindir_len = (ptrdiff_t)sizeof(bindir) - 1;
00420 const ptrdiff_t libdir_len = (ptrdiff_t)sizeof(libdir) - 1;
00421 *p = 0;
00422 if (p - libpath >= bindir_len && !STRCASECMP(p - bindir_len, bindir)) {
00423 p -= bindir_len;
00424 *p = 0;
00425 }
00426 else if (p - libpath >= libdir_len && !STRCASECMP(p - libdir_len, libdir)) {
00427 p -= libdir_len;
00428 *p = 0;
00429 }
00430 }
00431 #if !VARIABLE_LIBPATH
00432 else {
00433 strlcpy(libpath, ".", sizeof(libpath));
00434 p = libpath + 1;
00435 }
00436 baselen = p - libpath;
00437 #define PREFIX_PATH() rb_str_new(libpath, baselen)
00438 #else
00439 baselen = p - libpath;
00440 rb_str_resize(sopath, baselen);
00441 libpath = RSTRING_PTR(sopath);
00442 #define PREFIX_PATH() sopath
00443 #endif
00444
00445 #define BASEPATH() rb_str_buf_cat(rb_str_buf_new(baselen+len), libpath, baselen)
00446
00447 #define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), (path), (len))
00448 #else
00449 static const char exec_prefix[] = RUBY_EXEC_PREFIX;
00450 #define RUBY_RELATIVE(path, len) rubylib_mangled_path((path), (len))
00451 #define PREFIX_PATH() RUBY_RELATIVE(exec_prefix, sizeof(exec_prefix)-1)
00452 #endif
00453 load_path = GET_VM()->load_path;
00454
00455 if (safe_level == 0) {
00456 #ifdef MANGLED_PATH
00457 rubylib_mangled_path("", 0);
00458 #endif
00459 ruby_push_include(getenv("RUBYLIB"), identical_path);
00460 }
00461
00462 id_initial_load_path_mark = rb_intern_const("@gem_prelude_index");
00463 while (*paths) {
00464 size_t len = strlen(paths);
00465 VALUE path = RUBY_RELATIVE(paths, len);
00466 rb_ivar_set(path, id_initial_load_path_mark, path);
00467 rb_ary_push(load_path, path);
00468 paths += len + 1;
00469 }
00470
00471 rb_const_set(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"), rb_obj_freeze(PREFIX_PATH()));
00472 }
00473
00474
00475 static void
00476 add_modules(VALUE *req_list, const char *mod)
00477 {
00478 VALUE list = *req_list;
00479
00480 if (!list) {
00481 *req_list = list = rb_ary_new();
00482 RBASIC(list)->klass = 0;
00483 }
00484 rb_ary_push(list, rb_obj_freeze(rb_str_new2(mod)));
00485 }
00486
00487 static void
00488 require_libraries(VALUE *req_list)
00489 {
00490 VALUE list = *req_list;
00491 VALUE self = rb_vm_top_self();
00492 ID require;
00493 rb_thread_t *th = GET_THREAD();
00494 rb_block_t *prev_base_block = th->base_block;
00495 int prev_parse_in_eval = th->parse_in_eval;
00496 th->base_block = 0;
00497 th->parse_in_eval = 0;
00498
00499 Init_ext();
00500 CONST_ID(require, "require");
00501 while (list && RARRAY_LEN(list) > 0) {
00502 VALUE feature = rb_ary_shift(list);
00503 rb_funcall2(self, require, 1, &feature);
00504 }
00505 *req_list = 0;
00506
00507 th->parse_in_eval = prev_parse_in_eval;
00508 th->base_block = prev_base_block;
00509 }
00510
00511 static void
00512 process_sflag(int *sflag)
00513 {
00514 if (*sflag > 0) {
00515 long n;
00516 VALUE *args;
00517 VALUE argv = rb_argv;
00518
00519 n = RARRAY_LEN(argv);
00520 args = RARRAY_PTR(argv);
00521 while (n > 0) {
00522 VALUE v = *args++;
00523 char *s = StringValuePtr(v);
00524 char *p;
00525 int hyphen = FALSE;
00526
00527 if (s[0] != '-')
00528 break;
00529 n--;
00530 if (s[1] == '-' && s[2] == '\0')
00531 break;
00532
00533 v = Qtrue;
00534
00535 for (p = s + 1; *p; p++) {
00536 if (*p == '=') {
00537 *p++ = '\0';
00538 v = rb_str_new2(p);
00539 break;
00540 }
00541 if (*p == '-') {
00542 hyphen = TRUE;
00543 }
00544 else if (*p != '_' && !ISALNUM(*p)) {
00545 VALUE name_error[2];
00546 name_error[0] =
00547 rb_str_new2("invalid name for global variable - ");
00548 if (!(p = strchr(p, '='))) {
00549 rb_str_cat2(name_error[0], s);
00550 }
00551 else {
00552 rb_str_cat(name_error[0], s, p - s);
00553 }
00554 name_error[1] = args[-1];
00555 rb_exc_raise(rb_class_new_instance(2, name_error, rb_eNameError));
00556 }
00557 }
00558 s[0] = '$';
00559 if (hyphen) {
00560 for (p = s + 1; *p; ++p) {
00561 if (*p == '-')
00562 *p = '_';
00563 }
00564 }
00565 rb_gv_set(s, v);
00566 }
00567 n = RARRAY_LEN(argv) - n;
00568 while (n--) {
00569 rb_ary_shift(argv);
00570 }
00571 *sflag = -1;
00572 }
00573 }
00574
00575 static long proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt);
00576
00577 static void
00578 moreswitches(const char *s, struct cmdline_options *opt, int envopt)
00579 {
00580 long argc, i, len;
00581 char **argv, *p;
00582 const char *ap = 0;
00583 VALUE argstr, argary;
00584
00585 while (ISSPACE(*s)) s++;
00586 if (!*s) return;
00587 argstr = rb_str_tmp_new((len = strlen(s)) + 2);
00588 argary = rb_str_tmp_new(0);
00589
00590 p = RSTRING_PTR(argstr);
00591 *p++ = ' ';
00592 memcpy(p, s, len + 1);
00593 ap = 0;
00594 rb_str_cat(argary, (char *)&ap, sizeof(ap));
00595 while (*p) {
00596 ap = p;
00597 rb_str_cat(argary, (char *)&ap, sizeof(ap));
00598 while (*p && !ISSPACE(*p)) ++p;
00599 if (!*p) break;
00600 *p++ = '\0';
00601 while (ISSPACE(*p)) ++p;
00602 }
00603 argc = RSTRING_LEN(argary) / sizeof(ap);
00604 ap = 0;
00605 rb_str_cat(argary, (char *)&ap, sizeof(ap));
00606 argv = (char **)RSTRING_PTR(argary);
00607
00608 while ((i = proc_options(argc, argv, opt, envopt)) > 1 && (argc -= i) > 0) {
00609 argv += i;
00610 if (**argv != '-') {
00611 *--*argv = '-';
00612 }
00613 if ((*argv)[1]) {
00614 ++argc;
00615 --argv;
00616 }
00617 }
00618
00619
00620 rb_str_resize(argary, 0);
00621 rb_str_resize(argstr, 0);
00622 }
00623
00624 #define NAME_MATCH_P(name, str, len) \
00625 ((len) < (int)sizeof(name) && strncmp((str), (name), (len)) == 0)
00626
00627 #define UNSET_WHEN(name, bit, str, len) \
00628 if (NAME_MATCH_P((name), (str), (len))) { \
00629 *(unsigned int *)arg &= ~(bit); \
00630 return; \
00631 }
00632
00633 #define SET_WHEN(name, bit, str, len) \
00634 if (NAME_MATCH_P((name), (str), (len))) { \
00635 *(unsigned int *)arg |= (bit); \
00636 return; \
00637 }
00638
00639 static void
00640 enable_option(const char *str, int len, void *arg)
00641 {
00642 #define UNSET_WHEN_DISABLE(bit) UNSET_WHEN(#bit, DISABLE_BIT(bit), str, len)
00643 UNSET_WHEN_DISABLE(gems);
00644 UNSET_WHEN_DISABLE(rubyopt);
00645 if (NAME_MATCH_P("all", str, len)) {
00646 *(unsigned int *)arg = 0U;
00647 return;
00648 }
00649 rb_warn("unknown argument for --enable: `%.*s'", len, str);
00650 }
00651
00652 static void
00653 disable_option(const char *str, int len, void *arg)
00654 {
00655 #define SET_WHEN_DISABLE(bit) SET_WHEN(#bit, DISABLE_BIT(bit), str, len)
00656 SET_WHEN_DISABLE(gems);
00657 SET_WHEN_DISABLE(rubyopt);
00658 if (NAME_MATCH_P("all", str, len)) {
00659 *(unsigned int *)arg = ~0U;
00660 return;
00661 }
00662 rb_warn("unknown argument for --disable: `%.*s'", len, str);
00663 }
00664
00665 static void
00666 dump_option(const char *str, int len, void *arg)
00667 {
00668 #define SET_WHEN_DUMP(bit) SET_WHEN(#bit, DUMP_BIT(bit), str, len)
00669 SET_WHEN_DUMP(version);
00670 SET_WHEN_DUMP(copyright);
00671 SET_WHEN_DUMP(usage);
00672 SET_WHEN_DUMP(yydebug);
00673 SET_WHEN_DUMP(syntax);
00674 SET_WHEN_DUMP(parsetree);
00675 SET_WHEN_DUMP(parsetree_with_comment);
00676 SET_WHEN_DUMP(insns);
00677 rb_warn("don't know how to dump `%.*s',", len, str);
00678 rb_warn("but only [version, copyright, usage, yydebug, syntax, parsetree, parsetree_with_comment, insns].");
00679 }
00680
00681 static void
00682 set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen)
00683 {
00684 VALUE ename;
00685
00686 if (!elen) elen = strlen(e);
00687 ename = rb_str_new(e, elen);
00688
00689 if (*name &&
00690 rb_funcall(ename, rb_intern("casecmp"), 1, *name) != INT2FIX(0)) {
00691 rb_raise(rb_eRuntimeError,
00692 "%s already set to %s", type, RSTRING_PTR(*name));
00693 }
00694 *name = ename;
00695 }
00696
00697 #define set_internal_encoding_once(opt, e, elen) \
00698 set_option_encoding_once("default_internal", &(opt)->intern.enc.name, (e), (elen))
00699 #define set_external_encoding_once(opt, e, elen) \
00700 set_option_encoding_once("default_external", &(opt)->ext.enc.name, (e), (elen))
00701 #define set_source_encoding_once(opt, e, elen) \
00702 set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen))
00703
00704 static long
00705 proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt)
00706 {
00707 long n, argc0 = argc;
00708 const char *s;
00709
00710 if (argc == 0)
00711 return 0;
00712
00713 for (argc--, argv++; argc > 0; argc--, argv++) {
00714 const char *const arg = argv[0];
00715 if (arg[0] != '-' || !arg[1])
00716 break;
00717
00718 s = arg + 1;
00719 reswitch:
00720 switch (*s) {
00721 case 'a':
00722 if (envopt) goto noenvopt;
00723 opt->do_split = TRUE;
00724 s++;
00725 goto reswitch;
00726
00727 case 'p':
00728 if (envopt) goto noenvopt;
00729 opt->do_print = TRUE;
00730
00731 case 'n':
00732 if (envopt) goto noenvopt;
00733 opt->do_loop = TRUE;
00734 s++;
00735 goto reswitch;
00736
00737 case 'd':
00738 ruby_debug = Qtrue;
00739 ruby_verbose = Qtrue;
00740 s++;
00741 goto reswitch;
00742
00743 case 'y':
00744 if (envopt) goto noenvopt;
00745 opt->dump |= DUMP_BIT(yydebug);
00746 s++;
00747 goto reswitch;
00748
00749 case 'v':
00750 if (opt->verbose) {
00751 s++;
00752 goto reswitch;
00753 }
00754 ruby_show_version();
00755 opt->verbose = 1;
00756 case 'w':
00757 ruby_verbose = Qtrue;
00758 s++;
00759 goto reswitch;
00760
00761 case 'W':
00762 {
00763 size_t numlen;
00764 int v = 2;
00765
00766 if (*++s) {
00767 v = scan_oct(s, 1, &numlen);
00768 if (numlen == 0)
00769 v = 1;
00770 s += numlen;
00771 }
00772 switch (v) {
00773 case 0:
00774 ruby_verbose = Qnil;
00775 break;
00776 case 1:
00777 ruby_verbose = Qfalse;
00778 break;
00779 default:
00780 ruby_verbose = Qtrue;
00781 break;
00782 }
00783 }
00784 goto reswitch;
00785
00786 case 'c':
00787 if (envopt) goto noenvopt;
00788 opt->dump |= DUMP_BIT(syntax);
00789 s++;
00790 goto reswitch;
00791
00792 case 's':
00793 if (envopt) goto noenvopt;
00794 forbid_setid("-s");
00795 if (!opt->sflag) opt->sflag = 1;
00796 s++;
00797 goto reswitch;
00798
00799 case 'h':
00800 if (envopt) goto noenvopt;
00801 opt->dump |= DUMP_BIT(usage);
00802 goto switch_end;
00803
00804 case 'l':
00805 if (envopt) goto noenvopt;
00806 opt->do_line = TRUE;
00807 rb_output_rs = rb_rs;
00808 s++;
00809 goto reswitch;
00810
00811 case 'S':
00812 if (envopt) goto noenvopt;
00813 forbid_setid("-S");
00814 opt->do_search = TRUE;
00815 s++;
00816 goto reswitch;
00817
00818 case 'e':
00819 if (envopt) goto noenvopt;
00820 forbid_setid("-e");
00821 if (!*++s) {
00822 s = argv[1];
00823 argc--, argv++;
00824 }
00825 if (!s) {
00826 rb_raise(rb_eRuntimeError, "no code specified for -e");
00827 }
00828 if (!opt->e_script) {
00829 opt->e_script = rb_str_new(0, 0);
00830 if (opt->script == 0)
00831 opt->script = "-e";
00832 }
00833 rb_str_cat2(opt->e_script, s);
00834 rb_str_cat2(opt->e_script, "\n");
00835 break;
00836
00837 case 'r':
00838 forbid_setid("-r");
00839 if (*++s) {
00840 add_modules(&opt->req_list, s);
00841 }
00842 else if (argv[1]) {
00843 add_modules(&opt->req_list, argv[1]);
00844 argc--, argv++;
00845 }
00846 break;
00847
00848 case 'i':
00849 if (envopt) goto noenvopt;
00850 forbid_setid("-i");
00851 ruby_set_inplace_mode(s + 1);
00852 break;
00853
00854 case 'x':
00855 if (envopt) goto noenvopt;
00856 opt->xflag = TRUE;
00857 s++;
00858 if (*s && chdir(s) < 0) {
00859 rb_fatal("Can't chdir to %s", s);
00860 }
00861 break;
00862
00863 case 'C':
00864 case 'X':
00865 if (envopt) goto noenvopt;
00866 s++;
00867 if (!*s) {
00868 s = argv[1];
00869 argc--, argv++;
00870 }
00871 if (!s || !*s) {
00872 rb_fatal("Can't chdir");
00873 }
00874 if (chdir(s) < 0) {
00875 rb_fatal("Can't chdir to %s", s);
00876 }
00877 break;
00878
00879 case 'F':
00880 if (envopt) goto noenvopt;
00881 if (*++s) {
00882 rb_fs = rb_reg_new(s, strlen(s), 0);
00883 }
00884 break;
00885
00886 case 'E':
00887 if (!*++s && (!--argc || !(s = *++argv))) {
00888 rb_raise(rb_eRuntimeError, "missing argument for -E");
00889 }
00890 goto encoding;
00891
00892 case 'U':
00893 set_internal_encoding_once(opt, "UTF-8", 0);
00894 ++s;
00895 goto reswitch;
00896
00897 case 'K':
00898 if (*++s) {
00899 const char *enc_name = 0;
00900 switch (*s) {
00901 case 'E': case 'e':
00902 enc_name = "EUC-JP";
00903 break;
00904 case 'S': case 's':
00905 enc_name = "Windows-31J";
00906 break;
00907 case 'U': case 'u':
00908 enc_name = "UTF-8";
00909 break;
00910 case 'N': case 'n': case 'A': case 'a':
00911 enc_name = "ASCII-8BIT";
00912 break;
00913 }
00914 if (enc_name) {
00915 opt->src.enc.name = rb_str_new2(enc_name);
00916 if (!opt->ext.enc.name)
00917 opt->ext.enc.name = opt->src.enc.name;
00918 }
00919 s++;
00920 }
00921 goto reswitch;
00922
00923 case 'T':
00924 {
00925 size_t numlen;
00926 int v = 1;
00927
00928 if (*++s) {
00929 v = scan_oct(s, 2, &numlen);
00930 if (numlen == 0)
00931 v = 1;
00932 s += numlen;
00933 }
00934 if (v > opt->safe_level) opt->safe_level = v;
00935 }
00936 goto reswitch;
00937
00938 case 'I':
00939 forbid_setid("-I");
00940 if (*++s)
00941 ruby_incpush_expand(s);
00942 else if (argv[1]) {
00943 ruby_incpush_expand(argv[1]);
00944 argc--, argv++;
00945 }
00946 break;
00947
00948 case '0':
00949 if (envopt) goto noenvopt;
00950 {
00951 size_t numlen;
00952 int v;
00953 char c;
00954
00955 v = scan_oct(s, 4, &numlen);
00956 s += numlen;
00957 if (v > 0377)
00958 rb_rs = Qnil;
00959 else if (v == 0 && numlen >= 2) {
00960 rb_rs = rb_str_new2("\n\n");
00961 }
00962 else {
00963 c = v & 0xff;
00964 rb_rs = rb_str_new(&c, 1);
00965 }
00966 }
00967 goto reswitch;
00968
00969 case '-':
00970 if (!s[1] || (s[1] == '\r' && !s[2])) {
00971 argc--, argv++;
00972 goto switch_end;
00973 }
00974 s++;
00975
00976 # define is_option_end(c, allow_hyphen) \
00977 (!(c) || ((allow_hyphen) && (c) == '-') || (c) == '=')
00978 # define check_envopt(name, allow_envopt) \
00979 (((allow_envopt) || !envopt) ? (void)0 : \
00980 rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name))
00981 # define need_argument(name, s) \
00982 ((*(s)++ ? !*(s) : (!--argc || !((s) = *++argv))) ? \
00983 rb_raise(rb_eRuntimeError, "missing argument for --" name) \
00984 : (void)0)
00985 # define is_option_with_arg(name, allow_hyphen, allow_envopt) \
00986 (strncmp((name), s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], (allow_hyphen)) ? \
00987 (check_envopt(name, (allow_envopt)), s += n, need_argument(name, s), 1) : 0)
00988
00989 if (strcmp("copyright", s) == 0) {
00990 if (envopt) goto noenvopt_long;
00991 opt->dump |= DUMP_BIT(copyright);
00992 }
00993 else if (strcmp("debug", s) == 0) {
00994 ruby_debug = Qtrue;
00995 ruby_verbose = Qtrue;
00996 }
00997 else if (is_option_with_arg("enable", Qtrue, Qtrue)) {
00998 ruby_each_words(s, enable_option, &opt->disable);
00999 }
01000 else if (is_option_with_arg("disable", Qtrue, Qtrue)) {
01001 ruby_each_words(s, disable_option, &opt->disable);
01002 }
01003 else if (is_option_with_arg("encoding", Qfalse, Qtrue)) {
01004 char *p;
01005 encoding:
01006 do {
01007 # define set_encoding_part(type) \
01008 if (!(p = strchr(s, ':'))) { \
01009 set_##type##_encoding_once(opt, s, 0); \
01010 break; \
01011 } \
01012 else if (p > s) { \
01013 set_##type##_encoding_once(opt, s, p-s); \
01014 }
01015 set_encoding_part(external);
01016 if (!*(s = ++p)) break;
01017 set_encoding_part(internal);
01018 if (!*(s = ++p)) break;
01019 #if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
01020 set_encoding_part(source);
01021 if (!*(s = ++p)) break;
01022 #endif
01023 rb_raise(rb_eRuntimeError, "extra argument for %s: %s",
01024 (arg[1] == '-' ? "--encoding" : "-E"), s);
01025 # undef set_encoding_part
01026 } while (0);
01027 }
01028 else if (is_option_with_arg("internal-encoding", Qfalse, Qtrue)) {
01029 set_internal_encoding_once(opt, s, 0);
01030 }
01031 else if (is_option_with_arg("external-encoding", Qfalse, Qtrue)) {
01032 set_external_encoding_once(opt, s, 0);
01033 }
01034 #if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
01035 else if (is_option_with_arg("source-encoding", Qfalse, Qtrue)) {
01036 set_source_encoding_once(opt, s, 0);
01037 }
01038 #endif
01039 else if (strcmp("version", s) == 0) {
01040 if (envopt) goto noenvopt_long;
01041 opt->dump |= DUMP_BIT(version);
01042 }
01043 else if (strcmp("verbose", s) == 0) {
01044 opt->verbose = 1;
01045 ruby_verbose = Qtrue;
01046 }
01047 else if (strcmp("yydebug", s) == 0) {
01048 if (envopt) goto noenvopt_long;
01049 opt->dump |= DUMP_BIT(yydebug);
01050 }
01051 else if (is_option_with_arg("dump", Qfalse, Qfalse)) {
01052 ruby_each_words(s, dump_option, &opt->dump);
01053 }
01054 else if (strcmp("help", s) == 0) {
01055 if (envopt) goto noenvopt_long;
01056 opt->dump |= DUMP_BIT(usage);
01057 goto switch_end;
01058 }
01059 else {
01060 rb_raise(rb_eRuntimeError,
01061 "invalid option --%s (-h will show valid options)", s);
01062 }
01063 break;
01064
01065 case '\r':
01066 if (!s[1])
01067 break;
01068
01069 default:
01070 {
01071 if (ISPRINT(*s)) {
01072 rb_raise(rb_eRuntimeError,
01073 "invalid option -%c (-h will show valid options)",
01074 (int)(unsigned char)*s);
01075 }
01076 else {
01077 rb_raise(rb_eRuntimeError,
01078 "invalid option -\\x%02X (-h will show valid options)",
01079 (int)(unsigned char)*s);
01080 }
01081 }
01082 goto switch_end;
01083
01084 noenvopt:
01085
01086 rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: -%c", *s);
01087 break;
01088
01089 noenvopt_long:
01090 rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --%s", s);
01091 break;
01092
01093 case 0:
01094 break;
01095 # undef is_option_end
01096 # undef check_envopt
01097 # undef need_argument
01098 # undef is_option_with_arg
01099 }
01100 }
01101
01102 switch_end:
01103 return argc0 - argc;
01104 }
01105
01106 static void
01107 ruby_init_prelude(void)
01108 {
01109 Init_prelude();
01110 rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"));
01111 }
01112
01113 static int
01114 opt_enc_index(VALUE enc_name)
01115 {
01116 const char *s = RSTRING_PTR(enc_name);
01117 int i = rb_enc_find_index(s);
01118
01119 if (i < 0) {
01120 rb_raise(rb_eRuntimeError, "unknown encoding name - %s", s);
01121 }
01122 else if (rb_enc_dummy_p(rb_enc_from_index(i))) {
01123 rb_raise(rb_eRuntimeError, "dummy encoding is not acceptable - %s ", s);
01124 }
01125 return i;
01126 }
01127
01128 #define rb_progname (GET_VM()->progname)
01129 VALUE rb_argv0;
01130
01131 static VALUE
01132 false_value(void)
01133 {
01134 return Qfalse;
01135 }
01136
01137 static VALUE
01138 true_value(void)
01139 {
01140 return Qtrue;
01141 }
01142
01143 #define rb_define_readonly_boolean(name, val) \
01144 rb_define_virtual_variable((name), (val) ? true_value : false_value, 0)
01145
01146 static VALUE
01147 uscore_get(void)
01148 {
01149 VALUE line;
01150
01151 line = rb_lastline_get();
01152 if (TYPE(line) != T_STRING) {
01153 rb_raise(rb_eTypeError, "$_ value need to be String (%s given)",
01154 NIL_P(line) ? "nil" : rb_obj_classname(line));
01155 }
01156 return line;
01157 }
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169 static VALUE
01170 rb_f_sub(argc, argv)
01171 int argc;
01172 VALUE *argv;
01173 {
01174 VALUE str = rb_funcall3(uscore_get(), rb_intern("sub"), argc, argv);
01175 rb_lastline_set(str);
01176 return str;
01177 }
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190 static VALUE
01191 rb_f_gsub(argc, argv)
01192 int argc;
01193 VALUE *argv;
01194 {
01195 VALUE str = rb_funcall3(uscore_get(), rb_intern("gsub"), argc, argv);
01196 rb_lastline_set(str);
01197 return str;
01198 }
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210 static VALUE
01211 rb_f_chop(void)
01212 {
01213 VALUE str = rb_funcall3(uscore_get(), rb_intern("chop"), 0, 0);
01214 rb_lastline_set(str);
01215 return str;
01216 }
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230 static VALUE
01231 rb_f_chomp(argc, argv)
01232 int argc;
01233 VALUE *argv;
01234 {
01235 VALUE str = rb_funcall3(uscore_get(), rb_intern("chomp"), argc, argv);
01236 rb_lastline_set(str);
01237 return str;
01238 }
01239
01240 static VALUE
01241 process_options(int argc, char **argv, struct cmdline_options *opt)
01242 {
01243 NODE *tree = 0;
01244 VALUE parser;
01245 VALUE iseq;
01246 rb_encoding *enc, *lenc;
01247 const char *s;
01248 char fbuf[MAXPATHLEN];
01249 int i = (int)proc_options(argc, argv, opt, 0);
01250 rb_thread_t *th = GET_THREAD();
01251 rb_env_t *env = 0;
01252
01253 argc -= i;
01254 argv += i;
01255
01256 if (opt->dump & DUMP_BIT(usage)) {
01257 usage(origarg.argv[0]);
01258 return Qtrue;
01259 }
01260
01261 if (!(opt->disable & DISABLE_BIT(rubyopt)) &&
01262 opt->safe_level == 0 && (s = getenv("RUBYOPT"))) {
01263 VALUE src_enc_name = opt->src.enc.name;
01264 VALUE ext_enc_name = opt->ext.enc.name;
01265 VALUE int_enc_name = opt->intern.enc.name;
01266
01267 opt->src.enc.name = opt->ext.enc.name = opt->intern.enc.name = 0;
01268 moreswitches(s, opt, 1);
01269 if (src_enc_name)
01270 opt->src.enc.name = src_enc_name;
01271 if (ext_enc_name)
01272 opt->ext.enc.name = ext_enc_name;
01273 if (int_enc_name)
01274 opt->intern.enc.name = int_enc_name;
01275 }
01276
01277 if (opt->dump & DUMP_BIT(version)) {
01278 ruby_show_version();
01279 return Qtrue;
01280 }
01281 if (opt->dump & DUMP_BIT(copyright)) {
01282 ruby_show_copyright();
01283 }
01284
01285 if (opt->safe_level >= 4) {
01286 OBJ_TAINT(rb_argv);
01287 OBJ_TAINT(GET_VM()->load_path);
01288 }
01289
01290 if (!opt->e_script) {
01291 if (argc == 0) {
01292 if (opt->verbose)
01293 return Qtrue;
01294 opt->script = "-";
01295 }
01296 else {
01297 opt->script = argv[0];
01298 if (opt->script[0] == '\0') {
01299 opt->script = "-";
01300 }
01301 else if (opt->do_search) {
01302 char *path = getenv("RUBYPATH");
01303
01304 opt->script = 0;
01305 if (path) {
01306 opt->script = dln_find_file_r(argv[0], path, fbuf, sizeof(fbuf));
01307 }
01308 if (!opt->script) {
01309 opt->script = dln_find_file_r(argv[0], getenv(PATH_ENV), fbuf, sizeof(fbuf));
01310 }
01311 if (!opt->script)
01312 opt->script = argv[0];
01313 }
01314 argc--;
01315 argv++;
01316 }
01317 }
01318
01319 opt->script_name = rb_str_new_cstr(opt->script);
01320 opt->script = RSTRING_PTR(opt->script_name);
01321 #if defined DOSISH || defined __CYGWIN__
01322 translit_char(RSTRING_PTR(opt->script_name), '\\', '/');
01323 #endif
01324
01325 ruby_init_loadpath_safe(opt->safe_level);
01326 rb_enc_find_index("encdb");
01327 lenc = rb_locale_encoding();
01328 rb_enc_associate(rb_progname, lenc);
01329 rb_obj_freeze(rb_progname);
01330 parser = rb_parser_new();
01331 if (opt->dump & DUMP_BIT(yydebug)) {
01332 rb_parser_set_yydebug(parser, Qtrue);
01333 }
01334 if (opt->ext.enc.name != 0) {
01335 opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
01336 }
01337 if (opt->intern.enc.name != 0) {
01338 opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
01339 }
01340 if (opt->src.enc.name != 0) {
01341 opt->src.enc.index = opt_enc_index(opt->src.enc.name);
01342 src_encoding_index = opt->src.enc.index;
01343 }
01344 if (opt->ext.enc.index >= 0) {
01345 enc = rb_enc_from_index(opt->ext.enc.index);
01346 }
01347 else {
01348 enc = lenc;
01349 }
01350 rb_enc_set_default_external(rb_enc_from_encoding(enc));
01351 if (opt->intern.enc.index >= 0) {
01352 enc = rb_enc_from_index(opt->intern.enc.index);
01353 rb_enc_set_default_internal(rb_enc_from_encoding(enc));
01354 opt->intern.enc.index = -1;
01355 }
01356 rb_enc_associate(opt->script_name, lenc);
01357 rb_obj_freeze(opt->script_name);
01358 {
01359 long i;
01360 VALUE load_path = GET_VM()->load_path;
01361 for (i = 0; i < RARRAY_LEN(load_path); ++i) {
01362 rb_enc_associate(RARRAY_PTR(load_path)[i], lenc);
01363 }
01364 }
01365 if (!(opt->disable & DISABLE_BIT(gems))) {
01366 #if defined DISABLE_RUBYGEMS && DISABLE_RUBYGEMS
01367 rb_require("rubygems");
01368 #else
01369 rb_define_module("Gem");
01370 #endif
01371 }
01372 ruby_init_prelude();
01373 ruby_set_argv(argc, argv);
01374 process_sflag(&opt->sflag);
01375
01376 {
01377
01378 VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING"));
01379 rb_binding_t *bind;
01380
01381 GetBindingPtr(toplevel_binding, bind);
01382 GetEnvPtr(bind->env, env);
01383 }
01384
01385 #define PREPARE_PARSE_MAIN(expr) do { \
01386 th->parse_in_eval--; \
01387 th->base_block = &env->block; \
01388 expr; \
01389 th->parse_in_eval++; \
01390 th->base_block = 0; \
01391 } while (0)
01392
01393 if (opt->e_script) {
01394 VALUE progname = rb_progname;
01395 rb_encoding *eenc;
01396 if (opt->src.enc.index >= 0) {
01397 eenc = rb_enc_from_index(opt->src.enc.index);
01398 }
01399 else {
01400 eenc = lenc;
01401 }
01402 rb_enc_associate(opt->e_script, eenc);
01403 rb_vm_set_progname(rb_progname = opt->script_name);
01404 require_libraries(&opt->req_list);
01405 rb_vm_set_progname(rb_progname = progname);
01406
01407 PREPARE_PARSE_MAIN({
01408 tree = rb_parser_compile_string(parser, opt->script, opt->e_script, 1);
01409 });
01410 }
01411 else {
01412 if (opt->script[0] == '-' && !opt->script[1]) {
01413 forbid_setid("program input from stdin");
01414 }
01415
01416 PREPARE_PARSE_MAIN({
01417 tree = load_file(parser, opt->script, 1, opt);
01418 });
01419 }
01420 rb_progname = opt->script_name;
01421 rb_vm_set_progname(rb_progname);
01422 if (opt->dump & DUMP_BIT(yydebug)) return Qtrue;
01423
01424 if (opt->ext.enc.index >= 0) {
01425 enc = rb_enc_from_index(opt->ext.enc.index);
01426 }
01427 else {
01428 enc = lenc;
01429 }
01430 rb_enc_set_default_external(rb_enc_from_encoding(enc));
01431 if (opt->intern.enc.index >= 0) {
01432
01433 enc = rb_enc_from_index(opt->intern.enc.index);
01434 rb_enc_set_default_internal(rb_enc_from_encoding(enc));
01435 }
01436 else if (!rb_default_internal_encoding())
01437
01438 rb_enc_set_default_internal(Qnil);
01439 rb_stdio_set_default_encoding();
01440
01441 if (!tree) return Qfalse;
01442
01443 process_sflag(&opt->sflag);
01444 opt->xflag = 0;
01445
01446 if (opt->safe_level >= 4) {
01447 FL_UNSET(rb_argv, FL_TAINT);
01448 FL_UNSET(GET_VM()->load_path, FL_TAINT);
01449 }
01450
01451 if (opt->dump & DUMP_BIT(syntax)) {
01452 printf("Syntax OK\n");
01453 return Qtrue;
01454 }
01455
01456 if (opt->do_print) {
01457 PREPARE_PARSE_MAIN({
01458 tree = rb_parser_append_print(parser, tree);
01459 });
01460 }
01461 if (opt->do_loop) {
01462 PREPARE_PARSE_MAIN({
01463 tree = rb_parser_while_loop(parser, tree, opt->do_line, opt->do_split);
01464 });
01465 rb_define_global_function("sub", rb_f_sub, -1);
01466 rb_define_global_function("gsub", rb_f_gsub, -1);
01467 rb_define_global_function("chop", rb_f_chop, 0);
01468 rb_define_global_function("chomp", rb_f_chomp, -1);
01469 }
01470
01471 if (opt->dump & DUMP_BIT(parsetree) || opt->dump & DUMP_BIT(parsetree_with_comment)) {
01472 rb_io_write(rb_stdout, rb_parser_dump_tree(tree, opt->dump & DUMP_BIT(parsetree_with_comment)));
01473 rb_io_flush(rb_stdout);
01474 return Qtrue;
01475 }
01476
01477 PREPARE_PARSE_MAIN({
01478 VALUE path = Qnil;
01479 if (!opt->e_script && strcmp(opt->script, "-"))
01480 path = rb_realpath_internal(Qnil, opt->script_name, 1);
01481 iseq = rb_iseq_new_main(tree, opt->script_name, path);
01482 });
01483
01484 if (opt->dump & DUMP_BIT(insns)) {
01485 rb_io_write(rb_stdout, rb_iseq_disasm(iseq));
01486 rb_io_flush(rb_stdout);
01487 return Qtrue;
01488 }
01489
01490 rb_define_readonly_boolean("$-p", opt->do_print);
01491 rb_define_readonly_boolean("$-l", opt->do_line);
01492 rb_define_readonly_boolean("$-a", opt->do_split);
01493
01494 rb_set_safe_level(opt->safe_level);
01495 rb_gc_set_params();
01496
01497 return iseq;
01498 }
01499
01500 struct load_file_arg {
01501 VALUE parser;
01502 const char *fname;
01503 int script;
01504 struct cmdline_options *opt;
01505 };
01506
01507 static VALUE
01508 load_file_internal(VALUE arg)
01509 {
01510 extern VALUE rb_stdin;
01511 struct load_file_arg *argp = (struct load_file_arg *)arg;
01512 VALUE parser = argp->parser;
01513 const char *fname = argp->fname;
01514 int script = argp->script;
01515 struct cmdline_options *opt = argp->opt;
01516 VALUE f;
01517 int line_start = 1;
01518 NODE *tree = 0;
01519 rb_encoding *enc;
01520 ID set_encoding;
01521 int xflag = 0;
01522
01523 if (!fname)
01524 rb_load_fail(fname);
01525 if (strcmp(fname, "-") == 0) {
01526 f = rb_stdin;
01527 }
01528 else {
01529 int fd, mode = O_RDONLY;
01530 #if defined DOSISH || defined __CYGWIN__
01531 {
01532 const char *ext = strrchr(fname, '.');
01533 if (ext && STRCASECMP(ext, ".exe") == 0) {
01534 mode |= O_BINARY;
01535 xflag = 1;
01536 }
01537 }
01538 #endif
01539 if ((fd = open(fname, mode)) < 0) {
01540 rb_load_fail(fname);
01541 }
01542 rb_update_max_fd(fd);
01543
01544 f = rb_io_fdopen(fd, mode, fname);
01545 }
01546
01547 CONST_ID(set_encoding, "set_encoding");
01548 if (script) {
01549 VALUE c = 1;
01550 VALUE line;
01551 char *p;
01552 int no_src_enc = !opt->src.enc.name;
01553 int no_ext_enc = !opt->ext.enc.name;
01554 int no_int_enc = !opt->intern.enc.name;
01555
01556 enc = rb_ascii8bit_encoding();
01557 rb_funcall(f, set_encoding, 1, rb_enc_from_encoding(enc));
01558
01559 if (xflag || opt->xflag) {
01560 line_start--;
01561 search_shebang:
01562 forbid_setid("-x");
01563 opt->xflag = FALSE;
01564 while (!NIL_P(line = rb_io_gets(f))) {
01565 line_start++;
01566 if (RSTRING_LEN(line) > 2
01567 && RSTRING_PTR(line)[0] == '#'
01568 && RSTRING_PTR(line)[1] == '!') {
01569 if ((p = strstr(RSTRING_PTR(line), "ruby")) != 0) {
01570 goto start_read;
01571 }
01572 }
01573 }
01574 rb_raise(rb_eLoadError, "no Ruby script found in input");
01575 }
01576
01577 c = rb_io_getbyte(f);
01578 if (c == INT2FIX('#')) {
01579 c = rb_io_getbyte(f);
01580 if (c == INT2FIX('!')) {
01581 line = rb_io_gets(f);
01582 if (NIL_P(line))
01583 return 0;
01584
01585 if ((p = strstr(RSTRING_PTR(line), "ruby")) == 0) {
01586
01587 goto search_shebang;
01588 }
01589
01590 start_read:
01591 p += 4;
01592 RSTRING_PTR(line)[RSTRING_LEN(line) - 1] = '\0';
01593 if (RSTRING_PTR(line)[RSTRING_LEN(line) - 2] == '\r')
01594 RSTRING_PTR(line)[RSTRING_LEN(line) - 2] = '\0';
01595 if ((p = strstr(p, " -")) != 0) {
01596 moreswitches(p + 1, opt, 0);
01597 }
01598
01599
01600 rb_io_ungetbyte(f, rb_str_new2("!\n"));
01601 }
01602 else if (!NIL_P(c)) {
01603 rb_io_ungetbyte(f, c);
01604 }
01605 rb_io_ungetbyte(f, INT2FIX('#'));
01606 if (no_src_enc && opt->src.enc.name) {
01607 opt->src.enc.index = opt_enc_index(opt->src.enc.name);
01608 src_encoding_index = opt->src.enc.index;
01609 }
01610 if (no_ext_enc && opt->ext.enc.name) {
01611 opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
01612 }
01613 if (no_int_enc && opt->intern.enc.name) {
01614 opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
01615 }
01616 }
01617 else if (!NIL_P(c)) {
01618 rb_io_ungetbyte(f, c);
01619 }
01620 else {
01621 if (f != rb_stdin) rb_io_close(f);
01622 f = Qnil;
01623 }
01624 rb_vm_set_progname(rb_progname = opt->script_name);
01625 require_libraries(&opt->req_list);
01626 }
01627 if (opt->src.enc.index >= 0) {
01628 enc = rb_enc_from_index(opt->src.enc.index);
01629 }
01630 else if (f == rb_stdin) {
01631 enc = rb_locale_encoding();
01632 }
01633 else {
01634 enc = rb_usascii_encoding();
01635 }
01636 if (NIL_P(f)) {
01637 f = rb_str_new(0, 0);
01638 rb_enc_associate(f, enc);
01639 return (VALUE)rb_parser_compile_string(parser, fname, f, line_start);
01640 }
01641 rb_funcall(f, set_encoding, 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
01642 tree = rb_parser_compile_file(parser, fname, f, line_start);
01643 rb_funcall(f, set_encoding, 1, rb_parser_encoding(parser));
01644 if (script && tree && rb_parser_end_seen_p(parser)) {
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657 rb_define_global_const("DATA", f);
01658 }
01659 else if (f != rb_stdin) {
01660 rb_io_close(f);
01661 }
01662 return (VALUE)tree;
01663 }
01664
01665 static VALUE
01666 restore_lineno(VALUE lineno)
01667 {
01668 return rb_gv_set("$.", lineno);
01669 }
01670
01671 static NODE *
01672 load_file(VALUE parser, const char *fname, int script, struct cmdline_options *opt)
01673 {
01674 struct load_file_arg arg;
01675 arg.parser = parser;
01676 arg.fname = fname;
01677 arg.script = script;
01678 arg.opt = opt;
01679 return (NODE *)rb_ensure(load_file_internal, (VALUE)&arg, restore_lineno, rb_gv_get("$."));
01680 }
01681
01682 void *
01683 rb_load_file(const char *fname)
01684 {
01685 struct cmdline_options opt;
01686
01687 return load_file(rb_parser_new(), fname, 0, cmdline_options_init(&opt));
01688 }
01689
01690 static void
01691 set_arg0(VALUE val, ID id)
01692 {
01693 char *s;
01694 long i;
01695
01696 if (origarg.argv == 0)
01697 rb_raise(rb_eRuntimeError, "$0 not initialized");
01698 StringValue(val);
01699 s = RSTRING_PTR(val);
01700 i = RSTRING_LEN(val);
01701
01702 setproctitle("%.*s", (int)i, s);
01703
01704 rb_progname = rb_obj_freeze(rb_external_str_new(s, i));
01705 }
01706
01707 void
01708 ruby_script(const char *name)
01709 {
01710 if (name) {
01711 rb_progname = rb_external_str_new(name, strlen(name));
01712 rb_vm_set_progname(rb_progname);
01713 }
01714 }
01715
01716 static void
01717 init_ids(struct cmdline_options *opt)
01718 {
01719 rb_uid_t uid = getuid();
01720 rb_uid_t euid = geteuid();
01721 rb_gid_t gid = getgid();
01722 rb_gid_t egid = getegid();
01723
01724 if (uid != euid) opt->setids |= 1;
01725 if (egid != gid) opt->setids |= 2;
01726 if (uid && opt->setids) {
01727 if (opt->safe_level < 1) opt->safe_level = 1;
01728 }
01729 }
01730
01731 #undef forbid_setid
01732 static void
01733 forbid_setid(const char *s, struct cmdline_options *opt)
01734 {
01735 if (opt->setids & 1)
01736 rb_raise(rb_eSecurityError, "no %s allowed while running setuid", s);
01737 if (opt->setids & 2)
01738 rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s);
01739 if (opt->safe_level > 0)
01740 rb_raise(rb_eSecurityError, "no %s allowed in tainted mode", s);
01741 }
01742
01743 static void
01744 verbose_setter(VALUE val, ID id, void *data)
01745 {
01746 VALUE *variable = data;
01747 *variable = RTEST(val) ? Qtrue : val;
01748 }
01749
01750 static VALUE
01751 opt_W_getter(ID id, void *data)
01752 {
01753 VALUE *variable = data;
01754 switch (*variable) {
01755 case Qnil:
01756 return INT2FIX(0);
01757 case Qfalse:
01758 return INT2FIX(1);
01759 case Qtrue:
01760 return INT2FIX(2);
01761 }
01762 return Qnil;
01763 }
01764
01765 void
01766 ruby_prog_init(void)
01767 {
01768 rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter);
01769 rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter);
01770 rb_define_hooked_variable("$-w", &ruby_verbose, 0, verbose_setter);
01771 rb_define_hooked_variable("$-W", &ruby_verbose, opt_W_getter, rb_gvar_readonly_setter);
01772 rb_define_variable("$DEBUG", &ruby_debug);
01773 rb_define_variable("$-d", &ruby_debug);
01774
01775 rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0);
01776 rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);
01777
01778
01779
01780
01781
01782
01783
01784
01785 rb_define_global_const("ARGV", rb_argv);
01786 }
01787
01788 void
01789 ruby_set_argv(int argc, char **argv)
01790 {
01791 int i;
01792 VALUE av = rb_argv;
01793
01794 #if defined(USE_DLN_A_OUT)
01795 if (origarg.argv)
01796 dln_argv0 = origarg.argv[0];
01797 else
01798 dln_argv0 = argv[0];
01799 #endif
01800 rb_ary_clear(av);
01801 for (i = 0; i < argc; i++) {
01802 VALUE arg = rb_external_str_new_cstr(argv[i]);
01803
01804 OBJ_FREEZE(arg);
01805 rb_ary_push(av, arg);
01806 }
01807 }
01808
01809 void *
01810 ruby_process_options(int argc, char **argv)
01811 {
01812 struct cmdline_options opt;
01813 VALUE iseq;
01814
01815 ruby_script(argv[0]);
01816 rb_argv0 = rb_str_new4(rb_progname);
01817 rb_gc_register_mark_object(rb_argv0);
01818 iseq = process_options(argc, argv, cmdline_options_init(&opt));
01819
01820 #ifndef HAVE_SETPROCTITLE
01821 {
01822 extern void ruby_init_setproctitle(int argc, char *argv[]);
01823 ruby_init_setproctitle(argc, argv);
01824 }
01825 #endif
01826
01827 return (void*)(struct RData*)iseq;
01828 }
01829
01830 static void
01831 fill_standard_fds(void)
01832 {
01833 int f0, f1, f2, fds[2];
01834 struct stat buf;
01835 f0 = fstat(0, &buf) == -1 && errno == EBADF;
01836 f1 = fstat(1, &buf) == -1 && errno == EBADF;
01837 f2 = fstat(2, &buf) == -1 && errno == EBADF;
01838 if (f0) {
01839 if (pipe(fds) == 0) {
01840 close(fds[1]);
01841 if (fds[0] != 0) {
01842 dup2(fds[0], 0);
01843 close(fds[0]);
01844 }
01845 }
01846 }
01847 if (f1 || f2) {
01848 if (pipe(fds) == 0) {
01849 close(fds[0]);
01850 if (f1 && fds[1] != 1)
01851 dup2(fds[1], 1);
01852 if (f2 && fds[1] != 2)
01853 dup2(fds[1], 2);
01854 if (fds[1] != 1 && fds[1] != 2)
01855 close(fds[1]);
01856 }
01857 }
01858 }
01859
01860 void
01861 ruby_sysinit(int *argc, char ***argv)
01862 {
01863 #if defined(_WIN32)
01864 void rb_w32_sysinit(int *argc, char ***argv);
01865 rb_w32_sysinit(argc, argv);
01866 #endif
01867 origarg.argc = *argc;
01868 origarg.argv = *argv;
01869 #if defined(USE_DLN_A_OUT)
01870 dln_argv0 = origarg.argv[0];
01871 #endif
01872 fill_standard_fds();
01873 }
01874