Support rastport clipping rectangle for layerless rastports
[tangerine.git] / rom / dos / systemtaglist.c
blob0bc7e5668f30a9dc6623b5f36f35cc2e507bbf0d
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #ifdef DEBUG
10 #undef DEBUG
11 #endif
12 # define DEBUG 1
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 /*****************************************************************************
28 NAME */
30 #include <proto/dos.h>
32 AROS_LH2(LONG, SystemTagList,
34 /* SYNOPSIS */
35 AROS_LHA(CONST_STRPTR , command, D1),
36 AROS_LHA(struct TagItem *, tags, D2),
38 /* LOCATION */
39 struct DosLibrary *, DOSBase, 101, Dos)
41 /* FUNCTION
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
51 NP_Seglist
52 NP_FreeSeglist
53 NP_Entry
54 NP_Input
55 NP_Error
56 NP_Output
57 NP_CloseInput
58 NP_CloseOutput
59 NP_CloseError
60 NP_HomeDir
61 NP_Cli
62 NP_Arguments
63 NP_Synchrounous
64 NP_UserData
67 INPUTS
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.
73 RESULT
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.
79 NOTES
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()
90 and Output().
92 EXAMPLE
94 BUGS
96 SEE ALSO
98 Execute(), CreateNewProc(), Input(), Output(), <dos/dostags.h>
100 INTERNALS
102 *****************************************************************************/
104 AROS_LIBFUNC_INIT
105 AROS_LIBBASE_EXT_DECL(struct DosLibrary *, DOSBase)
107 BPTR cis = Input(), cos = Output(), ces = Error(), script = NULL;
108 BPTR shellseg = NULL;
109 STRPTR cShell = NULL;
110 BOOL script_opened = FALSE;
111 BOOL cis_opened = FALSE;
112 BOOL cos_opened = FALSE;
113 BOOL ces_opened = FALSE;
114 BOOL isBoot = TRUE;
115 BOOL isBackground = TRUE;
116 BOOL isAsynch = FALSE;
117 LONG rc = -1;
118 LONG *cliNumPtr = NULL;
120 struct TagItem *newtags, *tags2 = tags, *tag;
122 while ((tag = NextTagItem(&tags2)))
124 switch (tag->ti_Tag)
126 case SYS_ScriptInput:
127 script = (BPTR)tag->ti_Data;
128 break;
130 case SYS_Input:
131 cis = (BPTR)tag->ti_Data;
132 break;
134 case SYS_Output:
135 cos = (BPTR)tag->ti_Data;
136 break;
138 case SYS_Error:
139 ces = (BPTR)tag->ti_Data;
140 break;
142 case SYS_CustomShell:
143 cShell = (STRPTR)tag->ti_Data;
144 break;
146 case SYS_UserShell:
147 isBoot = !tag->ti_Data;
148 break;
150 case SYS_Background:
151 isBackground = tag->ti_Data;
152 break;
154 case SYS_Asynch:
155 isAsynch = tag->ti_Data;
156 break;
158 case SYS_CliNumPtr:
159 cliNumPtr = (LONG *)tag->ti_Data;
160 break;
164 /* Set up the streams */
165 if (!cis)
167 cis = Open("NIL:", FMF_READ);
168 if (!cis) goto end;
170 cis_opened = TRUE;
172 else
173 if (cis == (BPTR)SYS_DupStream)
175 cis = DupFH(Input(), FMF_READ, DOSBase);
176 if (!cis) goto end;
178 cis_opened = TRUE;
181 if (!cos)
183 if (IsInteractive(cis))
184 cos = DupFH(cis, FMF_WRITE, DOSBase);
185 else
186 cos = Open("*", FMF_WRITE);
188 if (!cos) goto end;
190 cos_opened = TRUE;
192 else
193 if (cos == (BPTR)SYS_DupStream)
195 cos = DupFH(Output(), FMF_WRITE, DOSBase);
196 if (!cos) goto end;
198 cos_opened = TRUE;
201 if (!ces)
203 if (IsInteractive(cis))
204 ces = DupFH(cos, FMF_WRITE, DOSBase);
205 else
206 ces = Open("*", FMF_WRITE);
208 if (!ces) goto end;
210 ces_opened = TRUE;
212 else
213 if (ces == (BPTR)SYS_DupStream)
215 ces = DupFH(Output(), FMF_WRITE, DOSBase);
216 if (!ces) goto end;
218 ces_opened = TRUE;
221 /* Load the shell */
222 #warning implement UserShell and BootShell
223 shellseg = LoadSeg("C:Shell");
224 if (!shellseg)
225 goto end;
227 newtags = CloneTagItems(tags);
228 if (newtags)
230 struct CliStartupMessage csm;
231 struct Process *me = (struct Process *)FindTask(NULL);
232 struct Process *cliproc;
234 struct TagItem proctags[] =
236 { NP_Entry , (IPTR) NewCliProc }, /* 0 */
237 { NP_Priority , me->pr_Task.tc_Node.ln_Pri }, /* 1 */
238 { NP_StackSize , AROS_STACKSIZE }, /* 2 */
239 { NP_Name , isBoot ? (IPTR)"Boot Shell" :
240 isBackground ?
241 (IPTR)"Background CLI" :
242 (IPTR)"New Shell" }, /* 3 */
243 { NP_Input , (IPTR)cis }, /* 4 */
244 { NP_Output , (IPTR)cos }, /* 5 */
245 { NP_CloseInput , (isAsynch || cis_opened) }, /* 6 */
246 { NP_CloseOutput, (isAsynch || cos_opened) }, /* 7 */
247 { NP_Cli , (IPTR)TRUE }, /* 8 */
248 { NP_WindowPtr , isAsynch ? (IPTR)NULL :
249 (IPTR)me->pr_WindowPtr }, /* 9 */
250 { NP_Arguments , (IPTR)command }, /* 10 */
251 { NP_Synchronous, FALSE }, /* 11 */
252 { NP_Error , (IPTR)ces }, /* 12 */
253 { NP_CloseError , (isAsynch || ces_opened) &&
255 Since old AmigaOS programs don't know anything about Error()
256 being handled by this function, don't close the Error stream
257 if it's the same as the caller's one.
259 ces != Error() }, /* 13 */
260 { TAG_END , 0 } /* 14 */
263 Tag filterList[] =
265 NP_Seglist,
266 NP_FreeSeglist,
267 NP_Entry,
268 NP_Input,
269 NP_Output,
270 NP_CloseInput,
271 NP_CloseOutput,
272 NP_CloseError,
273 NP_HomeDir,
274 NP_Cli,
275 NULL
278 FilterTagItems(newtags, filterList, TAGFILTER_NOT);
280 proctags[sizeof(proctags)/(sizeof(proctags[0])) - 1].ti_Tag = TAG_MORE;
281 proctags[sizeof(proctags)/(sizeof(proctags[0])) - 1].ti_Data = (IPTR)newtags;
283 cliproc = CreateNewProc(proctags);
285 if (cliproc)
287 csm.csm_Msg.mn_Node.ln_Type = NT_MESSAGE;
288 csm.csm_Msg.mn_Length = sizeof(csm);
289 csm.csm_Msg.mn_ReplyPort = &me->pr_MsgPort;
291 csm.csm_CurrentInput = script;
292 csm.csm_ShellSeg = shellseg;
293 csm.csm_Background = isBackground;
294 csm.csm_Asynch = isAsynch;
296 PutMsg(&cliproc->pr_MsgPort, (struct Message *)&csm);
297 WaitPort(&me->pr_MsgPort);
298 GetMsg(&me->pr_MsgPort);
300 if (cliNumPtr) *cliNumPtr = csm.csm_CliNumber;
302 rc = csm.csm_ReturnCode;
304 script_opened =
305 cis_opened =
306 cos_opened =
307 ces_opened = FALSE;
309 shellseg = NULL;
311 FreeTagItems(newtags);
314 end:
315 UnLoadSeg(shellseg);
316 if (script_opened) Close(script);
317 if (cis_opened) Close(cis);
318 if (cos_opened) Close(cos);
319 if (ces_opened) Close(ces);
321 return rc;
323 AROS_LIBFUNC_EXIT
324 } /* SystemTagList */
326 static BPTR DupFH(BPTR fh, LONG mode, struct DosLibrary * DOSBase)
328 BPTR ret = NULL;
330 if (fh)
332 BPTR olddir = CurrentDir(fh);
333 ret = Open("", mode);
335 CurrentDir(olddir);
338 return ret;