Unix command line arguments to kill process after a single print - c

I need to pass unix arguments to run C file so that it prints a certain line "Hello World" a single time only. The file uses fork to print the sentence multiple times but I need to send a kill signal to kill the processes after the sentence "Hello World" is printed once only.
I tried
./"file name" sleep 4 KILL -9
I do not think I am using the right syntax here.
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
int m, i, c = 0;
pid_t pgid;
m = atoi(argv[1]);
for(i = 0; i < 3; ++i)
{
if(fork() > 0)
{
c = 1;
}
}
if(!c)
{
pgid = getpgid(getpid());
setpgid(getpid(), getpid());
kill(m * pgid, SIGINT);
}
sleep(3);
if(fork() > 0)
{
puts("Hello World");
}
return 0;
}
It is printing few times and then it hangs.

Related

C program that tells the user which child process finished first

I am working on an assignment that involves using fork. The program runs two separate programs simultaneously and tells the user which one finished first. If a child finishes, the other child still running should be killed immediately.
My code so far is this...
int main(int argc, char **argv) {
if (argc != 2) {
perror("Invalid number of arguments!");
exit(1);
}
pid_t pid;
pid_t wpid;
int status = 0;
for (int i = 0; i < 2; i++) {
if ((pid = fork()) == 0) {
execv("/bin/sh", argv[i+1]);
}
}
while ((wpid = wait(&status)) > 0);
printf("%s finished first!", <Insert winning program here>);
return 0;
}
From my understanding, this runs the programs and will not let the parent process continue until the child processes have finished. Now I'm wondering how I can terminate another child and return the winning process.
But how can I immediately get the pid of the losing process so that I can kill it?
Just as TonyB told: the "parent" saves the pid of the new child. 2) wait will tell you the pid of the winning process. More verbose: Save the PID of both children, wait for any one, compare the return value to (one of) the saved PIDs; the matching one is the winner, the non-matching one is the loser. E. g.:
#define _POSIX_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
int main(int argc, char **argv)
{
if (argc != 3) // with two program arguments, argc is 3
fputs("Invalid number of arguments!\n", stderr), exit(EXIT_FAILURE);
pid_t pid[2]; // to store both child pids
pid_t wpid;
for (int i = 0; i < 2; i++)
if ((pid[i] = fork()) == 0)
execl("/bin/sh", "sh", "-c", argv[i+1], NULL),
perror(argv[i+1]), exit(EXIT_FAILURE);
wpid = wait(NULL); // wait for first
int wi = wpid==pid[0] ? 0 : 1; // get index of winner
kill(pid[!wi], SIGKILL), wait(NULL); // kill and reap loser
printf("%s finished first!\n", argv[wi+1]);
return 0;
}

simple shell for multiple commands in a line

my program should print out a prompt: myshell> when it is ready to accept input. It must read a line of input, accepting several possible commands. This is a very simple shell, so it only accepts two command: run and exit.
#include<stdio.h>
#include<string.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int h=0;
void keep(int sig){
h=1;
}
int main()
{
signal(SIGINT,keep);//gets into the interrupt
while(1)
{
printf("myshell>");
char line[255];
fgets(line, 255, stdin);
if(!strcmp(line,"\n")){//checks if the given line is not empty
continue;
}
if(h)
{
h=0;
continue;
}
int g = 0;
char *words[5];
words[g] = strtok(line," \n");//Tokenize the given line
while (words[g]!=NULL)//splitting the tokens
{
g++;
words[g] = strtok(NULL," \n");
}
if(strcmp(words[0],"run")==0)
{
int status;
printf("myshell:Started child pid %d \n",getpid());
pid_t result = fork();
printf("myshell:Started child pid %d \n",getpid());
if(result>0)
{
wait(&status);//gets into the wait state
}
else if (result == 0)//new child process created
{
char *args[3];
int k=0;
while(k<4)//take the whole string into array and execute
{
args[k] = words[k+1];
k++;
}
int output;
output = execvp(*args,args);
if(output==-1)
{
printf("myshell: could not find the program %s\n",words[1]);
}
}
}
else if(strcmp(words[0],"exit")==0)//comparing with the exit
{
exit(1);
}
else
{
printf("myshell: %s is not a valid command\n",words[0]);
}
}
return 0;
}
it works good with
./myshell
myshell> run ls
myshell: started child pid 7973
myshell myshell.c
MY shell should support using ; to execute multiple programs with a single command. To make it simple, let's assume there is a space before and after the ;. For example:
./myshell
myshell> run ls -l ; date ; who
But this is not working with this code.

