c++ for unix command line operation - c++

I have a remote unix shell which I log on often to checkout files with but the system keep resetting my locals setting when I logon to it.
I was planning to write the code to execute a list of commands when I log on.
#include<iostream>
#include<stdlib.h>
int main(){
char javah[]="JAVA_HOME=/appl/usr/jdk/jdk1.6.0_20";
char anth[]="ANT_HOME=/appl/usr/ant/instances/1.8.2";
char path[]="PATH=$ANT_HOME/bin:$PATH";
system("bash");
system("cd");
system("cd insurancePPC.11");
system("0x0C");
system("ls");
putenv(javah);
putenv(anth);
putenv(path);
std::cout << "JAVA_HOME=" << getenv("JAVA_HOME");
std::cout << "\n";
std::cout << "ANT_HOME=" << getenv("ANT_HOME");
std::cout << "\n";
std::cout << "PATH=" << getenv("PATH");
std::cout << "\n";
system("cd tools");
std::cout << "command executed successfully...\n";
return 0;
}
Can anyone tell me why this wasn't working as expected?

cd is a built in command of the shell and only affects the current process (i.e. the current running shell.)
When you run system("cd insurancePPC.11"); it starts a new shell, that new shell changes the directory to insurancePPC.11 and exits. Your own process is unaffected by that cd command.
You are much better off writing these commands in a text file and run it as a shell script via the source command.
Create a file named myenv.sh with this content:
JAVA_HOME=/appl/usr/jdk/jdk1.6.0_20
export JAVA_HOME
ANT_HOME=/appl/usr/ant/instances/1.8.2
export ANT_HOME
PATH=$ANT_HOME/bin:$PATH
export PATH
cd
cd insurancePPC.11
ls
echo JAVA_HOME=$JAVA_HOME
echo ANT_HOME=$ANT_HOME
echo PATH=$PATH
cd tools
And from your command line run source myenv.sh Or if your shell supports it, use the shorthand . myenv.sh

There's no need to write a C program here. Just save the following as mysettings.sh:
export JAVA_HOME=/appl/usr/jdk/jdk1.6.0_20
export ANT_HOME=/appl/usr/ant/instances/1.8.2
PATH=$ANT_HOME/bin:$PATH
cd tools
When you log in, run
. mysettings.sh

Related

How to access to an output file with Docker

