popen and system behaves unexpectedly with multiple quoted file paths - c++

I am trying to execute a dos command from within my C++ program, however soon as I add quotes to the output filepath (of a redirection) the command no longer gets executed and returns instantly. I've shown an example below of a path without spaces, but since paths may have spaces and thus be quoted for the shell to understand it properly I need to solve this dilemma - and I'm trying to get the simplest case working first.
i.e.
The following WORKS:
sprintf(exec_cmd,"\"C:/MySQL Server 5.5/bin/mysqldump.exe\" -u%s -p%s %s > C:/backup.bak",user,password,db_name);
system(exec_cmd);
The following does NOT work (notice the quotes around the output):
sprintf(exec_cmd,"\"C:/MySQL Server 5.5/bin/mysqldump.exe\" -u%s -p%s %s > \"C:/backup.bak\"",user,password,db_name);
system(exec_cmd);
I'm guessing it is choking somewhere. I've tried the same "exec_cmd" in popen to no avail.
Any help/advice is greatly appreciated.

I don't think your shell (cmd.exe) allows redirection to a file name with spaces. I couldn't make my command.com from DOS 6.22 accept it (I don't have a cmd.exe nearby to test).
Anyway, you can use the --result-file option to pass the redirection to the command itself.
mysqldump ... --result-file="file name" ...

Related

How can I find why system can not run my application?

I have a c++ program that run a command and pass some arguments to it. The code is as follow:
int RunApplication(fs::path applicationPathName,std::string arguments)
{
std::string applicationShortPath=GetShortFileName(applicationPathName);
std::string cmd="\""+applicationShortPath +"\" "+ arguments+" >>log.txt 2>&1 \"";
std::cout<<cmd<<std::endl;
int result=std::system(cmd.c_str());
return result;
}
When I run system command, the cmd window appears shortly and then closes, but the result is 1 and the cmd was not run (the command should generate output which is not generated).
To check that the cmd is correct, I stopped the application just before system line and copy/ paste cmd content to a cmd window and it worked.
I am wondering how can I find why application is not run in system()?
the cmd has this value just before running it:
"D:/DEVELO~3/x64/Debug/enfuse.exe" -w --hard-mask --exposure-weight=1 --saturation-weight=0.328 --contrast-weight=0.164 -o "C:/Users/m/AppData/Local/Temp/1.tif" "C:/Users/m/AppData/Local/Temp/1.jpg" "C:/Users/m/AppData/Local/Temp/2.jpg" >>log.txt 2>&1 "
How can I find why it is not working?
Is there any way that I set the system so it doesn't close cmd window so I can inspect it?
is there any better way to run a command on OS?
Does Boost has any solution for this?
Edit
After running it with cmd /k, I get this error message:
The input line is too long.
How can I fix it other than reducing cmd line?
There are two different things here: if you have to start a suprocess, "system" is not the best way of doing it (better to use the proper API, like CreateProcess, or a multiplatform wrapper, but avoid to go through the command interpreter, to avoid to open to potential malware injection).
But in this case system() is probably the right way to go since you in fact need the command interpreter (you cannot manage things like >>log.txt 2>&1 with only a process creation.)
The problem looks like a failure in the called program: may be the path is not correct or some of the files it has to work with are not existent or accessible with appropriate-permission and so on.
One of the firt thing to do: open a command prompt and paste the string you posted, in there. Does it run? Does it say something about any error?
Another thing to check is how escape sequence are used in C++ literals: to get a '\', you need '\\' since the first is the escape for the second (like \n, or \t etc.). Although it seems not the case, here, it is one of the most common mistakes.
Use cmd /k to keep the terminal: http://ss64.com/nt/cmd.html
Or just spawn cmd.exe instead and inspect the environment, permissions, etc. You can manually paste that command to see whether it would work from that shell. If it does, you know that paths, permssions and environment are ok, so you have some other issue on your hands (argument escaping, character encoding issues)
Check here How to execute a command and get output of command within C++ using POSIX?
Boost.Process is not official yet http://www.highscore.de/boost/process/

How to use SublimeLinter's cmd attribute

I'm writing a SublimeLinter (a SublimeText plugin) plugin that uses luacheck for a custom syntax we use. So far I have it working with simply cmd = 'luacheck #', the # being apparently replaced by the filename when SublimeLinter calls luacheck. The problem is that with SublimeLinter on 'background' mode, the warnings don't actually update until the file is saved, e.g. if I remove a line containing a warning the warning will still be there, just highlighting a blank space (until I save, that is). I have a feeling that this is because I'm using the # and since this is replaced by the filename, luacheck won't update till the file is updated. However, the SublimeLinter documentation on cmd is not great, and I'm having trouble figuring out how to write one correctly. None of the plugins on their GitHub seem to use #, either. If I copy the default lua plugin (which uses cmd = 'luac -p * -') and use cmd = 'luacheck * -', luacheck executes but only returns an I/O error. Could someone maybe provide some more insight into how SublimeLinter's cmd attribute works?
EDIT: I was able to fix this issue by using tempfile_suffix = 'lua' in linter.py. According to the SublimeLinter docs, this is used for linters that don't use stdin, so I suppose my issue could have been with luacheck instead.
I was able to fix this issue by using tempfile_suffix = 'lua' in linter.py. According to the SublimeLinter docs, this is used for linters that don't use stdin, so I suppose my issue could have been with luacheck instead.

Calls to system() do not behave the same way as in command prompt (cmd)

I need to cut&paste a folder into another folder through code in C++. But some directory names are problematic, such as the ones which have japanese symbols. However, the same commands introduced through cmd all work fine.
system("move dirName dirName2"); //work
system("move ディレクトリ dirName2"); //does not work (system cannot find the specified file)
system("move ディレクトリ.txt dirName2"); //work
Funny enough, if the item which has the japanese symbols is a file and not a folder, the operation works fine even using calls to system().
I have no idea why the second call to system() does not work or how to solve it.
PS: I'm working with Windows7.
"move dirName dirName2", it is a const char* type, while the Japanese chars are not ASII chars, you should use the unicode API here, try:
_wsystem(L"move ディレクトリ dirName2")
It is likely that you need to use _wsystem instead to accomodate the wide characters. See the relevant MSDN pagefor details, but the syntax of the call is the same.

Wmic /format switch invalid XSL?

I have a quick question, should be relatively simple for those who have some more experience in WMI-command processor than I do (and since I'm an absolute beginner thats not hard :-) )
I fail to understand why wmic /format switch works the way it does. I open up cmd.exe and type
wmic process list brief /format:htable > processlist.html
this does exactly what I want and no bothers further on. Whereas if I go to wmic processor, and try to execute the same command exactly as above...
wmic:root\cli>process list brief /format:htable > processlist.html
I receive the error tag: "Invalid XSL format (or) file name."
Here goes the screenshot. Note I have already copied XSL files from wbem to sys32 dir
Can someone explain to me why these 2 commands that for me look exactly the same, with the only difference that one is executed outside wmic environment and the other one is from inside, the latter one doesn't work? I just fail to understand it.
Please advise so I can comprehend this a bit better! :-)
Try this
copy /y %WINDIR%\system32\wbem\en-US\*.xsl %WINDIR%\system32\
And then
wmic:root\cli>process list brief /format:htable.xsl > processlist.html
Note the presence of the extension after "htable"
You are attempting to use CMD.EXE > redirection while you are within the interactive WMIC context. That can't work.
You can use the WMIC /output:filename switch while in interactive mode. Each subsequent command will overwrite the output of the previous command. You can get multiple commands to go to the same file by using /append:filename instead. You can reset the output back to stdout using /output:stdout.
/output:processlist.html
process list brief /format:htable
/output:stdout
Did you try specifying a full path in the wmic:root\cli>process call? My bets are that the first worked because it output the file to the current directory.

Executing a command from C++, What is expected in argv[0]?

I am using execv() to run commands from /bin/ such as 'ls', 'pwd', 'echo' from my c++ program, and I am wondering what value I should provide in argv[0];
const char * path = getPath();
char ** argv = getArgs();
execv(path,argv);
argv[0] is supposed to be the program name. It's passed to the program's main function. Some programs differentiate their behavior depending on what string argv[0] is. For example the GNU bash shell will disable some of its features if called using sh instead of bash. Best give it the same value that you pass to path.
In linux, argv[0] is the process name displayed by the top utility (which it probably gets from reading entries in /proc/)
argv[0] should be the full path of the command that you want to run.
I know that this is not the answer you're looking for but is there a specific reason why you're doing this? The reason I ask is that most if not all of the actions people normally run with either system() or execv() are available in libraries on either Windows or Unix and are safer, faster and less likely to suffer from circumstantial errors. By that I mean, for example, when the PATH changes and suddenly your code stops working.
If you're passing in a string, either in whole or in part, and running it then you also leave yourself open to a user gaining access to the system by entering a command that could be damaging. E.g. imagine you've implemented a file search using find /home -name and your user types in:
"%" -exec rm {} \;
Ouch!