System() function, and calling internet explorer from it, DevC++ - c++

I tried making a program that'd take website info, then feed it to system() to start website. I'm aware that characters like (\, ",') don't get fed to the output directly, so I used escape sequences.
I wrote this program, but the command prompt just refuses to go past C:\ path. But if I copy paste the command displayed by my program, internet explorer gets launched. But the case isn't so for my program. Can anybody tell me where is the error?
Here is my code:
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
cout<<"Please enter the website you wish to visit: ";
string website,web;
cin>>web;
web= " " + web;
website = "\"%ProgramFiles%\\Internet Explorer\\iexplore\""+web;
cout<<"\n"<<website<<endl<<endl<<endl;
system(website.c_str());
return 0;
}

You are using an environment variable, %ProgramFiles%, in your system command-line; these are specific to the MS-DOS prompt environment, and generally not available in system implementations.
I suggest replacing that with the full path, such as \"C:\Program Files\Internet Explorer\iexplore\", and see if that works.
If that works, then your implementation doesn't implicitly replace environment variables the way a full Command Prompt does, so you will need to query the environment variable separately and construct the path before you run system. See getenv for one possible way (I'm not sure what mingw32 supports, so you may have other options as well).
If that doesn't remedy the problem, I suggest checking if you can launch something simpler, like notepad.exe, to verify that there is nothing interfering with launching an application in general, such as your environment path or permissions.

Pass it in double double quotes:
website = "\"\"%ProgramFiles%\\Internet Explorer\\iexplore\"\""+web;
The system("something") call actually runs the command interpreter cmd in a way similar (but probably not identical) to cmd /c something. This has implications when there are spaces in the command name, see e.g this. I cannot tell exactly why single double quotes work when there's no environment variable involved, and do not work otherwise, but the fact is, double double quotes do work.
If you want to launch the user's preferred browser, consider calling
system("start http://" + websitename);
instead.

Get that environment variable value first.
#include <iostream>
#include <ShlObj.h>
int main() {
char pathToPf[MAX_PATH];
if (S_OK == SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, pathToPf))
std::cout << pathToPf << std::endl;
return 0;
}
See SHGetFolderPath documentation...
Note that I was lazy and using the ASCII version of this function. Use it without the A postfix and deal with the conversation ;)

Related

how to pass on some output from a c++ program to the shell so that it can be used in the shell

Is there any good way i can make some data created by my c++ program available to the shell after exiting the program?
I have a c++ program, inside which i have a string containing a path:
std::string path = "/home/some/path"
I want this path to be available after the c++ program exits main and i am returned to the shell, so that i can use that path (e.g. cd to that path).
I have considered/tried the following approaches:
I tried making an environment variable in c++ program using setenv(). However the environment variable only exists while in the c++ program, and it is apparently not possible to make those changes visible in the shell after exiting the program.
(considered) writing the path to a temporary file, so that a bash script could later access the details of the path from it. However i have read many suggestions to not do that due to security vulnerabilities.
I tried calling the bash script from within the c++ program, using system(). This does not work if i try to cd to that directory (exiting the program will keep me in the same directory as before).
I figure that if i am desperate, i could have my program cout the path, and use the solutions as described here:
$ ./program | tee output.txt
Then the path is stored inside the file. This works technically, but has the undesirable effect of creating a file and printing the path to the screen, and is basically creating a temporary file.
another option to, again, cout in my program, and use command substitution. running in the shell
$ var=$(./program)
storing the path in var. This didnt work because my program does many things including requiring user input before calling
std::cout<< path << std::endl;.
Particularly, i have observed this approach to not display a curses window, which is required for the program.
the only solution that has worked is piping the output to tee.
Environment variables are only an input, they cannot be used to return any information from a program.
You are already using std::cin and std::cout for user input, and std::cerr should be reserved for error messages. However, you can have the shell open more filedescriptors, and have your program write to those. However, doing this with pure C++ is not possible. But if you don't mind using POSIX C functions:
#include <cstdio>
int main() {
FILE *f = fdopen(3, "w");
fprintf(f, "some path\n");
}
And then use it like so:
./program 3> output.txt
This of course creates an undesirable file. I don't think there is any way to store the output from an extra filedescriptor directly to a variable in bash. However, you could create a temporary file inside /dev/shm, so it will never be written to disk, or create a FIFO object and redirect the output from the program to the FIFO, and then read it back. For some examples of how to do this, see this question.
You could write the output that you want the user to see to stderr instead of stdout. Only output what you need your shell script to see to stdout:
#include <iostream>
int main() {
std::clog << "Enter data: "; // clog prints to stderr like cerr
std::string line;
std::getline(std::cin, line);
std::cout << line << '\n';
}
Then this will work:
var=$(./program)

