C++ exec executed bash scripts stops randomly - c++

I'm executing a bash script via execvp but the script stops execution half-way.
Have a look at my code:
int main()
{
char* params[2];
//First Parameter has to be the executable path
params[0] = (char*) ::malloc(sizeof(char) * 40);
::strcpy(params[0], "/home/test.sh");
//execv needs an null pointer as last argument
params[1] = NULL;
//Execute target executable
::execvp(params[0], params);
//Only if ::exec() returns: output error
std::cout << "Exec Failed!";
exit(1);
}
I used the following bash script for testing:
#!/bin/bash -vx
echo "1" >> /home/out.txt
echo "2" >> /home/out.txt
echo "3" >> /home/out.txt
echo "4" >> /home/out.txt
echo "5" >> /home/out.txt
exit 0
Most times the script doesn't even execute, means no file is being created or nothing is being written into an existing file. Somtimes, however the script executes partially or even complete meaning the textfile contains
1
up to
1
2
3
4
5
But no matter what happens inside the bash script the application always exits with error code 0.
Why is this happening?
If i execute the bash script manually everything works fine reaching the end of my script every time. Therefore, i assume it has to do something with my execvp call instead of the bash script.
I'm running, therefore tested the program on an beaglebone black system (am335x) with debian 8.6.

here is what I did to make this program work:
Note: I re-wrote it in C
The proposed C code:
#include <stdio.h> // perror()
#include <stdlib.h> // exit()
#include <string.h> // strcpy()
#include <unistd.h> // execvp()
int main( void )
{
char* params[2];
//First Parameter has to be the executable path
params[0] = "/home/rkwill/rtest.sh";
//execv needs an null pointer as last argument
params[1] = NULL;
//Execute target executable
execvp(params[0], params);
perror( "execvp failed" );
exit(1);
}
then, in my user directory: /home/rkwill/
touch rtest.sh
then edited 'rtest.sh' to contain:
#!/bin/bash -vx
# generate file if not already in existence
touch /home/rkwill/out.txt
echo "1" >> /home/rkwill/out.txt
echo "2" >> /home/rkwill/out.txt
echo "3" >> /home/rkwill/out.txt
echo "4" >> /home/rkwill/out.txt
echo "5" >> /home/rkwill/out.txt
exit 0
Then made the bash script executable via
chmod 777 rtest.sh
Note: I used the directory /home/rkwill because I do not have permission to write in the /home directory.
the first time I ran the program the resulting 'out.txt file contained
1
2
3
4
5
each successive run appended a repeat of the above output to 'out.txt'

Related

Trying to print current working directory on my shell prompt, output keeps printing more than necessary

I am working on building a small shell project and am currently working on displaying the prompt. The prompt should read: 1730sh:[current working directory]$
Whenever I run my code below, my prompt correctly shows the current directory and the prompt, but each time stdin is taken, the prompt and the current working directory are printed multiple times.
Here is my code snippet:
int main(){
char cmd[100], command [100], *param[20];
char *envp[] = {(char *) "PATH=/bin", 0}; //enviornment variables
/* Begin loop*/
while (true){
/* Display Prompt*/
char *cwd;
if ((cwd = getcwd(NULL, 0)) == NULL){
perror("getcwd() error");
}else{
cout << "1730sh:" << cwd << "$ ";
}
//delete[] cwd;
//free(cwd);
fgetc(stdin);
}
}
I've tried deleting cwd and freeing cwd but both do not help solve the issue. I want the prompt and the current directory to print once before stdin instead of multiple times.
Here is an example output:
1730sh:/home/ugrads/kadam/cs1730/Phillips-Kadam-Project4/src$ command
1730sh:/home/ugrads/kadam/cs1730/Phillips-Kadam-Project4/src$
1730sh:/home/ugrads/kadam/cs1730/Phillips-Kadam-Project4/src$
1730sh:/home/ugrads/kadam/cs1730/Phillips-Kadam-Project4/src$
1730sh:/home/ugrads/kadam/cs1730/Phillips-Kadam-Project4/src$
1730sh:/home/ugrads/kadam/cs1730/Phillips-Kadam-Project4/src$
1730sh:/home/ugrads/kadam/cs1730/Phillips-Kadam-Project4/src$
1730sh:/home/ugrads/kadam/cs1730/Phillips-Kadam-Project4/src$
1730sh:/home/ugrads/kadam/cs1730/Phillips-Kadam-Project4/src$ command
Should I be using malloc()? I haven't tried that one.

