@@ -259,6 +259,9 @@ static const char g_arg_separator[] = "`$";
259259static const char g_redirect_out1 [] = ">" ;
260260static const char g_redirect_out2 [] = ">>" ;
261261static const char g_redirect_in1 [] = "<" ;
262+ #ifdef CONFIG_NSH_PIPELINE
263+ static const char g_pipeline1 [] = "|" ;
264+ #endif
262265#ifdef NSH_HAVE_VARS
263266static const char g_exitstatus [] = "?" ;
264267static 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