I want to make a program that executes programs from the main argument.
Let's say I have the program progr1.c and progr2.c running . Now I compile the program progr3.c using the other two programs as arguments. This should be the result :
./progr3 progr1 progr2
Result of progr1
Result of progr2
This is what I have done so far :
void main (int args , char **s) {
int i , x , status;
if (args >= 2) {
x = fork ();
for ( i = 1 ; i < args ; i++) {
if (x == 0) {
execv (s[1],s);
}
else
{
wait (&status);
_exit(i);
}
x= fork();
}
}
_exit(0);
}
This code only does the output of the first argument program. So Im guessing fork() and execv() are not working together as I wanted them to . How can I change the program inorder to do what I want?
When you run
execv (s[1],s); // That should have been s[i]
prog3 is replaced by prog1. Hence, the logic of prog3 is lost.
You need to use fork and then execv on the child process if you want to retain the logic of prog3.
If you are interested in just the output of prog1 and prog2, you can use system(s[i])
Update
A working example using fork.
#include <unistd.h>
int main()
{
char* programs[] = {"/usr/bin/ls", "/usr/bin/date"};
char* args[] = {NULL, NULL};
for (int i = 0; i < 2; ++i )
{
int pid = fork();
if ( pid )
{
// Child
args[0] = programs[i];
execv(programs[i], args);
}
}
}
execv replaces the current process with the command specified.
Instead, use system to create a new process. No need for forking either:
int system(const char *command)
Related
I have a C program (let's call it "progam1") as well as 3 input files (say "in1.txt", "in2.txt", in3.txt") and 3 initially empty output files ("out1, "out2","out3") that represent operations on various polygons.
From progam1::main, I call fork 3 times, and within each child process, I use dup2 to redirect standard input/output into one of the input/output files, and then call execve("helper",...), where helper is another C program that parses the input, does some calculations, and prints output.
The problem I can't seem to solve is whenever I call execve(helper,...) more than once, the first call works fine (input/output is as I'd expect), but then something goes wrong; I seem to either end up with a file helper.exe.stackdump, or the system continually prints the same data to an output file, or some other unexpected result.
As an experiment, I wrote another C program - "simpleWrite.c", which simply copies the input to the output. I'm running all these programs using cygwin.
If I pass simpleWrite to all 3 execve calls in program1,
then everything works fine (all 3 redirected inputs are copied to the
3 output files as expected).
If I pass simpleWrite to one child (say the 3rd child) and run ./program1 from the terminal, then the system finishes and the 1st and 3rd child processes work as expected. The 2nd output is empty, and I end up with a file "helper.exe.stackdump" in my directory.
If I only pass helper to all 3 children execs and run ./program1 from the terminal, then the system never finishes. When I check the output files, one output is as expected, one output is empty, and one output prints the correct data infinitely many times.
Can anyone can explain what's likely going on!? Or explain what a stackdump file is and how to inspect it, or suggest how I can do to fix this?
Here is a general idea of what my code looks like:
//program1.c
#define INPUT1 "in1.txt"
#definte OUTPUT1 "out1.txt"
// same for rest of input/output files
char* my_argv[2];
int main(int argc, char* argv[])
{
char prog_name[20] = "helper";
char prog_name2[20] = "simpleWrite";
my_argv[0] = "helper";
my_argv[1] = NULL;
pid_t pid1, pid2, pid3, pid;
int status;
if ((pid1 = fork()) < 0) {
printf("Failed to fork process 1\n");
exit(1);
}
else if (pid1 == 0)
{
// redirection here for the child only
int fd_in = open_file_desc(INPUT1);
int fd_out = open_file_desc(OUTPUT1);
dup2(fd_in, 0);
dup2(fd_out,1);
close(fd_in);
close(fd_out);
execve(prog_name, my_argv, NULL);
//alternately, execve(prog_name2, my_argv, NULL);
}
if ((pid2 = fork()) < 0) {
//...
}
else if (pid2 == 0)
{
int fd_in2 = open_file_desc(INPUT2);
int fd_out2 = open_file_desc(OUTPUT2);
...// same idea as above
}
// likewise for pid3
...
//back in parent process
pid = wait(&status);
printf("\n***Parent detects process %d was terminated ***\n", pid);
pid = wait(&status);
printf("\n*** Parent detects process %d was terminated ***\n", pid);
pid = wait(&status);
printf("\n*** Parent detects process %d was terminated ***\n", pid);
// dup2(sav_stdin, 0);
// dup2(sav_stdout, 1);
// dup2(sav_stderr, 2);
exit(0);
}
//helper.c
enum POLYGON { HEXAGON = 6, HEPTAGON = 7, OCTAGON = 8 };
struct point {
short *X, *Y;
};
struct polygon
{
enum POLYGON type;
struct point points;
};
struct Node {
struct polygon* poly;
struct Node* next;
};
struct Node *HEAD = NULL;
struct Node *TAIL = NULL;
int main()
{
int lastCommand = 0, polygonscreated =0, newPolygonBit;
//other variables needed for parsing/calculations
while (!lastCommand)
{
scanf("%llx", &input);
//parsing stuff
if (newPolygonBit == 1)
{
polygonscreated = polygonscreated+1;
scanf("%llx", &setOfPoints1);
scanf("%llx", &setOfPoints2);
struct polygon* polyptr = createPolygon(polyType, setOfPoints1, setOfPoints2);
func[ADD_POLYGON](polyptr);
}
lastCommand = input & 1;
}
freeList(HEAD);
printf("Created %d polygons", polygonscreated);
return polygonscreated;
}
//simpleWrite.c
int main()
{
char c;
while( read(0, &c, 1) > 0){
write(1, &c,1);
}
return 0;
}
I had a similar problem with a similar code.
My problem was that I expected my child process to execute in a specific order. In this case let's say you want your 3 child to execute as follow:
-Child A
-Child B
-Child C
But the scheduler might execute them in a different order. Let's say A-C-B.
I hope this can help.
I have a C program that computes the next prime number after 100, I need to execute this program using execlp function. The prime number program and execlp function are both different files but are in the same directory. Any help is appreciated, below is my code for execlp function and my C program. I've already tried running the program using execlp, but it doesn't seem to work. I've included the path, the program to run and NULL as arguments.
//Main program, that runs execlp function
int main(int argc, char *argv[]) {
int pid;
int start=0;
pid = fork(); /* fork a child process */
if(pid > 0) { /* parent continues here */
count(start, 'P');
wait(NULL); /* to get printing done before shell prompt */
} else if(pid == 0) { /* child got here */
execlp("/home/student/Documents/FIT2100/PRAC3/", "./primeNum",
NULL); /* execute primeNum program*/
} else { /* there is a problem with fork */
perror("Failed to fork a process\n");
exit(1);
}
}
//Prime number program, filename is called primeNum.c
int main() {
bool isPrime = false;
int counter = 0;
int inputNum;
inputNum = 100;
while(isPrime == false){
inputNum += 1;
for(int i = 1; i <= inputNum; i++){
if(inputNum % i == 0){
counter++;
}
}
if(counter <= 2){
isPrime = true;
}
}
printf("Next prime after 100 is %d\n", inputNum);
}
The 'path' argument to execl() is the pathname of the executable, not the directory containing the executable. Making a guess, you probably need:
execlp("/home/student/Documents/FIT2100/PRAC3/primeNum", "primeNum", (char *)NULL);
The first argument is the absolute pathname of the program; the second is the string that will passed as argv[0]; the NULL (which should strictly be (char *)NULL or (char *)0 to avoid possible problems with #define NULL 0 — as shown) marks the end of the arguments. There's nothing to stop you using "pink elephant" as the argv[0] value if you want to.
A relative pathname is perfectly acceptable; if an open() call would find the executable file using the name, then it is OK for use with execl().
I have the below C code in linux (using gcc):
void doWho(void)
{
char entry[10];
int ret, i;
ret = read(0, entry, 10);
if (*entry == 'u')
{
for(i=0; i<3; i++)
{
execl("/usr/bin/who","who",NULL);
}
}
}
int main(int argc, char *argv[])
{
int childpid;
printf("Before it forks\n");
childpid = fork();
if(childpid == 0)
{
printf("This is a child process\n");
doWho();
exit(0);
} else
{
printf("This is the parent process\n");
wait(NULL);
}
return 0;
}
I want the parent process to keep waiting indefinitely and run "who" every time I press the "u" key. I only get the desired effect one time and then the child and parent processes exit. Any help on this?
Observe below loop :
for(i=0; i<3; i++)
{
execl("/usr/bin/who","who",NULL);
}
It doesn't matter how many times you rotate the loop , it will execute only once because when child process starts running(PCB created), you are calling function doWho then control will come to doWho function and in doWho function what you are doing ? execl(). what execl() does is that " it replaces current process(child) with new process, after when i = 0 whole child process image got replaced with new one using execl(), so there is nothing left in child process that's why it will execute only once.
If you want to execute as many as you should use fork() in the function because then exec will replace every process created by fork(), but it's not advised to run fork() in loop because your program may crash when there are no more resource available.
So replace your doWho function as
void doWho(void)
{
char entry[10] = {0};
int ret, i;
for(; ;) {
/** who command will be executed when ever condition is true **/
ret = read(0, entry, 10);
__fpurge(stdin);//to clear stdin buffer everytime
if (*entry == 'u') {
if(fork()==0)//only this newly created process will be replaces by execl not one was in main()
execl("/usr/bin/who","who",NULL);
else
;// this parents does nothing
}
}
}
I hope it helps.
I have the following code:
int main(int argc, char **argv)
{
char *program;
char stringa[1000] = "";
int num = 123;
char snum[5];
program = argv[1];
sprintf(stringa, "./%s", program);
pid_t pid = fork();
if (pid < 0 ) {
perror("fork failed.");
exit(1); }
else if (pid == 0) {
char* args[] = {stringa, NULL};
execv(args[0], args);
}
else {
char procmon_str[] = "./procmon ";
num = pid;
sprintf(snum, "%d",num);
printf("PID of child is %s", snum);
char* args2[] = {procmon_str, snum, NULL};
execv(args2[0], args2);
sleep(20);
kill(num, SIGTERM);
sleep(2);
int parent_pid = getpid();
printf("PID of parent is %d", parent_pid);
kill(parent_pid, SIGTERM);
}
wait(NULL);
return 0;
}
The idea is to call with program with 1 command line argument which is a name of another compiled C program in the same folder.
I want to execute that program from within the C code (hence the use of fork()), and at the same time i want to launch another program from within the parent part of the fork().
The part that is in the child part of fork() works perfectly, but when i run it through the shell it says Terminated right after and does not execute the code in the parent part of the fork().
Why is that?
Your program call fork(). Now the execution of the parent process and the child process proceeds in parallel.
The child:
Builds the argument array args[].
Calls execv() and is replaced by the program supplied as argument.
The parent, in parallel with the child:
Builds the argument array args2[].
Calls execv() and is replaced by ./procmon.
The code from sleep(20) onwards in not reached unless the execv() fails (which you did not check for).
Read the manual page for fork() again, and redo the logic of the program.
I am new to system calls and C programming and am working on my university assignment.
I want to call the 'ls' command and have it print the directory.
What I have: (I have added comments in so you can see what I see coming through each variable.
int execute( command* cmd ){
char full_path[50];
find_fullP(full_path, p_cmd);
//find_fullP successfully updates full_path to /bin/ls
char* args[p_cmd->argc];
args[0] = p_cmd->name;
int i;
for(i = 1; i < p_cmd->argc; i++){
args[i] = p_cmd->argv[i];
}
/*
* this piece of code updates an args variable which holds arguments
* (stored in the struct) in case the command is something else that takes
* arguments. In this case, it will hold nothing since the command
* will be just 'ls'.
*/
int child_process_status;
pid_t child_pid;
pid_t pid;
child_pid = fork();
if ( child_pid == 0 ) {
execv( full_path, args );
perror("fork child process error condition!" );
}
pid = wait( &child_process_status );
return 0;
}
I am not seeing anything happening and am confused, any idea?
Here's the minimal program that invokes ls using execv. Things to note
the list of args should include the executable as the first arg
the list of args must be NULL terminated
if the args are set up correctly, then args[0] can be passed as the first parameter to execv
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main( void )
{
int status;
char *args[2];
args[0] = "/bin/ls"; // first arg is the full path to the executable
args[1] = NULL; // list of args must be NULL terminated
if ( fork() == 0 )
execv( args[0], args ); // child: call execv with the path and the args
else
wait( &status ); // parent: wait for the child (not really necessary)
return 0;
}