How do I read input .in files in command line on windows

I completed my code but the problem is I don't know how to test it based on instructions given.
The instructor provided us with 3 input files with the following values:
file1: 33 20
file2: 5 7
file3: 18 15
I'm supposed to take these values and create event objects with these stored values. Problem is the instructor is giving the testing method on Ubuntu and she displayed how to input file in command line like:
./sApp < simulationShuffled3.in
So i'm just really confused as to how I'm suppose to get it working. I am currently using Windows console, VStudios and sublime text with a terminal attachment.
The code I'm currently using that's following from an example from my course notes is
while (getline(cin >> ws, aLine)) { // while (there is data)
stringstream ss(aLine);
ss >> arrivalTime >> processingTime;
Event newEvent = Event('A',arrivalTime,processingTime);
eventPriorityQueue.enqueue(newEvent);
}
Read input from stdin in Windows [&/or] Linux
You can do this in three ways:
In Command prompt (windows)
In Powershell (windows/linux)
In WSL & Linux
1: in Windows Cmd
type input.in | python file_requiring_input.py # in python
type input.in | go run file_requiring_input.go # in go
type input.in | node file_requiring_input.js # in js
javac file_requiring_input.java &&
type input.in | java file_requiring_input # in java
g++ file_requiring_input.cpp &&
type input.in | a.exe # in cpp
gcc file_requiring_input.c &&
type input.in | a.exe # in c
Another way
python file_requiring_input.py < input.in # in python
g++ file_requiring_input.cpp &&
a.exe < input.in # in cpp
2: in Powershell
gc .\input.in | python file_requiring_input.py # in python
g++ .\file_requiring_input.cpp ;
gc .\input.in | .\a.exe # in cpp
gc is short for Get-Content. Other aliases of gc are cat and type.
which means that all three names can be used as replacement or gc
3: use wsl for windows //Linux commands
cat input.in | python file_requiring_input.py # in python
g++ file_requiring_input.cpp &&
cat input.in | ./a.out # in cpp
another way
python file_requiring_input.py < input.in # in python
g++ file_requiring_input.cpp &&
./a.out < input.in # in cpp
have edited the code testing everything out hopefully. Do correct me if I am wrong or if anything more is to be added .
Also input.in is more generally a text file so you can create input.txt file as you wish and it would work the same
Well, as this is an assignment, I'm not going to provide you with a ready-made code. Rather, I'll just point you to the right direction.
In Windows, you can provide the arguments to your executable separated by space on Command Prompt like this:
C:\Assignment> Test.exe file1.in file2.in file3.in
And, it'll work on Ubuntu as well.
So, you need to study Command Line Arguments, File Handling, reading from file; and, you'll have to convert these strings read from files to integers.
Command Line Arguments: http://en.cppreference.com/w/c/language/main_function
File Handling: http://en.cppreference.com/w/cpp/io/basic_fstream
Here's a minimal example for reading from a file (std::ifstream):
I've a test file at C:\Test\Test.txt with the following contents:
11 22
12 23
23 34
Here's is main.cpp to test it:
#include <iostream>
#include <fstream>
#include <string>
int main( int argc, char *argv[] )
{
const std::string filename { R"(C:\Test\Test.txt)" };
std::ifstream ifs { filename };
if ( !ifs.is_open() )
{
std::cerr << "Could not open file!" << std::endl;
return -1;
}
int arrivalTime { 0 };
int processingTime { 0 };
while ( ifs >> arrivalTime >> processingTime )
{
std::cout << "Arrival Time : " << arrivalTime << '\n'
<< "Processing Time : " << processingTime << std::endl;
}
ifs.close();
return 0;
}
Output:
Arrival Time : 11
Processing Time : 22
Arrival Time : 12
Processing Time : 23
Arrival Time : 23
Processing Time : 34

how to turn program into deamon program

