root/trunk/minid/oslib.d

Revision 440, 7.7 kB (checked in by JarrettBillingsley, 1 week ago)

Closes #51, at least I feel like it does.

Line 
1 /******************************************************************************
2 License:
3 Copyright (c) 2008 Jarrett Billingsley
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the
7 use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it freely,
11 subject to the following restrictions:
12
13     1. The origin of this software must not be misrepresented; you must not
14     claim that you wrote the original software. If you use this software in a
15     product, an acknowledgment in the product documentation would be
16     appreciated but is not required.
17
18     2. Altered source versions must be plainly marked as such, and must not
19     be misrepresented as being the original software.
20
21     3. This notice may not be removed or altered from any source distribution.
22 ******************************************************************************/
23
24 module minid.oslib;
25
26 import tango.stdc.stdlib;
27 import tango.stdc.stringz;
28 import tango.sys.Environment;
29 import tango.sys.Process;
30
31 import minid.ex;
32 import minid.interpreter;
33 import minid.types;
34 import minid.utils;
35
36 struct OSLib
37 {
38 static:
39     public void init(MDThread* t)
40     {
41         pushGlobal(t, "modules");
42         field(t, -1, "customLoaders");
43
44         newFunction(t, function uword(MDThread* t, uword numParams)
45         {
46             importModule(t, "stream");
47             pop(t);
48
49             ProcessObj.init(t);
50             newFunction(t, &system, "system"); newGlobal(t, "system");
51             newFunction(t, &getEnv, "getEnv"); newGlobal(t, "getEnv");
52
53             return 0;
54         }, "os");
55        
56         fielda(t, -2, "os");
57         importModule(t, "os");
58         pop(t, 3);
59     }
60
61     uword system(MDThread* t, uword numParams)
62     {
63         if(numParams == 0)
64             pushBool(t, .system(null) ? true : false);
65         else
66         {
67             auto cmd = checkStringParam(t, 1);
68
69             if(cmd.length < 128)
70             {
71                 char[128] buf = void;
72                 buf[0 .. cmd.length] = cmd[];
73                 buf[cmd.length] = 0;
74                 pushInt(t, .system(buf.ptr));
75             }
76             else
77             {
78                 auto arr = t.vm.alloc.allocArray!(char)(cmd.length + 1);
79                 scope(exit) t.vm.alloc.freeArray(arr);
80                 arr[0 .. cmd.length] = cmd[];
81                 arr[cmd.length] = 0;
82                 pushInt(t, .system(arr.ptr));
83             }
84         }
85
86         return 1;
87     }
88
89     uword getEnv(MDThread* t, uword numParams)
90     {
91         if(numParams == 0)
92         {
93             newTable(t);
94
95             foreach(k, v; Environment.get())
96             {
97                 pushString(t, k);
98                 pushString(t, v);
99                 idxa(t, -3);
100             }
101         }
102         else
103         {
104             auto val = Environment.get(checkStringParam(t, 1), optStringParam(t, 2, null));
105
106             if(val is null)
107                 pushNull(t);
108             else
109                 pushString(t, val);
110         }
111
112         return 1;
113     }
114
115     struct ProcessObj
116     {
117     static:
118         enum Fields
119         {
120             process,
121             stdin,
122             stdout,
123             stderr
124         }
125
126         public static void init(MDThread* t)
127         {
128             CreateClass(t, "Process", (CreateClass* c)
129             {
130                 c.method("constructor", &constructor);
131                 c.method("isRunning",   &isRunning);
132                 c.method("workDir",     &workDir);
133                 c.method("stdin",       &stdin);
134                 c.method("stdout",      &stdout);
135                 c.method("stderr",      &stderr);
136                 c.method("execute",     &execute);
137                 c.method("wait",        &wait);
138                 c.method("kill",        &kill);
139             });
140            
141             newFunction(t, &allocator, "Process.allocator");
142             setAllocator(t, -2);
143
144             newGlobal(t, "Process");
145         }
146
147         Process getProcess(MDThread* t)
148         {
149             checkInstParam(t, 0, "Process");
150             getExtraVal(t, 0, Fields.process);
151             auto ret = cast(Process)getNativeObj(t, -1);
152             assert(ret !is null);
153             pop(t);
154             return ret;
155         }
156        
157         uword allocator(MDThread* t, uword numParams)
158         {
159             newInstance(t, 0, Fields.max + 1);
160            
161             dup(t);
162             pushNull(t);
163             rotateAll(t, 3);
164             methodCall(t, 2, "constructor", 0);
165             return 1;
166         }
167
168         public uword constructor(MDThread* t, uword numParams)
169         {
170             checkInstParam(t, 0, "Process");
171            
172             getExtraVal(t, 0, Fields.process);
173            
174             if(!isNull(t, -1))
175                 throwException(t, "Attempting to call constructor on an already-initialized Process");
176            
177             pop(t);
178
179             pushNativeObj(t, new Process());
180             setExtraVal(t, 0, Fields.process);
181             return 0;
182         }
183
184         public uword isRunning(MDThread* t, uword numParams)
185         {
186             auto p = getProcess(t);
187             pushBool(t, safeCode(t, p.isRunning()));
188             return 1;
189         }
190
191         public uword workDir(MDThread* t, uword numParams)
192         {
193             auto p = getProcess(t);
194
195             if(numParams == 0)
196             {
197                 pushString(t, safeCode(t, p.workDir));
198                 return 1;
199             }
200
201             safeCode(t, p.workDir = checkStringParam(t, 1));
202             return 0;
203         }
204
205         public uword execute(MDThread* t, uword numParams)
206         {
207             auto p = getProcess(t);
208
209             char[][char[]] env = null;
210
211             if(numParams > 1)
212             {
213                 checkParam(t, 2, MDValue.Type.Table);
214                 dup(t, 2);
215
216                 foreach(word k, word v; foreachLoop(t, 1))
217                 {
218                     if(!isString(t, k) || !isString(t, v))
219                         throwException(t, "env parameter must be a table mapping from strings to strings");
220
221                     env[getString(t, k)] = getString(t, v);
222                 }
223             }
224            
225             if(isString(t, 1))
226                 safeCode(t, p.execute(getString(t, 1), env));
227             else
228             {
229                 checkParam(t, 1, MDValue.Type.Array);
230                 auto num = len(t, 1);
231                 auto cmd = new char[][cast(uword)num];
232
233                 for(uword i = 0; i < num; i++)
234                 {
235                     idxi(t, 1, i);
236                    
237                     if(!isString(t, -1))
238                         throwException(t, "cmd parameter must be an array of strings");
239
240                     cmd[i] = getString(t, -1);
241                     pop(t);
242                 }
243
244                 safeCode(t, p.execute(cmd, env));
245             }
246
247             pushNull(t);
248             dup(t);
249             dup(t);
250             setExtraVal(t, 0, Fields.stdin);
251             setExtraVal(t, 0, Fields.stdout);
252             setExtraVal(t, 0, Fields.stderr);
253
254             return 0;
255         }
256        
257         public uword stdin(MDThread* t, uword numParams)
258         {
259             auto p = getProcess(t);
260
261             getExtraVal(t, 0, Fields.stdin);
262            
263             if(isNull(t, -1))
264             {
265                 pop(t);
266                 lookupCT!("stream.OutputStream")(t);
267                 pushNull(t);
268                 pushNativeObj(t, cast(Object)p.stdin.output);
269                 rawCall(t, -3, 1);
270                 dup(t);
271                 setExtraVal(t, 0, Fields.stdin);
272             }
273
274             return 1;
275         }
276        
277         public uword stdout(MDThread* t, uword numParams)
278         {
279             auto p = getProcess(t);
280
281             getExtraVal(t, 0, Fields.stdout);
282            
283             if(isNull(t, -1))
284             {
285                 pop(t);
286                 lookupCT!("stream.InputStream")(t);
287                 pushNull(t);
288                 pushNativeObj(t, cast(Object)p.stdout.input);
289                 rawCall(t, -3, 1);
290                 dup(t);
291                 setExtraVal(t, 0, Fields.stdout);
292             }
293
294             return 1;
295         }
296        
297         public uword stderr(MDThread* t, uword numParams)
298         {
299             auto p = getProcess(t);
300
301             getExtraVal(t, 0, Fields.stderr);
302            
303             if(isNull(t, -1))
304             {
305                 pop(t);
306                 lookupCT!("stream.InputStream")(t);
307                 pushNull(t);
308                 pushNativeObj(t, cast(Object)p.stderr.input);
309                 rawCall(t, -3, 1);
310                 dup(t);
311                 setExtraVal(t, 0, Fields.stderr);
312             }
313
314             return 1;
315         }
316        
317         public uword wait(MDThread* t, uword numParams)
318         {
319             auto p = getProcess(t);
320            
321             getExtraVal(t, 0, Fields.stdin);
322            
323             if(!isNull(t, -1))
324             {
325                 pushNull(t);
326                 methodCall(t, -2, "flush", 0);
327             }
328             else
329                 pop(t);
330
331             auto res = safeCode(t, p.wait());
332
333             switch(res.reason)
334             {
335                 case Process.Result.Exit:     pushString(t, "exit"); break;
336                 case Process.Result.Signal:   pushString(t, "signal"); break;
337                 case Process.Result.Stop:     pushString(t, "stop"); break;
338                 case Process.Result.Continue: pushString(t, "continue"); break;
339                 case Process.Result.Error:    pushString(t, "error"); break;
340                 default: assert(false);
341             }
342
343             pushInt(t, res.status);
344             return 2;
345         }
346
347         public uword kill(MDThread* t, uword numParams)
348         {
349             auto p = getProcess(t);
350             safeCode(t, p.kill());
351             return 0;
352         }
353     }
354 }
Note: See TracBrowser for help on using the browser.