2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
13 # include <aros/debug.h>
15 #include "dos_newcliproc.h"
16 #include "dos_intern.h"
17 #include <utility/tagitem.h>
18 #include <dos/dostags.h>
19 #include <proto/utility.h>
20 #include <dos/dosextens.h>
21 #include <aros/asmcall.h>
22 #include <exec/ports.h>
24 static BPTR
DupFH(BPTR fh
, LONG mode
, struct DosLibrary
* DOSBase
);
26 /*****************************************************************************
30 #include <proto/dos.h>
32 AROS_LH2(LONG
, SystemTagList
,
35 AROS_LHA(CONST_STRPTR
, command
, D1
),
36 AROS_LHA(struct TagItem
*, tags
, D2
),
39 struct DosLibrary
*, DOSBase
, 101, Dos
)
43 Execute a command via a shell. As defaults, the process will use the
44 current Input() and Output(), and the current directory as well as the
45 path will be inherited from your process. If no path is specified, this
46 path will be used to find the command.
47 Normally, the boot shell is used but other shells may be specified
48 via tags. The tags are passed through to CreateNewProc() except those
49 who conflict with SystemTagList(). Currently, these are
69 command -- program and arguments as a string
70 tags -- see <dos/dostags.h>. Note that both SystemTagList() tags and
71 tags for CreateNewProc() may be passed.
75 The return code of the command executed or -1 or if the command could
76 not run because the shell couldn't be created. If the command is not
77 found, the shell will return an error code, usually RETURN_ERROR.
81 You must close the input and output filehandles yourself (if needed)
82 after System() returns if they were specified via SYS_Input or
83 SYS_Output (also, see below).
84 You may NOT use the same filehandle for both SYS_Input and SYS_Output.
85 If you want them to be the same CON: window, set SYS_Input to a filehandle
86 on the CON: window and set SYS_Output to NULL. Then the shell will
87 automatically set the output by opening CONSOLE: on that handler.
88 If you specified SYS_Asynch, both the input and the output filehandles
89 will be closed when the command is finished (even if this was your Input()
98 Execute(), CreateNewProc(), Input(), Output(), <dos/dostags.h>
102 *****************************************************************************/
106 BPTR cis
= Input(), cos
= Output(), ces
= Error(), script
= NULL
;
107 BPTR shellseg
= NULL
;
108 STRPTR cShell
= NULL
;
109 BOOL script_opened
= FALSE
;
110 BOOL cis_opened
= FALSE
;
111 BOOL cos_opened
= FALSE
;
112 BOOL ces_opened
= FALSE
;
114 BOOL isBackground
= TRUE
;
115 BOOL isAsynch
= FALSE
;
117 LONG
*cliNumPtr
= NULL
;
119 struct TagItem
*newtags
, *tags2
= tags
, *tag
;
121 while ((tag
= NextTagItem(&tags2
)))
125 case SYS_ScriptInput
:
126 script
= (BPTR
)tag
->ti_Data
;
130 cis
= (BPTR
)tag
->ti_Data
;
134 cos
= (BPTR
)tag
->ti_Data
;
138 ces
= (BPTR
)tag
->ti_Data
;
141 case SYS_CustomShell
:
142 cShell
= (STRPTR
)tag
->ti_Data
;
146 isBoot
= !tag
->ti_Data
;
150 isBackground
= tag
->ti_Data
? TRUE
: FALSE
;
154 isAsynch
= tag
->ti_Data
? TRUE
: FALSE
;
158 cliNumPtr
= (LONG
*)tag
->ti_Data
;
163 /* Set up the streams */
166 cis
= Open("NIL:", FMF_READ
);
172 if (cis
== (BPTR
)SYS_DupStream
)
174 cis
= DupFH(Input(), FMF_READ
, DOSBase
);
182 if (IsInteractive(cis
))
183 cos
= DupFH(cis
, FMF_WRITE
, DOSBase
);
185 cos
= Open("*", FMF_WRITE
);
192 if (cos
== (BPTR
)SYS_DupStream
)
194 cos
= DupFH(Output(), FMF_WRITE
, DOSBase
);
202 if (IsInteractive(cis
))
203 ces
= DupFH(cos
, FMF_WRITE
, DOSBase
);
205 ces
= Open("*", FMF_WRITE
);
212 if (ces
== (BPTR
)SYS_DupStream
)
214 ces
= DupFH(Output(), FMF_WRITE
, DOSBase
);
221 #warning implement UserShell and BootShell
222 shellseg
= LoadSeg("C:Shell");
226 newtags
= CloneTagItems(tags
);
229 struct CliStartupMessage csm
;
230 struct Process
*me
= (struct Process
*)FindTask(NULL
);
231 struct Process
*cliproc
;
233 struct TagItem proctags
[] =
235 { NP_Entry
, (IPTR
) NewCliProc
}, /* 0 */
236 { NP_Priority
, me
->pr_Task
.tc_Node
.ln_Pri
}, /* 1 */
239 Disabled, because CreateNewProc() already handles NP_StackSize,
240 i.e. it uses either AROS_STACKSIZE or the stack from the parent
243 // { NP_StackSize , AROS_STACKSIZE },
244 { TAG_IGNORE
, 0 }, /* 2 */
245 { NP_Name
, isBoot
? (IPTR
)"Boot Shell" :
247 (IPTR
)"Background CLI" :
248 (IPTR
)"New Shell" }, /* 3 */
249 { NP_Input
, (IPTR
)cis
}, /* 4 */
250 { NP_Output
, (IPTR
)cos
}, /* 5 */
251 { NP_CloseInput
, (isAsynch
|| cis_opened
) }, /* 6 */
252 { NP_CloseOutput
, (isAsynch
|| cos_opened
) }, /* 7 */
253 { NP_Cli
, (IPTR
)TRUE
}, /* 8 */
254 { NP_WindowPtr
, isAsynch
? (IPTR
)NULL
:
255 (IPTR
)me
->pr_WindowPtr
}, /* 9 */
256 { NP_Arguments
, (IPTR
)command
}, /* 10 */
257 { NP_Synchronous
, FALSE
}, /* 11 */
258 { NP_Error
, (IPTR
)ces
}, /* 12 */
259 { NP_CloseError
, (isAsynch
|| ces_opened
) &&
261 Since old AmigaOS programs don't know anything about Error()
262 being handled by this function, don't close the Error stream
263 if it's the same as the caller's one.
265 ces
!= Error() }, /* 13 */
266 { TAG_END
, 0 } /* 14 */
284 FilterTagItems(newtags
, filterList
, TAGFILTER_NOT
);
286 proctags
[sizeof(proctags
)/(sizeof(proctags
[0])) - 1].ti_Tag
= TAG_MORE
;
287 proctags
[sizeof(proctags
)/(sizeof(proctags
[0])) - 1].ti_Data
= (IPTR
)newtags
;
289 cliproc
= CreateNewProc(proctags
);
293 csm
.csm_Msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
294 csm
.csm_Msg
.mn_Length
= sizeof(csm
);
295 csm
.csm_Msg
.mn_ReplyPort
= &me
->pr_MsgPort
;
297 csm
.csm_CurrentInput
= script
;
298 csm
.csm_ShellSeg
= shellseg
;
299 csm
.csm_Background
= isBackground
;
300 csm
.csm_Asynch
= isAsynch
;
302 PutMsg(&cliproc
->pr_MsgPort
, (struct Message
*)&csm
);
303 WaitPort(&me
->pr_MsgPort
);
304 GetMsg(&me
->pr_MsgPort
);
306 if (cliNumPtr
) *cliNumPtr
= csm
.csm_CliNumber
;
308 rc
= csm
.csm_ReturnCode
;
317 FreeTagItems(newtags
);
322 if (script_opened
) Close(script
);
323 if (cis_opened
) Close(cis
);
324 if (cos_opened
) Close(cos
);
325 if (ces_opened
) Close(ces
);
330 } /* SystemTagList */
332 static BPTR
DupFH(BPTR fh
, LONG mode
, struct DosLibrary
* DOSBase
)
338 BPTR olddir
= CurrentDir(fh
);
339 ret
= Open("", mode
);