Skip to content

Commit c052bd8

Browse files
JianyuWang0623xiaoxiang781216
authored andcommitted
nsh: Add pipeline support for nsh commandline
And nested pipeline supported. Test 1. Redirect in cat < /etc/init.d/rc.sysinit 2. Simple pipeline ls | cat 3. Nested pipeline ls | dd | cat | dd | cat Signed-off-by: wangjianyu3 <[email protected]>
1 parent 3da204c commit c052bd8

File tree

4 files changed

+186
-1
lines changed

4 files changed

+186
-1
lines changed

builtin/exec_builtin.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,19 @@ int exec_builtin(FAR const char *appname, FAR char * const *argv,
158158
goto errout_with_actions;
159159
}
160160
}
161+
#ifdef CONFIG_NSH_PIPELINE
162+
else if (param->fd_in != -1)
163+
{
164+
ret = posix_spawn_file_actions_adddup2(&file_actions,
165+
param->fd_in, 0);
166+
if (ret != 0)
167+
{
168+
serr("ERROR: posix_spawn_file_actions_adddup2 failed: %d\n",
169+
ret);
170+
goto errout_with_actions;
171+
}
172+
}
173+
#endif
161174

162175
/* Is output being redirected? */
163176

@@ -175,6 +188,19 @@ int exec_builtin(FAR const char *appname, FAR char * const *argv,
175188
goto errout_with_actions;
176189
}
177190
}
191+
#ifdef CONFIG_NSH_PIPELINE
192+
else if (param->fd_out != -1)
193+
{
194+
ret = posix_spawn_file_actions_adddup2(&file_actions,
195+
param->fd_out, 1);
196+
if (ret != 0)
197+
{
198+
serr("ERROR: posix_spawn_file_actions_adddup2 failed: %d\n",
199+
ret);
200+
goto errout_with_actions;
201+
}
202+
}
203+
#endif
178204
}
179205

180206
#ifdef CONFIG_LIBC_EXECFUNCS

nshlib/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,13 @@ config NSH_ALIAS_MAX_AMOUNT
231231

232232
endif # NSH_ALIAS
233233

234+
config NSH_PIPELINE
235+
bool "Enable pipeline support"
236+
default !DEFAULT_SMALL
237+
depends on PIPES
238+
---help---
239+
Enable pipeline support for nsh.
240+
234241
endmenu # Command Line Configuration
235242

236243
config NSH_BUILTIN_APPS

nshlib/nsh_fileapps.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,20 @@ int nsh_fileapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
126126
goto errout_with_actions;
127127
}
128128
}
129+
#ifdef CONFIG_NSH_PIPELINE
130+
else if (param->fd_in != -1)
131+
{
132+
ret = posix_spawn_file_actions_adddup2(&file_actions,
133+
param->fd_in, 0);
134+
if (ret != 0)
135+
{
136+
nsh_error(vtbl, g_fmtcmdfailed, cmd,
137+
"posix_spawn_file_actions_adddup2",
138+
NSH_ERRNO);
139+
goto errout_with_actions;
140+
}
141+
}
142+
#endif
129143

130144
/* Handle re-direction of output */
131145

@@ -147,6 +161,20 @@ int nsh_fileapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
147161
goto errout_with_attrs;
148162
}
149163
}
164+
#ifdef CONFIG_NSH_PIPELINE
165+
else if (param->fd_out != -1)
166+
{
167+
ret = posix_spawn_file_actions_adddup2(&file_actions,
168+
param->fd_out, 1);
169+
if (ret != 0)
170+
{
171+
nsh_error(vtbl, g_fmtcmdfailed, cmd,
172+
"posix_spawn_file_actions_adddup2",
173+
NSH_ERRNO);
174+
goto errout_with_actions;
175+
}
176+
}
177+
#endif
150178
}
151179

152180
#ifdef CONFIG_BUILTIN

nshlib/nsh_parse.c

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,9 @@ static const char g_arg_separator[] = "`$";
259259
static const char g_redirect_out1[] = ">";
260260
static const char g_redirect_out2[] = ">>";
261261
static const char g_redirect_in1[] = "<";
262+
#ifdef CONFIG_NSH_PIPELINE
263+
static const char g_pipeline1[] = "|";
264+
#endif
262265
#ifdef NSH_HAVE_VARS
263266
static const char g_exitstatus[] = "?";
264267
static const char g_lastpid[] = "!";
@@ -1601,6 +1604,16 @@ static FAR char *nsh_argument(FAR struct nsh_vtbl_s *vtbl,
16011604
argument = (FAR char *)g_redirect_in1;
16021605
}
16031606

1607+
#ifdef CONFIG_NSH_PIPELINE
1608+
/* Does the token begin with '|' -- pipeline? */
1609+
1610+
if (*pbegin == '|')
1611+
{
1612+
*saveptr = pbegin + 1;
1613+
argument = (FAR char *)g_pipeline1;
1614+
}
1615+
#endif
1616+
16041617
/* Does the token begin with '#' -- comment */
16051618

16061619
else if (*pbegin == '#')
@@ -2415,6 +2428,13 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
24152428
.file_out = NULL
24162429
};
24172430

