1 /**********************************************************************
6 created at: Tue Aug 10 12:47:31 JST 1993
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
12 **********************************************************************/
16 #include <sys/cygwin.h>
20 #include "ruby/wince.h"
22 #include "ruby/ruby.h"
23 #include "ruby/node.h"
24 #include "ruby/encoding.h"
25 #include "eval_intern.h"
28 #include <sys/types.h>
32 #include <sys/pstat.h>
38 #if defined(HAVE_FCNTL_H)
40 #elif defined(HAVE_SYS_FCNTL_H)
41 #include <sys/fcntl.h>
43 #ifdef HAVE_SYS_PARAM_H
44 # include <sys/param.h>
47 # define MAXPATHLEN 1024
50 #if defined(__MACOS__) && defined(__MWERKS__)
54 #include "ruby/util.h"
60 VALUE
rb_parser_get_yydebug(VALUE
);
61 VALUE
rb_parser_set_yydebug(VALUE
, VALUE
);
63 const char *ruby_get_inplace_mode(void);
64 void ruby_set_inplace_mode(const char *);
66 #define DISABLE_BIT(bit) (1U << disable_##bit)
67 enum disable_flag_bits
{
72 #define DUMP_BIT(bit) (1U << dump_##bit)
77 struct cmdline_options
{
79 int do_loop
, do_print
;
80 int do_check
, do_line
;
81 int do_split
, do_search
;
102 static void init_ids(struct cmdline_options
*);
104 #define src_encoding_index GET_VM()->src_encoding_index
106 static struct cmdline_options
*
107 cmdline_options_init(struct cmdline_options
*opt
)
109 MEMZERO(opt
, *opt
, 1);
111 opt
->src
.enc
.index
= src_encoding_index
;
115 struct cmdline_arguments
{
118 struct cmdline_options
*opt
;
121 static NODE
*load_file(VALUE
, const char *, int, struct cmdline_options
*);
122 static void forbid_setid(const char *, struct cmdline_options
*);
123 #define forbid_setid(s) forbid_setid(s, opt)
128 #if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE)
134 usage(const char *name
)
136 /* This message really ought to be max 23 lines.
137 * Removed -h because the user already knows that option. Others? */
139 static const char *const usage_msg
[] = {
140 "-0[octal] specify record separator (\\0, if no argument)",
141 "-a autosplit mode with -n or -p (splits $_ into $F)",
142 "-c check syntax only",
143 "-Cdirectory cd to directory, before executing your script",
144 "-d set debugging flags (set $DEBUG to true)",
145 "-e 'command' one line of script. Several -e's allowed. Omit [programfile]",
146 "-Eencoding specifies the character encoding for the program codes",
147 "-Fpattern split() pattern for autosplit (-a)",
148 "-i[extension] edit ARGV files in place (make backup if extension supplied)",
149 "-Idirectory specify $LOAD_PATH directory (may be used more than once)",
150 "-l enable line ending processing",
151 "-n assume 'while gets(); ... end' loop around your script",
152 "-p assume loop like -n but print line also like sed",
153 "-rlibrary require the library, before executing your script",
154 "-s enable some switch parsing for switches after script name",
155 "-S look for the script using PATH environment variable",
156 "-T[level] turn on tainting checks",
157 "-v print version number, then turn on verbose mode",
158 "-w turn warnings on for your script",
159 "-W[level] set warning level; 0=silence, 1=medium, 2=verbose (default)",
160 "-x[directory] strip off text before #!ruby line and perhaps cd to directory",
161 "--copyright print the copyright",
162 "--version print the version",
165 const char *const *p
= usage_msg
;
167 printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name
);
169 printf(" %s\n", *p
++);
172 VALUE
rb_get_load_path(void);
174 #ifndef CharNext /* defined as CharNext[AW] on Windows. */
175 #define CharNext(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
178 #if defined DOSISH || defined __CYGWIN__
180 translate_char(char *p
, int from
, int to
)
183 if ((unsigned char)*p
== from
)
190 #if defined _WIN32 || defined __CYGWIN__ || defined __DJGPP__
192 rubylib_mangled_path(const char *s
, unsigned int l
)
194 static char *newp
, *oldp
;
195 static int newl
, oldl
, notfound
;
199 if (!newp
&& !notfound
) {
200 newp
= getenv("RUBYLIB_PREFIX");
202 oldp
= newp
= strdup(newp
);
203 while (*newp
&& !ISSPACE(*newp
) && *newp
!= ';') {
204 newp
= CharNext(newp
); /* Skip digits. */
207 while (*newp
&& (ISSPACE(*newp
) || *newp
== ';')) {
208 newp
= CharNext(newp
); /* Skip whitespace. */
211 if (newl
== 0 || oldl
== 0) {
212 rb_fatal("malformed RUBYLIB_PREFIX");
214 translate_char(newp
, '\\', '/');
220 if (!newp
|| l
< oldl
|| STRNCASECMP(oldp
, s
, oldl
) != 0) {
221 return rb_str_new(s
, l
);
223 ret
= rb_str_new(0, l
+ newl
- oldl
);
224 ptr
= RSTRING_PTR(ret
);
225 memcpy(ptr
, newp
, newl
);
226 memcpy(ptr
+ newl
, s
+ oldl
, l
- oldl
);
227 ptr
[l
+ newl
- oldl
] = 0;
232 rubylib_mangled_path2(const char *s
)
234 return rubylib_mangled_path(s
, strlen(s
));
237 #define rubylib_mangled_path rb_str_new
238 #define rubylib_mangled_path2 rb_str_new2
242 push_include(const char *path
, VALUE (*filter
)(VALUE
))
244 const char sep
= PATH_SEP_CHAR
;
246 VALUE load_path
= GET_VM()->load_path
;
253 for (s
= p
; *s
&& *s
!= sep
; s
= CharNext(s
));
254 rb_ary_push(load_path
, (*filter
)(rubylib_mangled_path(p
, s
- p
)));
261 push_include_cygwin(const char *path
, VALUE (*filter
)(VALUE
))
264 char rubylib
[FILENAME_MAX
];
273 for (s
= p
; *s
&& *s
!= ';'; s
= CharNext(s
));
277 buf
= rb_str_new(p
, len
);
278 p
= RSTRING_PTR(buf
);
281 rb_str_resize(buf
, len
);
282 p
= strncpy(RSTRING_PTR(buf
), p
, len
);
285 if (cygwin_conv_to_posix_path(p
, rubylib
) == 0)
287 push_include(p
, filter
);
293 #define push_include push_include_cygwin
297 ruby_push_include(const char *path
, VALUE (*filter
)(VALUE
))
301 push_include(path
, filter
);
305 identical_path(VALUE path
)
311 ruby_incpush(const char *path
)
313 ruby_push_include(path
, identical_path
);
317 expand_include_path(VALUE path
)
319 char *p
= RSTRING_PTR(path
);
322 if (*p
== '.' && p
[1] == '/')
324 return rb_file_expand_path(path
, Qnil
);
328 ruby_incpush_expand(const char *path
)
330 ruby_push_include(path
, expand_include_path
);
333 #if defined DOSISH || defined __CYGWIN__
334 #define LOAD_RELATIVE 1
337 #if defined _WIN32 || defined __CYGWIN__
338 static HMODULE libruby
;
341 DllMain(HINSTANCE dll
, DWORD reason
, LPVOID reserved
)
343 if (reason
== DLL_PROCESS_ATTACH
)
350 ruby_init_loadpath(void)
353 #if defined LOAD_RELATIVE
354 char libpath
[MAXPATHLEN
+ 1];
358 #if defined _WIN32 || defined __CYGWIN__
359 GetModuleFileName(libruby
, libpath
, sizeof libpath
);
361 extern char *__dos_argv0
;
362 strncpy(libpath
, __dos_argv0
, sizeof(libpath
) - 1);
363 #elif defined(__human68k__)
365 strncpy(libpath
, _argv
[0], sizeof(libpath
) - 1);
366 #elif defined(__EMX__)
367 _execname(libpath
, sizeof(libpath
) - 1);
370 libpath
[sizeof(libpath
) - 1] = '\0';
372 translate_char(libpath
, '\\', '/');
373 #elif defined __CYGWIN__
375 char rubylib
[FILENAME_MAX
];
376 cygwin_conv_to_posix_path(libpath
, rubylib
);
377 strncpy(libpath
, rubylib
, sizeof(libpath
));
380 p
= strrchr(libpath
, '/');
383 if (p
- libpath
> 3 && !STRCASECMP(p
- 4, "/bin")) {
389 strcpy(libpath
, ".");
393 rest
= sizeof(libpath
) - 1 - (p
- libpath
);
395 #define RUBY_RELATIVE(path) (strncpy(p, (path), rest), libpath)
397 #define RUBY_RELATIVE(path) (path)
399 #define incpush(path) rb_ary_push(load_path, rubylib_mangled_path2(path))
400 load_path
= GET_VM()->load_path
;
402 if (rb_safe_level() == 0) {
403 ruby_incpush(getenv("RUBYLIB"));
406 #ifdef RUBY_SEARCH_PATH
407 incpush(RUBY_RELATIVE(RUBY_SEARCH_PATH
));
410 incpush(RUBY_RELATIVE(RUBY_SITE_LIB2
));
411 #ifdef RUBY_SITE_THIN_ARCHLIB
412 incpush(RUBY_RELATIVE(RUBY_SITE_THIN_ARCHLIB
));
414 incpush(RUBY_RELATIVE(RUBY_SITE_ARCHLIB
));
415 incpush(RUBY_RELATIVE(RUBY_SITE_LIB
));
417 incpush(RUBY_RELATIVE(RUBY_VENDOR_LIB2
));
418 #ifdef RUBY_VENDOR_THIN_ARCHLIB
419 incpush(RUBY_RELATIVE(RUBY_VENDOR_THIN_ARCHLIB
));
421 incpush(RUBY_RELATIVE(RUBY_VENDOR_ARCHLIB
));
422 incpush(RUBY_RELATIVE(RUBY_VENDOR_LIB
));
424 incpush(RUBY_RELATIVE(RUBY_LIB
));
425 #ifdef RUBY_THIN_ARCHLIB
426 incpush(RUBY_RELATIVE(RUBY_THIN_ARCHLIB
));
428 incpush(RUBY_RELATIVE(RUBY_ARCHLIB
));
430 if (rb_safe_level() == 0) {
437 add_modules(struct cmdline_options
*opt
, const char *mod
)
439 VALUE list
= opt
->req_list
;
442 opt
->req_list
= list
= rb_ary_new();
443 RBASIC(list
)->klass
= 0;
445 rb_ary_push(list
, rb_obj_freeze(rb_str_new2(mod
)));
448 extern void Init_ext(void);
449 extern VALUE
rb_vm_top_self(void);
452 require_libraries(struct cmdline_options
*opt
)
454 VALUE list
= opt
->req_list
;
457 Init_ext(); /* should be called here for some reason :-( */
458 CONST_ID(require
, "require");
459 while (list
&& RARRAY_LEN(list
) > 0) {
460 VALUE feature
= rb_ary_shift(list
);
461 rb_funcall2(rb_vm_top_self(), require
, 1, &feature
);
467 process_sflag(struct cmdline_options
*opt
)
472 VALUE argv
= rb_argv
;
474 n
= RARRAY_LEN(argv
);
475 args
= RARRAY_PTR(argv
);
478 char *s
= StringValuePtr(v
);
485 if (s
[1] == '-' && s
[2] == '\0')
489 /* check if valid name before replacing - with _ */
490 for (p
= s
+ 1; *p
; p
++) {
499 else if (*p
!= '_' && !ISALNUM(*p
)) {
502 rb_str_new2("invalid name for global variable - ");
503 if (!(p
= strchr(p
, '='))) {
504 rb_str_cat2(name_error
[0], s
);
507 rb_str_cat(name_error
[0], s
, p
- s
);
509 name_error
[1] = args
[-1];
510 rb_exc_raise(rb_class_new_instance(2, name_error
, rb_eNameError
));
515 for (p
= s
+ 1; *p
; ++p
) {
522 n
= RARRAY_LEN(argv
) - n
;
530 NODE
*rb_parser_append_print(VALUE
, NODE
*);
531 NODE
*rb_parser_while_loop(VALUE
, NODE
*, int, int);
532 static int proc_options(int argc
, char **argv
, struct cmdline_options
*opt
);
535 moreswitches(const char *s
, struct cmdline_options
*opt
)
542 argv
[0] = argv
[2] = 0;
543 while (*s
&& !ISSPACE(*s
))
545 argv
[1] = ALLOCA_N(char, s
- p
+ 2);
547 strncpy(argv
[1] + 1, p
, s
- p
);
548 argv
[1][s
- p
+ 1] = '\0';
549 proc_options(argc
, argv
, opt
);
550 while (*s
&& ISSPACE(*s
))
555 #define NAME_MATCH_P(name, str, len) \
556 ((len) < sizeof(name) && strncmp((str), name, (len)) == 0)
558 #define UNSET_WHEN(name, bit, str, len) \
559 if (NAME_MATCH_P(name, str, len)) { \
560 *(unsigned int *)arg &= ~(bit); \
564 #define SET_WHEN(name, bit, str, len) \
565 if (NAME_MATCH_P(name, str, len)) { \
566 *(unsigned int *)arg |= (bit); \
571 enable_option(const char *str
, int len
, void *arg
)
573 #define UNSET_WHEN_DISABLE(bit) UNSET_WHEN(#bit, DISABLE_BIT(bit), str, len)
574 UNSET_WHEN_DISABLE(gems
);
575 UNSET_WHEN_DISABLE(rubyopt
);
576 if (NAME_MATCH_P("all", str
, len
)) {
577 *(unsigned int *)arg
= 0U;
580 rb_warn("unknown argument for --enable: `%.*s'", len
, str
);
584 disable_option(const char *str
, int len
, void *arg
)
586 #define SET_WHEN_DISABLE(bit) SET_WHEN(#bit, DISABLE_BIT(bit), str, len)
587 SET_WHEN_DISABLE(gems
);
588 SET_WHEN_DISABLE(rubyopt
);
589 if (NAME_MATCH_P("all", str
, len
)) {
590 *(unsigned int *)arg
= ~0U;
593 rb_warn("unknown argument for --disable: `%.*s'", len
, str
);
597 dump_option(const char *str
, int len
, void *arg
)
599 #define SET_WHEN_DUMP(bit) SET_WHEN(#bit, DUMP_BIT(bit), str, len)
600 SET_WHEN_DUMP(insns
);
601 rb_warn("don't know how to dump `%.*s', (insns)", len
, str
);
605 proc_options(int argc
, char **argv
, struct cmdline_options
*opt
)
613 for (argc
--, argv
++; argc
> 0; argc
--, argv
++) {
614 if (argv
[0][0] != '-' || !argv
[0][1])
621 opt
->do_split
= Qtrue
;
626 opt
->do_print
= Qtrue
;
629 opt
->do_loop
= Qtrue
;
635 ruby_verbose
= Qtrue
;
652 ruby_verbose
= Qtrue
;
659 int v
= 2; /* -W as -W2 */
662 v
= scan_oct(s
, 1, &numlen
);
672 ruby_verbose
= Qfalse
;
675 ruby_verbose
= Qtrue
;
682 opt
->do_check
= Qtrue
;
693 usage(origarg
.argv
[0]);
694 rb_exit(EXIT_SUCCESS
);
698 opt
->do_line
= Qtrue
;
699 rb_output_rs
= rb_rs
;
705 opt
->do_search
= Qtrue
;
716 rb_raise(rb_eRuntimeError
, "no code specified for -e");
718 if (!opt
->e_script
) {
719 opt
->e_script
= rb_str_new(0, 0);
720 if (opt
->script
== 0)
723 rb_str_cat2(opt
->e_script
, s
);
724 rb_str_cat2(opt
->e_script
, "\n");
733 add_modules(opt
, argv
[1]);
740 ruby_set_inplace_mode(s
+ 1);
746 if (*s
&& chdir(s
) < 0) {
747 rb_fatal("Can't chdir to %s", s
);
759 rb_fatal("Can't chdir");
762 rb_fatal("Can't chdir to %s", s
);
768 rb_fs
= rb_reg_new(s
, strlen(s
), 0);
773 if (!*++s
) goto next_encoding
;
778 const char *enc_name
= 0;
784 enc_name
= "Windows-31J";
789 case 'N': case 'n': case 'A': case 'a':
790 enc_name
= "ASCII-8BIT";
794 opt
->src
.enc
.name
= rb_str_new2(enc_name
);
795 opt
->ext
.enc
.name
= opt
->src
.enc
.name
;
807 v
= scan_oct(s
, 2, &numlen
);
812 rb_set_safe_level(v
);
819 ruby_incpush_expand(s
);
821 ruby_incpush_expand(argv
[1]);
832 v
= scan_oct(s
, 4, &numlen
);
836 else if (v
== 0 && numlen
>= 2) {
837 rb_rs
= rb_str_new2("\n\n");
841 rb_rs
= rb_str_new(&c
, 1);
847 if (!s
[1] || (s
[1] == '\r' && !s
[2])) {
852 if (strcmp("copyright", s
) == 0)
854 else if (strcmp("debug", s
) == 0) {
856 ruby_verbose
= Qtrue
;
858 else if (strncmp("enable", s
, n
= 6) == 0 &&
859 (!s
[n
] || s
[n
] == '-' || s
[n
] == '=')) {
860 if ((s
+= n
+ 1)[-1] ? !*s
: (!--argc
|| !(s
= *++argv
))) {
861 rb_raise(rb_eRuntimeError
, "missing argument for --enable");
863 ruby_each_words(s
, enable_option
, &opt
->disable
);
865 else if (strncmp("disable", s
, n
= 7) == 0 &&
866 (!s
[n
] || s
[n
] == '-' || s
[n
] == '=')) {
867 if ((s
+= n
+ 1)[-1] ? !*s
: (!--argc
|| !(s
= *++argv
))) {
868 rb_raise(rb_eRuntimeError
, "missing argument for --disable");
870 ruby_each_words(s
, disable_option
, &opt
->disable
);
872 else if (strncmp("encoding", s
, n
= 8) == 0 && (!s
[n
] || s
[n
] == '=')) {
876 if (!--argc
|| !(s
= *++argv
)) {
877 rb_raise(rb_eRuntimeError
, "missing argument for --encoding");
881 opt
->ext
.enc
.name
= rb_str_new2(s
);
883 else if (strcmp("version", s
) == 0)
885 else if (strcmp("verbose", s
) == 0) {
887 ruby_verbose
= Qtrue
;
889 else if (strcmp("yydebug", s
) == 0)
891 else if (strncmp("dump", s
, n
= 4) == 0 && (!s
[n
] || s
[n
] == '=')) {
892 if (!(s
+= n
+ 1)[-1] && (!--argc
|| !(s
= *++argv
)) && *s
!= '-') break;
893 ruby_each_words(s
, dump_option
, &opt
->dump
);
895 else if (strcmp("help", s
) == 0) {
896 usage(origarg
.argv
[0]);
897 rb_exit(EXIT_SUCCESS
);
900 rb_raise(rb_eRuntimeError
,
901 "invalid option --%s (-h will show valid options)", s
);
912 rb_raise(rb_eRuntimeError
,
913 "invalid option -%c (-h will show valid options)",
914 (int)(unsigned char)*s
);
917 rb_raise(rb_eRuntimeError
,
918 "invalid option -\\x%02X (-h will show valid options)",
919 (int)(unsigned char)*s
);
933 void Init_prelude(void);
936 ruby_init_gems(int enable
)
938 if (enable
) rb_define_module("Gem");
943 opt_enc_index(VALUE enc_name
)
945 const char *s
= RSTRING_PTR(enc_name
);
946 int i
= rb_enc_find_index(s
);
949 rb_raise(rb_eRuntimeError
, "unknown encoding name - %s", s
);
951 else if (rb_enc_dummy_p(rb_enc_from_index(i
))) {
952 rb_raise(rb_eRuntimeError
, "dummy encoding is not acceptable - %s ", s
);
957 #define rb_progname (GET_VM()->progname)
961 process_options(VALUE arg
)
963 struct cmdline_arguments
*argp
= (struct cmdline_arguments
*)arg
;
964 struct cmdline_options
*opt
= argp
->opt
;
965 int argc
= argp
->argc
;
966 char **argv
= argp
->argv
;
970 rb_encoding
*enc
, *lenc
;
972 char fbuf
[MAXPATHLEN
];
973 int i
= proc_options(argc
, argv
, opt
);
979 if (!(opt
->disable
& DISABLE_BIT(rubyopt
)) &&
980 rb_safe_level() == 0 && (s
= getenv("RUBYOPT"))) {
981 VALUE src_enc_name
= opt
->src
.enc
.name
;
982 VALUE ext_enc_name
= opt
->ext
.enc
.name
;
986 if (*s
== 'T' || (*s
== '-' && *(s
+ 1) == 'T')) {
993 v
= scan_oct(s
, 2, &numlen
);
997 rb_set_safe_level(v
);
1006 } while (ISSPACE(*s
));
1012 if (!strchr("EIdvwWrK", *s
))
1013 rb_raise(rb_eRuntimeError
,
1014 "invalid switch in RUBYOPT: -%c", *s
);
1015 s
= moreswitches(s
, opt
);
1019 opt
->src
.enc
.name
= src_enc_name
;
1021 opt
->ext
.enc
.name
= ext_enc_name
;
1025 ruby_show_version();
1028 if (opt
->copyright
) {
1029 ruby_show_copyright();
1032 if (rb_safe_level() >= 4) {
1034 OBJ_TAINT(GET_VM()->load_path
);
1037 if (!opt
->e_script
) {
1038 if (argc
== 0) { /* no more args */
1044 opt
->script
= argv
[0];
1045 if (opt
->script
[0] == '\0') {
1048 else if (opt
->do_search
) {
1049 char *path
= getenv("RUBYPATH");
1053 opt
->script
= dln_find_file_r(argv
[0], path
, fbuf
, sizeof(fbuf
));
1056 opt
->script
= dln_find_file_r(argv
[0], getenv(PATH_ENV
), fbuf
, sizeof(fbuf
));
1059 opt
->script
= argv
[0];
1066 ruby_script(opt
->script
);
1067 #if defined DOSISH || defined __CYGWIN__
1068 translate_char(RSTRING_PTR(rb_progname
), '\\', '/');
1070 opt
->script_name
= rb_str_new4(rb_progname
);
1071 opt
->script
= RSTRING_PTR(opt
->script_name
);
1072 safe
= rb_safe_level();
1073 rb_set_safe_level_force(0);
1074 ruby_set_argv(argc
, argv
);
1077 ruby_init_loadpath();
1078 ruby_init_gems(!(opt
->disable
& DISABLE_BIT(gems
)));
1079 lenc
= rb_locale_encoding();
1080 for (i
= 0; i
< RARRAY_LEN(rb_argv
); i
++) {
1081 rb_enc_associate(RARRAY_PTR(rb_argv
)[i
], lenc
);
1083 parser
= rb_parser_new();
1084 if (opt
->yydebug
) rb_parser_set_yydebug(parser
, Qtrue
);
1085 if (opt
->ext
.enc
.name
!= 0) {
1086 opt
->ext
.enc
.index
= opt_enc_index(opt
->ext
.enc
.name
);
1088 if (opt
->src
.enc
.name
!= 0) {
1089 opt
->src
.enc
.index
= opt_enc_index(opt
->src
.enc
.name
);
1090 src_encoding_index
= opt
->src
.enc
.index
;
1092 if (opt
->ext
.enc
.index
>= 0) {
1093 enc
= rb_enc_from_index(opt
->ext
.enc
.index
);
1098 rb_enc_set_default_external(rb_enc_from_encoding(enc
));
1100 rb_set_safe_level_force(safe
);
1101 if (opt
->e_script
) {
1103 if (opt
->src
.enc
.index
>= 0) {
1104 eenc
= rb_enc_from_index(opt
->src
.enc
.index
);
1109 rb_enc_associate(opt
->e_script
, eenc
);
1110 require_libraries(opt
);
1111 tree
= rb_parser_compile_string(parser
, opt
->script
, opt
->e_script
, 1);
1114 if (opt
->script
[0] == '-' && !opt
->script
[1]) {
1115 forbid_setid("program input from stdin");
1117 tree
= load_file(parser
, opt
->script
, 1, opt
);
1120 if (!tree
) return Qfalse
;
1125 if (rb_safe_level() >= 4) {
1126 FL_UNSET(rb_argv
, FL_TAINT
);
1127 FL_UNSET(GET_VM()->load_path
, FL_TAINT
);
1130 if (opt
->do_check
) {
1131 printf("Syntax OK\n");
1135 if (opt
->do_print
) {
1136 tree
= rb_parser_append_print(parser
, tree
);
1139 tree
= rb_parser_while_loop(parser
, tree
, opt
->do_line
, opt
->do_split
);
1142 iseq
= rb_iseq_new(tree
, rb_str_new2("<main>"),
1143 opt
->script_name
, Qfalse
, ISEQ_TYPE_TOP
);
1145 if (opt
->dump
& DUMP_BIT(insns
)) {
1146 rb_io_write(rb_stdout
, ruby_iseq_disasm(iseq
));
1147 rb_io_flush(rb_stdout
);
1155 load_file(VALUE parser
, const char *fname
, int script
, struct cmdline_options
*opt
)
1157 extern VALUE rb_stdin
;
1164 rb_load_fail(fname
);
1165 if (strcmp(fname
, "-") == 0) {
1169 int fd
, mode
= O_RDONLY
;
1170 #if defined DOSISH || defined __CYGWIN__
1172 const char *ext
= strrchr(fname
, '.');
1173 if (ext
&& STRCASECMP(ext
, ".exe") == 0)
1177 if ((fd
= open(fname
, mode
)) < 0) {
1178 rb_load_fail(fname
);
1181 f
= rb_io_fdopen(fd
, mode
, fname
);
1185 VALUE c
= 1; /* something not nil */
1188 int no_src_enc
= !opt
->src
.enc
.name
;
1189 int no_ext_enc
= !opt
->ext
.enc
.name
;
1191 enc
= rb_usascii_encoding();
1192 rb_funcall(f
, rb_intern("set_encoding"), 1, rb_enc_from_encoding(enc
));
1196 opt
->xflag
= Qfalse
;
1197 while (!NIL_P(line
= rb_io_gets(f
))) {
1199 if (RSTRING_LEN(line
) > 2
1200 && RSTRING_PTR(line
)[0] == '#'
1201 && RSTRING_PTR(line
)[1] == '!') {
1202 if ((p
= strstr(RSTRING_PTR(line
), "ruby")) != 0) {
1207 rb_raise(rb_eLoadError
, "no Ruby script found in input");
1210 c
= rb_io_getbyte(f
);
1211 if (c
== INT2FIX('#')) {
1212 c
= rb_io_getbyte(f
);
1213 if (c
== INT2FIX('!')) {
1214 line
= rb_io_gets(f
);
1218 if ((p
= strstr(RSTRING_PTR(line
), "ruby")) == 0) {
1219 /* not ruby script, kick the program */
1222 char *pend
= RSTRING_PTR(line
) + RSTRING_LEN(line
);
1224 p
= RSTRING_PTR(line
); /* skip `#!' */
1225 if (pend
[-1] == '\n')
1226 pend
--; /* chomp line */
1227 if (pend
[-1] == '\r')
1230 while (p
< pend
&& ISSPACE(*p
))
1232 path
= p
; /* interpreter path */
1233 while (p
< pend
&& !ISSPACE(*p
))
1237 argv
= ALLOCA_N(char *, origarg
.argc
+ 3);
1239 MEMCPY(argv
+ 2, origarg
.argv
+ 1, char *, origarg
.argc
);
1242 argv
= origarg
.argv
;
1247 rb_fatal("Can't exec %s", path
);
1252 RSTRING_PTR(line
)[RSTRING_LEN(line
) - 1] = '\0';
1253 if (RSTRING_PTR(line
)[RSTRING_LEN(line
) - 2] == '\r')
1254 RSTRING_PTR(line
)[RSTRING_LEN(line
) - 2] = '\0';
1255 if ((p
= strstr(p
, " -")) != 0) {
1256 p
++; /* skip space before `-' */
1258 p
= moreswitches(p
+ 1, opt
);
1262 /* push back shebang for pragma may exist in next line */
1263 rb_io_ungetc(f
, rb_str_new2("!\n"));
1265 else if (!NIL_P(c
)) {
1268 rb_io_ungetc(f
, INT2FIX('#'));
1269 if (no_src_enc
&& opt
->src
.enc
.name
) {
1270 opt
->src
.enc
.index
= opt_enc_index(opt
->src
.enc
.name
);
1271 src_encoding_index
= opt
->src
.enc
.index
;
1273 if (no_ext_enc
&& opt
->ext
.enc
.name
) {
1274 opt
->ext
.enc
.index
= opt_enc_index(opt
->ext
.enc
.name
);
1277 else if (!NIL_P(c
)) {
1280 require_libraries(opt
); /* Why here? unnatural */
1282 if (opt
->src
.enc
.index
>= 0) {
1283 enc
= rb_enc_from_index(opt
->src
.enc
.index
);
1285 else if (f
== rb_stdin
) {
1286 enc
= rb_locale_encoding();
1289 enc
= rb_usascii_encoding();
1291 rb_funcall(f
, rb_intern("set_encoding"), 1, rb_enc_from_encoding(enc
));
1292 tree
= (NODE
*)rb_parser_compile_file(parser
, fname
, f
, line_start
);
1293 rb_funcall(f
, rb_intern("set_encoding"), 1, rb_parser_encoding(parser
));
1294 if (script
&& rb_parser_end_seen_p(parser
)) {
1295 rb_define_global_const("DATA", f
);
1297 else if (f
!= rb_stdin
) {
1304 rb_load_file(const char *fname
)
1306 struct cmdline_options opt
;
1308 return load_file(rb_parser_new(), fname
, 0, cmdline_options_init(&opt
));
1311 #if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE)
1312 #if !defined(_WIN32) && !(defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
1313 #define USE_ENVSPACE_FOR_ARG0
1316 #ifdef USE_ENVSPACE_FOR_ARG0
1317 extern char **environ
;
1321 get_arglen(int argc
, char **argv
)
1326 if (!argc
) return 0;
1328 /* See if all the arguments are contiguous in memory */
1329 for (i
= 1; i
< argc
; i
++) {
1330 if (argv
[i
] == s
+ 1) {
1332 s
+= strlen(s
); /* this one is ok too */
1338 #if defined(USE_ENVSPACE_FOR_ARG0)
1339 if (environ
&& (s
== environ
[0])) {
1341 for (i
= 1; environ
[i
]; i
++) {
1342 if (environ
[i
] == s
+ 1) {
1344 s
+= strlen(s
); /* this one is ok too */
1347 ruby_setenv("", NULL
); /* duplicate environ vars */
1355 set_arg0(VALUE val
, ID id
)
1360 if (origarg
.argv
== 0)
1361 rb_raise(rb_eRuntimeError
, "$0 not initialized");
1363 s
= RSTRING_PTR(val
);
1364 i
= RSTRING_LEN(val
);
1365 #if defined(PSTAT_SETCMD)
1368 char buf
[PST_CLEN
+ 1]; /* PST_CLEN is 64 (HP-UX 11.23) */
1369 strncpy(buf
, s
, PST_CLEN
);
1370 buf
[PST_CLEN
] = '\0';
1371 un
.pst_command
= buf
;
1372 pstat(PSTAT_SETCMD
, un
, PST_CLEN
, 0, 0);
1377 pstat(PSTAT_SETCMD
, un
, i
, 0, 0);
1379 #elif defined(HAVE_SETPROCTITLE)
1380 setproctitle("%.*s", (int)i
, s
);
1383 if (i
>= origarg
.len
) {
1387 memcpy(origarg
.argv
[0], s
, i
);
1391 char *t
= origarg
.argv
[0] + i
;
1394 if (i
+ 1 < origarg
.len
) memset(t
+ 1, ' ', origarg
.len
- i
- 1);
1395 for (j
= 1; j
< origarg
.argc
; j
++) {
1396 origarg
.argv
[j
] = t
;
1400 rb_progname
= rb_obj_freeze(rb_tainted_str_new(s
, i
));
1404 ruby_script(const char *name
)
1407 rb_progname
= rb_obj_freeze(rb_tainted_str_new2(name
));
1412 init_ids(struct cmdline_options
*opt
)
1414 rb_uid_t uid
= getuid();
1415 rb_uid_t euid
= geteuid();
1416 rb_gid_t gid
= getgid();
1417 rb_gid_t egid
= getegid();
1423 if (uid
!= euid
) opt
->setids
|= 1;
1424 if (egid
!= gid
) opt
->setids
|= 2;
1425 if (uid
&& opt
->setids
) {
1426 rb_set_safe_level(1);
1432 forbid_setid(const char *s
, struct cmdline_options
*opt
)
1434 if (opt
->setids
& 1)
1435 rb_raise(rb_eSecurityError
, "no %s allowed while running setuid", s
);
1436 if (opt
->setids
& 2)
1437 rb_raise(rb_eSecurityError
, "no %s allowed while running setgid", s
);
1438 if (rb_safe_level() > 0)
1439 rb_raise(rb_eSecurityError
, "no %s allowed in tainted mode", s
);
1443 verbose_setter(VALUE val
, ID id
, void *data
)
1445 VALUE
*variable
= data
;
1446 *variable
= RTEST(val
) ? Qtrue
: val
;
1450 opt_W_getter(ID id
, void *data
)
1452 VALUE
*variable
= data
;
1453 switch (*variable
) {
1461 return Qnil
; /* not reached */
1465 ruby_prog_init(void)
1467 rb_define_hooked_variable("$VERBOSE", &ruby_verbose
, 0, verbose_setter
);
1468 rb_define_hooked_variable("$-v", &ruby_verbose
, 0, verbose_setter
);
1469 rb_define_hooked_variable("$-w", &ruby_verbose
, 0, verbose_setter
);
1470 rb_define_hooked_variable("$-W", &ruby_verbose
, opt_W_getter
, 0);
1471 rb_define_variable("$DEBUG", &ruby_debug
);
1472 rb_define_variable("$-d", &ruby_debug
);
1474 rb_define_hooked_variable("$0", &rb_progname
, 0, set_arg0
);
1475 rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname
, 0, set_arg0
);
1477 rb_define_global_const("ARGV", rb_argv
);
1478 rb_global_variable(&rb_argv0
);
1482 * There is no way we can refer to them from ruby, so close them to save
1485 (void)fclose(stdaux
);
1486 (void)fclose(stdprn
);
1491 ruby_set_argv(int argc
, char **argv
)
1496 #if defined(USE_DLN_A_OUT)
1498 dln_argv0
= origarg
.argv
[0];
1500 dln_argv0
= argv
[0];
1503 for (i
= 0; i
< argc
; i
++) {
1504 VALUE arg
= rb_tainted_str_new2(argv
[i
]);
1507 rb_ary_push(av
, arg
);
1523 #define rb_define_readonly_boolean(name, val) \
1524 rb_define_virtual_variable((name), (val) ? true_value : false_value, 0)
1527 ruby_process_options(int argc
, char **argv
)
1529 struct cmdline_arguments args
;
1530 struct cmdline_options opt
;
1533 ruby_script(argv
[0]); /* for the time being */
1534 rb_argv0
= rb_str_new4(rb_progname
);
1537 args
.opt
= cmdline_options_init(&opt
);
1538 opt
.ext
.enc
.index
= -1;
1539 tree
= (NODE
*)rb_vm_call_cfunc(rb_vm_top_self(),
1540 process_options
, (VALUE
)&args
,
1543 rb_define_readonly_boolean("$-p", opt
.do_print
);
1544 rb_define_readonly_boolean("$-l", opt
.do_line
);
1545 rb_define_readonly_boolean("$-a", opt
.do_split
);
1551 ruby_sysinit(int *argc
, char ***argv
)
1553 #if defined(__APPLE__) && (defined(__MACH__) || defined(__DARWIN__))
1554 int i
, n
= *argc
, len
= 0;
1555 char **v1
= *argv
, **v2
, *p
;
1557 for (i
= 0; i
< n
; ++i
) {
1558 len
+= strlen(v1
[i
]) + 1;
1560 v2
= malloc((n
+ 1)* sizeof(char*) + len
);
1561 p
= (char *)&v2
[n
+ 1];
1562 for (i
= 0; i
< n
; ++i
) {
1563 int l
= strlen(v1
[i
]);
1564 memcpy(p
, v1
[i
], l
+ 1);
1570 #elif defined(__MACOS__) && defined(__MWERKS__)
1571 *argc
= ccommand(argv
);
1572 #elif defined(_WIN32)
1573 void rb_w32_sysinit(int *argc
, char ***argv
);
1574 rb_w32_sysinit(argc
, argv
);
1576 origarg
.argc
= *argc
;
1577 origarg
.argv
= *argv
;
1578 #if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE)
1579 origarg
.len
= get_arglen(origarg
.argc
, origarg
.argv
);
1581 #if defined(USE_DLN_A_OUT)
1582 dln_argv0
= origarg
.argv
[0];