63 lines
1.5 KiB
C
63 lines
1.5 KiB
C
#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;
|
|
}
|