From: ara.t.howard@... Date: 2006-12-22T00:48:04+09:00 Subject: Re: Kernel#system bug? On Thu, 21 Dec 2006, Charlton wrote: > Hi Nobu, > > Hm, I'm not sure I understand how this is natural. It's true that the > shell sets PWD and this here is the issue. in this command there is no shell involved: >>> puts "without semi-colon" >>> IO.popen("env").readlines.each do |entry| >>> puts entry if entry =~ /PWD/ >>> end which you can confirm thusly: harp:~ > cat a.rb IO.popen 'env' harp:~ > strace -f -- ruby a.rb 2>&1|grep exec execve("/home/ahoward/bin/ruby", ["ruby", "a.rb"], [/* 52 vars */]) = 0 set_thread_area({entry_number:-1 -> 6, base_addr:0xb75e1460, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 execve("/bin/env", ["env"], [/* 52 vars */]) = 0 set_thread_area({entry_number:-1 -> 6, base_addr:0xb75e2780, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 yet a semi-colon terminated command does indeed invoke /bin/sh: harp:~ > cat b.rb IO.popen 'env;' harp:~ > strace -f -- ruby b.rb 2>&1|grep exec execve("/home/ahoward/bin/ruby", ["ruby", "b.rb"], [/* 52 vars */]) = 0 set_thread_area({entry_number:-1 -> 6, base_addr:0xb75e0460, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 execve("/bin/sh", ["sh", "-c", "env;"], [/* 52 vars */]) = 0 set_thread_area({entry_number:-1 -> 6, base_addr:0xb75e0080, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 execve("/bin/env", ["env"], [/* 50 vars */]) = 0 set_thread_area({entry_number:-1 -> 6, base_addr:0xb75e4780, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 which you see here >>> puts "with semi-colon" >>> IO.popen("env;").readlines.each do |entry| >>> puts entry if entry =~ /PWD/ >>> end this is because the command 'env;' is, in fact, not valid. in a c program you will not be able to popen it. ruby, however, is kind, when it sees the special chars "*?{}[]<>()~&|\\$;'`\"\n" in your system call it runs your command via sh. this is doccumented somewhere, though i forget where attm... so what's happening is that, in one case, you exec 'env' which simply inherits the parents env, including current value of PWD. in the second case you actually exec sh, which sets ENV[PWD], which in turn runs env as a child process. in summary, nobu is right - simply use Dir.pwd and do not rely on auto-magical behaviour of child processes which set, or may not set, the PWD env var. similarly, if you want to avoid the special handling of cmd strings given to system/popen, make sure the commands given are valid (in the 'c' sense) so you bypass ruby filtering them via /bin/sh. regards. -a -- if you find yourself slandering anybody, first imagine that your mouth is filled with excrement. it will break you of the habit quickly enough. - the dalai lama