Merge the recent changes from HEAD onto the branch
[beagle.git] / Util / SafeProcess.cs
blobc9f3998deec7362f1545619476e7c551b265e528
1 //
2 // SafeProcess.cs
3 //
4 // Copyright (C) 2006 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
27 using System;
28 using System.IO;
29 using System.Runtime.InteropServices;
30 using Mono.Unix;
31 using GLib;
33 namespace Beagle.Util {
35 public class SafeProcess {
37 private bool redirect_stdin, redirect_stdout, redirect_stderr;
38 private string[] args;
39 private UnixStream stdin_stream, stdout_stream, stderr_stream;
40 private int pid;
42 public string[] Arguments {
43 get { return args; }
44 set { args = value; }
47 public bool RedirectStandardInput {
48 get { return redirect_stdin; }
49 set { redirect_stdin = value; }
52 public bool RedirectStandardOutput {
53 get { return redirect_stdout; }
54 set { redirect_stdout = value; }
57 public bool RedirectStandardError {
58 get { return redirect_stderr; }
59 set { redirect_stderr = value; }
62 public Stream StandardInput {
63 get { return stdin_stream; }
66 public Stream StandardOutput {
67 get { return stdout_stream; }
70 public Stream StandardError {
71 get { return stderr_stream; }
74 public int Id {
75 get { return pid; }
78 [DllImport ("libglib-2.0.so.0")]
79 static extern bool g_spawn_async_with_pipes (string working_directory,
80 string[] argv,
81 string[] envp,
82 int flags,
83 IntPtr child_setup,
84 IntPtr child_data,
85 out int pid,
86 [In,Out] IntPtr standard_input,
87 [In,Out] IntPtr standard_output,
88 [In,Out] IntPtr standard_error,
89 out IntPtr error);
91 public void Start ()
93 if (args == null)
94 throw new ArgumentException ("Arguments cannot be empty");
96 IntPtr error;
98 if (args [args.Length - 1] != null) {
99 // Need to null-terminate the array.
100 string[] tmp_args = new string [args.Length + 1];
101 Array.Copy (args, tmp_args, args.Length);
102 args = tmp_args;
105 IntPtr in_ptr = IntPtr.Zero, out_ptr = IntPtr.Zero, err_ptr = IntPtr.Zero;
107 try {
108 if (RedirectStandardInput)
109 in_ptr = Marshal.AllocHGlobal (IntPtr.Size);
111 if (RedirectStandardOutput)
112 out_ptr = Marshal.AllocHGlobal (IntPtr.Size);
114 if (RedirectStandardError)
115 err_ptr = Marshal.AllocHGlobal (IntPtr.Size);
117 g_spawn_async_with_pipes (null, args, null,
118 1 << 2, // G_SPAWN_SEARCH_PATH
119 IntPtr.Zero, IntPtr.Zero, out pid,
120 in_ptr, out_ptr, err_ptr, out error);
122 if (error != IntPtr.Zero)
123 throw new SafeProcessException (new GException (error));
125 if (in_ptr != IntPtr.Zero) {
126 IntPtr v = Marshal.ReadIntPtr (in_ptr);
127 stdin_stream = new UnixStream ((int) v);
130 if (out_ptr != IntPtr.Zero) {
131 IntPtr v = Marshal.ReadIntPtr (out_ptr);
132 stdout_stream = new UnixStream ((int) v);
135 if (err_ptr != IntPtr.Zero) {
136 IntPtr v = Marshal.ReadIntPtr (err_ptr);
137 stderr_stream = new UnixStream ((int) v);
140 } finally {
141 if (in_ptr != IntPtr.Zero)
142 Marshal.FreeHGlobal (in_ptr);
144 if (out_ptr != IntPtr.Zero)
145 Marshal.FreeHGlobal (out_ptr);
147 if (err_ptr != IntPtr.Zero)
148 Marshal.FreeHGlobal (err_ptr);
152 public void Close ()
154 if (stdin_stream != null)
155 stdin_stream.Close ();
157 if (stdout_stream != null)
158 stdout_stream.Close ();
160 if (stderr_stream != null)
161 stderr_stream.Close ();
165 public class SafeProcessException : Exception {
167 internal SafeProcessException (GException gexception) : base (gexception.Message) { }