2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Document the CLI startup packet
12 #include <aros/debug.h>
13 #include <proto/exec.h>
14 #include <proto/dos.h>
16 /* Return codes from CliInitRun() and CliInitNewcli()
19 #define FNF_VALIDFLAGS (1 << 31) /* Valid flags */
20 #define FNF_ASYNCSYSTEM (1 << 3) /* Async System() call */
21 #define FNF_SYSTEM (1 << 2) /* If this a System() call */
22 #define FNF_USERINPUT (1 << 1) /* User provided input stream */
23 #define FNF_RUNOUTPUT (1 << 0) /* C:Run provided output stream */
25 /* Shell startup packets.
27 * In truth, only dp_Res1 and dp_Res2 are 'public' - the rest of
28 * the arguments here are private, and are decoded by the
29 * DOS/CliInitRun() and DOS/CliInitNewcli() routines.
31 * NewCli/NewShell: (Asynchonous)
36 * dp_Arg1 = BPTR Lock of directory (shell must close)
37 * dp_Arg2 = BPTR to StandardInput
38 * dp_Arg3 = BPTR to StandardOuput
39 * dp_Arg4 = BPTR to CurrentInput
41 * dp_Arg5..dp_Arg7 are unused, and have junk data
43 * Boot CLI: (synchronous - this is AROS private - AOS uses a NULL Dos Packet pointer)
44 * dp_Type = -4 // AROS private
47 * dp_Arg1 = BPTR to Lock of directory (shell must close)
48 * dp_Arg2 = BPTR to StandardInput
49 * dp_Arg3 = BPTR to StandardOuput (can be BNULL if dp_Arg2 is Interactive)
50 * dp_Arg4 = BPTR to CurrentInput (is BNULL if there is no startup-sequence)
52 * dp_Arg5..dp_Arg7 are unused, and have junk data
55 * NOTE: KS 1.3: bfunc is a BCPL CliInit*() function,
60 * dp_Arg1 = BPTR to the old CommandLineInterface
61 * dp_Arg2 = BPTR to StandardInput
62 * dp_Arg3 = BPTR to StandardOuput
63 * dp_Arg4 = BPTR to CurrentInput
64 * dp_Arg5 = BPTR to Lock of directory (shell must close)
65 * dp_Arg6 = 0 (use CurrentInput/Open("*", MODE_NEWFILE) as Stdin/Stdout,
68 * dp_Arg7 is unused, and has junk data
70 * System (SYS_Async == FALSE)
74 * dp_Arg1 = BPTR to the old CommandLineInterface
75 * dp_Arg2 = BPTR to StandardInput
76 * dp_Arg3 = BPTR to StandardOuput
77 * dp_Arg4 = BPTR to CurrentInput
78 * dp_Arg5 = BPTR to Lock of directory (shell must close)
79 * dp_Arg6 = 0 to use CurrentInput/Open("*", MODE_NEWFILE) as Stdin/Stdout
81 * 1 to use StandardInput/StandardOutput,
82 * Do not Close() on exit
84 * dp_Arg7 is unused, and has junk data
86 * System (SYS_Asynch == TRUE):
90 * dp_Arg1 = BPTR to the old CommandLineInterface
91 * dp_Arg2 = BPTR to StandardInput
92 * dp_Arg3 = BPTR to StandardOuput
93 * dp_Arg4 = BPTR to CurrentInput
94 * dp_Arg5 = BPTR to Lock of directory (shell must close)
95 * dp_Arg6 = 0 to use CurrentInput/Open("*", MODE_NEWFILE) as Stdin/Stdout
97 * 1 to use StandardInput/StandardOutput,
98 * Do not Close() on exit
102 #define CLI_INVALID 0 /* Not a valid CLI type */
104 #define CLI_SYSTEM -2
105 #define CLI_ASYSTEM -3
106 #define CLI_BOOT -4 /* This is AROS specific. Not in AOS */
108 #include <proto/dos.h>
109 #include <proto/exec.h>
111 /* The following routine handles all the bureaucracy
112 * of creating a Shell suitable for placing in L:,
113 * including startup packet processing and replies,
114 * and pr_CLI initialization and cleanup.
116 * Your 'main' function will have a valid Cli()
117 * on entry. The following variables will
118 * be available to your 'main' routine:
120 * ULONG AROS_CLI_Flags; // As per the DOS/CliInitNewcli and
121 * // DOS/CliInitRun() Autodocs
122 * LONG AROS_CLI_Type; // One of the CLI_* types defined above
124 * Input() and Output() will be NULL
126 * Use the filehandles in Cli() for managing your
127 * input, output, and error streams.
129 * See Amiga Mail II-65: "Writing a UserShell" for details.
131 #define AROS_CLI(main) \
132 AROS_PROCH(main, argptr, argsize, SysBase) \
136 struct DosPacket *dp = (struct DosPacket *)argptr; \
137 extern SIPTR _shell_##main(ULONG flags, LONG type, struct ExecBase *SysBase D(, struct DosPacket *dp)); \
138 struct Process *me = (struct Process *)FindTask(NULL); \
139 D(struct DosPacket olddp;)\
143 struct CommandLineInterface *cli; \
149 WaitPort(&me->pr_MsgPort); \
150 dp = (APTR)(GetMsg(&me->pr_MsgPort)->mn_Node.ln_Name); \
152 DOSBase = OpenLibrary("dos.library", 36); \
153 if (DOSBase == NULL || dp->dp_Res2 != 0) { \
154 PutMsg(dp->dp_Port, dp->dp_Link); \
155 return RETURN_FAIL; \
157 D(CopyMem(dp, &olddp, sizeof(olddp));) \
158 flags = dp->dp_Res1 ? CliInitNewcli(dp) : CliInitRun(dp); \
159 if (flags & FNF_VALIDFLAGS) { \
160 if ((flags & FNF_SYSTEM) && (flags & FNF_ASYNCSYSTEM)) { \
161 PutMsg(dp->dp_Port, dp->dp_Link); \
164 /* CliInit*() already returned the packet for me */ \
165 if (IoErr() == (SIPTR)me) { \
166 return RETURN_ERROR; \
169 type = dp->dp_Type; \
170 me->pr_HomeDir = BNULL; \
171 segArray = BADDR(me->pr_SegList); \
172 segArray[4] = segArray[3]; \
173 segArray[3] = BNULL; \
174 segArray[0] = (BPTR)3; \
175 ret = _shell_##main(flags, type, SysBase D(, &olddp)); \
177 if (flags & FNF_VALIDFLAGS) { \
178 D(bug("AROS_CLI: System Exit\n")); \
179 if (!(flags & FNF_USERINPUT)) { \
180 D(bug("AROS_CLI: Close StandardInput\n")); \
181 Close(cli->cli_StandardInput); \
182 cli->cli_StandardInput = BNULL; \
184 if ((flags & FNF_RUNOUTPUT)) { \
185 D(bug("AROS_CLI: Close StandardOutput\n")); \
186 Flush(cli->cli_StandardOutput); \
187 Close(cli->cli_StandardOutput); \
188 cli->cli_StandardOutput = BNULL; \
190 if (!((flags & FNF_SYSTEM) && (flags & FNF_ASYNCSYSTEM))) { \
191 dp->dp_Res1 = cli->cli_ReturnCode; \
192 dp->dp_Res2 = cli->cli_Result2; \
193 D(bug("AROS_CLI: Reply with %d, %d\n", dp->dp_Res1, dp->dp_Res2)); \
194 PutMsg(dp->dp_Port, dp->dp_Link); \
197 D(bug("AROS_CLI: Shell Exit\n")); \
198 if (cli->cli_StandardInput != BNULL) { \
199 Close(cli->cli_StandardInput); \
200 cli->cli_StandardInput = BNULL; \
202 if (cli->cli_StandardOutput != BNULL) { \
203 /* A little bit of magic here. */ \
204 /* If this was interactive, we don't want to Flush() */ \
205 /* the StandardOutput stream. */ \
206 if (IsInteractive(cli->cli_StandardOutput)) { \
207 struct FileHandle *fh = ((struct FileHandle *)BADDR(cli->cli_StandardOutput)); \
208 fh->fh_Flags &= ~0x80000000; \
210 Close(cli->cli_StandardOutput); \
211 cli->cli_StandardOutput = BNULL; \
214 dir = CurrentDir(BNULL); \
215 if (dir) UnLock(dir); \
216 segArray[3] = segArray[4]; \
217 segArray[4] = BNULL; \
218 CloseLibrary(DOSBase); \
224 SIPTR _shell_##main(ULONG AROS_CLI_Flags, LONG AROS_CLI_Type, struct ExecBase *SysBase D(, struct DosPacket *AROS_CLI_DosPacket))
226 #endif /* DOS_CLIINIT_H */