[前][次][番号順一覧][スレッド一覧]

ruby-changes:23998

From: nobu <ko1@a...>
Date: Wed, 13 Jun 2012 09:56:39 +0900 (JST)
Subject: [ruby-changes:23998] nobu:r36049 (trunk): process.c: use shell for reserved or special built-in

nobu	2012-06-13 09:56:31 +0900 (Wed, 13 Jun 2012)

  New Revision: 36049

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=36049

  Log:
    process.c: use shell for reserved or special built-in
    
    * process.c (rb_exec_fillarg): use shell if the first word is reserved
      or special built-in name.
      http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html

  Modified files:
    trunk/ChangeLog
    trunk/process.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 36048)
+++ ChangeLog	(revision 36049)
@@ -1,5 +1,9 @@
-Wed Jun 13 09:55:29 2012  Nobuyoshi Nakada  <nobu@r...>
+Wed Jun 13 09:56:29 2012  Nobuyoshi Nakada  <nobu@r...>
 
+	* process.c (rb_exec_fillarg): use shell if the first word is reserved
+	  or special built-in name.
+	  http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
+
 	* process.c (rb_exec_fillarg): treat '=' only in the first word.  if
 	  the first word does not contain '=', it is the command name and
 	  environment assignments cannot be anymore.
Index: process.c
===================================================================
--- process.c	(revision 36048)
+++ process.c	(revision 36049)
@@ -79,6 +79,8 @@
 #include <grp.h>
 #endif
 
+#define numberof(array) (int)(sizeof(array)/sizeof((array)[0]))
+
 #if defined(HAVE_TIMES) || defined(_WIN32)
 static VALUE rb_cProcessTms;
 #endif
@@ -1824,6 +1826,20 @@
     return prog;
 }
 
+struct string_part {
+    const char *ptr;
+    size_t len;
+};
+
+static int
+compare_posix_sh(const void *key, const void *el)
+{
+    const struct string_part *word = key;
+    int ret = strncmp(word->ptr, el, word->len);
+    if (!ret && ((const char *)el)[word->len]) ret = -1;
+    return ret;
+}
+
 static void
 rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, struct rb_exec_arg *e)
 {
@@ -1850,10 +1866,40 @@
 
 #ifndef _WIN32
     if (e->use_shell) {
+	static const char posix_sh_cmds[][8] = {
+	    "!",		/* reserved */
+	    ".",		/* special built-in */
+	    "break",		/* special built-in */
+	    "case",		/* reserved */
+	    "colon",		/* special built-in */
+	    "continue",		/* special built-in */
+	    "do",		/* reserved */
+	    "done",		/* reserved */
+	    "elif",		/* reserved */
+	    "else",		/* reserved */
+	    "esac",		/* reserved */
+	    "eval",		/* special built-in */
+	    "exec",		/* special built-in */
+	    "exit",		/* special built-in */
+	    "export",		/* special built-in */
+	    "fi",		/* reserved */
+	    "for",		/* reserved */
+	    "if",		/* reserved */
+	    "in",		/* reserved */
+	    "readonly",		/* special built-in */
+	    "return",		/* special built-in */
+	    "set",		/* special built-in */
+	    "shift",		/* special built-in */
+	    "then",		/* reserved */
+	    "times",		/* special built-in */
+	    "trap",		/* special built-in */
+	    "unset",		/* special built-in */
+	    "until",		/* reserved */
+	    "while",		/* reserved */
+	};
 	const char *p;
-	int first = 1;
+	struct string_part first = {0, 0};
         int has_meta = 0;
-        int has_nonspace = 0;
         /*
          * meta characters:
          *
@@ -1879,18 +1925,32 @@
          * %    (used in Parameter Expansion)
          */
         for (p = RSTRING_PTR(prog); *p; p++) {
-            if (!has_nonspace && *p != ' ' && *p != '\t')
-                has_nonspace = 1;
-	    if (has_nonspace && (*p == ' ' || *p == '\t'))
-		first = 0;
+	    if (*p == ' ' || *p == '\t') {
+		if (first.ptr && !first.len) first.len = p - first.ptr;
+	    }
+	    else {
+		if (!first.ptr) first.ptr = p;
+	    }
             if (!has_meta && strchr("*?{}[]<>()~&|\\$;'`\"\n#", *p))
                 has_meta = 1;
-	    if (first && *p == '=')
-		has_meta = 1;
-            if (has_nonspace && has_meta)
+	    if (!first.len) {
+		if (*p == '=') {
+		    has_meta = 1;
+		}
+		else if (*p == '/') {
+		    first.len = SIZE_T_MAX; /* longer than any posix_sh_cmds */
+		}
+	    }
+	    if (has_meta)
                 break;
         }
-        if (has_nonspace && !has_meta) {
+	if (!has_meta && first.ptr) {
+	    if (!first.len) first.len = p - first.ptr;
+	    if (first.len > 0 && first.len <= sizeof(posix_sh_cmds[0]) &&
+		bsearch(&first, posix_sh_cmds, numberof(posix_sh_cmds), sizeof(posix_sh_cmds[0]), compare_posix_sh))
+		has_meta = 1;
+	}
+	if (!has_meta) {
             /* avoid shell since no shell meta charactor found. */
             e->use_shell = 0;
         }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]