5353#ifndef _A_DEVICE
5454#define _A_DEVICE 0x40u
5555#endif
56+ #ifndef FA_DEVICE
57+ #define FA_DEVICE 0x40u
58+ #endif
5659#include <libc/dosio.h>
5760#include <pc.h>
5861#include <io.h>
@@ -361,6 +364,42 @@ static void conv_unix_path_to_ms_dos(char *path)
361364 }
362365 }
363366
367+ /* check for form "NUL:"
368+ * returns:
369+ * -1 for invalid name (maybe has colon suffix, but doesn't resolve to a device)
370+ * 0 for a name without colon
371+ * 1 for is a device name with colon at position (*colon) */
372+ static int is_device_with_colon (const char * name , int * colon )
373+ {
374+ int ret = -1 ;
375+ int len ;
376+ char * s , * pcolon ;
377+ finddata_t ff ;
378+
379+ pcolon = strchr (name , ':' );
380+ if (!pcolon ) // Plain device name or file
381+ return 0 ;
382+
383+ len = strlen (name );
384+ if (& name [len - 1 ] != pcolon ) // More than one colon, or it's not the last character
385+ return -1 ;
386+
387+ if (len < 3 ) // Single ':' or probable drive '?:'
388+ return -1 ;
389+
390+ s = strndup (name , len - 1 );
391+ if (!s )
392+ return -1 ;
393+
394+ if (findfirst_f (s , & ff , FA_DEVICE , NULL ) == 0 && ff .ff_attrib == _A_DEVICE ) {
395+ * colon = len - 1 ;
396+ ret = 1 ;
397+ }
398+
399+ free (s );
400+ return ret ;
401+ }
402+
364403static int is_drive_spec (char * s ) // check for form "A:"
365404 {
366405 if (!isalpha (s [0 ]))
@@ -4568,13 +4607,31 @@ static void exec_cmd(int call)
45684607 }
45694608 else // open the pipe file
45704609 {
4571- if (pipe_file_redir_count [STDIN_INDEX ] > 0 )
4610+ int colon , rc ;
4611+
4612+ if (pipe_file_redir_count [STDIN_INDEX ] > 0 ) {
4613+ rc = is_device_with_colon (pipe_file [STDIN_INDEX ], & colon );
4614+ if (rc == -1 ) {
4615+ cprintf ("Invalid standard input device name '%s'\r\n" , pipe_file [STDIN_INDEX ]);
4616+ goto Exit ;
4617+ } else if (rc == 1 ) {
4618+ pipe_file [STDIN_INDEX ][colon ] = '\0' ;
4619+ }
45724620 pipe_fno [STDIN_INDEX ] = open (pipe_file [STDIN_INDEX ], O_TEXT |O_RDONLY , S_IRUSR );
4621+ }
45734622
4574- if (pipe_file_redir_count [STDOUT_INDEX ] > 1 )
4575- pipe_fno [STDOUT_INDEX ] = open (pipe_file [STDOUT_INDEX ], O_BINARY |O_WRONLY |O_APPEND |O_CREAT , S_IRUSR | S_IWUSR ); // open for append
4576- else if (pipe_file_redir_count [STDOUT_INDEX ] == 1 )
4577- pipe_fno [STDOUT_INDEX ] = open (pipe_file [STDOUT_INDEX ], O_BINARY |O_WRONLY |O_TRUNC |O_CREAT , S_IRUSR | S_IWUSR ); // open as new file
4623+ if (pipe_file_redir_count [STDOUT_INDEX ] > 0 ) {
4624+ rc = is_device_with_colon (pipe_file [STDOUT_INDEX ], & colon );
4625+ if (rc == -1 ) {
4626+ cprintf ("Invalid standard output device name '%s'\r\n" , pipe_file [STDOUT_INDEX ]);
4627+ goto Exit ;
4628+ } else if (rc == 1 ) {
4629+ pipe_file [STDOUT_INDEX ][colon ] = '\0' ;
4630+ }
4631+ if (pipe_file_redir_count [STDOUT_INDEX ] == 1 )
4632+ pipe_fno [STDOUT_INDEX ] = open (pipe_file [STDOUT_INDEX ], O_BINARY |O_WRONLY |O_TRUNC |O_CREAT , S_IRUSR | S_IWUSR ); // open as new file
4633+ else
4634+ pipe_fno [STDOUT_INDEX ] = open (pipe_file [STDOUT_INDEX ], O_BINARY |O_WRONLY |O_APPEND |O_CREAT , S_IRUSR | S_IWUSR ); // open for append
45784635
45794636 /* check for error
45804637 if (pipe_fno[pipe_index] < 0 ||
@@ -4589,6 +4646,7 @@ static void exec_cmd(int call)
45894646 goto Exit;
45904647 } */
45914648 }
4649+ }
45924650
45934651 for (pipe_index = 0 ; pipe_index < 2 ; pipe_index ++ )
45944652 {
@@ -4666,7 +4724,7 @@ static void exec_cmd(int call)
46664724 exec_cmd (true);
46674725 }
46684726
4669- /* Exit: */
4727+ Exit :
46704728 cmd_line [0 ] = '\0' ;
46714729 if (redir_result [STDIN_INDEX ] != -1 ) {
46724730 dup2 (old_std_fno [STDIN_INDEX ], STDIN_INDEX );
0 commit comments