2431+
#ifdef CONFIG_NSH_PIPELINE
2432+
int pipefd[2] =
2433+
{
2434+
-1, -1
2435+
};
2436+
#endif
2437+
24182438
NSH_MEMLIST_TYPE memlist;
24192439
NSH_ALIASLIST_TYPE alist;
24202440
FAR char *argv[MAX_ARGV_ENTRIES];
@@ -2424,9 +2444,15 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
24242444
int ret;
24252445
bool redirect_out_save = false;
24262446
bool redirect_in_save = false;
2447+
#ifdef CONFIG_NSH_PIPELINE
2448+
bool bg_save = false;
2449+
#endif
24272450
size_t redirect_out1_len = strlen(g_redirect_out1);
24282451
size_t redirect_out2_len = strlen(g_redirect_out2);
24292452
size_t redirect_in1_len = strlen(g_redirect_in1);
2453+
#ifdef CONFIG_NSH_PIPELINE
2454+
size_t pipeline1_len = strlen(g_pipeline1);
2455+
#endif
24302456

24312457
#ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP
24322458
char tracebuf[CONFIG_NSH_LINELEN + 1];
@@ -2647,6 +2673,89 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
26472673
param.oflags_in = O_RDONLY;
26482674
param.file_in = nsh_getfullpath(vtbl, arg);
26492675
}
2676+
#ifdef CONFIG_NSH_PIPELINE
2677+
else if (!strncmp(argv[argc], g_pipeline1, pipeline1_len))
2678+
{
2679+
FAR char *arg;
2680+
FAR char *sh_argv[4];
2681+
2682+
if (argv[argc][pipeline1_len])
2683+
{
2684+
arg = &argv[argc][pipeline1_len];
2685+
}
2686+
else
2687+
{
2688+
arg = nsh_argument(vtbl, &saveptr, &memlist, NULL, &isenvvar);
2689+
}
2690+
2691+
if (!arg)
2692+
{
2693+
nsh_error(vtbl, g_fmtarginvalid, cmd);
2694+
ret = ERROR;
2695+
goto dynlist_free;
2696+
}
2697+
2698+
for (ret = 0; ret < argc - 1; ret++)
2699+
{
2700+
FAR char *p_arg = argv[ret];
2701+
size_t len = strlen(p_arg);
2702+
2703+
/* Restore from split args to concat args. */
2704+
2705+
DEBUGASSERT(&p_arg[len + 1] == argv[ret + 1]);
2706+
p_arg[len] = ' ';
2707+
}
2708+
2709+
sh_argv[0] = "sh";
2710+
sh_argv[1] = "-c";
2711+
sh_argv[2] = argv[0];
2712+
sh_argv[3] = NULL;
2713+
2714+
ret = pipe2(pipefd, 0);
2715+
if (ret < 0)
2716+
{
2717+
ret = -errno;
2718+
goto dynlist_free;
2719+
}
2720+
2721+
redirect_out_save = vtbl->np.np_redir_out;
2722+
vtbl->np.np_redir_out = true;
2723+
param.fd_out = pipefd[1];
2724+
2725+
bg_save = vtbl->np.np_bg;
2726+
vtbl->np.np_bg = true;
2727+
2728+
ret = nsh_execute(vtbl, 4, sh_argv, &param);
2729+
2730+
vtbl->np.np_bg = bg_save;
2731+
2732+
if (param.fd_in != -1)
2733+
{
2734+
close(param.fd_in);
2735+
param.fd_in = -1;
2736+
vtbl->np.np_redir_in = redirect_in_save;
2737+
}
2738+
2739+
if (param.fd_out != -1)
2740+
{
2741+
close(param.fd_out);
2742+
param.fd_out = -1;
2743+
vtbl->np.np_redir_out = redirect_out_save;
2744+
}
2745+
2746+
redirect_in_save = vtbl->np.np_redir_in;
2747+
vtbl->np.np_redir_in = true;
2748+
param.fd_in = pipefd[0];
2749+
2750+
argv[0] = arg;
2751+
argc = 1;
2752+
2753+
if (ret == -1)
2754+
{
2755+
goto dynlist_free;
2756+
}
2757+
}
2758+
#endif
26502759
else
26512760
{
26522761
argc++;
@@ -2678,6 +2787,8 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
26782787

26792788
ret = nsh_execute(vtbl, argc, argv, &param);
26802789

2790+
dynlist_free:
2791+
26812792
/* Free any allocated resources */
26822793

26832794
/* Free the redirected output file path */
@@ -2687,6 +2798,13 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
26872798
nsh_freefullpath((char *)param.file_out);
26882799
vtbl->np.np_redir_out = redirect_out_save;
26892800
}
2801+
#ifdef CONFIG_NSH_PIPELINE
2802+
else if (param.fd_out != -1)
2803+
{
2804+
close(param.fd_out);
2805+
vtbl->np.np_redir_out = redirect_out_save;
2806+
}
2807+
#endif
26902808

26912809
/* Free the redirected input file path */
26922810

@@ -2695,8 +2813,14 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
26952813
nsh_freefullpath((char *)param.file_in);
26962814
vtbl->np.np_redir_in = redirect_in_save;
26972815
}
2816+
#ifdef CONFIG_NSH_PIPELINE
2817+
else if (param.fd_in != -1)
2818+
{
2819+
close(param.fd_in);
2820+
vtbl->np.np_redir_in = redirect_in_save;
2821+
}
2822+
#endif
26982823

2699-
dynlist_free:
27002824
NSH_ALIASLIST_FREE(vtbl, &alist);
27012825
NSH_MEMLIST_FREE(&memlist);
27022826
#ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP

0 commit comments

Comments
 (0)