Detecting semicolon as command line argument in linux - c++

I am trying to run a C++ application where I am passing some command line arguments to it as follows:
./startServer -ip 10.78.242.4 tcpip{ldap=no;port=2435}
The application is getting crashed because it is not able to get the correct port. Searching over the web, I found that ";" is treated an end of command character (Semicolon on command line in linux) so everything after that is getting ignored. I also understand the putting it inside the quotes will work fine. However, I do not want to force this restriction of putting the arguments in the quotes on the users. So, I want to know is there a way I can process the ";" character with the argv array?

The semicolon separates two commands so your command line is equivalent to
./startServer -ip 10.78.242.4 tcpip{ldap=no
port=2435}
Your application will never know anything about either the semi colon or the second command, these will be completely handled by the shell. You need to escape the colon with a back slash or enclose it in quotes. Other characters which may cause similar issues include: $,\-#`'":*?()&|
Complex strings are much easier to pass either from a file or through stdin.

You need to quote not only the ; but in the general case also the { and }:
./startServer -ip 10.78.242.4 'tcpip{ldap=no;port=2435}'
If your users are required to type in that complicated last argument, then they can also be made to quote it.

Related

Pass \ in command line arguments of C++

I am working on a C++ program where one of the command line arguments needs to be a passed a regex. For example: abc.exe --option ab\[0\]
When I access the option value from inside the program, it becomes ab\\[0\\] which becomes a different regex.
Inside the program when I try to replace \\[ with \[ using boost::replace_all, the result is [ which also is not the intended output for me.
So, any suggestions on how to pass and retain \[ this while passing it through command line arguments
You can quote the parameter:
abc.exe --option "ab\[0\]"
Or use the shell escape sequence:
abc.exe --option ab\\[0\\]
Did you try these?
It was a problem with how visual studio displays the symbol. When I looked on the ASCII code of the symbol, it was alright. Thanks #ScottK for helping me to debug this through your comments

Executing cmd commands from python program

from subprocess import *
s=Popen(['C:\Python27\Scripts\pyssim',"'C:\Users\P\Desktop\1.png'",'C:\Users\P\Desktop\2.png'],stderr=PIPE,stdout=PIPE,shell=True)
out,err=s.communicate()
print out
The python program above executes successfully but it shows no output.
Nothing is printed on the shell.
While running command on cmd it gives output "1".
Your command is failing because the parameters being passed to it are not what you think they are; keep in mind that backslashes are normally treated as the start of escape sequences in Python string literals. Specifically, the \1 and \2 are being treated as octal character escapes, rather than digits. If you looked at the contents of err, you would probably find something like a file not found error. Some possible solutions:
Double all of the backslashes, to escape them.
Put an 'r' in front of each string literal, to make them 'raw strings' that don't specially interpret backslashes.
Not actually applicable in this case, but you can often just use forward slashes instead - most of Windows will happily accept them instead of backslashes, the one exception being the command line (which is what you're actually invoking here).

Filename extraction with regex

I need to be able to only extract the filename (info.txt) from a line like:
07/01/2010 07:25p 953 info.txt
I've tried using this: /d+\s+\d+\s+\d+\s+(?.?)/, but it doesn't seem to work ...
How about
/\S+$/
I.e. the longest possible string of non-whitespace at the end of the line.
(Hard to know for sure without more info about the possible inputs.)
As #J V pointed out, filenames with spaces in them (like his username) will not be parsed properly by the above regexp. We don't know from the question whether that's possible.
But I have a suspicion that we're looking at the output of Windows DIR command, or something very similar. In that case, the most reliable approach might be just to hack off the first 39 characters and keep the rest:
/^.{39}(.+)$/
Then $1 will contain the filename.
Better option:
But if you are using Windows DIR (as per your new comment), and you can control the DIR command, try
DIR /b
which removes the unneeded cruft (assuming you don't need the date, size etc.) and gives you one filename per line.
OK, you're using a Unix dir (per newer comment). The CentOS dir I have outputs one file per line, nothing else, when you give it no command line options. Chances are very good that whichever dir you're using can be persuaded to output filenames like that... then you wouldn't have to worry about using a regex that may or may not be correct for every possible input. Try man dir or dir --help to find out what command-line options to use.
\d\d:\d\d\w\s+\d+\s+(.*?)$
$1 will be the file name
The problem with your original regex is that it forgets the special characters :, /, and (?.?) means nothing...
Assuming that the files have extension as .txt you can try.
(?<=(\s)*)\w*.txt
Why not just use the following regex:
\w+\.\w+

C++ on Windows: executable path with whitespace in system() call

I am trying to execute a file with parameters using the "system()" function in C++ on Windows, and it works as long as there are no whitespaces in the filename. For parameters, putting double quotes around the string works, but when I try the same with the executable itself, I get the following error:
"the filename,directory name, or volume label syntax is incorrect"
Does anyone know how to handle this correctly?
Use a string like this:
cmd /S /C "your entire command line string"
See: How do I deal with quote characters when using cmd.exe
It should work, look for the problem elsewhere.
Perhaps something in your flow is removing the whitespace or the double quotes from the string.

Converting argv back to a single string

I'm writing a (Win32 Console) program that wraps another process; it takes parameters as in the following example:
runas.exe user notepad foo.txt
That is: runas parses user and then will run notepad, passing the remaining parameters.
My problem is that argv is broken down into individual parameters, but CreateProcessAsUser requires a single lpszCommandLine parameter.
Building this command line is probably not as simple as just joining argv back together with spaces. Any pointers?
This is just an example. My first argument isn't actually a user name, and might have spaces in it. This makes manually parsing the result of GetCommandLine tricky.
Similarly, a naive concatenation of argv won't work, because it needs to deal with the case where the original arguments were quoted and might have spaces in them.
Manually recombining them is hard:
You could try to re-combine them, I think it would work, but be sure to following the same command line escaping rules that windows has. This could be more than the trivial solution you're looking for.
Also if there are any parameters that have spaces in them, then you would want to join them to the string with quotes around them. Here is an example of a strange escaping rule: if you have --folderpath "c:\test\" then the last backslash has to be doubled --folderpath "c:\test\\".
If you are using MFC:
You can can get the value you want from your derived CWinApp's theApp.m_lpCmdLine. Note you could still access them the other way too with __argc, and __argv or CommandLineToArgvW.
If you are using Win32 only (even without a GUI):
You can get it from WinMain. Which can be your program's entry point.
Note you could still access them the other way too with __argc, and __argv or CommandLineToArgvW.
If you must use a console based application with main or wmain:
The Win32 API GetCommandLine seems to be the way to go. You would need to still parse this to get past the .exe name though. Take into account quotes around the exe name/path too. If there are no such quotes at the start, then just go to the next space for the start.
You can use the GetCommandLine function.
Why not use 'WinMain' instead of 'main'? This should give you the string in the format you want.
There is Win32 API call that returns command line: GetCommandLine
Provided you have a string allocated with enough space then use strcat on each item in the list. Yes, it is as simple as joining them back together with spaces.
Edit: Of course, you would need to enclose any items containing spaces within quotes.