begin simple child process interface
This commit is contained in:
parent
8991d8ec04
commit
2e10e88504
3 changed files with 82 additions and 14 deletions
63
cli/child.c
Normal file
63
cli/child.c
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include "child.h"
|
||||||
|
#include "epty.h"
|
||||||
|
|
||||||
|
/* SIGTERM grace period before a child is sent SIGKILL.
|
||||||
|
* Value is in microseconds (us), 1000us = 1ms */
|
||||||
|
#define CHILD_GRACE_US 100000
|
||||||
|
|
||||||
|
/* Check if a child is still alive by pid
|
||||||
|
* by kill(3p) sending a null signal (0).
|
||||||
|
*/
|
||||||
|
static int is_alive(struct d_child *child) {
|
||||||
|
return (kill(child->pid, 0) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force a child to die, first by sending SIGTERM, otherwise SIGKILL.
|
||||||
|
* NOTE: killchild() ASSUMES the child is LIVING at the start.
|
||||||
|
* NOTE: Keep this in mind when threading!
|
||||||
|
*/
|
||||||
|
void killchild(struct d_child *child) {
|
||||||
|
int stat;
|
||||||
|
|
||||||
|
/* Request Death */
|
||||||
|
kill(child->pid, SIGTERM);
|
||||||
|
usleep(CHILD_GRACE_US);
|
||||||
|
|
||||||
|
/* Force Death */
|
||||||
|
if (is_alive(child))
|
||||||
|
kill(child->pid, SIGKILL);
|
||||||
|
|
||||||
|
/* Reap */
|
||||||
|
waitpid(child->pid, &stat, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fork to spawn a child process running bin/shfx in an "epty".
|
||||||
|
*/
|
||||||
|
int spawnchild(struct d_child *child) {
|
||||||
|
*child = (struct d_child){ 0 };
|
||||||
|
|
||||||
|
/* fork(2) and allocate an "error-piped pseudoterminal" (epty) */
|
||||||
|
switch (child->pid = forkepty(&child->fdmx, &child->fderr)) {
|
||||||
|
case -1:
|
||||||
|
perror("forkepty");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
case 0:
|
||||||
|
char *args[] = {"shfx", NULL};
|
||||||
|
execvp("shfx", args);
|
||||||
|
perror("execvp");
|
||||||
|
exit(1);
|
||||||
|
default:
|
||||||
|
usleep(1000);
|
||||||
|
char bufout[10];
|
||||||
|
bufout[9] = '\0';
|
||||||
|
read(child->fdmx, bufout, 9);
|
||||||
|
printf("child stdout: \"%s\"\n", bufout);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
14
cli/child.h
Normal file
14
cli/child.h
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef DORNE_CHILD_H
|
||||||
|
#define DORNE_CHILD_H
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
struct d_child {
|
||||||
|
pid_t pid;
|
||||||
|
int fdmx; /* PTY master fd (read/write) */
|
||||||
|
int fderr; /* child's stderr (readonly) */
|
||||||
|
} __attribute__((packed, aligned(4)));
|
||||||
|
|
||||||
|
int spawnchild(struct d_child *child);
|
||||||
|
|
||||||
|
#endif /* DORNE_CHILD_H */
|
||||||
19
cli/main.c
19
cli/main.c
|
|
@ -1,7 +1,8 @@
|
||||||
#include <stdio.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "mkpty.h"
|
#include "child.h"
|
||||||
|
|
||||||
// struct d_window {
|
// struct d_window {
|
||||||
// int ptmx; // fd
|
// int ptmx; // fd
|
||||||
|
|
@ -14,17 +15,7 @@
|
||||||
// }
|
// }
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
pid_t pid;
|
struct d_child child;
|
||||||
switch (pid = forkmkpty()) {
|
spawnchild(&child);
|
||||||
case -1:
|
|
||||||
perror("forkmkpty");
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
printf("fork: children\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("fork: parent\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue