C++ System(); function not working as expected / Windows console commands in C++ - 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<-

Related

Compile C/C++ with gVim 8.1 in Windows 10 (MinGW)

Since everything is 32-bit, I used :set makeprg=mingw32-make, and then tried compiling via :!make, which gave the following error message:
'make' is not recognized as an internal or external command, operable program or batch file.
shell returned 1
I tried the basic "Goodbye World" stuff:
#include <iostream>
int main() {
std::cout << "Goodbye World";
return 0;
}
What am I doing wrong? Other than being a noob.
:!make doesn't run 'makeprg'. It runs make. Since you are specifically trying to run mingw32-make.exe, presumably you don't have an executable named make.exe. (See :help :!)
:make runs 'makeprg'. (See :help :make, :help 'makeprg')
my goal is to see the "Goodbye World" either in console or terminal or any observable way. Would this require additional tinkering to the _vimrc file?
You would rather want to do it by tinkering with your makefile. Any arguments to :make will be passed to 'makeprg'. If you defined targets clean (to remove the Make artefacts) or run (to execute the product of your Make), you will be able to write :mak clean or :mak run in Vim to run those targets. Obviously, you can create your own commands and/or mappings to make those :make commands faster.
Note (and I completely overlooked this myself, silly me) that when you run a simple code, such as the one above, that does not need extensive file managements and Makefiles, all you need to go is :!gcc % for C and :!g++ % for C++. I believe (and I may be wrong, but this is a simple observation) that in Vim, :! indicates the following commands are to be executed in the system Command Prompt, and gcc/g++ is the command to invoke the GNU Compiler for C and C++ respectively. Finally, % is used to indicate the current filename, with all extensions intact. This is extremely useful in cases of keymapping, as I have done via the following:
nnoremap <F5> :!g++ %<CR>|"Press Func.5 to Compile via GNU Comp.

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

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.

C++ program cannot find latex command with system() function call

I am writing a C++ program which has to automatically generate some data to be used by students in an integrated exercise. I have already exported this data to .tex files and would also like the C++ program to be able to compile these tex files automatically.
Usually I would compile tex files from the command line by doing the following:
$ latex file.tex
$ latex file.tex
$ dvipdf file.dvi
So I tried doing the following in my C++ code (directory and filename are both strings):
//Move to the location where I created the files
string mycommand = "cd ";
mycommand += directory;
system(mycommand.c_str());
//Compile latex
mycommand = "latex " + filename + "_main.tex";
system(mycommand.c_str());
system(mycommand.c_str());
//Create .pdf
mycommand = "dvipdf " + filename + "_main.dvi";
system(mycommand.c_str());
Which then produces the following error message on the terminal output:
sh: latex: command not found
sh: latex: command not found
sh: dvipdf: command not found
I have searched this online but I have failed to find a solution for this problem, though I believe it is likely to be something very simple.
I am working on OSX and have the following version of latex installed:
pdfTeX 3.1415926-2.4-1.40.13 (TeX Live 2012)
kpathsea version 6.1.0
All help is greatly appreciated!
First, the path to the programs latex and dvipdf needs to be in your PATH environment variable.
Second, the calls of the shell via system are totally independent (in fact a new instance of the shell is started each time). So if you switch the directory in one, this does not affect the others. Switch instead the current directory of your program via:
chdir(directory.c_str())
You need for this
#include <cunistd>
using namespace std;
at the beginning of the file.
Please note that system calls with command lines depending on input parameters can be easily exploited to run arbitrary commands if the parameters (in your case the filename) are not carefully checked. As you do not have quotes, the program fails if there are e.g. whitespaces in the filename.

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.

DOS-reported error: Bad file number

I have a batch file that tries to compile a static library using Borland C++ Builder 6.0
It is called from Borland make (makefile created with bpr2mak) which is called from a .bat file (used to compile the whole project with Visual Studio and some Borland C++ Builder legacy projects), which is called from a bash shell script running inside Cygwin.
When I run the .bat file directly from a Cygwin shell, it runs OK, but when its being run from a Program calling cygwin with Boost::Process::launcher I'm getting this error:
C:\ARQUIV~1\Borland\CBUILD~1\Bin\..\BIN\TLib /u bclibs.lib #MAKE0000.###
DOS-reported error: Bad file number
TLIB 4.5 Copyright (c) 1987, 1999 Inprise Corporation
opening 'MAKE0000.###'
** error 1 ** deleting bclibs.lib
It's a complicated scenario, but this Program which calls cygwin is run whenever we need to build our software package which needs to be build for various Linux distos and Windows 32 and 64-bit.
Note: It's the only Borland Project failing, the other compile just fine (it's the only static library using borland also, so it can be some problem with the TLib tool.
The problem was that TLib does not like to have his output redirected (seen here) without having an input pipe as well. Solved by creating an input pipe to in the Boost::Process::launcher using set_stdin_behavior
I'm just guessing here, but this may have to do with long filenames and/or spaces in paths.
1) Modify your makefile so it would save current environment to a file, immediately before executing the failing command (set > d:\env.txt & echo CD=%CD% >> d:\env.txt). Then run it both ways (directly and via program) and compare the environments of good run and bad run.
2) Using filemon from Sysinternals, capture logs of disk access in both cases (these logs are going to be huge, though you can uncheck everything except Open in the filter to reduce the size). Again, compare and check for clues...
3) Try instaling everything involved to paths conforming to 8.3 scheme.
This error is not related to C++ itself. It happens when your build script opens too much files (more than defined in DOS command processor environment). To resolve this issue try to set value of files variable to 253. For Windows XP this variable defined in the file %WINDIR%\system32\config.nt.
files=253
Seems it is known bug in Borland C++ tools. Here is description and possible workaround for this issue:
Problem: Some static Lib projects will
not link correctly when compiled. You might see something
like this :
J:\Borland\CBUILD~1\bin\..\BIN\TLib /u debug\jpegD.lib #MAKE0000.###
DOS-reported error: Bad file number
TLIB 4.5 Copyright (c) 1987, 1999 Inprise Corporation
opening 'MAKE0000.###'
** error 1 ** deleting debug\jpegD.lib
MAKE failed, returned : 1
Workaround : In some cases (where the "Bad file number" error is seen) it may be possible to work around this by specifying -tDEFLIB.BMK in the BPR2MAKE Options field, and Turning off the "Capture Make Output" option.
I have not tested it, but I hope that helps.