I'm writting a C++ program, and want to use Docker on it. The Dockerfile looks like the following:
FROM gcc:7.2.0
ENV MYP /repo
WORKDIR ${MYP}
COPY . ${MYP}
RUN /bin/sh -c 'make'
ENTRYPOINT ["./program"]
CMD ["file1", "file2"]
This program needs two input files (file1 and file2) and is built and executed with as follows:
docker build -t image .
docker run -v /home/user/tmp/:/repo/dir image dir/file1 dir/file2
These input files are located in the host in /home/user/tmp/. In the original repository (repo/), the executable is located in its root directory, and the output file generated is saved in the same folder (i.e. they look like repo/program and repo/results.md).
When I run the above docker run command, I can see from the standard output that the executable is reading correctly the input files and generating the expected results. However, I hoped the written output file (generated by the program with std::ofstream) to be also saved in the mounted directory /home/user/tmp/, but its not.
How can I access this file? Is there a straightforward way to get it using the docker volume mechanism?
Docker version is 18.04.0-ce, build 3d479c0af6.
EDIT
The relevant code regarding how the program saves the output file result.md is the following:
std::string filename ("result.md"); // in the actual code this name is not hard-coded and depends on intput, but it will not include / chars
std::ofstream output_file;
output_file.open(filename.data(), std::ios::out);
output_file << some_data << etc << std::endl;
...
output_file.close();
In practice, the program is run as program file1 file2, and the output will be saved in the working directory, not matter if its the same where program is placed or not.
You need to be sure to save your file into the mounted directory. Right now, it looks like your file is being saved as a sibling to your program which is right outside of the mounted directory.
Since you mount with:
docker run -v /home/user/tmp/:/repo/dir image dir/file1 dir/file2
/repo/dir is the only folder you will see changes to. But if you are saving files to /repo, they will get saved there, but not seen on the host system after running.
Consider how you open your output file:
std::string filename ("result.md"); // in the actual code this name is not hard-coded and depends on intput, but it will not include / chars
std::ofstream output_file;
output_file.open(filename.data(), std::ios::out);
output_file << some_data << etc << std::endl;
...
output_file.close();
Since you set the output file to "result.md" with no path, it is going to be opened as a sibling to the program.
If you were to run
docker run -it --rm --entrypoint=/bin/bash image
which would open an interactive shell using your image and then run ./program some-file.text some-other-file.txt and then ran ls you would see the output file result.md as a sibling to program. That is outside of your mountpoint, which is why you don't see it on your host machine.
Consider this program. This program will take an input file and an output location. It will read in each line of the infile and wrap it in <p>. /some is the repository directory. /some/res/ is the folder that will be mounted to /repo/res/.
I provide 2 arguments to my program through docker run, the infile and outfile both of which are relative to /repo which is the working directory.
My program then saves to the outfile location which is within the mountpoint (/repo/res/). After docker run finishes, /some/res/out.txt is populated.
Folder structure:
.
├── Dockerfile
├── README.md
├── makefile
├── res
│   └── in.txt
└── test.cpp
Commands run:
docker build -t image .
docker run --rm -v ~/Desktop/some/res/:/repo/res/ image ./res/in.txt ./res/out.txt
Dockerfile:
FROM gcc:7.2.0
ENV MYP /repo
WORKDIR ${MYP}
COPY . ${MYP}
RUN /bin/sh -c 'make'
ENTRYPOINT ["./test"]
CMD ["file1", "file2"]
makefile:
test: test.cpp
g++ -o test test.cpp
.PHONY: clean
clean:
rm -f test
test.cpp:
#include <fstream>
#include <iostream>
#include <string>
int main(int argc, char **argv) {
if (argc < 3) {
std::cout << "Usage: test [infile] [outfile]" << std::endl;
return 1;
}
std::cout << "All args" << std::endl;
for (int i = 0; i < argc; i++) {
std::cout << argv[i] << std::endl;
}
std::string line;
std::ifstream infile(argv[1]);
std::ofstream outfile(argv[2]);
if (!(infile.is_open() && outfile.is_open())) {
std::cerr << "Unable to open files" << std::endl;
return 1;
}
while (getline(infile, line)) {
outfile << "<p>" << line << "</p>" << std::endl;
}
outfile.close();
return 0;
}
res/in.txt:
hello
world
res/out.txt (after running command):
<p>hello</p>
<p>world</p>
I would like yo post the Dockerfile I'm using right now, in the hope it can be useful to somebody. It doesn't need to specify a name or path for output files. Output files are always written in $PWD.
FROM alpine:3.4
LABEL version="1.0"
LABEL description="some nice description"
LABEL maintainer="user#home.com"
RUN apk update && apk add \
gcc \
g++ \
make \
git \
&& git clone https://gitlab.com/myuser/myrepo.git \
&& cd myrepo \
&& make \
&& cp program /bin \
&& rm -r /myrepo \
&& apk del g++ make git
WORKDIR /tmp
ENTRYPOINT ["program"]
I only need to run:
docker run --rm -v $PWD:/tmp image file1 file2
Inside the image, the working directory is tmp and cannot be changed, which is the one passed to the volume -v option. After running the image, all output files will be saved in the corresponding working directory of the host machine.
How about simply copying the files from the container to the host machine. This is the simplest solution that worked in my case.
sudo docker cp container-id:/path_in_container local_machine_path
container-id is the id of your docker container which can be found with docker ps if it's running or docker ps -a if it is stopped.
path_in_container is the path of the file in the container
local_machine_path is the path on your device/computer that you are working with. Please note that this has to be absolute path
Here's a working example:
sudo docker cp f1be7fe58g36:/app/Output/output_plan1.pdf' /Users/hissaan/Programming/Clients Data/testing_this.pdf'
Solution was tested on mac (m1 pro)

How can I launch Mozilla Firefox using C++?

Compiled through compiler like Code::Blocks, I have tried the following, bit it does not work:
/*Running Firefox.exe*/
#include <stdio.h>
/*using c++*/
#include <iostream>
#include <stdlib.h>
using namespace std;
int main ()
{
int x;
cout << "Checking if processor is available..." << endl;
/*System used here*/
if (system(NULL)) puts ("Proceed");
else exit (1);
cout<< "Executing Firefox..." << endl;
/*Having some error here saying not recognized as internal or external command*/
x = system ("C:/Program Files (x86)/Mozilla Firefox/firefox.exe");
/*cout here*/
cout <<"The value returned was:" << x << endl;
return 0;
}
Is it because Firefox is not recognized as a system of windows? If so how can I run Firefox, or even Internet Explorer from code?
Run cmd.exe (Windows command shell) and enter the string C:/Program Files (x86)/Mozilla Firefox/firefox.exe at the command line, and you will see the same problem - i.e. the problem is with your command string rather than your C++ code.
The space in the path requires the command string to be quoted:
system ("\"C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe\"") ;
or
system ("\"C:/Program Files (x86)/Mozilla Firefox/firefox.exe\"") ;
I believe you need to convert path to DOS format
Launch a command prompt cd into Mozilla Firefox folder
run this: for %I in (.) do echo %~sI
Copy the output to system command with \ replaced with \\ append firefox.exe at end
Is it because Firefox is not recognized as a system of windows?
If you open up cmd.exe and type in C:/Program Files... it won't work because spaces are used as a delimiter. Quote your path:
system("\"C:/Program Files (x86)/Mozilla Firefox/firefox.exe\"");
Although if you're targeting Windows you should consider using CreateProcess which saves you this trouble.
If so how can I run Firefox, or even Internet Explorer from code?
If you want to show a web page, use ShellExecute* and let the shell do the work. It will take care of launching Firefox, Internet Explorer, Chrome, or whatever browser the user has configured to view web pages.
*Read the Remarks section about initializing COM, first.
Try using windows API CreateProcess API

