Strange behviour while parsing command line arguments c++ - c++

here is an issue I have never seen before and thought it would be share-worthy. Im not sure why it happens though.
This is how I invoke my program:
./foo -switch1 arg1 -switch2 arg2 -switch3 arg3|arg4|arg5 -switch4 -arg6
Each switch is used to indicate a different type of argument and I parse them accordingly.
The problem occurs with switch3, which indicates that arg3, arg4, arg5 all correspond to the same switch and are delineated using the | character.
For some reason, I can run the program perfectly, but when I try to debug it using gdb, My program crashes with a during startup, program exited with code 127 error.
Here's what intrigues me. It also says bin/bash: arg4 not found. It takes the argument right after the first | character, which now I assume it perceives as the pipe character, and tries to invoke a bash script.
Why does this happen??? Doesn't the compiler take the entire command line string and consider space separated tokens as different arguments? Why is the | being interpreted differently? I tried adding arg3|arg4|arg5 in inverted quotes "", and it works fine. I also tried separating them by -, eg. arg3-arg4-arg5, and this works fine too.

The | character has a special meaning in bash: it creates a pipeline.
Your program only sees the following arguments:
./foo -switch1 arg1 -switch2 arg2 -switch3 arg3
The |arg4 syntax is interpreted by bash to mean that the (non-existent) arg4 command should be run, and that the standard output of ./foo should be piped into the standard input of arg4. The |arg5 ... is interpreted in the same manner.
To suppress this behaviour, run your program like so:
./foo -switch1 arg1 -switch2 arg2 -switch3 'arg3|arg4|arg5' -switch4 -arg6
(note the quotes).

The problem is that | is a pipe so you end up trying to call arg4 which the shell can not find. You need to quote the content in with pipes in them i.e. "arg3|arg4|arg5":
./foo -switch1 arg1 -switch2 arg2 -switch3 "arg3|arg4|arg5" -switch4 -arg6
If you are curious you can check out bash pitfalls. If you are not doing a lot of shell programming you may not see these problems often but when you do it may take you a while to figure out what is going on so learning more about shell programming can be helpful in the long term. I remember hitting number 3 and it took me a while to find a good solution the first time.

Related

Passing a angled bracket as a command-line argument input while debugging