How do I fix opening terminal error with c++ ncurses

I'm using CLion 2018.2.6 on MacOS. I'm trying to use ncurses but getting the error "Error opening terminal: unknown." I'm not sure how to fix this. Any help appreciated. Code below.
#include <iostream>
#include <ncurses.h>
using namespace std;
int main(){
initscr();
clear();
printw("Seems legit!");
refresh();
getch();
endwin();
}
The initscr manual page mentions this:
Unset TERM Variable
If the TERM variable is missing or empty, initscr uses the value "unknown", which normally corresponds to a terminal entry with the generic
(gn) capability. Generic entries are detected by setupterm (see
curs_terminfo(3x)) and cannot be used for full-screen operation. Other
implementations may handle a missing/empty TERM variable differently.
Also, depending on how your system is configured, ncurses may not even find the terminal database, e.g., if it is installed in a different location than the compiled-in default location. Like TERM, that can be fixed using the TERMINFO or TERMINFO_DIRS environments. As an additional complication, MacOS by default uses case-insensitive filesystems, and ncurses uses a different directory organization for that. The term(5) manual page mentions that:
A small number of terminal descriptions use uppercase characters in
their names. If the underlying filesystem ignores the difference
between uppercase and lowercase, ncurses represents the "first character" of the terminal name used as the intermediate level of a directory
tree in (two-character) hexadecimal form.
Check the path of terminfo folder in the application running system and the same path in your application like this,
Ex:- setenv("TERMINFO","/usr/share/terminfo", 1);
It working.

Include file read from terminal into function using #include

I have written a code which reads in mathematical functions from a text file which are in a C++ compatible format and applies mathematical operations to them. This is a brief summary of the code. I am aware that #include is a preprocessor directive so once the contents of the file have been read in it compiles the code via a bash script each time.
double myfunc(long double x){
return
#include "/.../filename"
}
int main{
"Maths stuff happens here"
}
This works as intended, but I want to be able to speed the process up and read the filename from the terminal rather than entering it into the script each time. To do this I tried using the following:
int g_argc;
char **g_argv;
void process_command_()
{
filename=argv[1]
}
double myfunc(long double x){
return
#include filename
}
int main{
"Maths stuff happens here"
}
It was somewhat of a stretch to think this would work, but I am unsure of how to read the filename from the terminal into my function as though I had typed it in myself due to the function being outside of int main(). I have looked around StackExchange and have found similar problems but none of the solutions has worked for my case.
Any help is greatly appreciated.
Edit for clarity This code is a numerical integration code which takes a very large integrand as input from a text file and the integration is done using the CUBA library. I moved the process from Maple into C++ to get a speed and accuracy increase. The script works wonderfully and can replicate known values ~ 400 times faster than what Maple/Mathematica can do.
Perhaps the easiest way for you would be this.
double myfunc(long double x){
return
#include MY_FILENAME
}
Then when you the compiler in process_command(), pass it an additional argument:
"-DMY_FILENAME=/path/to/your/file"
This is a string you need to build out of argv[1] or whatever stores your filename.
If you invoke a bash script that invokes the compiler, you need to pass your filename as an argument to the script, and arrange for the script to pass it along with -DMY_FILENAME= to the compiler itself.
WhiZTiM's comment/link made me realise this is a really silly question, so apologies for wasting your time. What I want can be done in the bash script. I just define a placeholder in the main.cpp
double myfunc(long double x){
return
#include <filename>
}
Next I put together a simple bash script to copy the main.cpp run file to the directory where the input .txt file is and using sed's find and replace command it switches the filename in main.cpp for the actual file which is taken from the terminal:
input_file=( "$PWD/${#}" )
cp ${HOME}/.../main.cpp $PWD
sed -i "s|filename|${input_file}|g" main.cpp
And then compile and run commands at the end of the script.
Thank you for all your help with this question. I can't believe I didn't see the solution was so simple.

