Ruby  1.9.3p429(2013-05-15revision40747)
ruby.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  ruby.c -
4 
5  $Author: usa $
6  created at: Tue Aug 10 12:47:31 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9  Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10  Copyright (C) 2000 Information-technology Promotion Agency, Japan
11 
12 **********************************************************************/
13 
14 #ifdef __CYGWIN__
15 #include <windows.h>
16 #include <sys/cygwin.h>
17 #endif
18 #include "ruby/ruby.h"
19 #include "ruby/encoding.h"
20 #include "internal.h"
21 #include "eval_intern.h"
22 #include "dln.h"
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <ctype.h>
26 
27 #ifdef __hpux
28 #include <sys/pstat.h>
29 #endif
30 #if defined(LOAD_RELATIVE) && defined(HAVE_DLADDR)
31 #include <dlfcn.h>
32 #endif
33 
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37 #if defined(HAVE_FCNTL_H)
38 #include <fcntl.h>
39 #elif defined(HAVE_SYS_FCNTL_H)
40 #include <sys/fcntl.h>
41 #endif
42 #ifdef HAVE_SYS_PARAM_H
43 # include <sys/param.h>
44 #endif
45 #ifndef MAXPATHLEN
46 # define MAXPATHLEN 1024
47 #endif
48 
49 #include "ruby/util.h"
50 
51 #ifndef HAVE_STDLIB_H
52 char *getenv();
53 #endif
54 
55 #define DISABLE_BIT(bit) (1U << disable_##bit)
60 };
61 
62 #define DUMP_BIT(bit) (1U << dump_##bit)
73 };
74 
76  int sflag, xflag;
79  int do_search;
80  unsigned int disable;
81  int verbose;
83  unsigned int setids;
84  unsigned int dump;
85  const char *script;
88  struct {
89  struct {
91  int index;
92  } enc;
93  } src, ext, intern;
95 };
96 
97 static void init_ids(struct cmdline_options *);
98 
99 #define src_encoding_index GET_VM()->src_encoding_index
100 
101 static struct cmdline_options *
103 {
104  MEMZERO(opt, *opt, 1);
105  init_ids(opt);
106  opt->src.enc.index = src_encoding_index;
107  opt->ext.enc.index = -1;
108  opt->intern.enc.index = -1;
109 #if defined DISABLE_RUBYGEMS && DISABLE_RUBYGEMS
110  opt->disable |= DISABLE_BIT(gems);
111 #endif
112  return opt;
113 }
114 
115 static NODE *load_file(VALUE, const char *, int, struct cmdline_options *);
116 static void forbid_setid(const char *, struct cmdline_options *);
117 #define forbid_setid(s) forbid_setid((s), opt)
118 
119 static struct {
120  int argc;
121  char **argv;
122 } origarg;
123 
124 static void
125 usage(const char *name)
126 {
127  /* This message really ought to be max 23 lines.
128  * Removed -h because the user already knows that option. Others? */
129 
130  static const char *const usage_msg[] = {
131  "-0[octal] specify record separator (\\0, if no argument)",
132  "-a autosplit mode with -n or -p (splits $_ into $F)",
133  "-c check syntax only",
134  "-Cdirectory cd to directory, before executing your script",
135  "-d set debugging flags (set $DEBUG to true)",
136  "-e 'command' one line of script. Several -e's allowed. Omit [programfile]",
137  "-Eex[:in] specify the default external and internal character encodings",
138  "-Fpattern split() pattern for autosplit (-a)",
139  "-i[extension] edit ARGV files in place (make backup if extension supplied)",
140  "-Idirectory specify $LOAD_PATH directory (may be used more than once)",
141  "-l enable line ending processing",
142  "-n assume 'while gets(); ... end' loop around your script",
143  "-p assume loop like -n but print line also like sed",
144  "-rlibrary require the library, before executing your script",
145  "-s enable some switch parsing for switches after script name",
146  "-S look for the script using PATH environment variable",
147  "-T[level=1] turn on tainting checks",
148  "-v print version number, then turn on verbose mode",
149  "-w turn warnings on for your script",
150  "-W[level=2] set warning level; 0=silence, 1=medium, 2=verbose",
151  "-x[directory] strip off text before #!ruby line and perhaps cd to directory",
152  "--copyright print the copyright",
153  "--version print the version",
154  NULL
155  };
156  const char *const *p = usage_msg;
157 
158  printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name);
159  while (*p)
160  printf(" %s\n", *p++);
161 }
162 
163 #ifdef MANGLED_PATH
164 static VALUE
165 rubylib_mangled_path(const char *s, unsigned int l)
166 {
167  static char *newp, *oldp;
168  static int newl, oldl, notfound;
169  char *ptr;
170  VALUE ret;
171 
172  if (!newp && !notfound) {
173  newp = getenv("RUBYLIB_PREFIX");
174  if (newp) {
175  oldp = newp = strdup(newp);
176  while (*newp && !ISSPACE(*newp) && *newp != ';') {
177  newp = CharNext(newp); /* Skip digits. */
178  }
179  oldl = newp - oldp;
180  while (*newp && (ISSPACE(*newp) || *newp == ';')) {
181  newp = CharNext(newp); /* Skip whitespace. */
182  }
183  newl = strlen(newp);
184  if (newl == 0 || oldl == 0) {
185  rb_fatal("malformed RUBYLIB_PREFIX");
186  }
187  translit_char(newp, '\\', '/');
188  }
189  else {
190  notfound = 1;
191  }
192  }
193  if (!newp || l < oldl || STRNCASECMP(oldp, s, oldl) != 0) {
194  return rb_str_new(s, l);
195  }
196  ret = rb_str_new(0, l + newl - oldl);
197  ptr = RSTRING_PTR(ret);
198  memcpy(ptr, newp, newl);
199  memcpy(ptr + newl, s + oldl, l - oldl);
200  ptr[l + newl - oldl] = 0;
201  return ret;
202 }
203 #else
204 #define rubylib_mangled_path rb_str_new
205 #endif
206 
207 static void
208 push_include(const char *path, VALUE (*filter)(VALUE))
209 {
210  const char sep = PATH_SEP_CHAR;
211  const char *p, *s;
212  VALUE load_path = GET_VM()->load_path;
213 
214  p = path;
215  while (*p) {
216  while (*p == sep)
217  p++;
218  if (!*p) break;
219  for (s = p; *s && *s != sep; s = CharNext(s));
220  rb_ary_push(load_path, (*filter)(rubylib_mangled_path(p, s - p)));
221  p = s;
222  }
223 }
224 
225 #ifdef __CYGWIN__
226 static void
227 push_include_cygwin(const char *path, VALUE (*filter)(VALUE))
228 {
229  const char *p, *s;
230  char rubylib[FILENAME_MAX];
231  VALUE buf = 0;
232 
233  p = path;
234  while (*p) {
235  unsigned int len;
236  while (*p == ';')
237  p++;
238  if (!*p) break;
239  for (s = p; *s && *s != ';'; s = CharNext(s));
240  len = s - p;
241  if (*s) {
242  if (!buf) {
243  buf = rb_str_new(p, len);
244  p = RSTRING_PTR(buf);
245  }
246  else {
247  rb_str_resize(buf, len);
248  p = strncpy(RSTRING_PTR(buf), p, len);
249  }
250  }
251 #ifdef HAVE_CYGWIN_CONV_PATH
252 #define CONV_TO_POSIX_PATH(p, lib) \
253  cygwin_conv_path(CCP_WIN_A_TO_POSIX|CCP_RELATIVE, (p), (lib), sizeof(lib))
254 #else
255 #define CONV_TO_POSIX_PATH(p, lib) \
256  cygwin_conv_to_posix_path((p), (lib))
257 #endif
258  if (CONV_TO_POSIX_PATH(p, rubylib) == 0)
259  p = rubylib;
260  push_include(p, filter);
261  if (!*s) break;
262  p = s + 1;
263  }
264 }
265 
266 #define push_include push_include_cygwin
267 #endif
268 
269 void
270 ruby_push_include(const char *path, VALUE (*filter)(VALUE))
271 {
272  if (path == 0)
273  return;
274  push_include(path, filter);
275 }
276 
277 static VALUE
279 {
280  return path;
281 }
282 static VALUE
284 {
286  return path;
287 }
288 
289 void
290 ruby_incpush(const char *path)
291 {
293 }
294 
295 static VALUE
297 {
298  char *p = RSTRING_PTR(path);
299  if (!p)
300  return path;
301  if (*p == '.' && p[1] == '/')
302  return path;
303  return rb_file_expand_path(path, Qnil);
304 }
305 
306 void
307 ruby_incpush_expand(const char *path)
308 {
310 }
311 
312 #if defined _WIN32 || defined __CYGWIN__
313 static HMODULE libruby;
314 
315 BOOL WINAPI
316 DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
317 {
318  if (reason == DLL_PROCESS_ATTACH)
319  libruby = dll;
320  return TRUE;
321 }
322 
323 HANDLE
324 rb_libruby_handle(void)
325 {
326  return libruby;
327 }
328 #endif
329 
330 void ruby_init_loadpath_safe(int safe_level);
331 
332 void
334 {
336 }
337 
338 void
339 ruby_init_loadpath_safe(int safe_level)
340 {
341  VALUE load_path;
342  ID id_initial_load_path_mark;
343  extern const char ruby_initial_load_paths[];
344  const char *paths = ruby_initial_load_paths;
345 #if defined LOAD_RELATIVE
346 # if defined HAVE_DLADDR || defined HAVE_CYGWIN_CONV_PATH
347 # define VARIABLE_LIBPATH 1
348 # else
349 # define VARIABLE_LIBPATH 0
350 # endif
351 # if VARIABLE_LIBPATH
352  char *libpath;
353  VALUE sopath;
354 # else
355  char libpath[MAXPATHLEN + 1];
356 # endif
357  size_t baselen;
358  char *p;
359 
360 #if defined _WIN32 || defined __CYGWIN__
361 # if VARIABLE_LIBPATH
362  sopath = rb_str_new(0, MAXPATHLEN);
363  libpath = RSTRING_PTR(sopath);
364  GetModuleFileName(libruby, libpath, MAXPATHLEN);
365 # else
366  GetModuleFileName(libruby, libpath, sizeof libpath);
367 # endif
368 #elif defined(__EMX__)
369  _execname(libpath, sizeof(libpath) - 1);
370 #elif defined(HAVE_DLADDR)
371  Dl_info dli;
372  if (dladdr((void *)(VALUE)expand_include_path, &dli)) {
373  char fbuf[MAXPATHLEN];
374  char *f = dln_find_file_r(dli.dli_fname, getenv(PATH_ENV), fbuf, sizeof(fbuf));
375  VALUE fname = rb_str_new_cstr(f ? f : dli.dli_fname);
376  rb_str_freeze(fname);
377  sopath = rb_realpath_internal(Qnil, fname, 1);
378  }
379  else {
380  sopath = rb_str_new(0, 0);
381  }
382  libpath = RSTRING_PTR(sopath);
383 #endif
384 
385 #if !VARIABLE_LIBPATH
386  libpath[sizeof(libpath) - 1] = '\0';
387 #endif
388 #if defined DOSISH
389  translit_char(libpath, '\\', '/');
390 #elif defined __CYGWIN__
391  {
392 # if VARIABLE_LIBPATH
393  const int win_to_posix = CCP_WIN_A_TO_POSIX | CCP_RELATIVE;
394  size_t newsize = cygwin_conv_path(win_to_posix, libpath, 0, 0);
395  if (newsize > 0) {
396  VALUE rubylib = rb_str_new(0, newsize);
397  p = RSTRING_PTR(rubylib);
398  if (cygwin_conv_path(win_to_posix, libpath, p, newsize) == 0) {
399  rb_str_resize(sopath, 0);
400  sopath = rubylib;
401  libpath = p;
402  }
403  }
404 # else
405  char rubylib[FILENAME_MAX];
406  cygwin_conv_to_posix_path(libpath, rubylib);
407  strncpy(libpath, rubylib, sizeof(libpath));
408 # endif
409  }
410 #endif
411  p = strrchr(libpath, '/');
412  if (p) {
413  static const char bindir[] = "/bin";
414 #ifdef LIBDIR_BASENAME
415  static const char libdir[] = "/"LIBDIR_BASENAME;
416 #else
417  static const char libdir[] = "/lib";
418 #endif
419  const ptrdiff_t bindir_len = (ptrdiff_t)sizeof(bindir) - 1;
420  const ptrdiff_t libdir_len = (ptrdiff_t)sizeof(libdir) - 1;
421  *p = 0;
422  if (p - libpath >= bindir_len && !STRCASECMP(p - bindir_len, bindir)) {
423  p -= bindir_len;
424  *p = 0;
425  }
426  else if (p - libpath >= libdir_len && !STRCASECMP(p - libdir_len, libdir)) {
427  p -= libdir_len;
428  *p = 0;
429  }
430  }
431 #if !VARIABLE_LIBPATH
432  else {
433  strlcpy(libpath, ".", sizeof(libpath));
434  p = libpath + 1;
435  }
436  baselen = p - libpath;
437 #define PREFIX_PATH() rb_str_new(libpath, baselen)
438 #else
439  baselen = p - libpath;
440  rb_str_resize(sopath, baselen);
441  libpath = RSTRING_PTR(sopath);
442 #define PREFIX_PATH() sopath
443 #endif
444 
445 #define BASEPATH() rb_str_buf_cat(rb_str_buf_new(baselen+len), libpath, baselen)
446 
447 #define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), (path), (len))
448 #else
449  static const char exec_prefix[] = RUBY_EXEC_PREFIX;
450 #define RUBY_RELATIVE(path, len) rubylib_mangled_path((path), (len))
451 #define PREFIX_PATH() RUBY_RELATIVE(exec_prefix, sizeof(exec_prefix)-1)
452 #endif
453  load_path = GET_VM()->load_path;
454 
455  if (safe_level == 0) {
456 #ifdef MANGLED_PATH
457  rubylib_mangled_path("", 0);
458 #endif
460  }
461 
462  id_initial_load_path_mark = rb_intern_const("@gem_prelude_index");
463  while (*paths) {
464  size_t len = strlen(paths);
465  VALUE path = RUBY_RELATIVE(paths, len);
466  rb_ivar_set(path, id_initial_load_path_mark, path);
467  rb_ary_push(load_path, path);
468  paths += len + 1;
469  }
470 
472 }
473 
474 
475 static void
476 add_modules(VALUE *req_list, const char *mod)
477 {
478  VALUE list = *req_list;
479  VALUE feature;
480 
481  if (!list) {
482  *req_list = list = rb_ary_new();
483  RBASIC(list)->klass = 0;
484  }
485  feature = rb_str_new2(mod);
486  RBASIC(feature)->klass = 0;
487  rb_ary_push(list, feature);
488 }
489 
490 static void
492 {
493  VALUE list = *req_list;
494  VALUE self = rb_vm_top_self();
495  ID require;
496  rb_thread_t *th = GET_THREAD();
497  rb_block_t *prev_base_block = th->base_block;
499  int prev_parse_in_eval = th->parse_in_eval;
500  th->base_block = 0;
501  th->parse_in_eval = 0;
502 
503  Init_ext(); /* should be called here for some reason :-( */
504  CONST_ID(require, "require");
505  while (list && RARRAY_LEN(list) > 0) {
506  VALUE feature = rb_ary_shift(list);
507  rb_enc_associate(feature, extenc);
508  RBASIC(feature)->klass = rb_cString;
509  OBJ_FREEZE(feature);
510  rb_funcall2(self, require, 1, &feature);
511  }
512  *req_list = 0;
513 
514  th->parse_in_eval = prev_parse_in_eval;
515  th->base_block = prev_base_block;
516 }
517 
518 static void
519 process_sflag(int *sflag)
520 {
521  if (*sflag > 0) {
522  long n;
523  VALUE *args;
524  VALUE argv = rb_argv;
525 
526  n = RARRAY_LEN(argv);
527  args = RARRAY_PTR(argv);
528  while (n > 0) {
529  VALUE v = *args++;
530  char *s = StringValuePtr(v);
531  char *p;
532  int hyphen = FALSE;
533 
534  if (s[0] != '-')
535  break;
536  n--;
537  if (s[1] == '-' && s[2] == '\0')
538  break;
539 
540  v = Qtrue;
541  /* check if valid name before replacing - with _ */
542  for (p = s + 1; *p; p++) {
543  if (*p == '=') {
544  *p++ = '\0';
545  v = rb_str_new2(p);
546  break;
547  }
548  if (*p == '-') {
549  hyphen = TRUE;
550  }
551  else if (*p != '_' && !ISALNUM(*p)) {
552  VALUE name_error[2];
553  name_error[0] =
554  rb_str_new2("invalid name for global variable - ");
555  if (!(p = strchr(p, '='))) {
556  rb_str_cat2(name_error[0], s);
557  }
558  else {
559  rb_str_cat(name_error[0], s, p - s);
560  }
561  name_error[1] = args[-1];
563  }
564  }
565  s[0] = '$';
566  if (hyphen) {
567  for (p = s + 1; *p; ++p) {
568  if (*p == '-')
569  *p = '_';
570  }
571  }
572  rb_gv_set(s, v);
573  }
574  n = RARRAY_LEN(argv) - n;
575  while (n--) {
576  rb_ary_shift(argv);
577  }
578  *sflag = -1;
579  }
580 }
581 
582 static long proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt);
583 
584 static void
585 moreswitches(const char *s, struct cmdline_options *opt, int envopt)
586 {
587  long argc, i, len;
588  char **argv, *p;
589  const char *ap = 0;
590  VALUE argstr, argary;
591 
592  while (ISSPACE(*s)) s++;
593  if (!*s) return;
594  argstr = rb_str_tmp_new((len = strlen(s)) + 2);
595  argary = rb_str_tmp_new(0);
596 
597  p = RSTRING_PTR(argstr);
598  *p++ = ' ';
599  memcpy(p, s, len + 1);
600  ap = 0;
601  rb_str_cat(argary, (char *)&ap, sizeof(ap));
602  while (*p) {
603  ap = p;
604  rb_str_cat(argary, (char *)&ap, sizeof(ap));
605  while (*p && !ISSPACE(*p)) ++p;
606  if (!*p) break;
607  *p++ = '\0';
608  while (ISSPACE(*p)) ++p;
609  }
610  argc = RSTRING_LEN(argary) / sizeof(ap);
611  ap = 0;
612  rb_str_cat(argary, (char *)&ap, sizeof(ap));
613  argv = (char **)RSTRING_PTR(argary);
614 
615  while ((i = proc_options(argc, argv, opt, envopt)) > 1 && (argc -= i) > 0) {
616  argv += i;
617  if (**argv != '-') {
618  *--*argv = '-';
619  }
620  if ((*argv)[1]) {
621  ++argc;
622  --argv;
623  }
624  }
625 
626  /* get rid of GC */
627  rb_str_resize(argary, 0);
628  rb_str_resize(argstr, 0);
629 }
630 
631 #define NAME_MATCH_P(name, str, len) \
632  ((len) < (int)sizeof(name) && strncmp((str), (name), (len)) == 0)
633 
634 #define UNSET_WHEN(name, bit, str, len) \
635  if (NAME_MATCH_P((name), (str), (len))) { \
636  *(unsigned int *)arg &= ~(bit); \
637  return; \
638  }
639 
640 #define SET_WHEN(name, bit, str, len) \
641  if (NAME_MATCH_P((name), (str), (len))) { \
642  *(unsigned int *)arg |= (bit); \
643  return; \
644  }
645 
646 static void
647 enable_option(const char *str, int len, void *arg)
648 {
649 #define UNSET_WHEN_DISABLE(bit) UNSET_WHEN(#bit, DISABLE_BIT(bit), str, len)
650  UNSET_WHEN_DISABLE(gems);
651  UNSET_WHEN_DISABLE(rubyopt);
652  if (NAME_MATCH_P("all", str, len)) {
653  *(unsigned int *)arg = 0U;
654  return;
655  }
656  rb_warn("unknown argument for --enable: `%.*s'", len, str);
657 }
658 
659 static void
660 disable_option(const char *str, int len, void *arg)
661 {
662 #define SET_WHEN_DISABLE(bit) SET_WHEN(#bit, DISABLE_BIT(bit), str, len)
663  SET_WHEN_DISABLE(gems);
664  SET_WHEN_DISABLE(rubyopt);
665  if (NAME_MATCH_P("all", str, len)) {
666  *(unsigned int *)arg = ~0U;
667  return;
668  }
669  rb_warn("unknown argument for --disable: `%.*s'", len, str);
670 }
671 
672 static void
673 dump_option(const char *str, int len, void *arg)
674 {
675 #define SET_WHEN_DUMP(bit) SET_WHEN(#bit, DUMP_BIT(bit), str, len)
677  SET_WHEN_DUMP(copyright);
680  SET_WHEN_DUMP(syntax);
681  SET_WHEN_DUMP(parsetree);
682  SET_WHEN_DUMP(parsetree_with_comment);
683  SET_WHEN_DUMP(insns);
684  rb_warn("don't know how to dump `%.*s',", len, str);
685  rb_warn("but only [version, copyright, usage, yydebug, syntax, parsetree, parsetree_with_comment, insns].");
686 }
687 
688 static void
689 set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen)
690 {
691  VALUE ename;
692 
693  if (!elen) elen = strlen(e);
694  ename = rb_str_new(e, elen);
695 
696  if (*name &&
697  rb_funcall(ename, rb_intern("casecmp"), 1, *name) != INT2FIX(0)) {
699  "%s already set to %s", type, RSTRING_PTR(*name));
700  }
701  *name = ename;
702 }
703 
704 #define set_internal_encoding_once(opt, e, elen) \
705  set_option_encoding_once("default_internal", &(opt)->intern.enc.name, (e), (elen))
706 #define set_external_encoding_once(opt, e, elen) \
707  set_option_encoding_once("default_external", &(opt)->ext.enc.name, (e), (elen))
708 #define set_source_encoding_once(opt, e, elen) \
709  set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen))
710 
711 static long
712 proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt)
713 {
714  long n, argc0 = argc;
715  const char *s;
716 
717  if (argc == 0)
718  return 0;
719 
720  for (argc--, argv++; argc > 0; argc--, argv++) {
721  const char *const arg = argv[0];
722  if (arg[0] != '-' || !arg[1])
723  break;
724 
725  s = arg + 1;
726  reswitch:
727  switch (*s) {
728  case 'a':
729  if (envopt) goto noenvopt;
730  opt->do_split = TRUE;
731  s++;
732  goto reswitch;
733 
734  case 'p':
735  if (envopt) goto noenvopt;
736  opt->do_print = TRUE;
737  /* through */
738  case 'n':
739  if (envopt) goto noenvopt;
740  opt->do_loop = TRUE;
741  s++;
742  goto reswitch;
743 
744  case 'd':
745  ruby_debug = Qtrue;
747  s++;
748  goto reswitch;
749 
750  case 'y':
751  if (envopt) goto noenvopt;
752  opt->dump |= DUMP_BIT(yydebug);
753  s++;
754  goto reswitch;
755 
756  case 'v':
757  if (opt->verbose) {
758  s++;
759  goto reswitch;
760  }
762  opt->verbose = 1;
763  case 'w':
765  s++;
766  goto reswitch;
767 
768  case 'W':
769  {
770  size_t numlen;
771  int v = 2; /* -W as -W2 */
772 
773  if (*++s) {
774  v = scan_oct(s, 1, &numlen);
775  if (numlen == 0)
776  v = 1;
777  s += numlen;
778  }
779  switch (v) {
780  case 0:
781  ruby_verbose = Qnil;
782  break;
783  case 1:
785  break;
786  default:
788  break;
789  }
790  }
791  goto reswitch;
792 
793  case 'c':
794  if (envopt) goto noenvopt;
795  opt->dump |= DUMP_BIT(syntax);
796  s++;
797  goto reswitch;
798 
799  case 's':
800  if (envopt) goto noenvopt;
801  forbid_setid("-s");
802  if (!opt->sflag) opt->sflag = 1;
803  s++;
804  goto reswitch;
805 
806  case 'h':
807  if (envopt) goto noenvopt;
808  opt->dump |= DUMP_BIT(usage);
809  goto switch_end;
810 
811  case 'l':
812  if (envopt) goto noenvopt;
813  opt->do_line = TRUE;
815  s++;
816  goto reswitch;
817 
818  case 'S':
819  if (envopt) goto noenvopt;
820  forbid_setid("-S");
821  opt->do_search = TRUE;
822  s++;
823  goto reswitch;
824 
825  case 'e':
826  if (envopt) goto noenvopt;
827  forbid_setid("-e");
828  if (!*++s) {
829  s = argv[1];
830  argc--, argv++;
831  }
832  if (!s) {
833  rb_raise(rb_eRuntimeError, "no code specified for -e");
834  }
835  if (!opt->e_script) {
836  opt->e_script = rb_str_new(0, 0);
837  if (opt->script == 0)
838  opt->script = "-e";
839  }
840  rb_str_cat2(opt->e_script, s);
841  rb_str_cat2(opt->e_script, "\n");
842  break;
843 
844  case 'r':
845  forbid_setid("-r");
846  if (*++s) {
847  add_modules(&opt->req_list, s);
848  }
849  else if (argv[1]) {
850  add_modules(&opt->req_list, argv[1]);
851  argc--, argv++;
852  }
853  break;
854 
855  case 'i':
856  if (envopt) goto noenvopt;
857  forbid_setid("-i");
858  ruby_set_inplace_mode(s + 1);
859  break;
860 
861  case 'x':
862  if (envopt) goto noenvopt;
863  opt->xflag = TRUE;
864  s++;
865  if (*s && chdir(s) < 0) {
866  rb_fatal("Can't chdir to %s", s);
867  }
868  break;
869 
870  case 'C':
871  case 'X':
872  if (envopt) goto noenvopt;
873  s++;
874  if (!*s) {
875  s = argv[1];
876  argc--, argv++;
877  }
878  if (!s || !*s) {
879  rb_fatal("Can't chdir");
880  }
881  if (chdir(s) < 0) {
882  rb_fatal("Can't chdir to %s", s);
883  }
884  break;
885 
886  case 'F':
887  if (envopt) goto noenvopt;
888  if (*++s) {
889  rb_fs = rb_reg_new(s, strlen(s), 0);
890  }
891  break;
892 
893  case 'E':
894  if (!*++s && (!--argc || !(s = *++argv))) {
895  rb_raise(rb_eRuntimeError, "missing argument for -E");
896  }
897  goto encoding;
898 
899  case 'U':
900  set_internal_encoding_once(opt, "UTF-8", 0);
901  ++s;
902  goto reswitch;
903 
904  case 'K':
905  if (*++s) {
906  const char *enc_name = 0;
907  switch (*s) {
908  case 'E': case 'e':
909  enc_name = "EUC-JP";
910  break;
911  case 'S': case 's':
912  enc_name = "Windows-31J";
913  break;
914  case 'U': case 'u':
915  enc_name = "UTF-8";
916  break;
917  case 'N': case 'n': case 'A': case 'a':
918  enc_name = "ASCII-8BIT";
919  break;
920  }
921  if (enc_name) {
922  opt->src.enc.name = rb_str_new2(enc_name);
923  if (!opt->ext.enc.name)
924  opt->ext.enc.name = opt->src.enc.name;
925  }
926  s++;
927  }
928  goto reswitch;
929 
930  case 'T':
931  {
932  size_t numlen;
933  int v = 1;
934 
935  if (*++s) {
936  v = scan_oct(s, 2, &numlen);
937  if (numlen == 0)
938  v = 1;
939  s += numlen;
940  }
941  if (v > opt->safe_level) opt->safe_level = v;
942  }
943  goto reswitch;
944 
945  case 'I':
946  forbid_setid("-I");
947  if (*++s)
949  else if (argv[1]) {
950  ruby_incpush_expand(argv[1]);
951  argc--, argv++;
952  }
953  break;
954 
955  case '0':
956  if (envopt) goto noenvopt;
957  {
958  size_t numlen;
959  int v;
960  char c;
961 
962  v = scan_oct(s, 4, &numlen);
963  s += numlen;
964  if (v > 0377)
965  rb_rs = Qnil;
966  else if (v == 0 && numlen >= 2) {
967  rb_rs = rb_str_new2("\n\n");
968  }
969  else {
970  c = v & 0xff;
971  rb_rs = rb_str_new(&c, 1);
972  }
973  }
974  goto reswitch;
975 
976  case '-':
977  if (!s[1] || (s[1] == '\r' && !s[2])) {
978  argc--, argv++;
979  goto switch_end;
980  }
981  s++;
982 
983 # define is_option_end(c, allow_hyphen) \
984  (!(c) || ((allow_hyphen) && (c) == '-') || (c) == '=')
985 # define check_envopt(name, allow_envopt) \
986  (((allow_envopt) || !envopt) ? (void)0 : \
987  rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name))
988 # define need_argument(name, s) \
989  ((*(s)++ ? !*(s) : (!--argc || !((s) = *++argv))) ? \
990  rb_raise(rb_eRuntimeError, "missing argument for --" name) \
991  : (void)0)
992 # define is_option_with_arg(name, allow_hyphen, allow_envopt) \
993  (strncmp((name), s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], (allow_hyphen)) ? \
994  (check_envopt(name, (allow_envopt)), s += n, need_argument(name, s), 1) : 0)
995 
996  if (strcmp("copyright", s) == 0) {
997  if (envopt) goto noenvopt_long;
998  opt->dump |= DUMP_BIT(copyright);
999  }
1000  else if (strcmp("debug", s) == 0) {
1001  ruby_debug = Qtrue;
1002  ruby_verbose = Qtrue;
1003  }
1004  else if (is_option_with_arg("enable", Qtrue, Qtrue)) {
1006  }
1007  else if (is_option_with_arg("disable", Qtrue, Qtrue)) {
1009  }
1010  else if (is_option_with_arg("encoding", Qfalse, Qtrue)) {
1011  char *p;
1012  encoding:
1013  do {
1014 # define set_encoding_part(type) \
1015  if (!(p = strchr(s, ':'))) { \
1016  set_##type##_encoding_once(opt, s, 0); \
1017  break; \
1018  } \
1019  else if (p > s) { \
1020  set_##type##_encoding_once(opt, s, p-s); \
1021  }
1022  set_encoding_part(external);
1023  if (!*(s = ++p)) break;
1024  set_encoding_part(internal);
1025  if (!*(s = ++p)) break;
1026 #if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
1027  set_encoding_part(source);
1028  if (!*(s = ++p)) break;
1029 #endif
1030  rb_raise(rb_eRuntimeError, "extra argument for %s: %s",
1031  (arg[1] == '-' ? "--encoding" : "-E"), s);
1032 # undef set_encoding_part
1033  } while (0);
1034  }
1035  else if (is_option_with_arg("internal-encoding", Qfalse, Qtrue)) {
1036  set_internal_encoding_once(opt, s, 0);
1037  }
1038  else if (is_option_with_arg("external-encoding", Qfalse, Qtrue)) {
1039  set_external_encoding_once(opt, s, 0);
1040  }
1041 #if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
1042  else if (is_option_with_arg("source-encoding", Qfalse, Qtrue)) {
1043  set_source_encoding_once(opt, s, 0);
1044  }
1045 #endif
1046  else if (strcmp("version", s) == 0) {
1047  if (envopt) goto noenvopt_long;
1048  opt->dump |= DUMP_BIT(version);
1049  }
1050  else if (strcmp("verbose", s) == 0) {
1051  opt->verbose = 1;
1052  ruby_verbose = Qtrue;
1053  }
1054  else if (strcmp("yydebug", s) == 0) {
1055  if (envopt) goto noenvopt_long;
1056  opt->dump |= DUMP_BIT(yydebug);
1057  }
1058  else if (is_option_with_arg("dump", Qfalse, Qfalse)) {
1059  ruby_each_words(s, dump_option, &opt->dump);
1060  }
1061  else if (strcmp("help", s) == 0) {
1062  if (envopt) goto noenvopt_long;
1063  opt->dump |= DUMP_BIT(usage);
1064  goto switch_end;
1065  }
1066  else {
1068  "invalid option --%s (-h will show valid options)", s);
1069  }
1070  break;
1071 
1072  case '\r':
1073  if (!s[1])
1074  break;
1075 
1076  default:
1077  {
1078  if (ISPRINT(*s)) {
1080  "invalid option -%c (-h will show valid options)",
1081  (int)(unsigned char)*s);
1082  }
1083  else {
1085  "invalid option -\\x%02X (-h will show valid options)",
1086  (int)(unsigned char)*s);
1087  }
1088  }
1089  goto switch_end;
1090 
1091  noenvopt:
1092  /* "EIdvwWrKU" only */
1093  rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: -%c", *s);
1094  break;
1095 
1096  noenvopt_long:
1097  rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --%s", s);
1098  break;
1099 
1100  case 0:
1101  break;
1102 # undef is_option_end
1103 # undef check_envopt
1104 # undef need_argument
1105 # undef is_option_with_arg
1106  }
1107  }
1108 
1109  switch_end:
1110  return argc0 - argc;
1111 }
1112 
1113 static void
1115 {
1116  Init_prelude();
1117  rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"));
1118 }
1119 
1120 static int
1122 {
1123  const char *s = RSTRING_PTR(enc_name);
1124  int i = rb_enc_find_index(s);
1125 
1126  if (i < 0) {
1127  rb_raise(rb_eRuntimeError, "unknown encoding name - %s", s);
1128  }
1129  else if (rb_enc_dummy_p(rb_enc_from_index(i))) {
1130  rb_raise(rb_eRuntimeError, "dummy encoding is not acceptable - %s ", s);
1131  }
1132  return i;
1133 }
1134 
1135 #define rb_progname (GET_VM()->progname)
1137 
1138 static VALUE
1140 {
1141  return Qfalse;
1142 }
1143 
1144 static VALUE
1146 {
1147  return Qtrue;
1148 }
1149 
1150 #define rb_define_readonly_boolean(name, val) \
1151  rb_define_virtual_variable((name), (val) ? true_value : false_value, 0)
1152 
1153 static VALUE
1155 {
1156  VALUE line;
1157 
1158  line = rb_lastline_get();
1159  if (TYPE(line) != T_STRING) {
1160  rb_raise(rb_eTypeError, "$_ value need to be String (%s given)",
1161  NIL_P(line) ? "nil" : rb_obj_classname(line));
1162  }
1163  return line;
1164 }
1165 
1166 /*
1167  * call-seq:
1168  * sub(pattern, replacement) -> $_
1169  * sub(pattern) { block } -> $_
1170  *
1171  * Equivalent to <code>$_.sub(<i>args</i>)</code>, except that
1172  * <code>$_</code> will be updated if substitution occurs.
1173  * Available only when -p/-n command line option specified.
1174  */
1175 
1176 static VALUE
1178  int argc;
1179  VALUE *argv;
1180 {
1181  VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("sub"), argc, argv);
1182  rb_lastline_set(str);
1183  return str;
1184 }
1185 
1186 /*
1187  * call-seq:
1188  * gsub(pattern, replacement) -> string
1189  * gsub(pattern) {|...| block } -> string
1190  *
1191  * Equivalent to <code>$_.gsub...</code>, except that <code>$_</code>
1192  * receives the modified result.
1193  * Available only when -p/-n command line option specified.
1194  *
1195  */
1196 
1197 static VALUE
1199  int argc;
1200  VALUE *argv;
1201 {
1202  VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("gsub"), argc, argv);
1203  rb_lastline_set(str);
1204  return str;
1205 }
1206 
1207 /*
1208  * call-seq:
1209  * chop -> string
1210  *
1211  * Equivalent to <code>($_.dup).chop!</code>, except <code>nil</code>
1212  * is never returned. See <code>String#chop!</code>.
1213  * Available only when -p/-n command line option specified.
1214  *
1215  */
1216 
1217 static VALUE
1219 {
1220  VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chop"), 0, 0);
1221  rb_lastline_set(str);
1222  return str;
1223 }
1224 
1225 
1226 /*
1227  * call-seq:
1228  * chomp -> $_
1229  * chomp(string) -> $_
1230  *
1231  * Equivalent to <code>$_ = $_.chomp(<em>string</em>)</code>. See
1232  * <code>String#chomp</code>.
1233  * Available only when -p/-n command line option specified.
1234  *
1235  */
1236 
1237 static VALUE
1239  int argc;
1240  VALUE *argv;
1241 {
1242  VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chomp"), argc, argv);
1243  rb_lastline_set(str);
1244  return str;
1245 }
1246 
1247 static VALUE
1248 process_options(int argc, char **argv, struct cmdline_options *opt)
1249 {
1250  NODE *tree = 0;
1251  VALUE parser;
1252  VALUE iseq;
1253  rb_encoding *enc, *lenc;
1254  const char *s;
1255  char fbuf[MAXPATHLEN];
1256  int i = (int)proc_options(argc, argv, opt, 0);
1257  rb_thread_t *th = GET_THREAD();
1258  rb_env_t *env = 0;
1259 
1260  argc -= i;
1261  argv += i;
1262 
1263  if (opt->dump & DUMP_BIT(usage)) {
1264  usage(origarg.argv[0]);
1265  return Qtrue;
1266  }
1267 
1268  if (!(opt->disable & DISABLE_BIT(rubyopt)) &&
1269  opt->safe_level == 0 && (s = getenv("RUBYOPT"))) {
1270  VALUE src_enc_name = opt->src.enc.name;
1271  VALUE ext_enc_name = opt->ext.enc.name;
1272  VALUE int_enc_name = opt->intern.enc.name;
1273 
1274  opt->src.enc.name = opt->ext.enc.name = opt->intern.enc.name = 0;
1275  moreswitches(s, opt, 1);
1276  if (src_enc_name)
1277  opt->src.enc.name = src_enc_name;
1278  if (ext_enc_name)
1279  opt->ext.enc.name = ext_enc_name;
1280  if (int_enc_name)
1281  opt->intern.enc.name = int_enc_name;
1282  }
1283 
1284  if (opt->dump & DUMP_BIT(version)) {
1286  return Qtrue;
1287  }
1288  if (opt->dump & DUMP_BIT(copyright)) {
1290  }
1291 
1292  if (opt->safe_level >= 4) {
1293  OBJ_TAINT(rb_argv);
1294  OBJ_TAINT(GET_VM()->load_path);
1295  }
1296 
1297  if (!opt->e_script) {
1298  if (argc == 0) { /* no more args */
1299  if (opt->verbose)
1300  return Qtrue;
1301  opt->script = "-";
1302  }
1303  else {
1304  opt->script = argv[0];
1305  if (opt->script[0] == '\0') {
1306  opt->script = "-";
1307  }
1308  else if (opt->do_search) {
1309  char *path = getenv("RUBYPATH");
1310 
1311  opt->script = 0;
1312  if (path) {
1313  opt->script = dln_find_file_r(argv[0], path, fbuf, sizeof(fbuf));
1314  }
1315  if (!opt->script) {
1316  opt->script = dln_find_file_r(argv[0], getenv(PATH_ENV), fbuf, sizeof(fbuf));
1317  }
1318  if (!opt->script)
1319  opt->script = argv[0];
1320  }
1321  argc--;
1322  argv++;
1323  }
1324  }
1325 
1326  opt->script_name = rb_str_new_cstr(opt->script);
1327  opt->script = RSTRING_PTR(opt->script_name);
1328 #if defined DOSISH || defined __CYGWIN__
1329  translit_char(RSTRING_PTR(opt->script_name), '\\', '/');
1330 #endif
1331 
1333  rb_enc_find_index("encdb");
1334  lenc = rb_locale_encoding();
1337  parser = rb_parser_new();
1338  if (opt->dump & DUMP_BIT(yydebug)) {
1339  rb_parser_set_yydebug(parser, Qtrue);
1340  }
1341  if (opt->ext.enc.name != 0) {
1342  opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
1343  }
1344  if (opt->intern.enc.name != 0) {
1345  opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
1346  }
1347  if (opt->src.enc.name != 0) {
1348  opt->src.enc.index = opt_enc_index(opt->src.enc.name);
1349  src_encoding_index = opt->src.enc.index;
1350  }
1351  if (opt->ext.enc.index >= 0) {
1352  enc = rb_enc_from_index(opt->ext.enc.index);
1353  }
1354  else {
1355  enc = lenc;
1356  }
1358  if (opt->intern.enc.index >= 0) {
1359  enc = rb_enc_from_index(opt->intern.enc.index);
1361  opt->intern.enc.index = -1;
1362  }
1363  rb_enc_associate(opt->script_name, lenc);
1364  rb_obj_freeze(opt->script_name);
1365  {
1366  long i;
1367  VALUE load_path = GET_VM()->load_path;
1368  for (i = 0; i < RARRAY_LEN(load_path); ++i) {
1369  rb_enc_associate(RARRAY_PTR(load_path)[i], lenc);
1370  }
1371  }
1372  if (!(opt->disable & DISABLE_BIT(gems))) {
1373 #if defined DISABLE_RUBYGEMS && DISABLE_RUBYGEMS
1374  rb_require("rubygems");
1375 #else
1376  rb_define_module("Gem");
1377 #endif
1378  }
1380  ruby_set_argv(argc, argv);
1381  process_sflag(&opt->sflag);
1382 
1383  {
1384  /* set eval context */
1385  VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING"));
1386  rb_binding_t *bind;
1387 
1388  GetBindingPtr(toplevel_binding, bind);
1389  GetEnvPtr(bind->env, env);
1390  }
1391 
1392 #define PREPARE_PARSE_MAIN(expr) do { \
1393  th->parse_in_eval--; \
1394  th->base_block = &env->block; \
1395  expr; \
1396  th->parse_in_eval++; \
1397  th->base_block = 0; \
1398 } while (0)
1399 
1400  if (opt->e_script) {
1401  VALUE progname = rb_progname;
1402  rb_encoding *eenc;
1403  if (opt->src.enc.index >= 0) {
1404  eenc = rb_enc_from_index(opt->src.enc.index);
1405  }
1406  else {
1407  eenc = lenc;
1408  }
1409  rb_enc_associate(opt->e_script, eenc);
1411  require_libraries(&opt->req_list);
1412  rb_vm_set_progname(rb_progname = progname);
1413 
1415  tree = rb_parser_compile_string(parser, opt->script, opt->e_script, 1);
1416  });
1417  }
1418  else {
1419  if (opt->script[0] == '-' && !opt->script[1]) {
1420  forbid_setid("program input from stdin");
1421  }
1422 
1424  tree = load_file(parser, opt->script, 1, opt);
1425  });
1426  }
1427  rb_progname = opt->script_name;
1429  if (opt->dump & DUMP_BIT(yydebug)) return Qtrue;
1430 
1431  if (opt->ext.enc.index >= 0) {
1432  enc = rb_enc_from_index(opt->ext.enc.index);
1433  }
1434  else {
1435  enc = lenc;
1436  }
1438  if (opt->intern.enc.index >= 0) {
1439  /* Set in the shebang line */
1440  enc = rb_enc_from_index(opt->intern.enc.index);
1442  }
1443  else if (!rb_default_internal_encoding())
1444  /* Freeze default_internal */
1447 
1448  if (!tree) return Qfalse;
1449 
1450  process_sflag(&opt->sflag);
1451  opt->xflag = 0;
1452 
1453  if (opt->safe_level >= 4) {
1455  FL_UNSET(GET_VM()->load_path, FL_TAINT);
1456  }
1457 
1458  if (opt->dump & DUMP_BIT(syntax)) {
1459  printf("Syntax OK\n");
1460  return Qtrue;
1461  }
1462 
1463  if (opt->do_print) {
1465  tree = rb_parser_append_print(parser, tree);
1466  });
1467  }
1468  if (opt->do_loop) {
1470  tree = rb_parser_while_loop(parser, tree, opt->do_line, opt->do_split);
1471  });
1472  rb_define_global_function("sub", rb_f_sub, -1);
1473  rb_define_global_function("gsub", rb_f_gsub, -1);
1475  rb_define_global_function("chomp", rb_f_chomp, -1);
1476  }
1477 
1478  if (opt->dump & DUMP_BIT(parsetree) || opt->dump & DUMP_BIT(parsetree_with_comment)) {
1479  rb_io_write(rb_stdout, rb_parser_dump_tree(tree, opt->dump & DUMP_BIT(parsetree_with_comment)));
1481  return Qtrue;
1482  }
1483 
1485  VALUE path = Qnil;
1486  if (!opt->e_script && strcmp(opt->script, "-"))
1487  path = rb_realpath_internal(Qnil, opt->script_name, 1);
1488  iseq = rb_iseq_new_main(tree, opt->script_name, path);
1489  });
1490 
1491  if (opt->dump & DUMP_BIT(insns)) {
1494  return Qtrue;
1495  }
1496 
1497  rb_define_readonly_boolean("$-p", opt->do_print);
1498  rb_define_readonly_boolean("$-l", opt->do_line);
1499  rb_define_readonly_boolean("$-a", opt->do_split);
1500 
1502  rb_gc_set_params();
1503 
1504  return iseq;
1505 }
1506 
1509  const char *fname;
1510  int script;
1512 };
1513 
1514 static VALUE
1516 {
1517  extern VALUE rb_stdin;
1518  struct load_file_arg *argp = (struct load_file_arg *)arg;
1519  VALUE parser = argp->parser;
1520  const char *fname = argp->fname;
1521  int script = argp->script;
1522  struct cmdline_options *opt = argp->opt;
1523  VALUE f;
1524  int line_start = 1;
1525  NODE *tree = 0;
1526  rb_encoding *enc;
1527  ID set_encoding;
1528  int xflag = 0;
1529 
1530  if (!fname)
1531  rb_load_fail(fname);
1532  if (strcmp(fname, "-") == 0) {
1533  f = rb_stdin;
1534  }
1535  else {
1536  int fd, mode = O_RDONLY;
1537 #if defined DOSISH || defined __CYGWIN__
1538  {
1539  const char *ext = strrchr(fname, '.');
1540  if (ext && STRCASECMP(ext, ".exe") == 0) {
1541  mode |= O_BINARY;
1542  xflag = 1;
1543  }
1544  }
1545 #endif
1546  if ((fd = open(fname, mode)) < 0) {
1547  rb_load_fail(fname);
1548  }
1549  rb_update_max_fd(fd);
1550 
1551  f = rb_io_fdopen(fd, mode, fname);
1552  }
1553 
1554  CONST_ID(set_encoding, "set_encoding");
1555  if (script) {
1556  VALUE c = 1; /* something not nil */
1557  VALUE line;
1558  char *p;
1559  int no_src_enc = !opt->src.enc.name;
1560  int no_ext_enc = !opt->ext.enc.name;
1561  int no_int_enc = !opt->intern.enc.name;
1562 
1563  enc = rb_ascii8bit_encoding();
1564  rb_funcall(f, set_encoding, 1, rb_enc_from_encoding(enc));
1565 
1566  if (xflag || opt->xflag) {
1567  line_start--;
1568  search_shebang:
1569  forbid_setid("-x");
1570  opt->xflag = FALSE;
1571  while (!NIL_P(line = rb_io_gets(f))) {
1572  line_start++;
1573  if (RSTRING_LEN(line) > 2
1574  && RSTRING_PTR(line)[0] == '#'
1575  && RSTRING_PTR(line)[1] == '!') {
1576  if ((p = strstr(RSTRING_PTR(line), "ruby")) != 0) {
1577  goto start_read;
1578  }
1579  }
1580  }
1581  rb_raise(rb_eLoadError, "no Ruby script found in input");
1582  }
1583 
1584  c = rb_io_getbyte(f);
1585  if (c == INT2FIX('#')) {
1586  c = rb_io_getbyte(f);
1587  if (c == INT2FIX('!')) {
1588  line = rb_io_gets(f);
1589  if (NIL_P(line))
1590  return 0;
1591 
1592  if ((p = strstr(RSTRING_PTR(line), "ruby")) == 0) {
1593  /* not ruby script, assume -x flag */
1594  goto search_shebang;
1595  }
1596 
1597  start_read:
1598  p += 4;
1599  RSTRING_PTR(line)[RSTRING_LEN(line) - 1] = '\0';
1600  if (RSTRING_PTR(line)[RSTRING_LEN(line) - 2] == '\r')
1601  RSTRING_PTR(line)[RSTRING_LEN(line) - 2] = '\0';
1602  if ((p = strstr(p, " -")) != 0) {
1603  moreswitches(p + 1, opt, 0);
1604  }
1605 
1606  /* push back shebang for pragma may exist in next line */
1607  rb_io_ungetbyte(f, rb_str_new2("!\n"));
1608  }
1609  else if (!NIL_P(c)) {
1610  rb_io_ungetbyte(f, c);
1611  }
1612  rb_io_ungetbyte(f, INT2FIX('#'));
1613  if (no_src_enc && opt->src.enc.name) {
1614  opt->src.enc.index = opt_enc_index(opt->src.enc.name);
1615  src_encoding_index = opt->src.enc.index;
1616  }
1617  if (no_ext_enc && opt->ext.enc.name) {
1618  opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
1619  }
1620  if (no_int_enc && opt->intern.enc.name) {
1621  opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
1622  }
1623  }
1624  else if (!NIL_P(c)) {
1625  rb_io_ungetbyte(f, c);
1626  }
1627  else {
1628  if (f != rb_stdin) rb_io_close(f);
1629  f = Qnil;
1630  }
1632  require_libraries(&opt->req_list); /* Why here? unnatural */
1633  }
1634  if (opt->src.enc.index >= 0) {
1635  enc = rb_enc_from_index(opt->src.enc.index);
1636  }
1637  else if (f == rb_stdin) {
1638  enc = rb_locale_encoding();
1639  }
1640  else {
1641  enc = rb_usascii_encoding();
1642  }
1643  if (NIL_P(f)) {
1644  f = rb_str_new(0, 0);
1645  rb_enc_associate(f, enc);
1646  return (VALUE)rb_parser_compile_string(parser, fname, f, line_start);
1647  }
1648  rb_funcall(f, set_encoding, 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
1649  tree = rb_parser_compile_file(parser, fname, f, line_start);
1650  rb_funcall(f, set_encoding, 1, rb_parser_encoding(parser));
1651  if (script && tree && rb_parser_end_seen_p(parser)) {
1652  /*
1653  * DATA is a File that contains the data section of the executed file.
1654  * To create a data section use <tt>__END__</tt>:
1655  *
1656  * $ cat t.rb
1657  * puts DATA.gets
1658  * __END__
1659  * hello world!
1660  *
1661  * $ ruby t.rb
1662  * hello world!
1663  */
1664  rb_define_global_const("DATA", f);
1665  }
1666  else if (f != rb_stdin) {
1667  rb_io_close(f);
1668  }
1669  return (VALUE)tree;
1670 }
1671 
1672 static VALUE
1674 {
1675  return rb_gv_set("$.", lineno);
1676 }
1677 
1678 static NODE *
1679 load_file(VALUE parser, const char *fname, int script, struct cmdline_options *opt)
1680 {
1681  struct load_file_arg arg;
1682  arg.parser = parser;
1683  arg.fname = fname;
1684  arg.script = script;
1685  arg.opt = opt;
1686  return (NODE *)rb_ensure(load_file_internal, (VALUE)&arg, restore_lineno, rb_gv_get("$."));
1687 }
1688 
1689 void *
1690 rb_load_file(const char *fname)
1691 {
1692  struct cmdline_options opt;
1693 
1694  return load_file(rb_parser_new(), fname, 0, cmdline_options_init(&opt));
1695 }
1696 
1697 static void
1699 {
1700  char *s;
1701  long i;
1702 
1703  if (origarg.argv == 0)
1704  rb_raise(rb_eRuntimeError, "$0 not initialized");
1705  StringValue(val);
1706  s = RSTRING_PTR(val);
1707  i = RSTRING_LEN(val);
1708 
1709  setproctitle("%.*s", (int)i, s);
1710 
1712 }
1713 
1714 void
1715 ruby_script(const char *name)
1716 {
1717  if (name) {
1718  rb_progname = rb_external_str_new(name, strlen(name));
1720  }
1721 }
1722 
1723 static void
1725 {
1726  rb_uid_t uid = getuid();
1727  rb_uid_t euid = geteuid();
1728  rb_gid_t gid = getgid();
1729  rb_gid_t egid = getegid();
1730 
1731  if (uid != euid) opt->setids |= 1;
1732  if (egid != gid) opt->setids |= 2;
1733  if (uid && opt->setids) {
1734  if (opt->safe_level < 1) opt->safe_level = 1;
1735  }
1736 }
1737 
1738 #undef forbid_setid
1739 static void
1740 forbid_setid(const char *s, struct cmdline_options *opt)
1741 {
1742  if (opt->setids & 1)
1743  rb_raise(rb_eSecurityError, "no %s allowed while running setuid", s);
1744  if (opt->setids & 2)
1745  rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s);
1746  if (opt->safe_level > 0)
1747  rb_raise(rb_eSecurityError, "no %s allowed in tainted mode", s);
1748 }
1749 
1750 static void
1751 verbose_setter(VALUE val, ID id, void *data)
1752 {
1753  VALUE *variable = data;
1754  *variable = RTEST(val) ? Qtrue : val;
1755 }
1756 
1757 static VALUE
1758 opt_W_getter(ID id, void *data)
1759 {
1760  VALUE *variable = data;
1761  switch (*variable) {
1762  case Qnil:
1763  return INT2FIX(0);
1764  case Qfalse:
1765  return INT2FIX(1);
1766  case Qtrue:
1767  return INT2FIX(2);
1768  }
1769  return Qnil; /* not reached */
1770 }
1771 
1772 void
1774 {
1779  rb_define_variable("$DEBUG", &ruby_debug);
1780  rb_define_variable("$-d", &ruby_debug);
1781 
1783  rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);
1784 
1785  /*
1786  * ARGV contains the command line arguments used to run ruby with the
1787  * first value containing the name of the executable.
1788  *
1789  * A library like OptionParser can be used to process command-line
1790  * arguments.
1791  */
1793 }
1794 
1795 void
1797 {
1798  int i;
1799  VALUE av = rb_argv;
1800 
1801 #if defined(USE_DLN_A_OUT)
1802  if (origarg.argv)
1803  dln_argv0 = origarg.argv[0];
1804  else
1805  dln_argv0 = argv[0];
1806 #endif
1807  rb_ary_clear(av);
1808  for (i = 0; i < argc; i++) {
1809  VALUE arg = rb_external_str_new_cstr(argv[i]);
1810 
1811  OBJ_FREEZE(arg);
1812  rb_ary_push(av, arg);
1813  }
1814 }
1815 
1816 void *
1818 {
1819  struct cmdline_options opt;
1820  VALUE iseq;
1821 
1822  ruby_script(argv[0]); /* for the time being */
1823  rb_argv0 = rb_str_new4(rb_progname);
1824  rb_gc_register_mark_object(rb_argv0);
1825  iseq = process_options(argc, argv, cmdline_options_init(&opt));
1826 
1827 #ifndef HAVE_SETPROCTITLE
1828  {
1829  extern void ruby_init_setproctitle(int argc, char *argv[]);
1830  ruby_init_setproctitle(argc, argv);
1831  }
1832 #endif
1833 
1834  return (void*)(struct RData*)iseq;
1835 }
1836 
1837 static void
1839 {
1840  int f0, f1, f2, fds[2];
1841  struct stat buf;
1842  f0 = fstat(0, &buf) == -1 && errno == EBADF;
1843  f1 = fstat(1, &buf) == -1 && errno == EBADF;
1844  f2 = fstat(2, &buf) == -1 && errno == EBADF;
1845  if (f0) {
1846  if (pipe(fds) == 0) {
1847  close(fds[1]);
1848  if (fds[0] != 0) {
1849  dup2(fds[0], 0);
1850  close(fds[0]);
1851  }
1852  }
1853  }
1854  if (f1 || f2) {
1855  if (pipe(fds) == 0) {
1856  close(fds[0]);
1857  if (f1 && fds[1] != 1)
1858  dup2(fds[1], 1);
1859  if (f2 && fds[1] != 2)
1860  dup2(fds[1], 2);
1861  if (fds[1] != 1 && fds[1] != 2)
1862  close(fds[1]);
1863  }
1864  }
1865 }
1866 
1867 void
1868 ruby_sysinit(int *argc, char ***argv)
1869 {
1870 #if defined(_WIN32)
1871  void rb_w32_sysinit(int *argc, char ***argv);
1872  rb_w32_sysinit(argc, argv);
1873 #endif
1874  origarg.argc = *argc;
1875  origarg.argv = *argv;
1876 #if defined(USE_DLN_A_OUT)
1877  dln_argv0 = origarg.argv[0];
1878 #endif
1880 }
1881