I'm writing a brainfuck interpreter in NASM, where code is supplied as a command line argument to the program. I'm trying to test looping, but GDB doesn't like my input. For example, this executes error-free when run on its own:
$./interpret "+++++[->+<]"
It hangs indefinitely, but I think that that's due to a bug in the looping logic in the interpreter (thus GDB).
If I load interpret into GDB though and attempt to supply the same argument, I get complaints:
gef➤ start "+++++[->+<]"
/bin/bash: line 1: ]: No such file or directory
/bin/bash: line 1: ]: No such file or directory
This seems to be due to < being interpreted as redirection despite the quotes, since [] works fine in GDB.
I tried escaping the STDIN redirection with \<, but that leads to the same error, and <<, but that leads to a warning:
gef➤ start "+++++[->+<<]"
/bin/bash: line 1: warning: here-document at line 1 delimited by end-of-file (wanted `]')
And the code gets cut off:
$r15 : 0x00007fffffffe428 → 0x002d5b2b2b2b2b2b ("+++++[-"?)
Is there a way to have GDB take what I give literally to start, and not attempt to do any redirection/interpretation of the arguments?
Is there a way to have GDB take what I give literally to start, and not attempt to do any redirection/interpretation of the arguments?
GDB isn't doing any interpretation, bash does. Using single-quotes instead of double-quotes may fix that.
(I wasn't able to replicate the problem using GDB-10.0 and bash-5.1.4 with double quotes though.)

How to execute the bash's sudo command using execvp function?

I have an executable, a.out which takes several command-line arguments. This executable needs to be run with root privileges, like sudo ./a.out arg1 arg2 ... .
How should I do this using the execvp system call in C++ ?
char *args[5];
args[0]="sudo";
args[1]="./a.out";
args[2]="arg1";
args[3]="arg2";
args[4]=NULL;
execvp("sudo", args);
The shell splits the given command into whitespace-delimited words. The first word gets looked up in PATH, and all the words are passed as parameters to the command.
Sinec execvp() will search the PATH for you, you can simply pass "sudo" as the command, then the arguments to the command. Note that the first argument to the command is the command's name.
The command you're executing is "sudo", so that's the first argument; then the remaining words as individual arguments, passed as an array.
This is not working: ?
execvp("/usr/bin/sudo", "./a.out arg1 erg2").

Prettify clang -v output

Is there any way to get clang output to insert carriage returns? When compiling with the verbose option, I just get these huge unreadable dumps of compiler flags and paths.
Use popen to start your clang session. Create a new command line as clang -v (including the space) and concatenate the arguments that you usually feed to clang itself. After the final argument, add 2>&1 to convert Clang's stderr output to regular stdout so popen can pick it up. Then loop over popen's input and parse each separate line, adding extra information where you see fit.
As an example, I grabbed the entire set of flags for my local Clang using
clang -cc1 --help
and incorporated this as a single long string in my C program. Then I looped over the return results from popen, scanning for flags starting with -, and when one was found, I scanned the long flags string for this. If it found something, I write it out on a separate line in green (using ANSI escape sequences). Then I test the flags string if an argument should follow – these usually have a leading <...> indicator. If so, I write it out in blue. Finally, I write out the entire flag explanation line until I encounter an end-of-line.
With my very rough program called colorclang – 123 lines of actual code – I get output like this:
As it is, it tests every input line for possible flags so there is some mis-coloring. More exact parsing is possible; I'd have to add separate routines for the single line starting with "/usr/bin/clang" (for the common Clang flags), the single line starting with "/usr/bin/ld" (and parse the loader flags), and possibly the lines after each #include .. statement.
Pieced together with the help of Complete list of clang flags?, Steve Kemp's answer to C: Run a System Command and Get Output?, and after deducing clang -v writes to stderr, larsman's answer to c popen won't catch stderr.

How can I parse command line arguments that themselves contain switches using boost::program_options?

I'm writing a program in C++ that is a wrapper for some benchmarks that contains some setup code at the beginning and analisys code in the end.
I want to run up to two benchmarks in parallel. The original commandlines for these are:
/path0/benchmark0 -switch0 -switch1 -switch2
/path1/benchmark1 -arg0 -arg1 -arg2 -arg4
And I want to put these on my wrapper's commandline:
wrapper -setup_arg0 -setup_arg1 -analysis_arg0 --command0 /path0/benchmark0 -switch0 -switch1 -switch2 --command1 /path1/benchmark1 -arg0 -arg1 -arg2 -arg4
Where I want to get two std::vector<std::string>s, one for each of command0 and command1, containing the original commandlines. This is how I'm doing it (using boost::program_options):
("command0", po::value<std::vector< std::string> >(&command0)->multitoken(), "command line for thread 0")
("command1", po::value<std::vector< std::string> >(&command1)->multitoken(), "command line for thread 1")
and this basically works. However, if the benchmark's arguments begin with - (as most switches on most programs I've seen do), the program_options tries to parse them as part of the wrapper's switches, because it doesn't know that they should be grouped together under command0 or command1.
Does program_options support that? If so, how?
Example:
Where I work there is a convention for doing this by "terminating" the multitoken like this:
wrapper <snip> --command0 /path0/benchmark0 -switch0 -switch1 -switch2 -command0-
(in this example I terminated --command0 with -command0-.)
How can I make program_options handle it like this?
I think it's best if you take command0 and command1's values as a single string. e.g.,
wrapper --command0 "/path0/benchmark0 ..." --command1 "/path1/benchmark1 ..."
Yes, there's more work for you in that you have to wordexp your respective command strings (unless you're already just passing those strings straight to the shell ;-)), but it more cleanly separates out what's for the wrapper and what's for the invoked commands.

posix_spawn a shell script, trouble passing arguments

I need a to be able to use some of the process control facilities provided by posix_spawn() like suspend/resume/kill etc, something that system() does not give me.
So use the following call to posix_spawn() to launch a shell script from a c++ program:
int result = posix_spawn(&spawnedPid, processExecutable, 0, 0, argumentList, 0);
where processExecutable is "foo.sh" and argumentList is {"bar",0,0,0}; The process foo.sh starts up just fine, except for the argumentList part. If I do something like "echo $1" in foo.sh, I get an empty string. If I launch a binary the same way, the arguments are just fine and I can reach them via argv[]. Is there anything I should be doing differently in order to pass arguments to foo.sh ?
Shame on me, the argumentList parameter of posix_spawn() is 0-based so echo $1 actually outputs argumentList[1], which is, naturally, set to 0. Case closed.