ruby.c
DEFINITIONS
This source file includes following functions.
- usage
- rubylib_mangle
- ruby_incpush
- ruby_init_loadpath
- add_modules
- require_libraries
- process_sflag
- moreswitches
- proc_options
- load_file
- rb_load_file
- load_stdin
- set_arg0
- ruby_script
- init_ids
- forbid_setid
- ruby_prog_init
- ruby_set_argv
- ruby_process_options
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #if defined _WIN32 || defined __CYGWIN__
16 #include <windows.h>
17 #endif
18 #include "ruby.h"
19 #include "dln.h"
20 #include "node.h"
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <ctype.h>
24
25 #ifdef __hpux
26 #include <sys/pstat.h>
27 #endif
28
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #ifndef HAVE_STRING_H
34 char *strchr _((const char*,const char));
35 char *strrchr _((const char*,const char));
36 char *strstr _((const char*,const char*));
37 #endif
38
39 #include "util.h"
40
41 #ifndef HAVE_STDLIB_H
42 char *getenv();
43 #endif
44
45 VALUE ruby_debug = Qfalse;
46 VALUE ruby_verbose = Qfalse;
47 static int sflag = 0;
48 static int xflag = 0;
49 extern int ruby_yydebug;
50
51 char *ruby_inplace_mode = Qfalse;
52
53 static void load_stdin _((void));
54 static void load_file _((char *, int));
55 static void forbid_setid _((const char *));
56
57 static VALUE do_loop = Qfalse, do_print = Qfalse;
58 static VALUE do_check = Qfalse, do_line = Qfalse;
59 static VALUE do_split = Qfalse;
60
61 static char *script;
62
63 static int origargc;
64 static char **origargv;
65
66 static void
67 usage(name)
68 const char *name;
69 {
70
71
72
73 static char *usage_msg[] = {
74 "-0[octal] specify record separator (\\0, if no argument)",
75 "-a autosplit mode with -n or -p (splits $_ into $F)",
76 "-c check syntax only",
77 "-Cdirectory cd to directory, before executing your script",
78 "-d set debugging flags (set $DEBUG to true)",
79 "-e 'command' one line of script. Several -e's allowed. Omit [programfile]",
80 "-Fpattern split() pattern for autosplit (-a)",
81 "-i[extension] edit ARGV files in place (make backup if extension supplied)",
82 "-Idirectory specify $LOAD_PATH directory (may be used more than once)",
83 "-Kkcode specifies KANJI (Japanese) code-set",
84 "-l enable line ending processing",
85 "-n assume 'while gets(); ... end' loop around your script",
86 "-p assume loop like -n but print line also like sed",
87 "-rlibrary require the library, before executing your script",
88 "-s enable some switch parsing for switches after script name",
89 "-S look for the script using PATH environment variable",
90 "-T[level] turn on tainting checks",
91 "-v print version number, then turn on verbose mode",
92 "-w turn warnings on for your script",
93 "-x[directory] strip off text before #!ruby line and perhaps cd to directory",
94 "--copyright print the copyright",
95 "--version print the version",
96 NULL
97 };
98 char **p = usage_msg;
99
100 printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name);
101 while (*p)
102 printf(" %s\n", *p++);
103 }
104
105 extern VALUE rb_load_path;
106
107 #define STATIC_FILE_LENGTH 255
108
109 #if defined _WIN32 || defined __CYGWIN__ || defined __DJGPP__
110 static char *
111 rubylib_mangle(s, l)
112 char *s;
113 unsigned int l;
114 {
115 static char *newp, *oldp;
116 static int newl, oldl, notfound;
117 static char newsub[STATIC_FILE_LENGTH+1];
118
119 if (!newp && !notfound) {
120 newp = getenv("RUBYLIB_PREFIX");
121 if (newp) {
122 char *s;
123
124 oldp = newp;
125 while (*newp && !ISSPACE(*newp) && *newp != ';') {
126 newp++; oldl++;
127 }
128 while (*newp && (ISSPACE(*newp) || *newp == ';')) {
129 newp++;
130 }
131 newl = strlen(newp);
132 if (newl == 0 || oldl == 0 || newl > STATIC_FILE_LENGTH) {
133 rb_fatal("malformed RUBYLIB_PREFIX");
134 }
135 strcpy(newsub, newp);
136 s = newsub;
137 while (*s) {
138 if (*s == '\\') *s = '/';
139 s++;
140 }
141 }
142 else {
143 notfound = 1;
144 }
145 }
146 if (l == 0) {
147 l = strlen(s);
148 }
149 if (!newp || l < oldl || strncasecmp(oldp, s, oldl) != 0) {
150 static char ret[STATIC_FILE_LENGTH+1];
151 strncpy(ret, s, l);
152 ret[l] = 0;
153 return ret;
154 }
155 if (l + newl - oldl > STATIC_FILE_LENGTH || newl > STATIC_FILE_LENGTH) {
156 rb_fatal("malformed RUBYLIB_PREFIX");
157 }
158 strcpy(newsub + newl, s + oldl);
159 newsub[l + newl - oldl] = 0;
160 return newsub;
161 }
162 #define rubylib_mangled_path(s, l) rb_str_new2(rubylib_mangle((s), (l)))
163 #define rubylib_mangled_path2(s) rb_str_new2(rubylib_mangle((s), 0))
164 #else
165 #define rubylib_mangled_path(s, l) rb_str_new((s), (l))
166 #define rubylib_mangled_path2(s) rb_str_new2(s)
167 #endif
168
169 void
170 ruby_incpush(path)
171 const char *path;
172 {
173 const char sep = PATH_SEP_CHAR;
174
175 if (path == 0) return;
176 #if defined(__CYGWIN__)
177 {
178 char rubylib[FILENAME_MAX];
179 conv_to_posix_path(path, rubylib, FILENAME_MAX);
180 path = rubylib;
181 }
182 #endif
183 if (strchr(path, sep)) {
184 const char *p, *s;
185 VALUE ary = rb_ary_new();
186
187 p = path;
188 while (*p) {
189 while (*p == sep) p++;
190 if (s = strchr(p, sep)) {
191 rb_ary_push(ary, rubylib_mangled_path(p, (int)(s-p)));
192 p = s + 1;
193 }
194 else {
195 rb_ary_push(ary, rubylib_mangled_path2(p));
196 break;
197 }
198 }
199 rb_ary_concat(rb_load_path, ary);
200 }
201 else {
202 rb_ary_push(rb_load_path, rubylib_mangled_path2(path));
203 }
204 }
205
206 #if defined _WIN32 || defined __CYGWIN__ || defined __DJGPP__ || defined __EMX__
207 #define LOAD_RELATIVE 1
208 #endif
209
210 void
211 ruby_init_loadpath()
212 {
213 #if defined LOAD_RELATIVE
214 char libpath[FILENAME_MAX+1];
215 char *p;
216 int rest;
217 #if defined _WIN32 || defined __CYGWIN__
218 # if defined LIBRUBY_SO
219 HMODULE libruby = GetModuleHandle(LIBRUBY_SO);
220 # else
221 HMODULE libruby = NULL;
222 # endif
223 GetModuleFileName(libruby, libpath, sizeof libpath);
224 #elif defined(DJGPP)
225 extern char *__dos_argv0;
226 strncpy(libpath, __dos_argv0, FILENAME_MAX);
227 #define CharNext(p) ((p) + mblen(p, MB_CUR_MAX))
228 #elif defined(__EMX__)
229 _execname(libpath, FILENAME_MAX);
230 #endif
231
232 #ifndef CharNext
233 #define CharNext(p) ((p) + 1)
234 #endif
235
236 for (p = libpath; *p; p = CharNext(p))
237 if (*p == '\\')
238 *p = '/';
239
240 p = strrchr(libpath, '/');
241 if (p) {
242 *p = 0;
243 if (p-libpath > 3 && !strcasecmp(p-4, "/bin")) {
244 p -= 4;
245 *p = 0;
246 }
247 }
248 else {
249 strcpy(libpath, ".");
250 p = libpath + 1;
251 }
252
253 rest = FILENAME_MAX - (p - libpath);
254
255 #define RUBY_RELATIVE(path) (strncpy(p, (path), rest), libpath)
256 #else
257 #define RUBY_RELATIVE(path) (path)
258 #endif
259
260 if (rb_safe_level() == 0) {
261 ruby_incpush(getenv("RUBYLIB"));
262 }
263
264 #ifdef RUBY_SEARCH_PATH
265 ruby_incpush(RUBY_RELATIVE(RUBY_SEARCH_PATH));
266 #endif
267
268 ruby_incpush(RUBY_RELATIVE(RUBY_SITE_LIB2));
269 #ifdef RUBY_SITE_THIN_ARCHLIB
270 ruby_incpush(RUBY_RELATIVE(RUBY_SITE_THIN_ARCHLIB));
271 #endif
272 ruby_incpush(RUBY_RELATIVE(RUBY_SITE_ARCHLIB));
273 ruby_incpush(RUBY_RELATIVE(RUBY_SITE_LIB));
274
275 ruby_incpush(RUBY_RELATIVE(RUBY_LIB));
276 #ifdef RUBY_THIN_ARCHLIB
277 ruby_incpush(RUBY_RELATIVE(RUBY_THIN_ARCHLIB));
278 #endif
279 ruby_incpush(RUBY_RELATIVE(RUBY_ARCHLIB));
280
281 if (rb_safe_level() == 0) {
282 ruby_incpush(".");
283 }
284 }
285
286 struct req_list {
287 char *name;
288 struct req_list *next;
289 };
290 static struct req_list req_list_head, *req_list_last = &req_list_head;
291
292 static void
293 add_modules(mod)
294 const char *mod;
295 {
296 struct req_list *list;
297
298 list = ALLOC(struct req_list);
299 list->name = ALLOC_N(char, strlen(mod)+1);
300 strcpy(list->name, mod);
301 list->next = 0;
302 req_list_last->next = list;
303 req_list_last = list;
304 }
305
306 extern void Init_ext _((void));
307
308 static void
309 require_libraries()
310 {
311 extern NODE *ruby_eval_tree;
312 extern NODE *ruby_eval_tree_begin;
313 NODE *save[3];
314 struct req_list *list = req_list_head.next;
315 struct req_list *tmp;
316
317 Init_ext();
318 save[0] = ruby_eval_tree;
319 save[1] = ruby_eval_tree_begin;
320 save[2] = NEW_NEWLINE(0);
321 ruby_eval_tree = ruby_eval_tree_begin = 0;
322 req_list_last = 0;
323 while (list) {
324 rb_require(list->name);
325 tmp = list->next;
326 free(list->name);
327 free(list);
328 list = tmp;
329 }
330 req_list_head.next = 0;
331 ruby_eval_tree = save[0];
332 ruby_eval_tree_begin = save[1];
333 ruby_current_node = save[2];
334 ruby_set_current_source();
335 ruby_current_node = 0;
336 rb_gc_force_recycle((VALUE)save[2]);
337 }
338
339 static void
340 process_sflag()
341 {
342 if (sflag) {
343 long n;
344 VALUE *args;
345
346 n = RARRAY(rb_argv)->len;
347 args = RARRAY(rb_argv)->ptr;
348 while (n > 0) {
349 VALUE v = *args++;
350 char *s = StringValuePtr(v);
351 char *p;
352
353 if (s[0] != '-') break;
354 n--;
355 if (s[1] == '-' && s[2] == '\0') break;
356
357 s[0] = '$';
358 if (p = strchr(s, '=')) {
359 *p++ = '\0';
360 rb_gv_set(s, rb_str_new2(p));
361 }
362 else {
363 rb_gv_set(s, Qtrue);
364 }
365 s[0] = '-';
366 }
367 n = RARRAY(rb_argv)->len - n;
368 while (n--) {
369 rb_ary_shift(rb_argv);
370 }
371 }
372 sflag = 0;
373 }
374
375 static void proc_options _((int argc, char **argv));
376
377 static char*
378 moreswitches(s)
379 char *s;
380 {
381 int argc; char *argv[3];
382 char *p = s;
383
384 argc = 2; argv[0] = argv[2] = 0;
385 while (*s && !ISSPACE(*s))
386 s++;
387 argv[1] = ALLOCA_N(char, s-p+2);
388 argv[1][0] = '-';
389 strncpy(argv[1]+1, p, s-p);
390 argv[1][s-p+1] = '\0';
391 proc_options(argc, argv);
392 while (*s && ISSPACE(*s))
393 s++;
394 return s;
395 }
396
397 static void
398 proc_options(argc, argv)
399 int argc;
400 char **argv;
401 {
402 char *argv0 = argv[0];
403 int do_search;
404 char *s;
405
406 int version = 0;
407 int copyright = 0;
408 int verbose = 0;
409 VALUE e_script = Qfalse;
410
411 if (argc == 0) return;
412
413 do_search = Qfalse;
414
415 for (argc--,argv++; argc > 0; argc--,argv++) {
416 if (argv[0][0] != '-' || !argv[0][1]) break;
417
418 s = argv[0]+1;
419 reswitch:
420 switch (*s) {
421 case 'a':
422 do_split = Qtrue;
423 s++;
424 goto reswitch;
425
426 case 'p':
427 do_print = Qtrue;
428
429 case 'n':
430 do_loop = Qtrue;
431 s++;
432 goto reswitch;
433
434 case 'd':
435 ruby_debug = Qtrue;
436 ruby_verbose = Qtrue;
437 s++;
438 goto reswitch;
439
440 case 'y':
441 ruby_yydebug = 1;
442 s++;
443 goto reswitch;
444
445 case 'v':
446 if (argv0 == 0 || verbose) {
447 s++;
448 goto reswitch;
449 }
450 ruby_show_version();
451 verbose = 1;
452 case 'w':
453 ruby_verbose = Qtrue;
454 s++;
455 goto reswitch;
456
457 case 'c':
458 do_check = Qtrue;
459 s++;
460 goto reswitch;
461
462 case 's':
463 forbid_setid("-s");
464 sflag = 1;
465 s++;
466 goto reswitch;
467
468 case 'h':
469 usage(origargv[0]);
470 exit(0);
471
472 case 'l':
473 do_line = Qtrue;
474 rb_output_rs = rb_rs;
475 s++;
476 goto reswitch;
477
478 case 'S':
479 forbid_setid("-S");
480 do_search = Qtrue;
481 s++;
482 goto reswitch;
483
484 case 'e':
485 forbid_setid("-e");
486 if (!*++s) {
487 s = argv[1];
488 argc--,argv++;
489 }
490 if (!s) {
491 fprintf(stderr, "%s: no code specified for -e\n", origargv[0]);
492 exit(2);
493 }
494 if (!e_script) {
495 e_script = rb_str_new(0,0);
496 if (script == 0) script = "-e";
497 }
498 rb_str_cat2(e_script, s);
499 rb_str_cat2(e_script, "\n");
500 break;
501
502 case 'r':
503 forbid_setid("-r");
504 if (*++s) {
505 add_modules(s);
506 }
507 else if (argv[1]) {
508 add_modules(argv[1]);
509 argc--,argv++;
510 }
511 break;
512
513 case 'i':
514 forbid_setid("-i");
515 if (ruby_inplace_mode) free(ruby_inplace_mode);
516 ruby_inplace_mode = strdup(s+1);
517 break;
518
519 case 'x':
520 xflag = Qtrue;
521 s++;
522 if (*s && chdir(s) < 0) {
523 rb_fatal("Can't chdir to %s", s);
524 }
525 break;
526
527 case 'C':
528 case 'X':
529 s++;
530 if (!*s) {
531 s = argv[1];
532 argc--,argv++;
533 }
534 if (!s || !*s) {
535 rb_fatal("Can't chdir");
536 }
537 if (chdir(s) < 0) {
538 rb_fatal("Can't chdir to %s", s);
539 }
540 break;
541
542 case 'F':
543 if (*++s) {
544 rb_fs = rb_str_new2(s);
545 }
546 break;
547
548 case 'K':
549 if (*++s) {
550 rb_set_kcode(s);
551 s++;
552 }
553 goto reswitch;
554
555 case 'T':
556 {
557 int numlen;
558 int v = 1;
559
560 if (*++s) {
561 v = scan_oct(s, 2, &numlen);
562 if (numlen == 0) v = 1;
563 s += numlen;
564 }
565 rb_set_safe_level(v);
566 }
567 goto reswitch;
568
569 case 'I':
570 forbid_setid("-I");
571 if (*++s)
572 ruby_incpush(s);
573 else if (argv[1]) {
574 ruby_incpush(argv[1]);
575 argc--,argv++;
576 }
577 break;
578
579 case '0':
580 {
581 int numlen;
582 int v;
583 char c;
584
585 v = scan_oct(s, 4, &numlen);
586 s += numlen;
587 if (v > 0377) rb_rs = Qnil;
588 else if (v == 0 && numlen >= 2) {
589 rb_rs = rb_str_new2("\n\n");
590 }
591 else {
592 c = v & 0xff;
593 rb_rs = rb_str_new(&c, 1);
594 }
595 }
596 goto reswitch;
597
598 case '-':
599 if (!s[1] || s[1] == '\r' && !s[2]) {
600 argc--,argv++;
601 goto switch_end;
602 }
603 s++;
604 if (strcmp("copyright", s) == 0)
605 copyright = 1;
606 else if (strcmp("debug", s) == 0) {
607 ruby_debug = Qtrue;
608 ruby_verbose = Qtrue;
609 }
610 else if (strcmp("version", s) == 0)
611 version = 1;
612 else if (strcmp("verbose", s) == 0) {
613 verbose = 1;
614 ruby_verbose = Qtrue;
615 }
616 else if (strcmp("yydebug", s) == 0)
617 ruby_yydebug = 1;
618 else if (strcmp("help", s) == 0) {
619 usage(origargv[0]);
620 exit(0);
621 }
622 else {
623 fprintf(stderr, "%s: invalid option --%s (-h will show valid options)\n",
624 origargv[0], s);
625 exit(2);
626 }
627 break;
628
629 default:
630 fprintf(stderr, "%s: invalid option -%c (-h will show valid options)\n",
631 origargv[0], *s);
632 exit(2);
633
634 case 0:
635 break;
636 }
637 }
638
639 switch_end:
640 if (argv0 == 0) return;
641
642 if (rb_safe_level() == 0 && (s = getenv("RUBYOPT"))) {
643 while (ISSPACE(*s)) s++;
644 if (*s == '-' && *(s+1) == 'T') {
645 int numlen;
646 int v = 1;
647
648 s += 2;
649 if (*++s) {
650 v = scan_oct(s, 2, &numlen);
651 if (numlen == 0) v = 1;
652 }
653 rb_set_safe_level(v);
654 }
655 else {
656 while (s && *s) {
657 if (*s == '-') {
658 s++;
659 if (ISSPACE(*s)) {
660 do {s++;} while (ISSPACE(*s));
661 continue;
662 }
663 }
664 if (!*s) break;
665 if (!strchr("IdvwrK", *s))
666 rb_raise(rb_eRuntimeError, "Illegal switch in RUBYOPT: -%c", *s);
667 s = moreswitches(s);
668 }
669 }
670 }
671
672 if (version) {
673 ruby_show_version();
674 exit(0);
675 }
676 if (copyright) {
677 ruby_show_copyright();
678 }
679
680 if (rb_safe_level() >= 4) {
681 OBJ_TAINT(rb_argv);
682 OBJ_TAINT(rb_load_path);
683 }
684
685 if (!e_script && argc == 0) {
686 if (verbose) exit(0);
687 script = "-";
688 }
689 else {
690 if (!e_script) {
691 script = argv[0];
692 }
693 if (script[0] == '\0') {
694 script = "-";
695 }
696 else {
697 if (do_search) {
698 char *path = getenv("RUBYPATH");
699
700 script = 0;
701 if (path) {
702 script = dln_find_file(argv[0], path);
703 }
704 if (!script) {
705 script = dln_find_file(argv[0], getenv("PATH"));
706 }
707 if (!script) script = argv[0];
708 }
709 }
710 if (!e_script) {
711 argc--; argv++;
712 }
713 }
714
715 ruby_script(script);
716 ruby_set_argv(argc, argv);
717 process_sflag();
718
719 ruby_init_loadpath();
720 ruby_sourcefile = rb_source_filename(argv0);
721 if (e_script) {
722 require_libraries();
723 rb_compile_string(script, e_script, 1);
724 }
725 else if (strlen(script) == 1 && script[0] == '-') {
726 load_stdin();
727 }
728 else {
729 load_file(script, 1);
730 }
731
732 process_sflag();
733 xflag = 0;
734
735 if (rb_safe_level() >= 4) {
736 FL_UNSET(rb_argv, FL_TAINT);
737 FL_UNSET(rb_load_path, FL_TAINT);
738 }
739 }
740
741 extern int ruby__end__seen;
742
743 static void
744 load_file(fname, script)
745 char *fname;
746 int script;
747 {
748 extern VALUE rb_stdin;
749 VALUE f;
750 int line_start = 1;
751
752 if (strcmp(fname, "-") == 0) {
753 f = rb_stdin;
754 }
755 else {
756 FILE *fp = fopen(fname, "r");
757
758 if (fp == NULL) {
759 rb_load_fail(fname);
760 }
761 fclose(fp);
762
763 f = rb_file_open(fname, "r");
764 #if defined DOSISH || defined __CYGWIN__
765 {
766 char *ext = strrchr(fname, '.');
767 if (ext && strcasecmp(ext, ".exe") == 0)
768 rb_io_binmode(f);
769 }
770 #endif
771 }
772
773 if (script) {
774 VALUE c = 1;
775 VALUE line;
776 char *p;
777
778 if (xflag) {
779 forbid_setid("-x");
780 xflag = Qfalse;
781 while (!NIL_P(line = rb_io_gets(f))) {
782 line_start++;
783 if (RSTRING(line)->len > 2
784 && RSTRING(line)->ptr[0] == '#'
785 && RSTRING(line)->ptr[1] == '!') {
786 if (p = strstr(RSTRING(line)->ptr, "ruby")) {
787 goto start_read;
788 }
789 }
790 }
791 rb_raise(rb_eLoadError, "No Ruby script found in input");
792 }
793
794 c = rb_io_getc(f);
795 if (c == INT2FIX('#')) {
796 line = rb_io_gets(f);
797 if (NIL_P(line)) return;
798 line_start++;
799
800 if (RSTRING(line)->len > 2 && RSTRING(line)->ptr[0] == '!') {
801 if ((p = strstr(RSTRING(line)->ptr, "ruby")) == 0) {
802
803 char **argv;
804 char *path;
805 char *pend = RSTRING(line)->ptr + RSTRING(line)->len;
806
807 p = RSTRING(line)->ptr + 1;
808 if (pend[-1] == '\n') pend--;
809 if (pend[-1] == '\r') pend--;
810 *pend = '\0';
811 while (p < pend && ISSPACE(*p))
812 p++;
813 path = p;
814 while (p < pend && !ISSPACE(*p))
815 p++;
816 *p++ = '\0';
817 if (p < pend) {
818 argv = ALLOCA_N(char*, origargc+3);
819 argv[1] = p;
820 MEMCPY(argv+2, origargv+1, char*, origargc);
821 }
822 else {
823 argv = origargv;
824 }
825 argv[0] = path;
826 execv(path, argv);
827
828 ruby_sourcefile = rb_source_filename(fname);
829 ruby_sourceline = 1;
830 rb_fatal("Can't exec %s", path);
831 }
832
833 start_read:
834 p += 4;
835 RSTRING(line)->ptr[RSTRING(line)->len-1] = '\0';
836 if (RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r')
837 RSTRING(line)->ptr[RSTRING(line)->len-2] = '\0';
838 if (p = strstr(p, " -")) {
839 p++;
840 while (*p == '-') {
841 p = moreswitches(p+1);
842 }
843 }
844 }
845 }
846 else if (!NIL_P(c)) {
847 rb_io_ungetc(f, c);
848 }
849 require_libraries();
850 if (NIL_P(c)) return;
851 }
852 rb_compile_file(fname, f, line_start);
853 if (script && ruby__end__seen) {
854 rb_define_global_const("DATA", f);
855 }
856 else if (f != rb_stdin) {
857 rb_io_close(f);
858 }
859
860 if (ruby_parser_stack_on_heap()) {
861 rb_gc();
862 }
863 }
864
865 void
866 rb_load_file(fname)
867 char *fname;
868 {
869 load_file(fname, 0);
870 }
871
872 static void
873 load_stdin()
874 {
875 forbid_setid("program input from stdin");
876 load_file("-", 1);
877 }
878
879 VALUE rb_progname;
880 VALUE rb_argv;
881 VALUE rb_argv0;
882
883 static void
884 set_arg0(val, id)
885 VALUE val;
886 ID id;
887 {
888 char *s;
889 long i;
890 static int len;
891
892 if (origargv == 0) rb_raise(rb_eRuntimeError, "$0 not initialized");
893 StringValue(val);
894 s = RSTRING(val)->ptr;
895 i = RSTRING(val)->len;
896 #ifdef __hpux
897 if (i >= PST_CLEN) {
898 union pstun j;
899 j.pst_command = s;
900 i = PST_CLEN;
901 RSTRING(val)->len = i;
902 *(s + i) = '\0';
903 pstat(PSTAT_SETCMD, j, PST_CLEN, 0, 0);
904 }
905 else {
906 union pstun j;
907 j.pst_command = s;
908 pstat(PSTAT_SETCMD, j, i, 0, 0);
909 }
910 rb_progname = rb_tainted_str_new(s, i);
911 #elif defined(HAVE_SETPROCTITLE)
912 setproctitle("%.*s", i, s);
913 rb_progname = rb_tainted_str_new(s, i);
914 #else
915 if (len == 0) {
916 char *s = origargv[0];
917 int i;
918
919 s += strlen(s);
920
921 for (i = 1; i < origargc; i++) {
922 if (origargv[i] == s + 1) {
923 s++;
924 s += strlen(s);
925 }
926 else {
927 break;
928 }
929 }
930 len = s - origargv[0];
931 }
932
933 if (i >= len) {
934 i = len;
935 memcpy(origargv[0], s, i);
936 origargv[0][i] = '\0';
937 }
938 else {
939 memcpy(origargv[0], s, i);
940 s = origargv[0]+i;
941 *s++ = '\0';
942 while (++i < len)
943 *s++ = ' ';
944 for (i = 1; i < origargc; i++)
945 origargv[i] = 0;
946 }
947 rb_progname = rb_tainted_str_new2(origargv[0]);
948 #endif
949 }
950
951 void
952 ruby_script(name)
953 char *name;
954 {
955 if (name) {
956 rb_progname = rb_tainted_str_new2(name);
957 ruby_sourcefile = rb_source_filename(name);
958 }
959 }
960
961 static int uid, euid, gid, egid;
962
963 static void
964 init_ids()
965 {
966 uid = (int)getuid();
967 euid = (int)geteuid();
968 gid = (int)getgid();
969 egid = (int)getegid();
970 #ifdef VMS
971 uid |= gid << 16;
972 euid |= egid << 16;
973 #endif
974 if (uid && (euid != uid || egid != gid)) {
975 rb_set_safe_level(1);
976 }
977 }
978
979 static void
980 forbid_setid(s)
981 const char *s;
982 {
983 if (euid != uid)
984 rb_raise(rb_eSecurityError, "No %s allowed while running setuid", s);
985 if (egid != gid)
986 rb_raise(rb_eSecurityError, "No %s allowed while running setgid", s);
987 if (rb_safe_level() > 0)
988 rb_raise(rb_eSecurityError, "No %s allowed in tainted mode", s);
989 }
990
991 void
992 ruby_prog_init()
993 {
994 init_ids();
995
996 ruby_sourcefile = rb_source_filename("ruby");
997 rb_define_variable("$VERBOSE", &ruby_verbose);
998 rb_define_variable("$-v", &ruby_verbose);
999 rb_define_variable("$-w", &ruby_verbose);
1000 rb_define_variable("$DEBUG", &ruby_debug);
1001 rb_define_variable("$-d", &ruby_debug);
1002 rb_define_readonly_variable("$-p", &do_print);
1003 rb_define_readonly_variable("$-l", &do_line);
1004
1005 rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0);
1006
1007 rb_argv = rb_ary_new();
1008 rb_define_readonly_variable("$*", &rb_argv);
1009 rb_define_global_const("ARGV", rb_argv);
1010 rb_define_readonly_variable("$-a", &do_split);
1011 rb_global_variable(&rb_argv0);
1012
1013 #ifdef MSDOS
1014
1015
1016
1017
1018 (void)fclose(stdaux);
1019 (void)fclose(stdprn);
1020 #endif
1021 }
1022
1023 void
1024 ruby_set_argv(argc, argv)
1025 int argc;
1026 char **argv;
1027 {
1028 int i;
1029
1030 #if defined(USE_DLN_A_OUT)
1031 if (origargv) dln_argv0 = origargv[0];
1032 else dln_argv0 = argv[0];
1033 #endif
1034 rb_ary_clear(rb_argv);
1035 for (i=0; i < argc; i++) {
1036 rb_ary_push(rb_argv, rb_tainted_str_new2(argv[i]));
1037 }
1038 }
1039
1040 void
1041 ruby_process_options(argc, argv)
1042 int argc;
1043 char **argv;
1044 {
1045 origargc = argc; origargv = argv;
1046
1047 ruby_script(argv[0]);
1048 rb_argv0 = rb_progname;
1049 #if defined(USE_DLN_A_OUT)
1050 dln_argv0 = argv[0];
1051 #endif
1052 proc_options(argc, argv);
1053
1054 if (do_check && ruby_nerrs == 0) {
1055 printf("Syntax OK\n");
1056 exit(0);
1057 }
1058 if (do_print) {
1059 rb_parser_append_print();
1060 }
1061 if (do_loop) {
1062 rb_parser_while_loop(do_line, do_split);
1063 }
1064 }