00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #if defined _WIN32 || defined __CYGWIN__
00016 #include <windows.h>
00017 #endif
00018 #ifdef _WIN32_WCE
00019 #include <winsock.h>
00020 #include "wince.h"
00021 #endif
00022 #include "ruby.h"
00023 #include "dln.h"
00024 #include "node.h"
00025 #include <stdio.h>
00026 #include <sys/types.h>
00027 #include <ctype.h>
00028
00029 #ifdef __hpux
00030 #include <sys/pstat.h>
00031 #endif
00032
00033 #ifdef HAVE_UNISTD_H
00034 #include <unistd.h>
00035 #endif
00036
00037 #ifndef HAVE_STRING_H
00038 char *strchr (const char*,const char);
00039 char *strrchr (const char*,const char);
00040 char *strstr (const char*,const char*);
00041 #endif
00042
00043 #include "util.h"
00044
00045 #ifndef HAVE_STDLIB_H
00046 char *getenv();
00047 #endif
00048
00049 VALUE ruby_debug = Qfalse;
00050 VALUE ruby_verbose = Qfalse;
00051 static int sflag = 0;
00052 static int xflag = 0;
00053 extern int ruby_yydebug;
00054
00055 char *ruby_inplace_mode = Qfalse;
00056
00057 static void load_stdin (void);
00058 static void load_file (const char *, int);
00059 static void forbid_setid (const char *);
00060
00061 static VALUE do_loop = Qfalse, do_print = Qfalse;
00062 static VALUE do_check = Qfalse, do_line = Qfalse;
00063 static VALUE do_split = Qfalse;
00064
00065 static char *script;
00066
00067 static int origargc;
00068 static char **origargv;
00069
00070 static void
00071 usage(name)
00072 const char *name;
00073 {
00074
00075
00076
00077 static char *usage_msg[] = {
00078 "-0[octal] specify record separator (\\0, if no argument)",
00079 "-a autosplit mode with -n or -p (splits $_ into $F)",
00080 "-c check syntax only",
00081 "-Cdirectory cd to directory, before executing your script",
00082 "-d set debugging flags (set $DEBUG to true)",
00083 "-e 'command' one line of script. Several -e's allowed. Omit [programfile]",
00084 "-Fpattern split() pattern for autosplit (-a)",
00085 "-i[extension] edit ARGV files in place (make backup if extension supplied)",
00086 "-Idirectory specify $LOAD_PATH directory (may be used more than once)",
00087 "-Kkcode specifies KANJI (Japanese) code-set",
00088 "-l enable line ending processing",
00089 "-n assume 'while gets(); ... end' loop around your script",
00090 "-p assume loop like -n but print line also like sed",
00091 "-rlibrary require the library, before executing your script",
00092 "-s enable some switch parsing for switches after script name",
00093 "-S look for the script using PATH environment variable",
00094 "-T[level] turn on tainting checks",
00095 "-v print version number, then turn on verbose mode",
00096 "-w turn warnings on for your script",
00097 "-W[level] set warning level; 0=silence, 1=medium, 2=verbose (default)",
00098 "-x[directory] strip off text before #!ruby line and perhaps cd to directory",
00099 "--copyright print the copyright",
00100 "--version print the version",
00101 NULL
00102 };
00103 char **p = usage_msg;
00104
00105 printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name);
00106 while (*p)
00107 printf(" %s\n", *p++);
00108 }
00109
00110 extern VALUE rb_load_path;
00111
00112 #define STATIC_FILE_LENGTH 255
00113
00114 #if defined _WIN32 || defined __CYGWIN__ || defined __DJGPP__
00115 static char *
00116 rubylib_mangle(s, l)
00117 char *s;
00118 unsigned int l;
00119 {
00120 static char *newp, *oldp;
00121 static int newl, oldl, notfound;
00122 static char newsub[STATIC_FILE_LENGTH+1];
00123
00124 if (!newp && !notfound) {
00125 newp = getenv("RUBYLIB_PREFIX");
00126 if (newp) {
00127 char *s;
00128
00129 oldp = newp;
00130 while (*newp && !ISSPACE(*newp) && *newp != ';') {
00131 newp++; oldl++;
00132 }
00133 while (*newp && (ISSPACE(*newp) || *newp == ';')) {
00134 newp++;
00135 }
00136 newl = strlen(newp);
00137 if (newl == 0 || oldl == 0 || newl > STATIC_FILE_LENGTH) {
00138 rb_fatal("malformed RUBYLIB_PREFIX");
00139 }
00140 strcpy(newsub, newp);
00141 s = newsub;
00142 while (*s) {
00143 if (*s == '\\') *s = '/';
00144 s++;
00145 }
00146 }
00147 else {
00148 notfound = 1;
00149 }
00150 }
00151 if (l == 0) {
00152 l = strlen(s);
00153 }
00154 if (!newp || l < oldl || strncasecmp(oldp, s, oldl) != 0) {
00155 static char ret[STATIC_FILE_LENGTH+1];
00156 strncpy(ret, s, l);
00157 ret[l] = 0;
00158 return ret;
00159 }
00160 if (l + newl - oldl > STATIC_FILE_LENGTH || newl > STATIC_FILE_LENGTH) {
00161 rb_fatal("malformed RUBYLIB_PREFIX");
00162 }
00163 strcpy(newsub + newl, s + oldl);
00164 newsub[l + newl - oldl] = 0;
00165 return newsub;
00166 }
00167 #define rubylib_mangled_path(s, l) rb_str_new2(rubylib_mangle((s), (l)))
00168 #define rubylib_mangled_path2(s) rb_str_new2(rubylib_mangle((s), 0))
00169 #else
00170 #define rubylib_mangled_path(s, l) rb_str_new((s), (l))
00171 #define rubylib_mangled_path2(s) rb_str_new2(s)
00172 #endif
00173
00174 void
00175 ruby_incpush(path)
00176 const char *path;
00177 {
00178 const char sep = PATH_SEP_CHAR;
00179
00180 if (path == 0) return;
00181 #if defined(__CYGWIN__)
00182 {
00183 char rubylib[FILENAME_MAX];
00184 conv_to_posix_path(path, rubylib, FILENAME_MAX);
00185 path = rubylib;
00186 }
00187 #endif
00188 if (strchr(path, sep)) {
00189 const char *p, *s;
00190 VALUE ary = rb_ary_new();
00191
00192 p = path;
00193 while (*p) {
00194 while (*p == sep) p++;
00195 if ((s = strchr(p, sep)) != 0) {
00196 rb_ary_push(ary, rubylib_mangled_path(p, (int)(s-p)));
00197 p = s + 1;
00198 }
00199 else {
00200 rb_ary_push(ary, rubylib_mangled_path2(p));
00201 break;
00202 }
00203 }
00204 rb_ary_concat(rb_load_path, ary);
00205 }
00206 else {
00207 rb_ary_push(rb_load_path, rubylib_mangled_path2(path));
00208 }
00209 }
00210
00211 #if defined DOSISH || defined __CYGWIN__
00212 #define LOAD_RELATIVE 1
00213 #endif
00214
00215 #if defined DOSISH || defined __CYGWIN__
00216 static inline void translate_char (char *, int, int);
00217
00218 static inline void
00219 translate_char(p, from, to)
00220 char *p;
00221 int from, to;
00222 {
00223 while (*p) {
00224 if ((unsigned char)*p == from)
00225 *p = to;
00226 #ifdef CharNext
00227 p = CharNext(p);
00228 #else
00229 p += mblen(p, MB_CUR_MAX);
00230 #endif
00231 }
00232 }
00233 #endif
00234
00235 void
00236 ruby_init_loadpath()
00237 {
00238 #if defined LOAD_RELATIVE
00239 char libpath[FILENAME_MAX+1];
00240 char *p;
00241 int rest;
00242 #if defined _WIN32 || defined __CYGWIN__
00243 HMODULE libruby = NULL;
00244 MEMORY_BASIC_INFORMATION m;
00245
00246 #ifndef _WIN32_WCE
00247 memset(&m, 0, sizeof(m));
00248 if (VirtualQuery(ruby_init_loadpath, &m, sizeof(m)) && m.State == MEM_COMMIT)
00249 libruby = (HMODULE)m.AllocationBase;
00250 #endif
00251 GetModuleFileName(libruby, libpath, sizeof libpath);
00252 #elif defined(DJGPP)
00253 extern char *__dos_argv0;
00254 strncpy(libpath, __dos_argv0, FILENAME_MAX);
00255 #elif defined(__human68k__)
00256 extern char **_argv;
00257 strncpy(libpath, _argv[0], FILENAME_MAX);
00258 #elif defined(__EMX__)
00259 _execname(libpath, FILENAME_MAX);
00260 #endif
00261
00262 libpath[FILENAME_MAX] = '\0';
00263 #if defined DOSISH || defined __CYGWIN__
00264 translate_char(libpath, '\\', '/');
00265 #endif
00266 p = strrchr(libpath, '/');
00267 if (p) {
00268 *p = 0;
00269 if (p-libpath > 3 && !strcasecmp(p-4, "/bin")) {
00270 p -= 4;
00271 *p = 0;
00272 }
00273 }
00274 else {
00275 strcpy(libpath, ".");
00276 p = libpath + 1;
00277 }
00278
00279 rest = FILENAME_MAX - (p - libpath);
00280
00281 #define RUBY_RELATIVE(path) (strncpy(p, (path), rest), libpath)
00282 #else
00283 #define RUBY_RELATIVE(path) (path)
00284 #endif
00285
00286 if (rb_safe_level() == 0) {
00287 ruby_incpush(getenv("RUBYLIB"));
00288 }
00289
00290 #ifdef RUBY_SEARCH_PATH
00291 ruby_incpush(RUBY_RELATIVE(RUBY_SEARCH_PATH));
00292 #endif
00293
00294 ruby_incpush(RUBY_RELATIVE(RUBY_SITE_LIB2));
00295 #ifdef RUBY_SITE_THIN_ARCHLIB
00296 ruby_incpush(RUBY_RELATIVE(RUBY_SITE_THIN_ARCHLIB));
00297 #endif
00298 ruby_incpush(RUBY_RELATIVE(RUBY_SITE_ARCHLIB));
00299 ruby_incpush(RUBY_RELATIVE(RUBY_SITE_LIB));
00300
00301 ruby_incpush(RUBY_RELATIVE(RUBY_LIB));
00302 #ifdef RUBY_THIN_ARCHLIB
00303 ruby_incpush(RUBY_RELATIVE(RUBY_THIN_ARCHLIB));
00304 #endif
00305 ruby_incpush(RUBY_RELATIVE(RUBY_ARCHLIB));
00306
00307 if (rb_safe_level() == 0) {
00308 ruby_incpush(".");
00309 }
00310 }
00311
00312 struct req_list {
00313 char *name;
00314 struct req_list *next;
00315 };
00316 static struct req_list req_list_head, *req_list_last = &req_list_head;
00317
00318 static void
00319 add_modules(mod)
00320 const char *mod;
00321 {
00322 struct req_list *list;
00323
00324 list = ALLOC(struct req_list);
00325 list->name = ALLOC_N(char, strlen(mod)+1);
00326 strcpy(list->name, mod);
00327 list->next = 0;
00328 req_list_last->next = list;
00329 req_list_last = list;
00330 }
00331
00332 extern void Init_ext (void);
00333
00334 static void
00335 require_libraries()
00336 {
00337 extern NODE *ruby_eval_tree;
00338 extern NODE *ruby_eval_tree_begin;
00339 NODE *save[3];
00340 struct req_list *list = req_list_head.next;
00341 struct req_list *tmp;
00342
00343 save[0] = ruby_eval_tree;
00344 save[1] = ruby_eval_tree_begin;
00345 save[2] = NEW_NEWLINE(0);
00346 ruby_eval_tree = ruby_eval_tree_begin = 0;
00347 ruby_current_node = 0;
00348 Init_ext();
00349 ruby_current_node = save[2];
00350 ruby_set_current_source();
00351 req_list_last = 0;
00352 while (list) {
00353 int state;
00354
00355 ruby_current_node = 0;
00356 rb_protect((VALUE (*)(VALUE))rb_require, (VALUE)list->name, &state);
00357 if (state) rb_jump_tag(state);
00358 tmp = list->next;
00359 free(list->name);
00360 free(list);
00361 list = tmp;
00362 ruby_current_node = save[2];
00363 ruby_set_current_source();
00364 }
00365 req_list_head.next = 0;
00366 ruby_eval_tree = save[0];
00367 ruby_eval_tree_begin = save[1];
00368 rb_gc_force_recycle((VALUE)save[2]);
00369 ruby_current_node = 0;
00370 }
00371
00372 static void
00373 process_sflag()
00374 {
00375 if (sflag) {
00376 long n;
00377 VALUE *args;
00378
00379 n = RARRAY(rb_argv)->len;
00380 args = RARRAY(rb_argv)->ptr;
00381 while (n > 0) {
00382 VALUE v = *args++;
00383 char *s = StringValuePtr(v);
00384 char *p;
00385 int hyphen = Qfalse;
00386
00387 if (s[0] != '-') break;
00388 n--;
00389 if (s[1] == '-' && s[2] == '\0') break;
00390
00391 v = Qtrue;
00392
00393 for (p = s + 1; *p; p++) {
00394 if (*p == '=') {
00395 *p++ = '\0';
00396 v = rb_str_new2(p);
00397 break;
00398 }
00399 if (*p == '-') {
00400 hyphen = Qtrue;
00401 }
00402 else if (*p != '_' && !ISALNUM(*p)) {
00403 VALUE name_error[2];
00404 name_error[0] = rb_str_new2("invalid name for global variable - ");
00405 if (!(p = strchr(p, '='))) {
00406 rb_str_cat2(name_error[0], s);
00407 }
00408 else {
00409 rb_str_cat(name_error[0], s, p - s);
00410 }
00411 name_error[1] = args[-1];
00412 rb_exc_raise(rb_class_new_instance(2, name_error, rb_eNameError));
00413 }
00414 }
00415 s[0] = '$';
00416 if (hyphen) {
00417 for (p = s + 1; *p; ++p) {
00418 if (*p == '-') *p = '_';
00419 }
00420 }
00421 rb_gv_set(s, v);
00422 }
00423 n = RARRAY(rb_argv)->len - n;
00424 while (n--) {
00425 rb_ary_shift(rb_argv);
00426 }
00427 }
00428 sflag = 0;
00429 }
00430
00431 static void proc_options (int argc, char **argv);
00432
00433 static char*
00434 moreswitches(s)
00435 char *s;
00436 {
00437 int argc; char *argv[3];
00438 char *p = s;
00439
00440 argc = 2; argv[0] = argv[2] = 0;
00441 while (*s && !ISSPACE(*s))
00442 s++;
00443 argv[1] = ALLOCA_N(char, s-p+2);
00444 argv[1][0] = '-';
00445 strncpy(argv[1]+1, p, s-p);
00446 argv[1][s-p+1] = '\0';
00447 proc_options(argc, argv);
00448 while (*s && ISSPACE(*s))
00449 s++;
00450 return s;
00451 }
00452
00453 static void
00454 proc_options(argc, argv)
00455 int argc;
00456 char **argv;
00457 {
00458 char *argv0 = argv[0];
00459 int do_search;
00460 char *s;
00461 NODE *volatile script_node = 0;
00462
00463 int version = 0;
00464 int copyright = 0;
00465 int verbose = 0;
00466 VALUE e_script = Qfalse;
00467
00468 if (argc == 0) return;
00469
00470 do_search = Qfalse;
00471
00472 for (argc--,argv++; argc > 0; argc--,argv++) {
00473 if (argv[0][0] != '-' || !argv[0][1]) break;
00474
00475 s = argv[0]+1;
00476 reswitch:
00477 switch (*s) {
00478 case 'a':
00479 do_split = Qtrue;
00480 s++;
00481 goto reswitch;
00482
00483 case 'p':
00484 do_print = Qtrue;
00485
00486 case 'n':
00487 do_loop = Qtrue;
00488 s++;
00489 goto reswitch;
00490
00491 case 'd':
00492 ruby_debug = Qtrue;
00493 ruby_verbose = Qtrue;
00494 s++;
00495 goto reswitch;
00496
00497 case 'y':
00498 ruby_yydebug = 1;
00499 s++;
00500 goto reswitch;
00501
00502 case 'v':
00503 if (argv0 == 0 || verbose) {
00504 s++;
00505 goto reswitch;
00506 }
00507 ruby_show_version();
00508 verbose = 1;
00509 case 'w':
00510 ruby_verbose = Qtrue;
00511 s++;
00512 goto reswitch;
00513
00514 case 'W':
00515 {
00516 int numlen;
00517 int v = 2;
00518
00519 if (*++s) {
00520 v = scan_oct(s, 1, &numlen);
00521 if (numlen == 0) v = 1;
00522 s += numlen;
00523 }
00524 switch (v) {
00525 case 0:
00526 ruby_verbose = Qnil; break;
00527 case 1:
00528 ruby_verbose = Qfalse; break;
00529 default:
00530 ruby_verbose = Qtrue; break;
00531 }
00532 }
00533 goto reswitch;
00534
00535 case 'c':
00536 do_check = Qtrue;
00537 s++;
00538 goto reswitch;
00539
00540 case 's':
00541 forbid_setid("-s");
00542 sflag = 1;
00543 s++;
00544 goto reswitch;
00545
00546 case 'h':
00547 usage(origargv[0]);
00548 exit(0);
00549
00550 case 'l':
00551 do_line = Qtrue;
00552 rb_output_rs = rb_rs;
00553 s++;
00554 goto reswitch;
00555
00556 case 'S':
00557 forbid_setid("-S");
00558 do_search = Qtrue;
00559 s++;
00560 goto reswitch;
00561
00562 case 'e':
00563 forbid_setid("-e");
00564 if (!*++s) {
00565 s = argv[1];
00566 argc--,argv++;
00567 }
00568 if (!s) {
00569 fprintf(stderr, "%s: no code specified for -e\n", origargv[0]);
00570 exit(2);
00571 }
00572 if (!e_script) {
00573 e_script = rb_str_new(0,0);
00574 if (script == 0) script = "-e";
00575 }
00576 rb_str_cat2(e_script, s);
00577 rb_str_cat2(e_script, "\n");
00578 break;
00579
00580 case 'r':
00581 forbid_setid("-r");
00582 if (*++s) {
00583 add_modules(s);
00584 }
00585 else if (argv[1]) {
00586 add_modules(argv[1]);
00587 argc--,argv++;
00588 }
00589 break;
00590
00591 case 'i':
00592 forbid_setid("-i");
00593 if (ruby_inplace_mode) free(ruby_inplace_mode);
00594 ruby_inplace_mode = strdup(s+1);
00595 break;
00596
00597 case 'x':
00598 xflag = Qtrue;
00599 s++;
00600 if (*s && chdir(s) < 0) {
00601 rb_fatal("Can't chdir to %s", s);
00602 }
00603 break;
00604
00605 case 'C':
00606 case 'X':
00607 s++;
00608 if (!*s) {
00609 s = argv[1];
00610 argc--,argv++;
00611 }
00612 if (!s || !*s) {
00613 rb_fatal("Can't chdir");
00614 }
00615 if (chdir(s) < 0) {
00616 rb_fatal("Can't chdir to %s", s);
00617 }
00618 break;
00619
00620 case 'F':
00621 if (*++s) {
00622 rb_fs = rb_reg_new(s, strlen(s), 0);
00623 }
00624 break;
00625
00626 case 'K':
00627 if (*++s) {
00628 rb_set_kcode(s);
00629 s++;
00630 }
00631 goto reswitch;
00632
00633 case 'T':
00634 {
00635 int numlen;
00636 int v = 1;
00637
00638 if (*++s) {
00639 v = scan_oct(s, 2, &numlen);
00640 if (numlen == 0) v = 1;
00641 s += numlen;
00642 }
00643 rb_set_safe_level(v);
00644 }
00645 goto reswitch;
00646
00647 case 'I':
00648 forbid_setid("-I");
00649 if (*++s)
00650 ruby_incpush(s);
00651 else if (argv[1]) {
00652 ruby_incpush(argv[1]);
00653 argc--,argv++;
00654 }
00655 break;
00656
00657 case '0':
00658 {
00659 int numlen;
00660 int v;
00661 char c;
00662
00663 v = scan_oct(s, 4, &numlen);
00664 s += numlen;
00665 if (v > 0377) rb_rs = Qnil;
00666 else if (v == 0 && numlen >= 2) {
00667 rb_rs = rb_str_new2("\n\n");
00668 }
00669 else {
00670 c = v & 0xff;
00671 rb_rs = rb_str_new(&c, 1);
00672 }
00673 }
00674 goto reswitch;
00675
00676 case '-':
00677 if (!s[1] || (s[1] == '\r' && !s[2])) {
00678 argc--,argv++;
00679 goto switch_end;
00680 }
00681 s++;
00682 if (strcmp("copyright", s) == 0)
00683 copyright = 1;
00684 else if (strcmp("debug", s) == 0) {
00685 ruby_debug = Qtrue;
00686 ruby_verbose = Qtrue;
00687 }
00688 else if (strcmp("version", s) == 0)
00689 version = 1;
00690 else if (strcmp("verbose", s) == 0) {
00691 verbose = 1;
00692 ruby_verbose = Qtrue;
00693 }
00694 else if (strcmp("yydebug", s) == 0)
00695 ruby_yydebug = 1;
00696 else if (strcmp("help", s) == 0) {
00697 usage(origargv[0]);
00698 exit(0);
00699 }
00700 else {
00701 fprintf(stderr, "%s: invalid option --%s (-h will show valid options)\n",
00702 origargv[0], s);
00703 exit(2);
00704 }
00705 break;
00706
00707 case '\r':
00708 if (!s[1]) break;
00709
00710 default:
00711 {
00712 const char *format;
00713 if (ISPRINT(*s)) {
00714 format = "%s: invalid option -%c (-h will show valid options)\n";
00715 }
00716 else {
00717 format = "%s: invalid option -\\%03o (-h will show valid options)\n";
00718 }
00719 fprintf(stderr, format, origargv[0], (int)(unsigned char)*s);
00720 }
00721 exit(2);
00722
00723 case 0:
00724 break;
00725 }
00726 }
00727
00728 switch_end:
00729 if (argv0 == 0) return;
00730
00731 if (rb_safe_level() == 0 && (s = getenv("RUBYOPT"))) {
00732 while (ISSPACE(*s)) s++;
00733 if (*s == 'T' || (*s == '-' && *(s+1) == 'T')) {
00734 int numlen;
00735 int v = 1;
00736
00737 if (*s != 'T') ++s;
00738 if (*++s) {
00739 v = scan_oct(s, 2, &numlen);
00740 if (numlen == 0) v = 1;
00741 }
00742 rb_set_safe_level(v);
00743 }
00744 else {
00745 while (s && *s) {
00746 if (*s == '-') {
00747 s++;
00748 if (ISSPACE(*s)) {
00749 do {s++;} while (ISSPACE(*s));
00750 continue;
00751 }
00752 }
00753 if (!*s) break;
00754 if (!strchr("IdvwrK", *s))
00755 rb_raise(rb_eRuntimeError, "illegal switch in RUBYOPT: -%c", *s);
00756 s = moreswitches(s);
00757 }
00758 }
00759 }
00760
00761 if (version) {
00762 ruby_show_version();
00763 exit(0);
00764 }
00765 if (copyright) {
00766 ruby_show_copyright();
00767 }
00768
00769 if (rb_safe_level() >= 4) {
00770 OBJ_TAINT(rb_argv);
00771 OBJ_TAINT(rb_load_path);
00772 }
00773
00774 if (!e_script) {
00775 if (argc == 0) {
00776 if (verbose) exit(0);
00777 script = "-";
00778 }
00779 else {
00780 script = argv[0];
00781 if (script[0] == '\0') {
00782 script = "-";
00783 }
00784 else if (do_search) {
00785 char *path = getenv("RUBYPATH");
00786
00787 script = 0;
00788 if (path) {
00789 script = dln_find_file(argv[0], path);
00790 }
00791 if (!script) {
00792 script = dln_find_file(argv[0], getenv(PATH_ENV));
00793 }
00794 if (!script) script = argv[0];
00795 script = ruby_sourcefile = rb_source_filename(script);
00796 script_node = NEW_NEWLINE(0);
00797 }
00798 #if defined DOSISH || defined __CYGWIN__
00799 translate_char(script, '\\', '/');
00800 #endif
00801 argc--; argv++;
00802 }
00803 }
00804
00805 ruby_script(script);
00806 ruby_set_argv(argc, argv);
00807 process_sflag();
00808
00809 ruby_init_loadpath();
00810 ruby_sourcefile = rb_source_filename(argv0);
00811 if (e_script) {
00812 require_libraries();
00813 rb_compile_string(script, e_script, 1);
00814 }
00815 else if (strlen(script) == 1 && script[0] == '-') {
00816 load_stdin();
00817 }
00818 else {
00819 load_file(script, 1);
00820 }
00821
00822 process_sflag();
00823 xflag = 0;
00824
00825 if (rb_safe_level() >= 4) {
00826 FL_UNSET(rb_argv, FL_TAINT);
00827 FL_UNSET(rb_load_path, FL_TAINT);
00828 }
00829 }
00830
00831 extern int ruby__end__seen;
00832
00833 static void
00834 load_file(fname, script)
00835 const char *fname;
00836 int script;
00837 {
00838 extern VALUE rb_stdin;
00839 VALUE f;
00840 int line_start = 1;
00841
00842 if (!fname) rb_load_fail(fname);
00843 if (strcmp(fname, "-") == 0) {
00844 f = rb_stdin;
00845 }
00846 else {
00847 FILE *fp = fopen(fname, "r");
00848
00849 if (fp == NULL) {
00850 rb_load_fail(fname);
00851 }
00852 fclose(fp);
00853
00854 f = rb_file_open(fname, "r");
00855 #if defined DOSISH || defined __CYGWIN__
00856 {
00857 char *ext = strrchr(fname, '.');
00858 if (ext && strcasecmp(ext, ".exe") == 0)
00859 rb_io_binmode(f);
00860 }
00861 #endif
00862 }
00863
00864 if (script) {
00865 VALUE c = 1;
00866 VALUE line;
00867 char *p;
00868
00869 if (xflag) {
00870 forbid_setid("-x");
00871 xflag = Qfalse;
00872 while (!NIL_P(line = rb_io_gets(f))) {
00873 line_start++;
00874 if (RSTRING(line)->len > 2
00875 && RSTRING(line)->ptr[0] == '#'
00876 && RSTRING(line)->ptr[1] == '!') {
00877 if ((p = strstr(RSTRING(line)->ptr, "ruby")) != 0) {
00878 goto start_read;
00879 }
00880 }
00881 }
00882 rb_raise(rb_eLoadError, "no Ruby script found in input");
00883 }
00884
00885 c = rb_io_getc(f);
00886 if (c == INT2FIX('#')) {
00887 line = rb_io_gets(f);
00888 if (NIL_P(line)) return;
00889 line_start++;
00890
00891 if (RSTRING(line)->len > 2 && RSTRING(line)->ptr[0] == '!') {
00892 if ((p = strstr(RSTRING(line)->ptr, "ruby")) == 0) {
00893
00894 char **argv;
00895 char *path;
00896 char *pend = RSTRING(line)->ptr + RSTRING(line)->len;
00897
00898 p = RSTRING(line)->ptr + 1;
00899 if (pend[-1] == '\n') pend--;
00900 if (pend[-1] == '\r') pend--;
00901 *pend = '\0';
00902 while (p < pend && ISSPACE(*p))
00903 p++;
00904 path = p;
00905 while (p < pend && !ISSPACE(*p))
00906 p++;
00907 *p++ = '\0';
00908 if (p < pend) {
00909 argv = ALLOCA_N(char*, origargc+3);
00910 argv[1] = p;
00911 MEMCPY(argv+2, origargv+1, char*, origargc);
00912 }
00913 else {
00914 argv = origargv;
00915 }
00916 argv[0] = path;
00917 execv(path, argv);
00918
00919 ruby_sourcefile = rb_source_filename(fname);
00920 ruby_sourceline = 1;
00921 rb_fatal("Can't exec %s", path);
00922 }
00923
00924 start_read:
00925 p += 4;
00926 RSTRING(line)->ptr[RSTRING(line)->len-1] = '\0';
00927 if (RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r')
00928 RSTRING(line)->ptr[RSTRING(line)->len-2] = '\0';
00929 if ((p = strstr(p, " -")) != 0) {
00930 p++;
00931 while (*p == '-') {
00932 p = moreswitches(p+1);
00933 }
00934 }
00935 }
00936 }
00937 else if (!NIL_P(c)) {
00938 rb_io_ungetc(f, c);
00939 }
00940 require_libraries();
00941 if (NIL_P(c)) return;
00942 }
00943 rb_compile_file(fname, f, line_start);
00944 if (script && ruby__end__seen) {
00945 rb_define_global_const("DATA", f);
00946 }
00947 else if (f != rb_stdin) {
00948 rb_io_close(f);
00949 }
00950
00951 if (ruby_parser_stack_on_heap()) {
00952 rb_gc();
00953 }
00954 }
00955
00956 void
00957 rb_load_file(fname)
00958 const char *fname;
00959 {
00960 load_file(fname, 0);
00961 }
00962
00963 static void
00964 load_stdin()
00965 {
00966 forbid_setid("program input from stdin");
00967 load_file("-", 1);
00968 }
00969
00970 VALUE rb_progname;
00971 VALUE rb_argv;
00972 VALUE rb_argv0;
00973
00974 #if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE) && !defined(DOSISH)
00975 static struct {
00976 char *begin, *end;
00977 } envspace;
00978 extern char **environ;
00979
00980 static void
00981 set_arg0space()
00982 {
00983 char *s;
00984 int i;
00985
00986 if (!environ || (s = environ[0]) == NULL) return;
00987 envspace.begin = s;
00988 s += strlen(s);
00989 for (i = 1; environ[i]; i++) {
00990 if (environ[i] == s + 1) {
00991 s++;
00992 s += strlen(s);
00993 }
00994 }
00995 envspace.end = s;
00996 }
00997 #else
00998 #define set_arg0space() ((void)0)
00999 #endif
01000
01001 static void
01002 set_arg0(val, id)
01003 VALUE val;
01004 ID id;
01005 {
01006 char *s;
01007 long i;
01008 #if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE)
01009 static int len;
01010 #endif
01011
01012 if (origargv == 0) rb_raise(rb_eRuntimeError, "$0 not initialized");
01013 StringValue(val);
01014 s = RSTRING(val)->ptr;
01015 i = RSTRING(val)->len;
01016 #if defined(PSTAT_SETCMD)
01017 if (i >= PST_CLEN) {
01018 union pstun j;
01019 j.pst_command = s;
01020 i = PST_CLEN;
01021 RSTRING(val)->len = i;
01022 *(s + i) = '\0';
01023 pstat(PSTAT_SETCMD, j, PST_CLEN, 0, 0);
01024 }
01025 else {
01026 union pstun j;
01027 j.pst_command = s;
01028 pstat(PSTAT_SETCMD, j, i, 0, 0);
01029 }
01030 rb_progname = rb_tainted_str_new(s, i);
01031 #elif defined(HAVE_SETPROCTITLE)
01032 setproctitle("%.*s", (int)i, s);
01033 rb_progname = rb_tainted_str_new(s, i);
01034 #else
01035 if (len == 0) {
01036 char *s = origargv[0];
01037 int i;
01038
01039 s += strlen(s);
01040
01041 for (i = 1; i < origargc; i++) {
01042 if (origargv[i] == s + 1) {
01043 s++;
01044 s += strlen(s);
01045 }
01046 else {
01047 break;
01048 }
01049 }
01050 #ifndef DOSISH
01051 if (s + 1 == envspace.begin) {
01052 s = envspace.end;
01053 ruby_setenv("", NULL);
01054 }
01055 #endif
01056 len = s - origargv[0];
01057 }
01058
01059 if (i >= len) {
01060 i = len;
01061 memcpy(origargv[0], s, i);
01062 origargv[0][i] = '\0';
01063 }
01064 else {
01065 memcpy(origargv[0], s, i);
01066 s = origargv[0]+i;
01067 *s++ = '\0';
01068 while (++i < len)
01069 *s++ = ' ';
01070 for (i = 1; i < origargc; i++)
01071 origargv[i] = 0;
01072 }
01073 rb_progname = rb_tainted_str_new2(origargv[0]);
01074 #endif
01075 }
01076
01077 void
01078 ruby_script(name)
01079 const char *name;
01080 {
01081 if (name) {
01082 rb_progname = rb_tainted_str_new2(name);
01083 ruby_sourcefile = rb_source_filename(name);
01084 }
01085 }
01086
01087 static int uid, euid, gid, egid;
01088
01089 static void
01090 init_ids()
01091 {
01092 uid = (int)getuid();
01093 euid = (int)geteuid();
01094 gid = (int)getgid();
01095 egid = (int)getegid();
01096 #ifdef VMS
01097 uid |= gid << 16;
01098 euid |= egid << 16;
01099 #endif
01100 if (uid && (euid != uid || egid != gid)) {
01101 rb_set_safe_level(1);
01102 }
01103 }
01104
01105 static void
01106 forbid_setid(s)
01107 const char *s;
01108 {
01109 if (euid != uid)
01110 rb_raise(rb_eSecurityError, "no %s allowed while running setuid", s);
01111 if (egid != gid)
01112 rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s);
01113 if (rb_safe_level() > 0)
01114 rb_raise(rb_eSecurityError, "no %s allowed in tainted mode", s);
01115 }
01116
01117 static void
01118 verbose_setter(val, id, variable)
01119 VALUE val;
01120 ID id;
01121 VALUE *variable;
01122 {
01123 ruby_verbose = RTEST(val) ? Qtrue : val;
01124 }
01125
01126 void
01127 ruby_prog_init()
01128 {
01129 init_ids();
01130
01131 ruby_sourcefile = rb_source_filename("ruby");
01132 rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter);
01133 rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter);
01134 rb_define_hooked_variable("$-w", &ruby_verbose, 0, verbose_setter);
01135 rb_define_variable("$DEBUG", &ruby_debug);
01136 rb_define_variable("$-d", &ruby_debug);
01137 rb_define_readonly_variable("$-p", &do_print);
01138 rb_define_readonly_variable("$-l", &do_line);
01139
01140 rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0);
01141 rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);
01142
01143 rb_define_readonly_variable("$*", &rb_argv);
01144 rb_argv = rb_ary_new();
01145 rb_define_global_const("ARGV", rb_argv);
01146 rb_define_readonly_variable("$-a", &do_split);
01147 rb_global_variable(&rb_argv0);
01148
01149 #ifdef MSDOS
01150
01151
01152
01153
01154 (void)fclose(stdaux);
01155 (void)fclose(stdprn);
01156 #endif
01157 }
01158
01159 void
01160 ruby_set_argv(argc, argv)
01161 int argc;
01162 char **argv;
01163 {
01164 int i;
01165
01166 #if defined(USE_DLN_A_OUT)
01167 if (origargv) dln_argv0 = origargv[0];
01168 else dln_argv0 = argv[0];
01169 #endif
01170 rb_ary_clear(rb_argv);
01171 for (i=0; i < argc; i++) {
01172 VALUE arg = rb_tainted_str_new2(argv[i]);
01173
01174 OBJ_FREEZE(arg);
01175 rb_ary_push(rb_argv, arg);
01176 }
01177 }
01178
01179 void
01180 ruby_process_options(argc, argv)
01181 int argc;
01182 char **argv;
01183 {
01184 origargc = argc; origargv = argv;
01185
01186 ruby_script(argv[0]);
01187 rb_argv0 = rb_progname;
01188 #if defined(USE_DLN_A_OUT)
01189 dln_argv0 = argv[0];
01190 #endif
01191 set_arg0space();
01192 proc_options(argc, argv);
01193
01194 if (do_check && ruby_nerrs == 0) {
01195 printf("Syntax OK\n");
01196 exit(0);
01197 }
01198 if (do_print) {
01199 rb_parser_append_print();
01200 }
01201 if (do_loop) {
01202 rb_parser_while_loop(do_line, do_split);
01203 }
01204 }
01205