static object chdir_restore(Frame caller, chdir_data args) { if (args.done) { chdir_blocking--; dir_chdir(caller, args.old_path); } return null; }
public override object Call(Class last_class, object recv, Frame caller, Proc block, Array rest) { String path; Eval.rb_secure(2, caller); if (Class.rb_scan_args(caller, rest, 0, 1, false) == 1) path = String.RStringValue(rest[0], caller); else { string dist = System.Environment.GetEnvironmentVariable("HOME"); if (dist == null || dist.Length == 0) dist = System.Environment.GetEnvironmentVariable("LOGDIR"); if (dist == null || dist.Length == 0) throw new ArgumentError("HOME/LOGDIR not set").raise(caller); path = new String(dist); } if (chdir_blocking > 0) { if (block != null) Errors.rb_warn("conflicting chdir during another chdir block"); } if (block != null) { string cwd = System.Environment.CurrentDirectory; chdir_data args = new chdir_data(); args.old_path = new String(cwd); args.old_path.Tainted = true; args.new_path = path; args.done = false; object result = null; try { result = chdir_yield(caller, block, args); } finally { chdir_restore(caller, args); } return result; } else { dir_chdir(caller, path); return 0; } }
static object chdir_yield(Frame caller, Proc block, chdir_data args) { dir_chdir(caller, args.new_path); args.done = true; chdir_blocking++; return Proc.rb_yield(block, caller, new object[] { args.new_path }); }