Terminating a c function - c

I want to make a function in c, that will capture video under Linux. I embedded ffmpeg command via system() in my c program, which captures video. ffmpeg terminates by pressing [q]. How can I include termination into my c program.
This function is part of a server.c program. When client requests for termination, I want video cature function to terminate. Is this possible?
#include<stdio.h>
#include <string.h>
main()
{
char command[180];
sprintf(command, "ffmpeg -f v4l2 -r 25 -s 640x480 -i /dev/video0 out.avi");
system(command);
}

As you asked sample for fork, exec, kill here is possible solution.
avconv is replacement for ffmpeg on my pc.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <sched.h>
#include <sys/wait.h>
pid_t parent_pid;
void sigquit_handler (int sig)
{
assert(sig == SIGKILL);
pid_t self = getpid();
if (parent_pid != self)
{
printf("recording done");
_exit(0);
}
}
int main()
{
int pid = 0;
int status;
pid_t child;
signal(SIGKILL, sigquit_handler);
parent_pid = getpid();
pid = fork();
if ( pid == 0)
{
execl("/usr/bin/avconv","avconv","-f","video4linux2","-r","25","-s","640x480","-i","/dev/video0","out.avi",(char*)0);
}
else if( pid > 0)
{
sleep(5);
kill(pid, SIGKILL);
child = wait(&status);
printf("child %d succesully quit\n", (int)child);
}
return 0;
}

Related

Obtaining the status of execv without stopping the execution of the parent

Is there a way to obtain the status of a command run with execv without waiting for it with waitpid or wait?
The program I need to do reads other executable program as argument and need to print the status of this program when executed with execv exactly when the command is finished executing, but needs to keep executing after the fork instead of waiting for the program passed as argument to finish executing.
Here is what I have right now which doesn't seem to capture any status:
#define _GNU_SOURCE
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio_ext.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/shm.h>
int status;
void child_exit_handler(int signal)
{
int pid = wait(&status);
}
int main(int argc, char *argv[])
{
pid_t pid;
signal(SIGCHLD, child_exit_handler);
for (int i = 1; i < argc; i++)
{
pid = fork();
if (pid == 0)
{
char *cmd[4];
cmd[0] = "sh";
cmd[1] = "-c";
cmd[2] = argv[i];
cmd[3] = NULL;
execv("/bin/bash", cmd);
}
}
if (pid > 0)
{
// do something;
// later do something with status
}
}

Printf fails to print in parent and child after fork

I'm trying to use date and wc with pipes on CentOS. I'm not able to printf that I'm in parent or child. Any help is appreciated.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>
#include <stdlib.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
/* pipe1.c - send information through pipe. */
void syserr(char* msg)
{
printf("%s", msg);
}
void child(int pfd[]){
dup2(pfd[1],1);
execl("/bin/date", "date", 0);
}
void main()
{
int pfd[2], i, pid;
char str[] = "Hello World!\n";
if (pipe(pfd) == -1)
syserr("pipe");
printf("pfd[0] = %d, pfd[1] = %d\n", pfd[0], pfd[1]);
pid=fork();
switch(pid) {
case -1:
syserr("fork");
case 0:
{
printf("I'm child'");
child(pfd);
}
default:{ /* parent only */
if(pid!=0)
{
printf("I'm parent'");
dup2(pfd[0],0); //input
execl("/bin/wc", "wc", 0);
}/*default*/
} /*switch*/
}
}
Remember that <stdio.h> is buffered, and stdout is generally line-buffered, at least when it is a terminal. See setvbuf(3)
So you should either end each of your printf format control string with a \n or call fflush(3) at appropriate places. In particular, do a fflush(NULL); before your fork and your execl.
Also use perror on failure (i.e. replace every call to syserr by perror) to understand how system calls are failing. See perror(3) & errno(3) & strerror(3).
BTW, your main is incorrectly declared. You should enable all warnings and debug info when compiling (e.g. compile with gcc -Wall -Wextra -g). Improve your code to get no more warnings. Then use the debugger gdb ...
Notice that to avoid zombie processes, your parent process should use some waiting system call like waitpid(2) or wait(2) or wait4(2)
Works now. I had to add close(pfd[0]); in child, and close(pfd[1]); in parent.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>
#include <stdlib.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
/* pipe1.c - send information through pipe. */
void child(int pfd[]){
printf("I'm in child func\n");
close(pfd[0]);
dup2(pfd[1],1);
execl("/bin/date", "date", 0);
}
int main(){
int pfd[2], pid;
if (pipe(pfd) == -1) perror("pipe");
printf("pfd[0] = %d, pfd[1] = %d\n", pfd[0], pfd[1]);
fflush(NULL);
pid=fork();
switch(pid) {
case -1:
perror("fork");
case 0:
{
printf("I'm child\n");
child(pfd);
}
default:{ /* parent only */
if(pid!=0){
printf("I'm daddy\n");
close(pfd[1]);
dup2(pfd[0],0); //input
execl("/bin/wc", "wc", 0);
}/*default*/
} /*switch*/
}
return 0;
}