I sometimes write program like this to process offline data:
load_model() //this may cost lots of time
while(cin >> inputs)
{
result = process_input(inputs)
cout << result
}
release_model()
This works fine if I only have to process offline data. However, when the data comes one by one I am in trouble. Since I have to load the model everytime which is time consuming.
I wonder if there is any way to CONVERT this program into a service WITHOUT modify the program itself. For example, I can redirect the cin and cout to two named pipes:
program < namedpipe_in > namedpipe_out
The I can put the inputs into the namedpipe_in like this
cat input > namedpipe_in
and read the result in another pipe:
cat namedpipe_out
However, this solution will not work since once I cat something to the namedpipe_in, the pipe will be close after cat operation and the program exits.
My question is how to fix this problem and make the pipes looks more like a queue instead of a memory buffer.
Thanks for your time reading.
Perhaps I am misunderstanding your question; please correct me if this is not what you are looking for.
To simulate your example, I wrote a simple C++ program which just takes in each input string and reverses it:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::cout << ":start:" << std::endl;
std::string str;
while(std::cin >> str)
{
std::reverse(str.begin(), str.end());
std::cout << str << std::endl;
}
}
The output binary of my example program is strflipper.
I have another file called in.log which is just an input file which I created via touch in.log.
Now I call
tail -f in.log | ./strflipper > out.log
and if I add something to the input log in a different terminal, the output log gets adjusted as such:
$ echo "abc" >> in.log
$ echo "foo" >> in.log
$ echo "bar baz" >> in.log
$ cat out.log
:start:
cba
oof
rab
zab
which of course is my expected output. As long as I don't kill the program, anything I add into in.log will automatically be processed within that loop without killing or restarting strflipper.

How do I execute a string as a shell script in C++?

I'm writing a program that needs to be able to execute a shell script provided by the user. I've gotten it to execute a single shell command, but the scripts provided will be more complicated than that.
Googling got me as far as the following code snippet:
FILE *pipe;
char str[100];
// The python line here is just an example, this is *not* about executing
// this particular line.
pipe = popen("python -c \"print 5 * 6\" 2>&1", "r");
fgets(str, 100, pipe);
cout << "Output: " << str << endl;
pclose(pipe)
So that this point str has 30 in it. So far so good. But what if the command has carriage returns in it, as a shell script file would, something like the following:
pipe = popen("python -c \"print 5 * 6\"\nbc <<< 5 + 6 2>&1", "r");
With this my goal is that str eventually have 30\n11.
To put another way, assume I have a file with the following contents:
python -c "print 5 * 6"
bc <<< 5 + 6
The argument I'm sending to popen above is the string representation of that file. I want to, from within C++, send that string (or something similar) to bash and have it execute exactly as if I were in the shell and sourced it with . file.sh, but setting the str variable to what I would see in the shell if it were executed there, in this case, 30\n11.
Yes, I could write this to a file and work it that way, but that seems like it should be unnecessary.
I wouldn't think this was a new problem, so either I'm thinking about it in a completely wrong way or there's a library that I simply don't know about that already does this.
use bash -c.
#include <stdio.h>
int main()
{
FILE *pipe = popen("bash -c \"echo asdf\necho 1234\" ", "r");
char ch;
while ((ch = fgetc(pipe)) != EOF)
putchar(ch);
}
Output:
asdf
1234
(I've test on cygwin)

Piping input to an already running cpp program?

include
Lets assume that this is the code I am running:
int main(int argc, char **argv) {
bool running = true;
string lineInput;
while (running)
{
while (cin >> lineInput)
{
cout << lineInput;
}
}
return 0;
}
What I would like to have happen is that I can call start a program from terminal by typing "./myProgram" That part is fairly straight forward. The part I'm not sure how to do is make it so that I can at a later point in time type echo "some text to echo" | myProgram and be able to have my program then print that text back out to the terminal.
Right now I can only make it work if I type:
echo "blah blah blah" | ./myProgram
So my goal is to have two separate steps. One where I start my program, and a second when I pipe it some input to use
I'm thinking you could do this with a named pipe.
mkfifo mypipe
./myProgram < mypipe &
cat file1.txt file2.txt file3.txt > mypipe
You can use mkfifo, and just read from that in the program as from an ordinary file.
There's also
pipe or socket_pair (bi-directional)