use m4_normalize on the output strings to remove trailing spaces/tabs and consolidate...
[AROS.git] / workbench / c / shellcommands / Pipe.c
blob474116ad90d7aa1de5ee82a00ffd71fcf297931a
1 /*
2 * Copyright (C) 2012, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
6 */
7 /******************************************************************************
9 NAME
11 Pipe <command>
13 SYNOPSIS
15 COMMAND/F
17 LOCATION
21 FUNCTION
23 Uses the _pchar and _mchar environment variables to split
24 the COMMAND into fragments.
26 Where _pchar is seen, the commands on either side are connected
27 with a PIPE: from the left side's Output() to the right side's Input().
29 Where _mchar is seen, the commands are executed in sequence, with
30 no PIPE: between them, and Input() and Output() comes from the
31 terminal.
33 INPUTS
35 COMMAND -- the command to execute
37 RESULT
39 NOTES
41 The "_pchar" and "_mchar" environment variables are used to determine
42 where to split the command, and what action to perform.
44 EXAMPLE
46 > set _pchar "|"
47 > set _mchar ";"
48 > echo Hello ; echo World
49 Hello
50 World
51 > Type S:Startup-Sequence | Sort
53 BUGS
55 Note that _pchar and _mchar are limited to 2 characters - any
56 additional characters will be silently ignored.
58 SEE ALSO
60 INTERNALS
62 HISTORY
64 ******************************************************************************/
66 #define DEBUG 0
68 #include <aros/debug.h>
69 #include <exec/execbase.h>
70 #include <exec/libraries.h>
71 #include <proto/exec.h>
72 #include <dos/dos.h>
73 #include <proto/dos.h>
74 #include <string.h>
75 #include <aros/shcommands.h>
77 static inline STRPTR NextToken(STRPTR *pstr, CONST_STRPTR tok)
79 STRPTR str, ostr = *pstr;
80 int toklen = strlen(tok);
82 if (*ostr == 0)
83 return NULL;
85 for (str = ostr; *str; str++) {
86 if (strncmp(str, tok, toklen) == 0) {
87 *str = 0;
88 str += strlen(tok);
89 *pstr = str;
90 return ostr;
94 /* Token not found? */
95 *pstr = ostr + strlen(ostr);
96 return ostr;
99 static BOOL Pipe(struct Library *DOSBase, BPTR pipe[2])
101 pipe[1]=Open("PIPE:*", MODE_NEWFILE);
102 if (pipe[1]) {
103 TEXT buff[64];
104 if (NameFromFH(pipe[1], buff, sizeof(buff)) != 0) {
105 pipe[0] = Open(buff, MODE_OLDFILE);
106 if (pipe[0])
107 return TRUE;
109 Close(pipe[1]);
111 return FALSE;
114 static LONG pcharExecute(struct Library *DOSBase, STRPTR cmd, CONST_STRPTR pchar, BPTR in, BPTR out)
116 STRPTR leftcmd, rightcmd;
117 BPTR pipe[2];
118 TEXT buff[64];
119 LONG ret = RETURN_FAIL;
121 leftcmd = NextToken(&cmd, pchar);
122 if (!leftcmd)
123 return RETURN_OK;
125 rightcmd = cmd;
126 if (*rightcmd == 0) {
127 /* No pipe character? */
128 return SystemTags(leftcmd, SYS_Input, in, SYS_Output, out, TAG_END);
131 if (Pipe(DOSBase, pipe)) {
132 BPTR cis = OpenFromLock(DupLockFromFH(in));
134 struct TagItem tags[] = {
135 { SYS_Input, (IPTR)cis },
136 { SYS_Output, (IPTR)pipe[1] },
137 { SYS_Asynch, TRUE },
138 { TAG_DONE, 0 }
141 if (SystemTagList(leftcmd, tags) == -1) {
142 PrintFault(IoErr(), leftcmd);
143 Close(cis);
144 Close(pipe[0]);
145 Close(pipe[1]);
146 return RETURN_FAIL;
149 ret = pcharExecute(DOSBase, rightcmd, pchar, pipe[0], out);
150 /* Flush pipe */
151 while (FGets(pipe[0], buff, sizeof buff) != NULL);
152 Close(pipe[0]);
155 return ret;
159 AROS_SH1(Pipe, 41.1,
160 AROS_SHA(STRPTR, , , /F, ""))
162 AROS_SHCOMMAND_INIT
163 CONST_STRPTR cmd = SHArg( );
164 struct CommandLineInterface *cli = Cli();
166 TEXT pchar[3], mchar[3];
167 LONG len, ret = RETURN_FAIL;
168 STRPTR tcmd, subcmd, cp;
170 len = GetVar("_pchar", pchar, sizeof pchar, GVF_LOCAL_ONLY | LV_VAR);
171 if (len <= 0)
172 pchar[0] = 0;
173 pchar[2] = 0;
175 len = GetVar("_mchar", mchar, sizeof mchar, GVF_LOCAL_ONLY | LV_VAR);
176 if (len <= 0)
177 mchar[0] = 0;
178 mchar[2] = 0;
180 /* Tokenize by mchar, if needed */
181 len = strlen(cmd) + 1;
182 if ((tcmd = AllocVec(len, MEMF_ANY))) {
183 CopyMem(cmd, tcmd, len);
184 cp = tcmd;
186 for (subcmd = NextToken(&cp, mchar); subcmd; subcmd = NextToken(&cp, mchar)) {
187 ret = pcharExecute((struct Library *)DOSBase, subcmd, pchar, Input(), Output());
188 if (ret >= cli->cli_FailLevel)
189 break;
192 FreeVec(tcmd);
195 return ret;
196 AROS_SHCOMMAND_EXIT