4 // Copyright (C) 2006 Novell, Inc.
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
29 using System
.Runtime
.InteropServices
;
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
;
41 public string[] Arguments
{
46 public bool RedirectStandardInput
{
47 get { return redirect_stdin; }
48 set { redirect_stdin = value; }
51 public bool RedirectStandardOutput
{
52 get { return redirect_stdout; }
53 set { redirect_stdout = value; }
56 public bool RedirectStandardError
{
57 get { return redirect_stderr; }
58 set { redirect_stderr = value; }
61 public Stream StandardInput
{
62 get { return stdin_stream; }
65 public Stream StandardOutput
{
66 get { return stdout_stream; }
69 public Stream StandardError
{
70 get { return stderr_stream; }
73 [DllImport ("libglib-2.0.so.0")]
74 static extern bool g_spawn_async_with_pipes (string working_directory
,
81 [In
,Out
] IntPtr standard_input
,
82 [In
,Out
] IntPtr standard_output
,
83 [In
,Out
] IntPtr standard_error
,
89 throw new ArgumentException ("Arguments cannot be empty");
93 if (args
[args
.Length
- 1] != null) {
94 // Need to null-terminate the array.
95 string[] tmp_args
= new string [args
.Length
+ 1];
96 Array
.Copy (args
, tmp_args
, args
.Length
);
100 IntPtr in_ptr
= IntPtr
.Zero
, out_ptr
= IntPtr
.Zero
, err_ptr
= IntPtr
.Zero
;
103 if (RedirectStandardInput
)
104 in_ptr
= Marshal
.AllocHGlobal (IntPtr
.Size
);
106 if (RedirectStandardOutput
)
107 out_ptr
= Marshal
.AllocHGlobal (IntPtr
.Size
);
109 if (RedirectStandardError
)
110 err_ptr
= Marshal
.AllocHGlobal (IntPtr
.Size
);
112 g_spawn_async_with_pipes (null, args
, null,
113 1 << 2, // G_SPAWN_SEARCH_PATH
114 IntPtr
.Zero
, IntPtr
.Zero
, IntPtr
.Zero
,
115 in_ptr
, out_ptr
, err_ptr
, out error
);
117 if (error
!= IntPtr
.Zero
)
118 throw new SafeProcessException (new GException (error
));
120 if (in_ptr
!= IntPtr
.Zero
) {
121 IntPtr v
= Marshal
.ReadIntPtr (in_ptr
);
122 stdin_stream
= new UnixStream ((int) v
);
125 if (out_ptr
!= IntPtr
.Zero
) {
126 IntPtr v
= Marshal
.ReadIntPtr (out_ptr
);
127 stdout_stream
= new UnixStream ((int) v
);
130 if (err_ptr
!= IntPtr
.Zero
) {
131 IntPtr v
= Marshal
.ReadIntPtr (err_ptr
);
132 stderr_stream
= new UnixStream ((int) v
);
136 if (in_ptr
!= IntPtr
.Zero
)
137 Marshal
.FreeHGlobal (in_ptr
);
139 if (out_ptr
!= IntPtr
.Zero
)
140 Marshal
.FreeHGlobal (out_ptr
);
142 if (err_ptr
!= IntPtr
.Zero
)
143 Marshal
.FreeHGlobal (err_ptr
);
149 if (stdin_stream
!= null)
150 stdin_stream
.Close ();
152 if (stdout_stream
!= null)
153 stdout_stream
.Close ();
155 if (stderr_stream
!= null)
156 stderr_stream
.Close ();
160 public class SafeProcessException
: Exception
{
162 internal SafeProcessException (GException gexception
) : base (gexception
.Message
) { }