Executing a command from C++, What is expected in argv[0]?

I am using execv() to run commands from /bin/ such as 'ls', 'pwd', 'echo' from my c++ program, and I am wondering what value I should provide in argv[0];
const char * path = getPath();
char ** argv = getArgs();
execv(path,argv);
argv[0] is supposed to be the program name. It's passed to the program's main function. Some programs differentiate their behavior depending on what string argv[0] is. For example the GNU bash shell will disable some of its features if called using sh instead of bash. Best give it the same value that you pass to path.
In linux, argv[0] is the process name displayed by the top utility (which it probably gets from reading entries in /proc/)
argv[0] should be the full path of the command that you want to run.
I know that this is not the answer you're looking for but is there a specific reason why you're doing this? The reason I ask is that most if not all of the actions people normally run with either system() or execv() are available in libraries on either Windows or Unix and are safer, faster and less likely to suffer from circumstantial errors. By that I mean, for example, when the PATH changes and suddenly your code stops working.
If you're passing in a string, either in whole or in part, and running it then you also leave yourself open to a user gaining access to the system by entering a command that could be damaging. E.g. imagine you've implemented a file search using find /home -name and your user types in:
"%" -exec rm {} \;
Ouch!

Link Checker With ShellExecute?

I've been tasked with going through a database and checking all of the links, on a weekly schedule. I normally work in PHP, but doing this in PHP would be very slow (it actually would timeout the page after about 100 URLs), so I decided to make a quick C++ app.
Admitidly, I haven't used C++ since college, so I'm a bit rusty.
I found the ShellExecute function, and that it would open the page no problem. Here is what I have so far:
#include <shlobj.h>
#include <iostream>
using namespace std;
int main()
{
if( ShellExecute(NULL,"find","http://example.com/fdafdafda.php",NULL,NULL,SW_SHOWDEFAULT) )
{
cout << "Yes";
} else {
cout << "No";
}
cout << endl;
system("PAUSE");
return 0;
}
The problem is that it always returns true, whether it is opening a valid page or not. It appears to be checking if the associated app (a browser in this case) is able to open the document with no problems, then returns true. It isn't looking to see if the browser is getting a 404 or not, it simply sees it open and run and is fine.
Is there a better way to do this? Am I missing a step?
As an aside, I have attempted to use the cURLcpp stuff, but can't seem to figure it out. All of the examples point to header files that don't exist in the download. I have a feeling cURLcpp is the better way to do this.
Thanks for any help.
I think you answered your own question. ShellExecute is really not appropriate for this task, and something like CURL would be better.
or if you don't want to use an external library you can check directly with InternetOpen, InternetOpenURL etc.
Documentation on the return value of ShellExecute :
If the function succeeds, it returns a value greater than 32. If the function fails, it returns an error value that indicates the cause of the failure. The return value is cast as an HINSTANCE for backward compatibility with 16-bit Windows applications. It is not a true HINSTANCE, however. It can be cast only to an int and compared to either 32 or the following error codes below.
See ShellExecute documentation.
And yes, CURL would be better.