Nodejs and UNIX newbie: run node command in a cpp program

I'd like to run a nodejs program through the system() function in stdlib.h. I can run the bash command /usr/local/bin/node ~/some_folder/xml2js.js in terminal, but when I ran this:
int main(int argc, const char * argv[])
{
// insert code here...
//system("/usr/local/bin/node ~/some_folder/xml2js.js");
system("~/some_folder/run.sh");
std::cout << "Hello, World!\n";
return 0;
}
It told me node: command not found.
the run.sh is below:
#! /bin/bash
node ./xml2js.js
Are there any other ways to call other programs in UNIX? And how to get the output of the command into stdout?
Try writing the absolute path to that script. It should work.
You could try system("/home/$(whoami)/some_folder/run.sh") assuming that your user's home folder is in /home.
Also, does that script have execute permissions? Also, check the return code of system.

Can t see the output of my c++ program (debian)

This might be a dumb question but...
I am programming some stuff in C++, it compile well on g++, but when I start the binary, there is nothing printed, even if I redirect the output in a file.
Example:
print.cpp
#include <iostream>
using namespace std;
/*...*/
int main ()
{
//Table tab;
//tab.set_all('_');
//tab.setc(1, 1, 'c');
//tab.setc(10, 5, 'd');
cout << "print" << endl;
//tab.print();
cout << "end" << endl;
return 0;
}
In shell:
>g++ print.cpp -o print
>print
>print > t
>cat t
>
Is it a problem in my code, or do I start my program in the wrong way?
By typing print in your shell you are executing the print command, which is a built-in of your shell that prints nothing without any arguments.
To launch your binary, type ./print. This solves the confusion between the print command and the binary print in the current directory.
If you just call
> print
you are actually executing /usr/bin/print, that from the man page is
NAME
run-mailcap, view, see, edit, compose, print - execute programs via entries in the mailcap file
Tu run your code you should do one of these three things:
If from the same directory
> ./print
From an other directory
> /path/to/exe/print
Add the directory where the exe live (/path/to/exe/) in the PATH before /usr/bin
> export PATH=/path/to/exe:$PATH
> print
If you want to add it permanently, just add export PATH=/path/to/exe:$PATH to you ~/.profile file
print is the name of a program from mailcap package. Typing print into the shell and hitting the Return key will execute it (from /usr/bin/print). Start your program by typing ./print.

How To Use C++ CGI Script?

I am currently enrolled in a web applications class at my college and we are learning about cgi scripts. I am having a hard time learning how to implement my CGI script. When I click on my link a window pops up asking me to download my helloworld.cgi file instead of just redirecting.
HTML:
<html>
<body>
click me
</body>
</html>
C++:
#include <iostream>
using namespace std;
int main(){
cout << "Content-type: text/html" << endl;
cout << "<html>" << endl;
cout << " <body>" << endl;
cout << " Hello World!" << endl;
cout << " </body>" << endl;
cout << "</html>" << endl;
return 0;
}
The CGI script is stored at /user/local/apache2/cgi-bin/helloworld.cgi
You need to compile the C++ file, and call the result helloworld.cgi. C++ is not a scripting language -- you can't just deploy it to your server.
On a typical *nix system, name the C++ file helloworld.cpp
gcc -o helloworld.cgi helloworld.cpp
Then put that file in your cgi-bin
Edit: you need two endl's after the last header item
cout << "Content-type: text/html" << endl << endl;
/user/local/apache2/cgi-bin/helloworld.cgi is the physical path of the file on your hard disk. To run the script through Apache, you need to specify the path relative to your server's document root, for eg. http://localhost/cgi-bin/helloworld.cgi.
I had this problem too, and this solution worked for me :
First run this commands on terminal:
sudo a2enmod cgi
sudo service apache2 restart
Then copy helloworld.cgi to /usr/lib/cgi-bin/
sudo cp helloworld.cgi /usr/lib/cgi-bin/
And finally change href link to:
click me
You just need to configure Apache to recognise a cgi-bin properly...
Have a read of this: http://httpd.apache.org/docs/1.3/howto/cgi.html
In Apache config ScriptAlias is probably what you want.
(I'm assuming you've compiled the binary to helloworld.cgi)