execve on linux, execute from arguments

I need to create a program that allows the user to execute a command passed as argument using execve in linux. I'm not sure about the syntax of the execve command. I wrote the program but it doesn't work with multiple arguments and I can't figure out why.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char **argv)
{
int status;
pid_t pid;
if((pid = fork())>0)
{
///Father process
wait(&status);
printf("Process terminated with status = %d\n",status);
}
else
{
///son process
int i;
char param[100];
printf("I'm the son woth PID= %d\n",getpid());
printf("%s\n",argv[0]);
printf("%s\n",argv[1]);
printf("%s\n",argv[2]);
strcpy(param,"/bin/");
strcat(param,argv[1]);
execve(param,argv,NULL);
exit(-1);
}
return 0;
}
A command that doesn't work using this code is
cp file1.txt file2.txt
Can someone help me?
This version is corrected:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char **argv)
{
int status;
pid_t pid;
if((pid = fork())>0)
{
///Father process
wait(&status);
printf("Process terminated with status = %d\n",status);
}
else
{
///son process
int i;
char program[100];
printf("I'm the son woth PID= %d\n",getpid());
strcpy(program,argv[1]);
printf("Program: %s\n", program);
execve(program, argv+1, NULL);
exit(0);
}
return 0;
}
Example:
$ ./a.out /bin/cp a.txt b.txt
I'm the son woth PID= 1590
Program: /bin/cp
/bin/cp
a.txt
b.txt
Process terminated with status = 0
Example 2:
./a.out /bin/ls
I'm the son woth PID= 3021
Program: /bin/ls
/bin/ls
a.c a.out
Process terminated with status = 0
I've added #include <unistd.h> because I needed it.
I recommend you to do more printf in order to understand and troubleshoot.
Edit As #jonathan-leffler say, you can use execvp to be able to exec programs using PATH:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char **argv)
{
int status;
pid_t pid;
if((pid = fork())>0)
{
///Father process
wait(&status);
printf("Process terminated with status = %d\n",status);
}
else
{
///son process
int i;
char program[100];
printf("I'm the son woth PID= %d\n",getpid());
strcpy(program,argv[1]);
printf("Program: %s\n", program);
execvp(program, argv+1);
exit(0);
}
return 0;
}
Example:
▶ ./a.out ls
I'm the son woth PID= 5056
Program: ls
a.c a.out
Process terminated with status = 0

signal handling on background process and file output

I have been considering the following code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
FILE* file;
void signal_handler(int _signal) {
switch(_signal){
case SIGTERM:
fprintf(file, "Ouch, the Daemon Child was killed!\n");
fflush(file);
abort();
default:
fprintf(file, "So what?!\n");
fflush(file);
}
}
int main() {
pid_t pid;
int status;
pid = fork();
if(pid != 0) {
// parent
waitpid(pid, &status, WNOHANG); // daemonize the child
} else {
// child
signal(SIGTERM, signal_handler);
file = fopen("daemon.txt", "w");
while(1) {
sleep(1);
fprintf(file, "Daemon child is alive.\n");
fflush(file);
}
}
return 0;
}
and I expected I could find at the end of daemon.txt the string Ouch, the Daemon Child was killed!, after sudo kill -KILL . However, this is not the case. Where is my fault?
You appear to be catching SIGTERM, and then sending SIGKILL, which you do not have a handler for. You will probably see your expected output if you use kill -TERM $pid rather than kill -KILL.

C UNIX: how to assign a new signal handler

I have a signal handler where I set ctrl+z/SIGTSTP to just be detected by the program. But when I want to change the signal handler of ctrl+z/SIGTSTP to its default behavior in the child process, the ctrl+z doesn't change. Is there a proper to change signal handlers?
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
void handler(int sig_num)
{
printf("detected %d\n",sig_num);
}
int main()
{
int x;
signal(SIGTSTP,handler);
pid_t pid = fork();
if(pid == 0)
{
signal(SIGTSTP,SIG_DFL);
printf("in child process \n");
while(1);
}
else if(pid > 0)
{
printf("running parent\n");
printf("waiting for my child to run\n");
wait(&x);
exit(0);
}
return 0;
}

Resources