How to run commands through PTY? - c

I want to interact with the child process through PTY, the parent process code is as follows:
#include <pty.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
pid_t child_pid, current_pid;
char name[BUFSIZ], buffer[BUFSIZ];
int master;
current_pid = getpid();
fprintf(stdout, "pid: %u\n", current_pid);
child_pid = forkpty(&master, &name[0], NULL, NULL);
if (child_pid == -1) {
perror("forkpty faild.");
return EXIT_FAILURE;
} else if (child_pid == 0) {
execl("./child", "./child");
} else {
read(master, &buffer[0], BUFSIZ);
fprintf(stdout, "%u: child message:\n%s", current_pid, buffer);
}
return EXIT_FAILURE;
}
The subprocess code is as follows:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
fprintf(stdout, "%s\n", isatty(fileno(stdout)) ? "true": "false");
return EXIT_SUCCESS;
}
compile and execute:
$ gcc main.c -o main && gcc child.c -o child
$ ./main
Why must the parent process fork first, and then execute the instruction through execl to be effective?
Can't exchange data directly?

Why must the parent process fork first, and then execute the instruction through execl to be effective?
Because that's how fork and everything that wraps it up works. After a successful fork you have two processes that are virtually identical, except for the return value of fork and the process' PID.
To launch a different program, one process must replace its program image with a different one, which is what execl does.

Related

Why does the parent process always executes later than the child process it creates without wait() in UNIX?

I have a homework question:
Q7: After executing the following code, a new file named myFile.txt is generated. Is the content in myFile.txt will be consistent? Why?
And here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
int main(int argc, char *argv[]){
printf("hello world (pid:%d)\n", (int)getpid());
int fd = open("myFile.txt", O_CREAT|O_RDWR);
if(fd == -1 ) {
printf("Unable to open the file\n exiting....\n");
return 0;
}
int rc = fork();
if (rc < 0) {
fprintf(stderr, "fork failed\n");
exit(1);
}
else if (rc == 0) {
printf("hello, I am child (pid:%d)\n", (int)getpid());
char myChar='a';
write(fd, &myChar,1);
printf("writing a character to the file from child\n");
}
else {
printf("hello, I am parent of %d (pid:%d)\n",
rc, (int)getpid());
char myChar='b';
write(fd, &myChar,1);
printf("writing a character to the file from parent\n");
}
return 0;
}
The parent will write "a" into myFile.txt while the child writes "b" into that file. I executed this program several times, finding the txt file consistent being "ba", meaning that the parent always comes after the child. However, I noticed that there's no wait() function called by the parent process. Can someone explain why the parent comes after the child?
The order of concurrent tasks are implementation defined by the OS. You need to use synchronization primitives to ensure a well defined order of actions if required (file locks, pipes, mutex, condition variables, semaphores etc).

How can a program which forks itself repeatedly in a loop be killed?

I made some weird experiment and created a program that forks itself and executes itself in the child process, which is forked again and executes itself again...and so on.
Only after exiting the ssh session I was connected to it stopped.
What are the possible ways to kill such program, which continuously changes it's own PID ?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int spawn (char* program, char** arg_list)
{
pid_t child_pid;
child_pid = fork ();
if (child_pid != 0)
/* This is the parent process. */
return child_pid;
else {
printf("my pid is %d my ppid is %d\n", getpid(), getppid());
execvp (program, arg_list);
fprintf (stderr, "an error occurred in execvp\n");
abort ();
}
}
int main ()
{
char* arg_list[] = {
"./1", /* argv[0], the name of the program. */
NULL
};
spawn ("./1", arg_list);
return 0;
}

In c, linux , about kill and raise

I run my C program on debian-linux ,the program is expected to output
$ ./kill_raise
Child(pid : 4877) is waiting for any signal
Parent kill 4877
but I just got
Parent kill 4877
the string in subprocess (Child(pid : %d) is waiting for any signal) is not print out,why?
and this is my program
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
pid_t pid;
int res;
pid = fork();
if (pid < 0)
{
perror ("Fork error\n");
exit(0);
}
if (pid == 0)
{
printf ("child(pid:%d) is waiting for signal\n", getpid());
raise(SIGSTOP);
exit(0);
}
else
{
if ((waitpid(pid, NULL, WNOHANG)) == 0)
{
if ((res = kill(pid, SIGKILL)) == 0)
{
printf ("parent kill %d\n", pid);
}
}
waitpid(pid, NULL, 0);
exit(0);
}
}
You're hitting a race condition. The parent is executing the kill before the child can execute its printf. Remove WNOHANG so the parent actually waits for the child to stop. Also, you need to add WUNTRACED so that waitpid reports the stop (by default, it will only report termination). Finally, you shouldn't be testing wait()'s return value against 0 in this case.

Explanation of code - fork, wait, execv

I'm trying to understand what the following code does:
#include <stdio.h>
#include <stdlib.h>
#include <syscall.h>
#include <unistd.h>
int main(void) {
int pid;
for(;;) {
pid = fork();
printf(getpid());
if(pid == -1) {
printf("fork failed");
exit(1);
}
if(pid == 0) {
execv("MYFORKAPP", NULL);
exit(2);
}
wait();
}
return 0;
}
The program itself is called MYFORKAPP. I'm learning about these 3 functions and I saw this code on the internet and I don't understand what it does.
I tried to run it (Fedora GCC) but the terminal is empty.
Should it at-least print the first getpid()?
Can you please explain me this code?
printf(getpid());
This may crash the program. printf() expects its first argument be a string, but getpid() will return a integer, so this integer will be used as a pointer to an array of character, this very likely leads to a crash, i.e. segmentation fault.
Besides that, what this program does is
fork() a child process and wait()
this child process will execuate the same program again
so it will fork() and wait()
and so on, until your system does not have enough resource to create new process
then fork() will fail, these different level child processes will exit one by one
finally, the first process created by your shell will exit, and the program ends.
What the following code does - segmentation fault.
Must be:
#include <stdio.h>
#include <stdlib.h>
#include <syscall.h>
#include <unistd.h>
int main(void) {
int pid;
for(;;) {
pid = fork();
if(pid == -1) {
printf("fork failed");
exit(1);
}
if(pid == 0) {
printf("child has pid %d\n", getpid());
execv("MYFORKAPP", NULL);
exit(2);
}
wait();
}
return 0;
}
This is a loop:
1. Parent creates a child process.
2. Child turnes to MYFORKAPP.
3. Parent wait for the child process.
4. Child terminates (may be).
5. goto 1

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