How do I open a terminal window with C++ in Ubuntu? - c++

I recently decided to start teaching myself C++ and thought a simple encryption project would be a good place to start, since it covers most of the basics (cout, cin, opening files, etc). Is there a way to have the code open a terminal window similar to the one opened when I compile and run from sublime text?
I have tried this so far, but it hasn't changed anything.
string cmd = "gnome-terminal-x sh-c 'ls-l; exec bash'";
system(cmd.c_str());
Essentially, I would like to be able to run the program by clicking the .exe, and have the terminal where all of the input and output goes pop up.

You don't need to write any code, you just need to configure the shortcut to launch the program in a terminal. Here's a Gnome dialog that shows that option:

Problem seems to be gnome-terminal, or then just my failure to give it the right arguments. For example gnome-terminal -x sh -c 'ls -l ; exec bash' from command line in another terminal just opens an empty gnome-terminal and spits out a bunch of glib warnings to original terminal... (Note to readers: if you can give the right command that works for gnome-terminal, please let me know in comments or just edit this paragraph.)
However, using xterm works, for example xterm -e sh -c 'ls -l; exec bash', or a line for your code:
string cmd = "xterm -e sh -c 'ls -l; exec bash'";
As a side note, the command to open the default x terminal window of the DE is x-terminal-emulator, but it quite often has the practical problem of different terminals taking different arguments, so sadly you're probably better of using a specific terminal, like that xterm, and requiring that to be installed, or letting user to configure what terminal to use, with what arguments (though letting user to specify any command to be run can also be a security risk, if user is not always trusted).
Just be very careful with escaping. For example, when you test the command form command line, and then copy-paste it to C++ string literal, you need to escape every " and \ one more time for C++. If you have trouble with this, check out C++11 raw strings.
Escaping becomes extra important if you construct the command string at runtime, and especially if you accept user input and add that to the string. In that case, better search for and use some existing library like GLib, or sanitize the user input very carefully (ie. just paranoidically reject anything with chars, which may have a special meaning in shell in some context).
If you are actually asking, how can my program open a console window for itself similar to how Windows console programs behave, and redirect it's own stdin, stdout and stderr there, as if it was launched from command line, that that is not very easy from the same binary, and it is not commonly done like that in Unix.
If you want a behaviour like that, you could create a desktop shortcut, but more general way is to write a wrapper shell script, which starts your binary in a terminal. What kind of script exactly, depends on how you want it to behave exactly: what will it do with stdio, will it return or wait for program to exit, how do you want it to find the binary, how does it behave when run from command line instead of double-clicking from GUI, etc.

Related

C++ System(); function not working as expected / Windows console commands in C++

