famzah / popen-noshell

A much faster popen() and system() implementation for Linux
68 stars 13 forks source link

popen-noshell is not accepting " * " in the command. #6

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. create a folder/directory named /flash using popen_noshell_compat().
fp = popen_noshell_compat ("mkdir /flash", "r", &pCloseArg, 1);

2. Open a new file and copy into the folder created above using 
popen_noshell_compat().
fp = popen_noshell_compat ("cp test.txt /flash/", "r", &pCloseArg, 1);

3. Delete all contents of /flash folder using popen_noshell_compat().
fp = popen_noshell_compat ("rm -f /flash/*", "r", &pCloseArg, 1);

Although the return value of the step 3 is successful. None of the contents of 
the folder /flash is deleted. The intended result is to delete all the contents 
of /flash directory

What is the expected output? What do you see instead?
In above example all the contents of the /flash folder should have been deleted 
on this command. Instead none of the contents of /flash directory is deleted.

What version of the product are you using? On what operating system?
OS: Linux 2.6.35.6-45.fc14.i686
GCC: gcc version 4.5.1 20100924 (Red Hat 4.5.1-4) (GCC)
popen-noshell version: 1.0

Please provide any additional information below.
In above example "pCloseArg" is structure instance of "struct 
popen_noshell_pass_to_pclose".

Test program can be provided on request.

Original issue reported on code.google.com by kartikes...@gmail.com on 7 Jul 2014 at 11:46

GoogleCodeExporter commented 9 years ago
Hi,

This all is expected behavior and I'll try to explain it in detail.

You don't get any error because you are running "rm -f" which ignores 
nonexistent files. If you run the command "rm /flash/*" you'll get the 
following error:

  rm: cannot remove `/flash/*': No such file or directory

The usage of popen_noshell_compat() is highly discouraged. As the documentation 
says, it is simpler than popen_noshell() but is more INSECURE. Furthermore, the 
docs say:

  Since shells have very complicated expansion, quoting and word splitting algorithms, we do NOT try to re-implement them here.
  This function does NOT support any special characters. ...
  The "command" is split only by space and tab delimiters.

Therefore, if you try to execute
{{{
popen_noshell_compat("rm -f /flash/*", ...)
}}}

you are actually executing
{{{
popen_noshell("rm", {"-f", "/flash/*"}, ...)
}}}

Thus you are telling "rm" to use the option "-f" and *literally* delete the 
filename "/flash/*". Note that Linux file-systems allow you to have a filename 
named "*".

You are expecting that "/flash/*" expands to all files in the folder "/flash" 
but that's a Bash feature. It is the Bash interpreter which expands the "*" 
special character to all files in the current directory. And it is the 
(unneeded) Bash execution which we are trying to avoid with popen_noshell().

In a nutshell:
  * avoid using popen_noshell_compat() and instead always use popen_noshell()
  * if you need the Bash arguments expansion or other Bash features, you should call Bash from within popen_noshell() first

Here is an example which emulates the standard popen() behavior which calls 
Bash first. There is still a benefit to use popen_noshell() instead of the 
standard popen() because of the faster fork which popen_noshell() does.

{{{
/* the command arguments used by popen_noshell() */
char *exec_file = "/bin/bash";
char *arg1 = "-c";
char *arg2 = "rm -f /flash/*";
char *arg3 = (char *) NULL; /* last element */
char *argv[] = {exec_file, arg1, arg2, arg3}; /* NOTE! The first argv[] must be 
the executed *exec_file itself */

fp = popen_noshell(exec_file, (const char * const *)argv, "r", &pclose_arg, 0);
}}}

Original comment by ivan.zah...@gmail.com on 11 Jul 2014 at 7:22

GoogleCodeExporter commented 9 years ago

Original comment by ivan.zah...@gmail.com on 11 Jul 2014 at 7:26