Add new strings.
[AROS.git] / rom / dos / systemtaglist.c
blob13c959bbea465224ce259ad7e3652c610e2ef63f
1 /*
2 Copyright © 1995-2007, 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
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;
113 BOOL isBoot = TRUE;
114 BOOL isBackground = TRUE;
115 BOOL isAsynch = FALSE;
116 LONG rc = -1;
117 LONG *cliNumPtr = NULL;
119 const struct TagItem *tags2 = tags;
120 struct TagItem *newtags, *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 ? TRUE : FALSE;
152 break;
154 case SYS_Asynch:
155 isAsynch = tag->ti_Data ? TRUE : FALSE;
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)
226 D(bug("Could not load C:Shell\n"));
227 goto end;
230 newtags = CloneTagItems(tags);
231 if (newtags)
233 struct CliStartupMessage csm;
234 struct Process *me = (struct Process *)FindTask(NULL);
235 struct Process *cliproc;
237 struct TagItem proctags[] =
239 { NP_Entry , (IPTR) NewCliProc }, /* 0 */
240 { NP_Priority , me->pr_Task.tc_Node.ln_Pri }, /* 1 */
243 Disabled, because CreateNewProc() already handles NP_StackSize,
244 i.e. it uses either AROS_STACKSIZE or the stack from the parent
245 process.
247 // { NP_StackSize , AROS_STACKSIZE },
248 { TAG_IGNORE , 0 }, /* 2 */
249 { NP_Name , isBoot ? (IPTR)"Boot Shell" :
250 isBackground ?
251 (IPTR)"Background CLI" :
252 (IPTR)"New Shell" }, /* 3 */
253 { NP_Input , (IPTR)cis }, /* 4 */
254 { NP_Output , (IPTR)cos }, /* 5 */
255 { NP_CloseInput , (isAsynch || cis_opened) }, /* 6 */
256 { NP_CloseOutput, (isAsynch || cos_opened) }, /* 7 */
257 { NP_Cli , (IPTR)TRUE }, /* 8 */
258 { NP_WindowPtr , isAsynch ? (IPTR)NULL :
259 (IPTR)me->pr_WindowPtr }, /* 9 */
260 { NP_Arguments , (IPTR)command }, /* 10 */
261 { NP_Synchronous, FALSE }, /* 11 */
262 { NP_Error , (IPTR)ces }, /* 12 */
263 { NP_CloseError , (isAsynch || ces_opened) &&
265 Since old AmigaOS programs don't know anything about Error()
266 being handled by this function, don't close the Error stream
267 if it's the same as the caller's one.
269 ces != Error() }, /* 13 */
270 { TAG_END , 0 } /* 14 */
273 Tag filterList[] =
275 NP_Seglist,
276 NP_FreeSeglist,
277 NP_Entry,
278 NP_Input,
279 NP_Output,
280 NP_CloseInput,
281 NP_CloseOutput,
282 NP_CloseError,
283 NP_HomeDir,
284 NP_Cli,
288 FilterTagItems(newtags, filterList, TAGFILTER_NOT);
290 proctags[sizeof(proctags)/(sizeof(proctags[0])) - 1].ti_Tag = TAG_MORE;
291 proctags[sizeof(proctags)/(sizeof(proctags[0])) - 1].ti_Data = (IPTR)newtags;
293 cliproc = CreateNewProc(proctags);
295 if (cliproc)
297 csm.csm_Msg.mn_Node.ln_Type = NT_MESSAGE;
298 csm.csm_Msg.mn_Length = sizeof(csm);
299 csm.csm_Msg.mn_ReplyPort = &me->pr_MsgPort;
301 csm.csm_CurrentInput = script;
302 csm.csm_ShellSeg = shellseg;
303 csm.csm_Background = isBackground;
304 csm.csm_Asynch = isAsynch;
306 PutMsg(&cliproc->pr_MsgPort, (struct Message *)&csm);
307 WaitPort(&me->pr_MsgPort);
308 GetMsg(&me->pr_MsgPort);
310 if (cliNumPtr) *cliNumPtr = csm.csm_CliNumber;
312 rc = csm.csm_ReturnCode;
314 script_opened =
315 cis_opened =
316 cos_opened =
317 ces_opened = FALSE;
319 shellseg = NULL;
321 FreeTagItems(newtags);
324 end:
325 UnLoadSeg(shellseg);
326 if (script_opened) Close(script);
327 if (cis_opened) Close(cis);
328 if (cos_opened) Close(cos);
329 if (ces_opened) Close(ces);
331 return rc;
333 AROS_LIBFUNC_EXIT
334 } /* SystemTagList */
336 static BPTR DupFH(BPTR fh, LONG mode, struct DosLibrary * DOSBase)
338 BPTR ret = NULL;
340 if (fh)
342 BPTR olddir = CurrentDir(fh);
343 ret = Open("", mode);
345 CurrentDir(olddir);
348 return ret;