From: Shugo Maeda Date: 2000-08-28T17:26:20+09:00 Subject: [ruby-list:24615] Re: レンタルサーバで eruby 前田です。 At Fri, 25 Aug 2000 17:08:51 +0900, Shugo Maeda wrote: > > #!/bin/sh > > /usr/local/bin/eruby -KS > > erubyが#!行の引数を見るようにすればこういうトリックは要らないはず > なんですよね。 > この点は対応したいです。 試しに実装しました。 ついでに、 -C [charset] specifies charset parameter for Content-Type というoptionを追加しました。 (#!行で見るのは-Kと-Cだけです。) #!/usr/bin/eruby -Ks -C shift_jis のようにファイルの先頭に書いておけば、それっぽい動作をするはずで す。 -- 前田 修吾 Index: eruby.c =================================================================== RCS file: /home/cvs/eruby/eruby.c,v retrieving revision 1.7 diff -u -r1.7 eruby.c --- eruby.c 2000/05/30 02:36:05 1.7 +++ eruby.c 2000/08/28 08:25:41 @@ -5,6 +5,11 @@ #include "ruby.h" +#include +#include +#include +#include +#include #include #ifdef HAVE_UNISTD_H #include @@ -31,6 +36,94 @@ #define EOP (-2) +static int parse_options(FILE *in, FILE *out) +{ + int c; + + do { + c = getc(in); + if (c == EOF) return 0; + } while (!isspace(c)); + + for (;;) { + c = getc(in); + again: + switch (c) { + case EOF: + return 0; + case '\n': + putc(c, out); + return 0; + case '-': + c = getc(in); + switch (c) { + case 'K': + { + char tmp[1]; + + c = getc(in); + if (c == EOF || c == '\n') + return -1; + tmp[0] = c; + rb_set_kcode(tmp); + while (c != EOF && !isspace(c)) { + c = getc(in); + } + goto again; + } + case 'C': + { + int term; + char tmp[1]; + VALUE charset = rb_str_new("", 0); + + c = getc(in); + while (isspace(c)) { + if (c == '\n') return -1; + c = getc(in); + } + if (c == EOF) { + return -1; + } + else if (c == '"' || c == '\'') { + term = c; + c = getc(in); + while (c != EOF && c != term) { + tmp[0] = c; + rb_str_cat(charset, tmp, 1); + c = getc(in); + } + eruby_charset = charset; + } + else { + while (c != EOF && !isspace(c)) { + tmp[0] = c; + rb_str_cat(charset, tmp, 1); + c = getc(in); + } + eruby_charset = charset; + goto again; + } + break; + } + default: + return -1; + } + break; + case ' ': + case '\t': + case '\v': + case '\f': + case '\r': + break; + default: + return -1; + } + } + + return 0; +} + static int parse_embedded_program(FILE *in, FILE *out, enum embedded_program_type type) { @@ -122,13 +215,20 @@ c = getc(in); if (c == '#') { - do { - c = getc(in); - if (c == '\n') { - putc('\n', out); - break; + c = getc(in); + if (c == '!') { + if (parse_options(in, out) == -1) + return ERUBY_INVALID_OPTION; + } + else { + while (c != EOF) { + c = getc(in); + if (c == '\n') { + putc(c, out); + break; + } } - } while (c != EOF); + } } else { ungetc(c, in); @@ -276,6 +376,7 @@ char *tmp; VALUE scriptname; FILE *in, *out; + int fd; int err; if (strcmp(filename, "-") == 0) { @@ -285,18 +386,29 @@ if ((in = fopen(filename, "r")) == NULL) rb_sys_fail(filename); } + retry: if ((tmp = eruby_mktemp(filename)) == NULL) - rb_fatal("Can't mktemp"); + rb_fatal("can't mktemp"); + fd = open(tmp, O_CREAT |O_EXCL | O_WRONLY, 0600); + if (fd < 0) { + free(tmp); + if (errno == EEXIST) + goto retry; + rb_fatal("cannot open temporary file: %s", tmp); + } scriptname = rb_str_new2(tmp); free(tmp); - if ((out = fopen(RSTRING(scriptname)->ptr, "w")) == NULL) - rb_fatal("Cannot open temporary file: %s", RSTRING(scriptname)->ptr); + if ((out = fdopen(fd, "w")) == NULL) + rb_fatal("cannot open temporary file: %s", RSTRING(scriptname)->ptr); err = eruby_compile(in, out); if (in != stdin) fclose(in); fclose(out); switch (err) { case ERUBY_MISSING_END_DELIMITER: rb_raise(rb_eSyntaxError, "missing end delimiter"); + break; + case ERUBY_INVALID_OPTION: + rb_raise(rb_eSyntaxError, "invalid #! line"); break; case ERUBY_SYSTEM_ERROR: rb_sys_fail(filename); Index: eruby.h =================================================================== RCS file: /home/cvs/eruby/eruby.h,v retrieving revision 1.7 diff -u -r1.7 eruby.h --- eruby.h 2000/05/18 08:09:13 1.7 +++ eruby.h 2000/08/28 08:25:41 @@ -11,6 +11,7 @@ enum eruby_compile_status { ERUBY_OK = 0, ERUBY_MISSING_END_DELIMITER, + ERUBY_INVALID_OPTION, ERUBY_SYSTEM_ERROR }; Index: eruby_main.c =================================================================== RCS file: /home/cvs/eruby/eruby_main.c,v retrieving revision 1.12 diff -u -r1.12 eruby_main.c --- eruby_main.c 2000/08/25 07:41:44 1.12 +++ eruby_main.c 2000/08/28 08:25:41 @@ -433,7 +433,7 @@ static VALUE defout_cancel(VALUE self) { - if (RSTRING(self)->len == 0) return; + if (RSTRING(self)->len == 0) return Qnil; RSTRING(self)->len = 0; RSTRING(self)->ptr[0] = '\0'; return Qnil; @@ -483,6 +483,7 @@ f: filter mode\n\ c: CGI mode\n\ n: NPH-CGI mode\n\ + -C [charset] specifies charset parameter for Content-Type\n\ -n, --noheader disables CGI header output\n\ -v, --verbose enables verbose mode\n\ --version print version information and exit\n\ @@ -564,9 +565,28 @@ break; #endif case 'K': - rb_set_kcode(++s); s++; + if (*s == '\0') { + fprintf(stderr, "%s: no arg given for -K\n", argv[0]); + exit(2); + } + rb_set_kcode(s); + s++; goto again; + case 'C': + s++; + if (*s == '\0') { + i++; + if (i == argc) { + fprintf(stderr, "%s: no arg given for -C\n", argv[0]); + exit(2); + } + eruby_charset = rb_str_new2(argv[i]); + } + else { + eruby_charset = rb_str_new2(s); + } + break; case 'd': ruby_debug = Qtrue; s++; @@ -625,6 +645,18 @@ char *out; int nout; + ruby_init(); +#if RUBY_VERSION_CODE >= 145 + rb_ary_push(rb_load_path, rb_str_new2(".")); +#endif + if (eruby_mode == MODE_CGI || eruby_mode == MODE_NPHCGI) + rb_set_safe_level(1); + + rb_defout = rb_str_new("", 0); + rb_define_singleton_method(rb_defout, "write", defout_write, 1); + rb_define_singleton_method(rb_defout, "cancel", defout_cancel, 0); + eruby_init(); + parse_options(argc, argv); if (eruby_mode == MODE_UNKNOWN) eruby_mode = guess_mode(); @@ -643,17 +675,6 @@ eruby_filename = "-"; } - ruby_init(); -#if RUBY_VERSION_CODE >= 145 - rb_ary_push(rb_load_path, rb_str_new2(".")); -#endif - if (eruby_mode == MODE_CGI || eruby_mode == MODE_NPHCGI) - rb_set_safe_level(1); - - rb_defout = rb_str_new("", 0); - rb_define_singleton_method(rb_defout, "write", defout_write, 1); - rb_define_singleton_method(rb_defout, "cancel", defout_cancel, 0); - eruby_init(); script = eruby_load(eruby_filename, 0, &state); if (state && !rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) { error_print(state, eruby_mode, script);