Hello friendly people of stack overflow!
I am currently working on a project using an Arduino Uno. Because i create all my files and sketches using a c++ program, i want to eliminate the Arduino IDE from my workflow. For that i can very easily use avrdude (which the IDE uses anyway) and some windows console commands.
These are the commands that i am using:
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude" "-CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM4 -b115200 -D -Uflash:w:C:\Users\Jzargo\AppData\Local\Temp\arduino_build_766345/EPaper_TestDither.ino.hex:i
"EPaper_TestDither.ino" is the arduino Sketch i want to compile and upload. When using the console and manually inserting the above commands, everything works as expected.
And here comes the part I am struggeling with:
Because i also dont want the user to manually open the console and type in some gibberish code, i want to integrate this command into my c++ program using the system(); function:
system("\"C:\\Program Files(x86)\\Arduino\\hardware\\tools\\avr/bin/avrdude\" \" - CC:\\Program Files(x86)\\Arduino\\\hardware\\tools\\avr/etc/avrdude.conf\" -v -patmega328p -carduino -PCOM4 -b115200 -D -Uflash:w:C:\\Users\\Jzargo\\AppData\\Local\\Temp\\arduino_build_766345/EPaper_TestDither.ino.hex:i");
When executing this function, the command cannot be executed because "Der Befehl "C:\Program" ist entweder falsch geschrieben oder konnte nicht gefunden werden.", which roughly translates to "The Command "C:\Program" is not written correctly or cant be found".
I do not understand why the console accepts the command when manually inserting it, but not when using the system(); function.
I hope you can help me figure this out.
Edit: By using
subst H: "C:\Program Files(x86)\Arduino\hardware\tools\avr\bin" and
system("\"H:/avrdude \"-CC:/Program Files (x86)/Arduino/hardware/tools/avr/etc/avrdude.conf\"\" -v -patmega328p -carduino -PCOM4 -b115200 -D -Uflash:w:C:/Users/Jzargo/AppData/Local/Temp/arduino_build_833906/EPaper_TestDither.ino.hex:i");
I was able to upload my sketch. Note the changed Placement of \".
But for some reason, this does not work when using C:\Program Files(x86)\Arduino\hardware\tools\avr\bin instead of H:.
Kindest regards
J'zargo
The command looks messed up with respect to the parameters, although I don't see how exactly that triggers your specific error.
The beginning is OK. The path is properly quoted (double quotes, protected by backslashes from the C compiler). But why do you have slashes and backslashes mixed? In some online examples I saw that people use forward slashes in Windows paths (C:/whatever...) ; that seems to work and is easier than using double backslashes all the time (but it should not trigger your — or any — error).
So system("\"C:\\Program Files(x86)\\Arduino\\hardware\\tools\\avr/bin/avrdude\" ... should call the right executable. Why don't you try that on its own (without parameters) to see whether the error persists?
I suspect that \" - CC:\\Program Files(x86)\\ ... is not correct though. avrdude expects a parameter -C<path>, not - C<path> (note the badly placed spaces before and after the dash).
As an aside, it may not hurt to quote parameters that contain funny characters like colons which may have special meanings.
The general advice for this kind of trouble:
Work in and with paths that do not contain spaces, brackets, or other non-identifier characters. If you don't want to change the avrdude installation path you can use the DOS subst command to create a drive whose root is C:\Program Files(x86) or even C:\Program Files(x86)\Arduino\hardware\tools\avr\bin, e.g. subst H: "C:\Program Files(x86)\Arduino\hardware\tools\avr\bin". The command would then be H:/avrdude :-).
If confronted with a bug you don't understand, simplify the problem radically until a toy version works; then add complexity bit by bit until you encounter the error; that should make it easier to recognize what triggered it.
Edit: I'm not sure this example is valid because I used the msys2 development environment and ran the example in a bash shell; I'm not even sure cmd is called as the system shell by the syste call!
In order to check the system call semantics I wrote the following minimal example (which uses mixed slashes/backslashes as a test). The current directory has a sub directory called "some dir" containing a minimal program showargs which simply writes its command line parameters to stdout:
$ ls -l "some dir" && echo && cat cmdline.c && echo && gcc -o cmdline cmdline.c && ./cmdline.exe
total 56
-rwxr-xr-x 1 Peter None 56097 Apr 16 17:23 showargs.exe
#include <stdlib.h>
int main(int argc, char **argv)
{
system("\".\\some dir/showargs\" 1 2 3");
}
->.\some dir/showargs<-
->1<-
->2<-
->3<-

Hiding console command used while using system()? C++ Linux

Well, I will put it plain and simple: I am a C++ pleb. Still trying to learn though.
My question is: is it possible to run a command though the terminal using system() command without letting the command be shown in the console/terminal?
Example:
system("sudo service sshd start") ;
Output: Sudo service sshd start
Where as I want:
system("sudo service sshd start") ;
output: (Blank)
Note: I am on linux.
The system standard library function starts up a subshell and executes the provided string as a command within that subshell. (Note that a subshell is simply a process running a shell interpreter; the particular shell interpreter invoked by system will depend on your system. No terminal emulator is used; at least, not on Unix or Unix-like systems.)
The system function does not reassign any file descriptors before starting the subshell, so the command executes with the current standard input, output and error assignments. Many commands will output to stdout and/or stderr, and those outputs will not be supressed by system.
If you want the command to execute silently, then you can redirect stdout and/or stderr in the command itself:
system("sudo service sshd start >>/dev/null 2>>/dev/null") ;
Of course, that will hide any error messages which might result from the command failing, so you should check the return value of system and provide your own error message (or log the information) if it is not 0.
This really has very little to do with the system call or the fact that you are triggering the subshell from within your own executable. The same command would have the same behaviour if typed directly into a shell.

What is the difference between calling a script from the shell and using system()?

I have built a bash script to start up some processes in my system. It simply calls the process and associated config file. Same as I would call from the command line.
#!/bin/bash
# Start specified process in a new session
setsid $1 &>/dev/null &
So to start up someprocess, I would call from the command line:
root#supercomputer:~# start someprocess
This works like a charm. Every process, every time. But when I make a system call from a different running C++ process, someprocess never starts up.
system( "start someprocess" )
This approach for 90% of my processes, except for one. The only difference in the working and not working processes is that the non-working one uses proprietary libraries underneath. I recently added the setsid option to the bash script in hopes that starting a new session would help, but it made no difference. I've also tried popen, and execv. No change.
So my question is what is the difference between calling something with system() and just making that same call from the command line?
All processes are written in C++ on Linux.
.bashrc is only invoked if bash is run as interactive, non-login shell. If it's invoked as non-interactive shell, as when using system() on a script with a bash shebang, it only reads the configuration file pointed to by $BASH_ENV.
That means you have the following options:
add -l to the shebang - causes the shell to read ~/.profile at startup
set $BASH_ENV to the script you want sourced before calling system()
add -i to the shebang - invokes bash as interactive shell and causes it to read ~/.bashrc, but will also effect how bash handles input/output.
I'd recommend the first option.
You can find a detailed explanation of how bash reads it's startup files here. I'm not sure this will solve your problem completely, but it may at leas shed some light on that part of the issue.
Check the environment variables that are used in the system() call. For example, call system to print out some of the variables, and see if they match what you see from the command line.
Likely they are not being sourced correctly.

What is a 'shebang' line?

Currently I'm trying to start programming on my new Mac. I installed TextWrangler, and chose C++ as my language of choice; since I have some prior knowledge of it, from when I used Windows.
So, I wrote the ever so common "Hello World" program. Although, when I tried to run it, I got an error:
"This file doesn’t appear to contain a valid ‘shebang’ line (application error code: 13304)"
I tried searching the error code to find out how to fix this, but I couldn't find anything.. I have no idea what a 'shebang' line is... Can someone help me out?
You need to compile it with a compiler first. I assume you tried to run the source file like ./source but C++ doesn't work this way.
With some compilers however, you can provide a shebang-line as the first line of the source file (the #! is known as shebang or crunchbang, hence the name), like so:
#!/path/to/compiler
So that the shell knows what application is used to run that sort of file, and when you attempt to run the source file by itself, the compiler will compile and run it for you. That's a compiler-dependent feature though, so I recommend just plain compiling with G++ or whatever Macs use to get an executable, then run that.
While I wouldn't recommend it for regular C++ development, I'm using a simple shell script wrapper for small C++ utilities. Here is a Hello World example:
#if 0 // -- build and run wrapper script for C++ ------------------------------
TMP=$(mktemp -d)
c++ -o ${TMP}/a.out ${0} && ${TMP}/a.out ${#:1} ; RV=${?}
rm -rf ${TMP}
exit ${RV}
#endif // ----------------------------------------------------------------------
#include <iostream>
int main(int argc, char *argv[])
{
std::cout << "Hello world" << std::endl;
return 0;
}
It does appear that you are trying to run the source file directly, however you will need to compile using a C++ compiler, such as that included in the gcc (GNU Compiler Collection) which contains the C++ compiler g++ for the Mac. It is not included with the Mac, you have to download it first:
from http://www.tech-recipes.com/rx/726/mac-os-x-install-gcc-compiler/ : "To install the gcc compiler, download the xcode package from http://connect.apple.com/. You’ll need to register for an Apple Developer Connection account. Once you’ve registered, login and click Download Software and then Developer Tools. Find the Download link next to Xcode Tools (version) – CD Image and click it!"
Once it's installed, if you are going for a quick Hello World, then, from a terminal window in the directory of your source file, you can execute the command g++ HelloWorld.cpp -o HelloWorld. Then you should be able to run it as ./HelloWorld.
Also, if you're coming from a Visual Studio world, you might want to give Mono and MonoDevelop a try. Mono is a free implementation of C# (and other languages), and MonoDevelop is an IDE which is very similar to Visual Studio. MonoDevelop supports C# and other .NET languages, including Visual Basic .NET, as well as C/C++ development. I have not used it extensively, but it does seem to be very similar to VS, so you won't have to learn new everything all in a day. I also have used KDevelop, which I liked a lot while I was using it, although that's been a while now. It has a lot of support for GNU-style development in C/C++, and was very powerful as I recall.
Good luck with your endeavors!
Links:
Mono: http://mono-project.com/Main_Page
MonoDevelop: http://monodevelop.com/
KDevelop: http://kdevelop.org/
shebang is http://en.wikipedia.org/wiki/Shebang_%28Unix%29.
not sure why your program is not running. you will need to compile and link to make an executable.
What I find confusing (/interesting) is C++ program giving "Shebang line" error. Shebang line is a way for the Unix like operating system to specify which program should be used to interpret the rest of the file. The shebang line usually points to the path of the interpreter. C++ is a compiled language and does not have interpreter for it.
To get the real technical details of how shebang lines work, do a man execve and get that man page online here - man execve.
If you're on a mac then doing something like this on the commandline:
g++ -o program program.cpp
Will compile and link your program into an executable called program. Then you can run it like:
./program
The reason you got the 'shebang' error is probably because you tried to run the cpp file like:
./program.cpp
And the shell tries to find an interpreter to run the code in the file. Because this is C++ there is no relevant interpreter but if your file contains Python or Bash then having a line like this
#!/usr/bin/python
at the 1st line in your source file will tell the shell to use the python interpreter
The lines that start with a pattern like this: #!/.../.../.. is called a shebang line. In other words, a shebang is the character sequence consisting of the characters number sign and exclamation mark (#!).In Unix-like operating systems, when a text file with a shebang is used as if it is an executable, the program loader mechanism parses the rest of the file's initial line as an interpreter directive. The loader executes the specified interpreter program, passing to it as an argument the path that was initially used when attempting to run the script, so that the program may use the file as input data.

Input redirection in gdb (MinGW)

I'm trying to get gdb to run programs with input redirection to stdin. For example, without gdb I would run a program like this:
prog < input.txt
Now in gdb, the usual way to do this is run < input.txt. However, it doesn't work for me and when doing this nothing gets redirected into stdin.
I'm using Windows with MinGW. What could be the problem?
As far back as the late '90s, broken command line redirection was a known and assumed limitation. My suspicion is that it remains that way, since the mingw32 port of gdb still gleefully passes on verbatim all run arguments (including redirects) to the debugee.
Several possible workarounds:
if you have the option to alter the command line interface, then implement bbadour's suggestion
otherwise, if you can easily suspend the process before the point you want to debug at, invoke the debugee (with redirection) from a shell and attach to it while it is already running
otherwise, if you have symbols for the debugee (gcc -g) or you know the address of main() (gcc -Wl,-Map,mapfile) and can set a breakpoint there, proceed in the following manner (tested with mingw gdb 6.8.0):
# gdb debugee.exe
(gdb) b main
(gdb) run non-redirect-arguments-if-any
(gdb) p dup2(open("/tmp/input.txt", 0), 0)
(gdb) c
I ran into the same issue here, and I just got into the habit of adding a command-line argument to allow grabbing input from a file.
e.g. Parsing a "-i ifile" argument using argc and argv to get input from ifile instead of stdin and parsing a "-o ofile" to write output to ofile instead of stdout.
Then I just use those arguments instead of redirects.
The tools that come with MinGW often are not the latest versions and often have features omitted. ::shrug::
Input redirection is supported starting with GDB 8.0. From the NEWS file:
Native debugging on MS-Windows supports command-line redirection
Command-line arguments used for starting programs on MS-Windows
can now include redirection symbols supported by native Windows
shells, such as '<', '>', '>>', '2>&1', etc. This affects GDB
commands such as "run", "start", and "set args", as well as the
corresponding MI features.