Output of C++ function system(command) does not show color in Linux terminal - c++

When I directly run a command in my Linux terminal, say "ls", the output is with color. However, when I run a C++ program which calls system("ls"), the output does not have color.
Is there way to get the latter way to also display colored output?
Thanks!

The answer for why there's no color lies here.
system() executes a command specified in command by calling /bin/sh -c
command, and returns after the command has been completed.
sh -c ignores aliases. Perhaps somewhere you have an alias where ls means ls --color=auto.
So for example, if I do sh -c 'ls', I will get no color.
Proof:
wow ♪[01:04 AM][vnbraun#chernobyl ~]$ which ls
alias ls='ls --color=auto'
/bin/ls
wow ♪[01:08 AM][vnbraun#chernobyl ~]$ sh -c 'which ls'
/bin/ls
Therefore, you can try doing system("ls --color=auto");.

You could run
system("/bin/ls --color=auto");
But I don't think you really should run ls from your C++ program. Perhaps you want to use -some combination of- readdir(3), stat(2), nftw(3), glob(3), wordexp(3) etc etc....
I don't think that forking a shell which then runs /bin/ls is useful from a C++ program. There are simpler ways to achieve your goal (which I cannot guess).
You probably should read Advanced Linux Programming

Try invoking ls --color=auto or ls --color=always to display ls with colors.

This is likely due to a bash configuration file somewhere in your system aliasing "ls" to "ls --color".
Using "ls --color" in your program should work.

Related

/bin/sh: 1: Syntax error: "(" unexpected after running Makefile [duplicate]

I often find Bash syntax very helpful, e.g. process substitution like in diff <(sort file1) <(sort file2).
Is it possible to use such Bash commands in a Makefile? I'm thinking of something like this:
file-differences:
diff <(sort file1) <(sort file2) > $#
In my GNU Make 3.80 this will give an error since it uses the shell instead of bash to execute the commands.
From the GNU Make documentation,
5.3.2 Choosing the Shell
------------------------
The program used as the shell is taken from the variable `SHELL'. If
this variable is not set in your makefile, the program `/bin/sh' is
used as the shell.
So put SHELL := /bin/bash at the top of your makefile, and you should be good to go.
BTW: You can also do this for one target, at least for GNU Make. Each target can have its own variable assignments, like this:
all: a b
a:
#echo "a is $$0"
b: SHELL:=/bin/bash # HERE: this is setting the shell for b only
b:
#echo "b is $$0"
That'll print:
a is /bin/sh
b is /bin/bash
See "Target-specific Variable Values" in the documentation for more details. That line can go anywhere in the Makefile, it doesn't have to be immediately before the target.
You can call bash directly, use the -c flag:
bash -c "diff <(sort file1) <(sort file2) > $#"
Of course, you may not be able to redirect to the variable $#, but when I tried to do this, I got -bash: $#: ambiguous redirect as an error message, so you may want to look into that before you get too into this (though I'm using bash 3.2.something, so maybe yours works differently).
One way that also works is putting it this way in the first line of the your target:
your-target: $(eval SHELL:=/bin/bash)
#echo "here shell is $$0"
If portability is important you may not want to depend on a specific shell in your Makefile. Not all environments have bash available.
You can call bash directly within your Makefile instead of using the default shell:
bash -c "ls -al"
instead of:
ls -al
There is a way to do this without explicitly setting your SHELL variable to point to bash. This can be useful if you have many makefiles since SHELL isn't inherited by subsequent makefiles or taken from the environment. You also need to be sure that anyone who compiles your code configures their system this way.
If you run sudo dpkg-reconfigure dash and answer 'no' to the prompt, your system will not use dash as the default shell. It will then point to bash (at least in Ubuntu). Note that using dash as your system shell is a bit more efficient though.
It's not a direct answer to the question, makeit is limited Makefile replacement with bash syntax and it can be useful in some cases (I'm the author)
rules can be defined as bash-functions
auto-completion feature
Basic idea is to have while loop in the end of the script:
while [ $# != 0 ]; do
if [ "$(type -t $1)" == 'function' ]; then
$1
else
exit 1
fi
shift
done
https://asciinema.org/a/435159

What shell does std::system use?

TL;DR; I guess the shell that std::system use, is sh. But, I'm not sure.
I tried to print the shell, using this code: std::system("echo $SHELL"), and the output was /bin/bash. It was weird for me. So, I wanted to see, what happens if I do that in sh? And, the same output: /bin/bash. Also, if I use a command like SHELL="/usr/bin/something", to set the SHELL variable to another string, it will print the new string that I set to it (/usr/bin/something), and it looks it's not a good way to see what shell it's using. Then, I tried to check it, using the ps command, and the output was: bash, a.out, ps. It was weird to see bash in this list. So, I created a custom shell, and change the shell in gnome-terminal to it:
#include <iostream>
int main()
{
std::string input;
while (true)
{
std::string command;
std::getline(std::cin, command);
std::system(command.c_str());
}
}
Now, it's easier to test, and I think, the results is better.
Then, I tried to test the ps command again, but in the custom shell, and the results was: test_shell, ps.
It was weird again. How the shell isn't sh, nor bash? And, the final test I did was: echo $0. And, the results was sh, in both custom shell, and normal program.
Edit
It seems like /bin/sh is linked to /bin/bash (ll /bin/sh command's output is /bin/sh -> bash), and actually, it seems like the only difference between sh and bash is filename, and the files's contents are the same. I checked the difference between these files with diff command too:
$ xxd /bin/sh > sh
$ xxd /bin/bash > bash
$ diff sh bash
(+ Yes, $SHELL doesn't means the running shell (I didn't know that when I was testing, and I just wanted to see what happens))
The GNU sources (https://github.com/lattera/glibc/blob/master/sysdeps/posix/system.c) say
/bin/sh
So, whatever /bin/sh is hardlinked to is the shell invoked by std::system() on Linux.
(This is correct, as /bin/sh is expected to be linked to a sane shell capable of doing things with the system.)
According to cppreference.com, std::system
calls the host environment's command processor (e.g. /bin/sh, cmd.exe, command.com)
This means the shell used will depend on the operating system.
On any POSIX OS (including Linux), the shell used by std::system is /bin/sh. (Though as the OP points out, /bin/sh could be a symlink to another shell.)
As for the SHELL environment variable, as has been pointed out in the comments, this environment variable cannot be used to reliably identify the running shell program. SHELL is defined by POSIX to
represent a pathname of the user's preferred command language interpreter
(source)

Procedure for using gdb to examine output and error messages returned by a called program

I've got a program written in C++ which has a function that looks similar to this:
std::string cmd = "curl -s http://x.x.x.x/latest/meta-data/public-hostname";
std::vector<std::string> output;
runCmd(cmd, output);
If the curl command fails the program silently ignores it. I need to be able to examine what's happening when the program gets to this point: I'd like to look at the output generated by curl, including error message and return code.
How do I do this with gdb? Please walk me through the steps of running the program with gdb so I can see what's happening with curl. It's a fairly large program. I am only interested in this particular function call, I want to ignore everything else up to that point.
i should note that I don't have the environment to compile the code. All I've got is the binary.
Not sure gdb will help you much as you spawn a sub process.
I would suggest changing the code to
std::string cmd = "curl -s http://x.x.x.x/latest/meta-data/public-hostname 2>/tmp/error | tee /tmp/output";
so that /tmp/erro and /tmp/output gives you what happened;
EDIT:
as compilation os not possible, you may use this trick:
create a script named curl containing:
#!/bin/bash
/usr/bin/curl $# 2>/tmp/error | tee /tmp/output
(don't forget to change permission to +x)
then, when executing your program just do:
PATH=.:$PATH ./yout_binary
assuming your script is in .
then the program will use your 'fake' curl
I would use strace for this task, rather then gdb:
strace -f -s 1024 -o log ./program
Here -f mean to trace child processes as well. You need it because this line of code runCmd(cmd, output); most likely does fork() to run child process.
-s 1024 specifies maximum string size to print. By default it is 32 which is often too short.
Once you save the output to log file, you should easealy find something like curl -s in it. This is where the child process starts. You can see what it writes to stderr or stdout in lines like write(2, "... or write(1, ".... At the end of the process execution you will see it's exit code, for example 1 exit code:
exit_group(1) = ?

How to work in batch mode

I have inherited an ANSI C++ program that: has no GUIs and is supposed to run in batch mode, generating lots of data (we are talking 100,000+ ASCII files). We are thinking that in long term we’ll run it under UNIX. For now, I have a MacBook Air running OS X 10.9.4 and I loaded Xcode 5.1.1. It compiles without errors or warnings.
I need to test a program as follows:
<prompt> myprogram datain dataout1 datout2
Where is the compiled program? In which directory? Can I copy my datain file in that directory?
For repeated execution under Windows (Command Prompt window) I normally would have a batch file of the type:
myprogram datain1 dataout11 datout12
myprogram datain2 dataout21 datout22
myprogram datain3 dataout31 datout32
........
myprogram datainn dataoutn1 datoutn2
Can I do something similar with OS X? Where can I find the applicable documentation?
You will want to look for your terminal emulation program. See http://en.wikipedia.org/wiki/Terminal_(OS_X) for how to use it, and it should be the bash shell which is one of the unix shells
You can also do a shell script see
http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html for some bash shell scripting info
For such a simple operation, you can write a shell script that will look almost exactly the same as the batch file you use on Windows. The key difference between Windows' cmd.exe and *nix shells here is that the current directory is not part of the search path for executables (the way it is on Windows), so if you put the shell script in the same folder as the compiled executable, you will need to prefix the program name with ./ (to mean "look in the current directory"). For example:
#!/bin/sh
./myprogram datain1 dataout11 datout12
./myprogram datain2 dataout21 datout22
./myprogram datain3 dataout31 datout32
........
./myprogram datainn dataoutn1 datoutn2
If the shell script and executable are not in the same folder, you can use either an absolute path or an appropriate relative path.
Also, to run the script you will either need to make it executable:
$ chmod +x myscript.sh
$ ./myscript.sh
or invoke the shell with the script as an argument:
$ sh myscript.sh

Try to execute command line codes from c++ linux

I tried the following code, to communicate with the command line from c++ code.
#include<iostream>
#include<cv.h>
int main()
{
system("gnome-terminal");
system("cd");
}
The gnome-terminal command is executing fine. After I close the terminal, when am expecting the cd to execute, however, is not happening. Could you please help me and point out the reason? Thanks. I was expecting the function to make the cmd go down to the home directory
, but it did not. am working in linux
I tried it even by removing gnome. simple cd is not working. am I doing something rong>?
If I try ls, it seems to be working fine!
My main aim is to open a new terminal, and execute commands on that new terminal through the present program that opened the new terminal. Could you please tell me how I can achieve this??
If you want to run a program and wait for it to finish before executing next line, take a look at this page and example code here: http://www.thegeekstuff.com/2012/03/c-process-control-functions/
But if you want to run gnome-terminal and execute a command in newly created window, do this:
system("gnome-terminal -x sh -c 'cd /tmp ; ls -la'");
The system function creates a shell child process to execute the specified command.
cd is a shell command which changes the current working directory of that shell process only.
So the child's cd probably works fine, but it has no effect on your C++ program, which is a different process.
Instead, you probably want to look at the Linux system call chdir.
Thanks for your help!! This command worked perfectly fine from this link
https://superuser.com/questions/198015/open-gnome-terminal-programmatically-and-execute-commands-after-bashrc-was-execu
gnome-terminal -x sh -c 'command1; command2; exec bash'
and I entered the respective commands in the new window. But to change the working directory in the shell am working o, I haven't still figured that out.