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 /* TODO: move to VM */
61 VALUE ruby_debug
= Qfalse
;
62 VALUE ruby_verbose
= Qfalse
;
63 VALUE
rb_parser_get_yydebug(VALUE
);
64 VALUE
rb_parser_set_yydebug(VALUE
, VALUE
);
66 const char *ruby_get_inplace_mode(void);
67 void ruby_set_inplace_mode(const char *);
69 #define DISABLE_BIT(bit) (1U << disable_##bit)
70 enum disable_flag_bits
{
75 struct cmdline_options
{
77 int do_loop
, do_print
;
78 int do_check
, do_line
;
79 int do_split
, do_search
;
97 struct cmdline_arguments
{
100 struct cmdline_options
*opt
;
103 static NODE
*load_file(VALUE
, const char *, int, struct cmdline_options
*);
104 static void forbid_setid(const char *);
109 #if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE)
115 usage(const char *name
)
117 /* This message really ought to be max 23 lines.
118 * Removed -h because the user already knows that option. Others? */
120 static const char *const usage_msg
[] = {
121 "-0[octal] specify record separator (\\0, if no argument)",
122 "-a autosplit mode with -n or -p (splits $_ into $F)",
123 "-c check syntax only",
124 "-Cdirectory cd to directory, before executing your script",
125 "-d set debugging flags (set $DEBUG to true)",
126 "-e 'command' one line of script. Several -e's allowed. Omit [programfile]",
127 "-Eencoding specifies the character encoding for the program codes",
128 "-Fpattern split() pattern for autosplit (-a)",
129 "-i[extension] edit ARGV files in place (make backup if extension supplied)",
130 "-Idirectory specify $LOAD_PATH directory (may be used more than once)",
131 "-l enable line ending processing",
132 "-n assume 'while gets(); ... end' loop around your script",
133 "-p assume loop like -n but print line also like sed",
134 "-rlibrary require the library, before executing your script",
135 "-s enable some switch parsing for switches after script name",
136 "-S look for the script using PATH environment variable",
137 "-T[level] turn on tainting checks",
138 "-v print version number, then turn on verbose mode",
139 "-w turn warnings on for your script",
140 "-W[level] set warning level; 0=silence, 1=medium, 2=verbose (default)",
141 "-x[directory] strip off text before #!ruby line and perhaps cd to directory",
142 "--copyright print the copyright",
143 "--version print the version",
146 const char *const *p
= usage_msg
;
148 printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name
);
150 printf(" %s\n", *p
++);
153 VALUE
rb_get_load_path(void);
155 #ifndef CharNext /* defined as CharNext[AW] on Windows. */
156 #define CharNext(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
159 #if defined DOSISH || defined __CYGWIN__
161 translate_char(char *p
, int from
, int to
)
164 if ((unsigned char)*p
== from
)
171 #if defined _WIN32 || defined __CYGWIN__ || defined __DJGPP__
173 rubylib_mangled_path(const char *s
, unsigned int l
)
175 static char *newp
, *oldp
;
176 static int newl
, oldl
, notfound
;
180 if (!newp
&& !notfound
) {
181 newp
= getenv("RUBYLIB_PREFIX");
183 oldp
= newp
= strdup(newp
);
184 while (*newp
&& !ISSPACE(*newp
) && *newp
!= ';') {
185 newp
= CharNext(newp
); /* Skip digits. */
188 while (*newp
&& (ISSPACE(*newp
) || *newp
== ';')) {
189 newp
= CharNext(newp
); /* Skip whitespace. */
192 if (newl
== 0 || oldl
== 0) {
193 rb_fatal("malformed RUBYLIB_PREFIX");
195 translate_char(newp
, '\\', '/');
201 if (!newp
|| l
< oldl
|| STRNCASECMP(oldp
, s
, oldl
) != 0) {
202 return rb_str_new(s
, l
);
204 ret
= rb_str_new(0, l
+ newl
- oldl
);
205 ptr
= RSTRING_PTR(ret
);
206 memcpy(ptr
, newp
, newl
);
207 memcpy(ptr
+ newl
, s
+ oldl
, l
- oldl
);
208 ptr
[l
+ newl
- oldl
] = 0;
213 rubylib_mangled_path2(const char *s
)
215 return rubylib_mangled_path(s
, strlen(s
));
218 #define rubylib_mangled_path rb_str_new
219 #define rubylib_mangled_path2 rb_str_new2
223 push_include(const char *path
, VALUE (*filter
)(VALUE
))
225 const char sep
= PATH_SEP_CHAR
;
227 VALUE load_path
= GET_VM()->load_path
;
234 for (s
= p
; *s
&& *s
!= sep
; s
= CharNext(s
));
235 rb_ary_push(load_path
, (*filter
)(rubylib_mangled_path(p
, s
- p
)));
242 push_include_cygwin(const char *path
, VALUE (*filter
)(VALUE
))
245 char rubylib
[FILENAME_MAX
];
254 for (s
= p
; *s
&& *s
!= ';'; s
= CharNext(s
));
258 buf
= rb_str_new(p
, len
);
259 p
= RSTRING_PTR(buf
);
262 rb_str_resize(buf
, len
);
263 p
= strncpy(RSTRING_PTR(buf
), p
, len
);
266 if (cygwin_conv_to_posix_path(p
, rubylib
) == 0)
268 push_include(p
, filter
);
274 #define push_include push_include_cygwin
278 ruby_push_include(const char *path
, VALUE (*filter
)(VALUE
))
282 push_include(path
, filter
);
286 identical_path(VALUE path
)
292 ruby_incpush(const char *path
)
294 ruby_push_include(path
, identical_path
);
298 expand_include_path(VALUE path
)
300 char *p
= RSTRING_PTR(path
);
303 if (*p
== '.' && p
[1] == '/')
305 return rb_file_expand_path(path
, Qnil
);
309 ruby_incpush_expand(const char *path
)
311 ruby_push_include(path
, expand_include_path
);
314 #if defined DOSISH || defined __CYGWIN__
315 #define LOAD_RELATIVE 1
318 #if defined _WIN32 || defined __CYGWIN__
319 static HMODULE libruby
;
322 DllMain(HINSTANCE dll
, DWORD reason
, LPVOID reserved
)
324 if (reason
== DLL_PROCESS_ATTACH
)
331 ruby_init_loadpath(void)
334 #if defined LOAD_RELATIVE
335 char libpath
[MAXPATHLEN
+ 1];
339 #if defined _WIN32 || defined __CYGWIN__
340 GetModuleFileName(libruby
, libpath
, sizeof libpath
);
342 extern char *__dos_argv0
;
343 strncpy(libpath
, __dos_argv0
, sizeof(libpath
) - 1);
344 #elif defined(__human68k__)
346 strncpy(libpath
, _argv
[0], sizeof(libpath
) - 1);
347 #elif defined(__EMX__)
348 _execname(libpath
, sizeof(libpath
) - 1);
351 libpath
[sizeof(libpath
) - 1] = '\0';
353 translate_char(libpath
, '\\', '/');
354 #elif defined __CYGWIN__
356 char rubylib
[FILENAME_MAX
];
357 cygwin_conv_to_posix_path(libpath
, rubylib
);
358 strncpy(libpath
, rubylib
, sizeof(libpath
));
361 p
= strrchr(libpath
, '/');
364 if (p
- libpath
> 3 && !STRCASECMP(p
- 4, "/bin")) {
370 strcpy(libpath
, ".");
374 rest
= sizeof(libpath
) - 1 - (p
- libpath
);
376 #define RUBY_RELATIVE(path) (strncpy(p, (path), rest), libpath)
378 #define RUBY_RELATIVE(path) (path)
380 #define incpush(path) rb_ary_push(load_path, rubylib_mangled_path2(path))
381 load_path
= GET_VM()->load_path
;
383 if (rb_safe_level() == 0) {
384 ruby_incpush(getenv("RUBYLIB"));
387 #ifdef RUBY_SEARCH_PATH
388 incpush(RUBY_RELATIVE(RUBY_SEARCH_PATH
));
391 incpush(RUBY_RELATIVE(RUBY_SITE_LIB2
));
392 #ifdef RUBY_SITE_THIN_ARCHLIB
393 incpush(RUBY_RELATIVE(RUBY_SITE_THIN_ARCHLIB
));
395 incpush(RUBY_RELATIVE(RUBY_SITE_ARCHLIB
));
396 incpush(RUBY_RELATIVE(RUBY_SITE_LIB
));
398 incpush(RUBY_RELATIVE(RUBY_VENDOR_LIB2
));
399 #ifdef RUBY_VENDOR_THIN_ARCHLIB
400 incpush(RUBY_RELATIVE(RUBY_VENDOR_THIN_ARCHLIB
));
402 incpush(RUBY_RELATIVE(RUBY_VENDOR_ARCHLIB
));
403 incpush(RUBY_RELATIVE(RUBY_VENDOR_LIB
));
405 incpush(RUBY_RELATIVE(RUBY_LIB
));
406 #ifdef RUBY_THIN_ARCHLIB
407 incpush(RUBY_RELATIVE(RUBY_THIN_ARCHLIB
));
409 incpush(RUBY_RELATIVE(RUBY_ARCHLIB
));
411 if (rb_safe_level() == 0) {
418 struct req_list
*next
;
421 struct req_list
*last
, head
;
422 } req_list
= {&req_list
.head
,};
425 add_modules(const char *mod
)
427 struct req_list
*list
;
429 list
= ALLOC(struct req_list
);
430 list
->name
= ALLOC_N(char, strlen(mod
) + 1);
431 strcpy(list
->name
, mod
);
433 req_list
.last
->next
= list
;
434 req_list
.last
= list
;
437 extern void Init_ext(void);
438 extern VALUE
rb_vm_top_self(void);
441 require_libraries(void)
443 struct req_list
*list
= req_list
.head
.next
;
444 struct req_list
*tmp
;
445 ID require
= rb_intern("require");
447 Init_ext(); /* should be called here for some reason :-( */
450 VALUE feature
= rb_str_new2(list
->name
);
455 rb_funcall2(rb_vm_top_self(), require
, 1, &feature
);
457 req_list
.head
.next
= 0;
461 process_sflag(struct cmdline_options
*opt
)
466 VALUE argv
= rb_argv
;
468 n
= RARRAY_LEN(argv
);
469 args
= RARRAY_PTR(argv
);
472 char *s
= StringValuePtr(v
);
479 if (s
[1] == '-' && s
[2] == '\0')
483 /* check if valid name before replacing - with _ */
484 for (p
= s
+ 1; *p
; p
++) {
493 else if (*p
!= '_' && !ISALNUM(*p
)) {
496 rb_str_new2("invalid name for global variable - ");
497 if (!(p
= strchr(p
, '='))) {
498 rb_str_cat2(name_error
[0], s
);
501 rb_str_cat(name_error
[0], s
, p
- s
);
503 name_error
[1] = args
[-1];
504 rb_exc_raise(rb_class_new_instance(2, name_error
, rb_eNameError
));
509 for (p
= s
+ 1; *p
; ++p
) {
516 n
= RARRAY_LEN(argv
) - n
;
524 NODE
*rb_parser_append_print(VALUE
, NODE
*);
525 NODE
*rb_parser_while_loop(VALUE
, NODE
*, int, int);
526 static int proc_options(int argc
, char **argv
, struct cmdline_options
*opt
);
529 moreswitches(const char *s
, struct cmdline_options
*opt
)
536 argv
[0] = argv
[2] = 0;
537 while (*s
&& !ISSPACE(*s
))
539 argv
[1] = ALLOCA_N(char, s
- p
+ 2);
541 strncpy(argv
[1] + 1, p
, s
- p
);
542 argv
[1][s
- p
+ 1] = '\0';
543 proc_options(argc
, argv
, opt
);
544 while (*s
&& ISSPACE(*s
))
549 #define NAME_MATCH_P(name, str, len) \
550 ((len) < sizeof(name) && strncmp((str), name, (len)) == 0)
552 #define UNSET_WHEN(name, bit, str, len) \
553 if (NAME_MATCH_P(name, str, len)) { \
554 *(unsigned int *)arg &= ~(bit); \
558 #define SET_WHEN(name, bit, str, len) \
559 if (NAME_MATCH_P(name, str, len)) { \
560 *(unsigned int *)arg |= (bit); \
565 enable_option(const char *str
, int len
, void *arg
)
567 #define UNSET_WHEN_DISABLE(bit) UNSET_WHEN(#bit, DISABLE_BIT(bit), str, len)
568 UNSET_WHEN_DISABLE(gems
);
569 UNSET_WHEN_DISABLE(rubyopt
);
570 if (NAME_MATCH_P("all", str
, len
)) {
571 *(unsigned int *)arg
= 0U;
574 rb_warn("unknown argument for --enable: `%.*s'", len
, str
);
578 disable_option(const char *str
, int len
, void *arg
)
580 #define SET_WHEN_DISABLE(bit) SET_WHEN(#bit, DISABLE_BIT(bit), str, len)
581 SET_WHEN_DISABLE(gems
);
582 SET_WHEN_DISABLE(rubyopt
);
583 if (NAME_MATCH_P("all", str
, len
)) {
584 *(unsigned int *)arg
= ~0U;
587 rb_warn("unknown argument for --disable: `%.*s'", len
, str
);
591 proc_options(int argc
, char **argv
, struct cmdline_options
*opt
)
599 for (argc
--, argv
++; argc
> 0; argc
--, argv
++) {
600 if (argv
[0][0] != '-' || !argv
[0][1])
607 opt
->do_split
= Qtrue
;
612 opt
->do_print
= Qtrue
;
615 opt
->do_loop
= Qtrue
;
621 ruby_verbose
= Qtrue
;
638 ruby_verbose
= Qtrue
;
645 int v
= 2; /* -W as -W2 */
648 v
= scan_oct(s
, 1, &numlen
);
658 ruby_verbose
= Qfalse
;
661 ruby_verbose
= Qtrue
;
668 opt
->do_check
= Qtrue
;
679 usage(origarg
.argv
[0]);
680 rb_exit(EXIT_SUCCESS
);
684 opt
->do_line
= Qtrue
;
685 rb_output_rs
= rb_rs
;
691 opt
->do_search
= Qtrue
;
702 rb_raise(rb_eRuntimeError
, "no code specified for -e");
704 if (!opt
->e_script
) {
705 opt
->e_script
= rb_str_new(0, 0);
706 if (opt
->script
== 0)
709 rb_str_cat2(opt
->e_script
, s
);
710 rb_str_cat2(opt
->e_script
, "\n");
719 add_modules(argv
[1]);
726 ruby_set_inplace_mode(s
+ 1);
732 if (*s
&& chdir(s
) < 0) {
733 rb_fatal("Can't chdir to %s", s
);
745 rb_fatal("Can't chdir");
748 rb_fatal("Can't chdir to %s", s
);
754 rb_fs
= rb_reg_new(s
, strlen(s
), 0);
759 if (!*++s
) goto next_encoding
;
764 const char *enc_name
= 0;
770 enc_name
= "Windows-31J";
775 case 'N': case 'n': case 'A': case 'a':
776 enc_name
= "ASCII-8BIT";
780 opt
->src
.enc
.name
= rb_str_new2(enc_name
);
781 opt
->ext
.enc
.name
= opt
->src
.enc
.name
;
793 v
= scan_oct(s
, 2, &numlen
);
798 rb_set_safe_level(v
);
805 ruby_incpush_expand(s
);
807 ruby_incpush_expand(argv
[1]);
818 v
= scan_oct(s
, 4, &numlen
);
822 else if (v
== 0 && numlen
>= 2) {
823 rb_rs
= rb_str_new2("\n\n");
827 rb_rs
= rb_str_new(&c
, 1);
833 if (!s
[1] || (s
[1] == '\r' && !s
[2])) {
838 if (strcmp("copyright", s
) == 0)
840 else if (strcmp("debug", s
) == 0) {
842 ruby_verbose
= Qtrue
;
844 else if (strncmp("enable", s
, n
= 6) == 0 &&
845 (!s
[n
] || s
[n
] == '-' || s
[n
] == '=')) {
846 if ((s
+= n
+ 1)[-1] ? !*s
: (!--argc
|| !(s
= *++argv
))) {
847 rb_raise(rb_eRuntimeError
, "missing argument for --enable");
849 ruby_each_words(s
, enable_option
, &opt
->disable
);
851 else if (strncmp("disable", s
, n
= 7) == 0 &&
852 (!s
[n
] || s
[n
] == '-' || s
[n
] == '=')) {
853 if ((s
+= n
+ 1)[-1] ? !*s
: (!--argc
|| !(s
= *++argv
))) {
854 rb_raise(rb_eRuntimeError
, "missing argument for --disable");
856 ruby_each_words(s
, disable_option
, &opt
->disable
);
858 else if (strncmp("encoding", s
, n
= 8) == 0 && (!s
[n
] || s
[n
] == '=')) {
862 if (!--argc
|| !(s
= *++argv
)) {
863 rb_raise(rb_eRuntimeError
, "missing argument for --encoding");
867 opt
->ext
.enc
.name
= rb_str_new2(s
);
869 else if (strcmp("version", s
) == 0)
871 else if (strcmp("verbose", s
) == 0) {
873 ruby_verbose
= Qtrue
;
875 else if (strcmp("yydebug", s
) == 0)
877 else if (strcmp("help", s
) == 0) {
878 usage(origarg
.argv
[0]);
879 rb_exit(EXIT_SUCCESS
);
882 rb_raise(rb_eRuntimeError
,
883 "invalid option --%s (-h will show valid options)", s
);
894 rb_raise(rb_eRuntimeError
,
895 "invalid option -%c (-h will show valid options)",
896 (int)(unsigned char)*s
);
899 rb_raise(rb_eRuntimeError
,
900 "invalid option -\\x%02X (-h will show valid options)",
901 (int)(unsigned char)*s
);
915 void Init_prelude(void);
918 ruby_init_gems(int enable
)
921 gem
= rb_define_module("Gem");
922 rb_const_set(gem
, rb_intern("Enable"), enable
? Qtrue
: Qfalse
);
927 opt_enc_index(VALUE enc_name
)
929 const char *s
= RSTRING_PTR(enc_name
);
930 int i
= rb_enc_find_index(s
);
933 rb_raise(rb_eRuntimeError
, "unknown encoding name - %s", s
);
935 else if (rb_enc_dummy_p(rb_enc_from_index(i
))) {
936 rb_raise(rb_eRuntimeError
, "dummy encoding is not acceptable - %s ", s
);
943 static int src_encoding_index
= -1; /* TODO: VM private */
946 process_options(VALUE arg
)
948 struct cmdline_arguments
*argp
= (struct cmdline_arguments
*)arg
;
949 struct cmdline_options
*opt
= argp
->opt
;
950 int argc
= argp
->argc
;
951 char **argv
= argp
->argv
;
956 int i
= proc_options(argc
, argv
, opt
);
962 if (!(opt
->disable
& DISABLE_BIT(rubyopt
)) &&
963 rb_safe_level() == 0 && (s
= getenv("RUBYOPT"))) {
964 VALUE src_enc_name
= opt
->src
.enc
.name
;
965 VALUE ext_enc_name
= opt
->ext
.enc
.name
;
969 if (*s
== 'T' || (*s
== '-' && *(s
+ 1) == 'T')) {
976 v
= scan_oct(s
, 2, &numlen
);
980 rb_set_safe_level(v
);
989 } while (ISSPACE(*s
));
995 if (!strchr("EIdvwWrK", *s
))
996 rb_raise(rb_eRuntimeError
,
997 "invalid switch in RUBYOPT: -%c", *s
);
998 s
= moreswitches(s
, opt
);
1002 opt
->src
.enc
.name
= src_enc_name
;
1004 opt
->ext
.enc
.name
= ext_enc_name
;
1008 ruby_show_version();
1011 if (opt
->copyright
) {
1012 ruby_show_copyright();
1015 if (rb_safe_level() >= 4) {
1017 OBJ_TAINT(GET_VM()->load_path
);
1020 if (!opt
->e_script
) {
1021 if (argc
== 0) { /* no more args */
1027 opt
->script
= argv
[0];
1028 if (opt
->script
[0] == '\0') {
1031 else if (opt
->do_search
) {
1032 char *path
= getenv("RUBYPATH");
1036 opt
->script
= dln_find_file(argv
[0], path
);
1039 opt
->script
= dln_find_file(argv
[0], getenv(PATH_ENV
));
1042 opt
->script
= argv
[0];
1049 ruby_script(opt
->script
);
1050 #if defined DOSISH || defined __CYGWIN__
1051 translate_char(RSTRING_PTR(rb_progname
), '\\', '/');
1053 opt
->script_name
= rb_str_new4(rb_progname
);
1054 opt
->script
= RSTRING_PTR(opt
->script_name
);
1055 ruby_set_argv(argc
, argv
);
1058 ruby_init_loadpath();
1059 safe
= rb_safe_level();
1060 rb_set_safe_level_force(0);
1061 ruby_init_gems(!(opt
->disable
& DISABLE_BIT(gems
)));
1062 parser
= rb_parser_new();
1063 if (opt
->yydebug
) rb_parser_set_yydebug(parser
, Qtrue
);
1064 if (opt
->ext
.enc
.name
!= 0) {
1065 opt
->ext
.enc
.index
= opt_enc_index(opt
->ext
.enc
.name
);
1067 if (opt
->src
.enc
.name
!= 0) {
1068 opt
->src
.enc
.index
= opt_enc_index(opt
->src
.enc
.name
);
1069 src_encoding_index
= opt
->src
.enc
.index
;
1071 if (opt
->ext
.enc
.index
>= 0) {
1072 enc
= rb_enc_from_index(opt
->ext
.enc
.index
);
1075 enc
= rb_locale_encoding();
1077 rb_enc_set_default_external(rb_enc_from_encoding(enc
));
1079 rb_set_safe_level_force(safe
);
1080 if (opt
->e_script
) {
1082 if (opt
->src
.enc
.index
>= 0) {
1083 eenc
= rb_enc_from_index(opt
->src
.enc
.index
);
1086 eenc
= rb_locale_encoding();
1088 rb_enc_associate(opt
->e_script
, eenc
);
1089 require_libraries();
1090 tree
= rb_parser_compile_string(parser
, opt
->script
, opt
->e_script
, 1);
1093 if (opt
->script
[0] == '-' && !opt
->script
[1]) {
1094 forbid_setid("program input from stdin");
1096 tree
= load_file(parser
, opt
->script
, 1, opt
);
1099 if (!tree
) return Qfalse
;
1104 if (rb_safe_level() >= 4) {
1105 FL_UNSET(rb_argv
, FL_TAINT
);
1106 FL_UNSET(GET_VM()->load_path
, FL_TAINT
);
1109 if (opt
->do_check
) {
1110 printf("Syntax OK\n");
1114 if (opt
->do_print
) {
1115 tree
= rb_parser_append_print(parser
, tree
);
1118 tree
= rb_parser_while_loop(parser
, tree
, opt
->do_line
, opt
->do_split
);
1121 return rb_iseq_new(tree
, rb_str_new2("<main>"),
1122 opt
->script_name
, Qfalse
, ISEQ_TYPE_TOP
);
1126 load_file(VALUE parser
, const char *fname
, int script
, struct cmdline_options
*opt
)
1128 extern VALUE rb_stdin
;
1135 rb_load_fail(fname
);
1136 if (strcmp(fname
, "-") == 0) {
1140 int fd
, mode
= O_RDONLY
;
1141 #if defined DOSISH || defined __CYGWIN__
1143 const char *ext
= strrchr(fname
, '.');
1144 if (ext
&& STRCASECMP(ext
, ".exe") == 0)
1148 if ((fd
= open(fname
, mode
)) < 0) {
1149 rb_load_fail(fname
);
1152 f
= rb_io_fdopen(fd
, mode
, fname
);
1156 VALUE c
= 1; /* something not nil */
1159 int no_src_enc
= !opt
->src
.enc
.name
;
1160 int no_ext_enc
= !opt
->ext
.enc
.name
;
1162 enc
= rb_usascii_encoding();
1163 rb_funcall(f
, rb_intern("set_encoding"), 1, rb_enc_from_encoding(enc
));
1167 opt
->xflag
= Qfalse
;
1168 while (!NIL_P(line
= rb_io_gets(f
))) {
1170 if (RSTRING_LEN(line
) > 2
1171 && RSTRING_PTR(line
)[0] == '#'
1172 && RSTRING_PTR(line
)[1] == '!') {
1173 if ((p
= strstr(RSTRING_PTR(line
), "ruby")) != 0) {
1178 rb_raise(rb_eLoadError
, "no Ruby script found in input");
1181 c
= rb_io_getbyte(f
);
1182 if (c
== INT2FIX('#')) {
1183 c
= rb_io_getbyte(f
);
1184 if (c
== INT2FIX('!')) {
1185 line
= rb_io_gets(f
);
1189 if ((p
= strstr(RSTRING_PTR(line
), "ruby")) == 0) {
1190 /* not ruby script, kick the program */
1193 char *pend
= RSTRING_PTR(line
) + RSTRING_LEN(line
);
1195 p
= RSTRING_PTR(line
); /* skip `#!' */
1196 if (pend
[-1] == '\n')
1197 pend
--; /* chomp line */
1198 if (pend
[-1] == '\r')
1201 while (p
< pend
&& ISSPACE(*p
))
1203 path
= p
; /* interpreter path */
1204 while (p
< pend
&& !ISSPACE(*p
))
1208 argv
= ALLOCA_N(char *, origarg
.argc
+ 3);
1210 MEMCPY(argv
+ 2, origarg
.argv
+ 1, char *, origarg
.argc
);
1213 argv
= origarg
.argv
;
1218 rb_fatal("Can't exec %s", path
);
1223 RSTRING_PTR(line
)[RSTRING_LEN(line
) - 1] = '\0';
1224 if (RSTRING_PTR(line
)[RSTRING_LEN(line
) - 2] == '\r')
1225 RSTRING_PTR(line
)[RSTRING_LEN(line
) - 2] = '\0';
1226 if ((p
= strstr(p
, " -")) != 0) {
1227 p
++; /* skip space before `-' */
1229 p
= moreswitches(p
+ 1, opt
);
1233 /* push back shebang for pragma may exist in next line */
1234 rb_io_ungetc(f
, rb_str_new2("!\n"));
1236 else if (!NIL_P(c
)) {
1239 rb_io_ungetc(f
, INT2FIX('#'));
1240 if (no_src_enc
&& opt
->src
.enc
.name
) {
1241 opt
->src
.enc
.index
= opt_enc_index(opt
->src
.enc
.name
);
1242 src_encoding_index
= opt
->src
.enc
.index
;
1244 if (no_ext_enc
&& opt
->ext
.enc
.name
) {
1245 opt
->ext
.enc
.index
= opt_enc_index(opt
->ext
.enc
.name
);
1248 else if (!NIL_P(c
)) {
1251 require_libraries(); /* Why here? unnatural */
1253 if (opt
->src
.enc
.index
>= 0) {
1254 enc
= rb_enc_from_index(opt
->src
.enc
.index
);
1256 else if (f
== rb_stdin
) {
1257 enc
= rb_locale_encoding();
1260 enc
= rb_usascii_encoding();
1262 rb_funcall(f
, rb_intern("set_encoding"), 1, rb_enc_from_encoding(enc
));
1263 tree
= (NODE
*)rb_parser_compile_file(parser
, fname
, f
, line_start
);
1264 rb_funcall(f
, rb_intern("set_encoding"), 1, rb_parser_encoding(parser
));
1265 if (script
&& rb_parser_end_seen_p(parser
)) {
1266 rb_define_global_const("DATA", f
);
1268 else if (f
!= rb_stdin
) {
1275 rb_load_file(const char *fname
)
1277 struct cmdline_options opt
;
1279 MEMZERO(&opt
, opt
, 1);
1280 opt
.src
.enc
.index
= src_encoding_index
;
1281 return load_file(rb_parser_new(), fname
, 0, &opt
);
1284 #if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE)
1285 #if !defined(_WIN32) && !(defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
1286 #define USE_ENVSPACE_FOR_ARG0
1289 #ifdef USE_ENVSPACE_FOR_ARG0
1290 extern char **environ
;
1294 get_arglen(int argc
, char **argv
)
1299 if (!argc
) return 0;
1301 /* See if all the arguments are contiguous in memory */
1302 for (i
= 1; i
< argc
; i
++) {
1303 if (argv
[i
] == s
+ 1) {
1305 s
+= strlen(s
); /* this one is ok too */
1311 #if defined(USE_ENVSPACE_FOR_ARG0)
1312 if (environ
&& (s
== environ
[0])) {
1314 for (i
= 1; environ
[i
]; i
++) {
1315 if (environ
[i
] == s
+ 1) {
1317 s
+= strlen(s
); /* this one is ok too */
1320 ruby_setenv("", NULL
); /* duplicate environ vars */
1328 set_arg0(VALUE val
, ID id
)
1333 if (origarg
.argv
== 0)
1334 rb_raise(rb_eRuntimeError
, "$0 not initialized");
1336 s
= RSTRING_PTR(val
);
1337 i
= RSTRING_LEN(val
);
1338 #if defined(PSTAT_SETCMD)
1341 char buf
[PST_CLEN
+ 1]; /* PST_CLEN is 64 (HP-UX 11.23) */
1342 strncpy(buf
, s
, PST_CLEN
);
1343 buf
[PST_CLEN
] = '\0';
1344 un
.pst_command
= buf
;
1345 pstat(PSTAT_SETCMD
, un
, PST_CLEN
, 0, 0);
1350 pstat(PSTAT_SETCMD
, un
, i
, 0, 0);
1352 #elif defined(HAVE_SETPROCTITLE)
1353 setproctitle("%.*s", (int)i
, s
);
1356 if (i
>= origarg
.len
) {
1360 memcpy(origarg
.argv
[0], s
, i
);
1361 t
= origarg
.argv
[0] + i
;
1364 if (i
+ 1 < origarg
.len
) memset(t
+ 1, ' ', origarg
.len
- i
- 1);
1368 for (j
= 1; j
< origarg
.argc
; j
++) {
1369 origarg
.argv
[j
] = t
;
1373 rb_progname
= rb_tainted_str_new(s
, i
);
1377 ruby_script(const char *name
)
1380 rb_progname
= rb_tainted_str_new2(name
);
1384 static int uid
, euid
, gid
, egid
;
1389 uid
= (int)getuid();
1390 euid
= (int)geteuid();
1391 gid
= (int)getgid();
1392 egid
= (int)getegid();
1397 if (uid
&& (euid
!= uid
|| egid
!= gid
)) {
1398 rb_set_safe_level(1);
1403 forbid_setid(const char *s
)
1406 rb_raise(rb_eSecurityError
, "no %s allowed while running setuid", s
);
1408 rb_raise(rb_eSecurityError
, "no %s allowed while running setgid", s
);
1409 if (rb_safe_level() > 0)
1410 rb_raise(rb_eSecurityError
, "no %s allowed in tainted mode", s
);
1414 verbose_setter(VALUE val
, ID id
, VALUE
*variable
)
1416 ruby_verbose
= RTEST(val
) ? Qtrue
: val
;
1420 opt_W_getter(VALUE val
, ID id
)
1422 if (ruby_verbose
== Qnil
)
1424 if (ruby_verbose
== Qfalse
)
1426 if (ruby_verbose
== Qtrue
)
1428 return Qnil
; /* not reached */
1432 ruby_prog_init(void)
1436 rb_define_hooked_variable("$VERBOSE", &ruby_verbose
, 0, verbose_setter
);
1437 rb_define_hooked_variable("$-v", &ruby_verbose
, 0, verbose_setter
);
1438 rb_define_hooked_variable("$-w", &ruby_verbose
, 0, verbose_setter
);
1439 rb_define_virtual_variable("$-W", opt_W_getter
, 0);
1440 rb_define_variable("$DEBUG", &ruby_debug
);
1441 rb_define_variable("$-d", &ruby_debug
);
1443 rb_define_hooked_variable("$0", &rb_progname
, 0, set_arg0
);
1444 rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname
, 0, set_arg0
);
1446 rb_define_global_const("ARGV", rb_argv
);
1447 rb_global_variable(&rb_argv0
);
1451 * There is no way we can refer to them from ruby, so close them to save
1454 (void)fclose(stdaux
);
1455 (void)fclose(stdprn
);
1460 ruby_set_argv(int argc
, char **argv
)
1463 rb_encoding
*enc
= rb_locale_encoding();
1466 #if defined(USE_DLN_A_OUT)
1468 dln_argv0
= origarg
.argv
[0];
1470 dln_argv0
= argv
[0];
1473 for (i
= 0; i
< argc
; i
++) {
1474 VALUE arg
= rb_tainted_str_new2(argv
[i
]);
1475 rb_enc_associate(arg
, enc
);
1478 rb_ary_push(av
, arg
);
1494 #define rb_define_readonly_boolean(name, val) \
1495 rb_define_virtual_variable((name), (val) ? true_value : false_value, 0)
1498 ruby_process_options(int argc
, char **argv
)
1500 struct cmdline_arguments args
;
1501 struct cmdline_options opt
;
1504 MEMZERO(&opt
, opt
, 1);
1505 ruby_script(argv
[0]); /* for the time being */
1506 rb_argv0
= rb_progname
;
1510 opt
.src
.enc
.index
= src_encoding_index
;
1511 opt
.ext
.enc
.index
= -1;
1512 tree
= (NODE
*)rb_vm_call_cfunc(rb_vm_top_self(),
1513 process_options
, (VALUE
)&args
,
1516 rb_define_readonly_boolean("$-p", opt
.do_print
);
1517 rb_define_readonly_boolean("$-l", opt
.do_line
);
1518 rb_define_readonly_boolean("$-a", opt
.do_split
);
1524 ruby_sysinit(int *argc
, char ***argv
)
1526 #if defined(__APPLE__) && (defined(__MACH__) || defined(__DARWIN__))
1527 int i
, n
= *argc
, len
= 0;
1528 char **v1
= *argv
, **v2
, *p
;
1530 for (i
= 0; i
< n
; ++i
) {
1531 len
+= strlen(v1
[i
]) + 1;
1533 v2
= malloc((n
+ 1)* sizeof(char*) + len
);
1534 p
= (char *)&v2
[n
+ 1];
1535 for (i
= 0; i
< n
; ++i
) {
1536 int l
= strlen(v1
[i
]);
1537 memcpy(p
, v1
[i
], l
+ 1);
1543 #elif defined(__MACOS__) && defined(__MWERKS__)
1544 *argc
= ccommand(argv
);
1545 #elif defined(_WIN32)
1546 void rb_w32_sysinit(int *argc
, char ***argv
);
1547 rb_w32_sysinit(argc
, argv
);
1549 origarg
.argc
= *argc
;
1550 origarg
.argv
= *argv
;
1551 #if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE)
1552 origarg
.len
= get_arglen(origarg
.argc
, origarg
.argv
);
1554 #if defined(USE_DLN_A_OUT)
1555 dln_argv0
= origarg
.argv
[0];