How to execute a program by fork and exec

I have a binary file that contains a program with function written in C inside that looks like:
int main()
{
int a, b;
foo(a,b);
return 0;
}
And now I want to execute that program by using fork() and execve() in another program called "solver".
int main(int argc, char* argv[])
{
pid_t process;
process = fork();
if(process==0)
{
if(execve(argv[0], (char**)argv, NULL) == -1)
printf("The process could not be started\n");
}
return 0;
}
Is that a good way? Because it compiles, but I'm not sure whether the arguments of function inside "worker" program receive variables passed by command line to "solver" program
I believe you are trying to achieve something like that:
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
static char *sub_process_name = "./work";
int main(int argc, char *argv[])
{
pid_t process;
process = fork();
if (process < 0)
{
// fork() failed.
perror("fork");
return 2;
}
if (process == 0)
{
// sub-process
argv[0] = sub_process_name; // Just need to change where argv[0] points to.
execv(argv[0], argv);
perror("execv"); // Ne need to check execv() return value. If it returns, you know it failed.
return 2;
}
int status;
pid_t wait_result;
while ((wait_result = wait(&status)) != -1)
{
printf("Process %lu returned result: %d\n", (unsigned long) wait_result, status);
}
printf("All children have finished.\n");
return 0;
}
./work will be launched with the same arguments as your original program.

combine fork execl wait

I have to create prog1 which take one argument with number of children have to create. (example "./prog1 5" - will create 5 children) Each of children will generate random number from 1 to 20. This number will be given to execl which will start prog2 (in same folder) which take as a argument this random number. Prog2 should sleep this random number time. After that it should return this random number to parent.
I created something like this but it still don't work properly.
prog1:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int n, i, pid;
int u = getppid();
int procesy = 0;
pid_t proc_id;
n = atoi(argv[1]);
for(i = 0; i < n; i++)
{
proc_id = fork();
if(proc_id==0)
{
srand(getpid());
u = 1 + rand()%20;
execl("./prog2", "prog2", u,0);
}
else
{
procesy++;
}
}
if(u == getppid())
{
for(i = 0; i < n; i++)
{
pid = wait(&u);
printf("Process %d ende\n", pid);
procesy--;
}
if(procesy == 0) printf("endc\n");
}
return 1;
}
prog2:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int n;
n = atoi(argv[1]);
sleep(n);
exit(n);
}
Change your loop to look something like the following, in order to properly call execl():
if(proc_id==0)
{
char arg[16];
srand(getpid());
sprintf(arg, "%d", 1 + rand()%20);
execl("./prog2", "prog2", arg, 0);
printf("I should not be here!\n");
exit(-1);
}
Then get rid of if(u == getppid()) (but keep the contents of the conditional). It seems with that if you were trying to filter out the child from running that block. When execl() works, the child is not going to run anything in this code after the execl()... the printf and exit I added will not be run. Those lines will only run if execl() fails, and in this simple case, the only way it will fail is if you've provided improper arguments.

Grabbing the return value from execv()

//code for foo (run executable as ./a.out)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>
int main (int argc, char **argv) {
pid_t pid;
pid = fork();
int i = 1;
char *parms[] = {"test2", "5", NULL}; //test executable named test2
if(pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
else if(pid == 0) {
printf("Child pid is %d\n", pid);
i = execv("test2", parms); //exec call to test with a param of 5
}
else {
wait(NULL);
}
printf("I is now %d\n", i); //i is still 1 here, why?
return 0;
}
Hey everybody, I am trying to learn a little bit about fork and execv() calls. I make my foo.c program above make a call to a file I have named test.c. I fork a child and have the child make a call to execv, which will just add 10 to the parameter read in. I am unsure of why the variable does not change, at the bottom of my foo.c function. Does the call need to be a pointer or return an address? Any help would be greatly appreciated. Thanks
Code for test.c (executable named test2)
#include <stdio.h>
int main(int argc, char ** argv[]) {
int i = atoi(argv[1]);
i = i +10;
printf("I in test is %d\n", i);
return i;
}
You only call execv() in the child process. The exec() family functions never return if it runs successfully. See evec(3):
The exec() functions only return if an error has occurred. The return value is -1, and errno is set to indicate the error.
You printed the value of i in the parent process, it never changed in the parent process.
To get the exit status from the child process, you can make use of wait() or waitpid():
else {
int waitstatus;
wait(&waitstatus);
i = WEXITSTATUS(waitstatus);
}

Resources