|
Szabolcs Nagy |
d18f44 |
#define _GNU_SOURCE
|
|
Szabolcs Nagy |
d18f44 |
#include <unistd.h>
|
|
Szabolcs Nagy |
d18f44 |
#include <sys/wait.h>
|
|
Szabolcs Nagy |
d18f44 |
#include <errno.h>
|
|
Szabolcs Nagy |
d18f44 |
#include <string.h>
|
|
Szabolcs Nagy |
d18f44 |
#include "test.h"
|
|
Szabolcs Nagy |
d18f44 |
|
|
Szabolcs Nagy |
d18f44 |
#define TEST(c, ...) ( (c) || (t_error(#c " failed: " __VA_ARGS__),0) )
|
|
Szabolcs Nagy |
d18f44 |
|
|
Szabolcs Nagy |
d18f44 |
static int w(pid_t pid)
|
|
Szabolcs Nagy |
d18f44 |
{
|
|
Szabolcs Nagy |
d18f44 |
int r, s;
|
|
Szabolcs Nagy |
d18f44 |
r = waitpid(pid, &s, 0);
|
|
Szabolcs Nagy |
d18f44 |
if (r == -1)
|
|
Szabolcs Nagy |
d18f44 |
t_error("waitpid failed: %s\n", strerror(errno));
|
|
Szabolcs Nagy |
d18f44 |
else if (r != pid)
|
|
Szabolcs Nagy |
d18f44 |
t_error("child pid was %d, waitpid returned %d\n", pid, r);
|
|
Szabolcs Nagy |
d18f44 |
else
|
|
Szabolcs Nagy |
d18f44 |
return s;
|
|
Szabolcs Nagy |
d18f44 |
return -1;
|
|
Szabolcs Nagy |
d18f44 |
}
|
|
Szabolcs Nagy |
d18f44 |
|
|
Szabolcs Nagy |
d18f44 |
static void test_exit(int code)
|
|
Szabolcs Nagy |
d18f44 |
{
|
|
Szabolcs Nagy |
d18f44 |
pid_t pid;
|
|
Szabolcs Nagy |
d18f44 |
if((pid = vfork()) == 0) {
|
|
Szabolcs Nagy |
d18f44 |
_exit(code);
|
|
Szabolcs Nagy |
d18f44 |
t_error("exit failed: %s\n", strerror(errno));
|
|
Szabolcs Nagy |
d18f44 |
}
|
|
Szabolcs Nagy |
d18f44 |
if (pid == -1) {
|
|
Szabolcs Nagy |
d18f44 |
t_error("vfork failed: %s\n", strerror(errno));
|
|
Szabolcs Nagy |
d18f44 |
return;
|
|
Szabolcs Nagy |
d18f44 |
}
|
|
Szabolcs Nagy |
d18f44 |
int r = w(pid);
|
|
Szabolcs Nagy |
d18f44 |
TEST(WIFEXITED(r), "child terminated abnormally\n");
|
|
Szabolcs Nagy |
d18f44 |
TEST(WEXITSTATUS(r) == code, "child exited with %d, expected %d\n", WEXITSTATUS(r), code);
|
|
Szabolcs Nagy |
d18f44 |
}
|
|
Szabolcs Nagy |
d18f44 |
|
|
Szabolcs Nagy |
d18f44 |
static int sh(const char *cmd)
|
|
Szabolcs Nagy |
d18f44 |
{
|
|
Szabolcs Nagy |
d18f44 |
pid_t pid;
|
|
Szabolcs Nagy |
d18f44 |
if((pid = vfork()) == 0) {
|
|
Szabolcs Nagy |
d18f44 |
execl("/bin/sh", "/bin/sh", "-c", cmd, (char*)0);
|
|
Szabolcs Nagy |
d18f44 |
t_error("execl failed: %s\n", strerror(errno));
|
|
Szabolcs Nagy |
d18f44 |
_exit(1);
|
|
Szabolcs Nagy |
d18f44 |
}
|
|
Szabolcs Nagy |
d18f44 |
if (pid == -1) {
|
|
Szabolcs Nagy |
d18f44 |
t_error("vfork failed: %s\n", strerror(errno));
|
|
Szabolcs Nagy |
d18f44 |
return -1;
|
|
Szabolcs Nagy |
d18f44 |
}
|
|
Szabolcs Nagy |
d18f44 |
return w(pid);
|
|
Szabolcs Nagy |
d18f44 |
}
|
|
Szabolcs Nagy |
d18f44 |
|
|
Szabolcs Nagy |
d18f44 |
static void test_shell_exit(const char *cmd, int code)
|
|
Szabolcs Nagy |
d18f44 |
{
|
|
Szabolcs Nagy |
d18f44 |
int r = sh(cmd);
|
|
Szabolcs Nagy |
d18f44 |
TEST(WIFEXITED(r), "child terminated abnormally\n");
|
|
Szabolcs Nagy |
d18f44 |
TEST(WEXITSTATUS(r) == code, "child exited with %d, expected %d\n", WEXITSTATUS(r), code);
|
|
Szabolcs Nagy |
d18f44 |
}
|
|
Szabolcs Nagy |
d18f44 |
|
|
Szabolcs Nagy |
d18f44 |
static void test_shell_kill(const char *cmd, int sig)
|
|
Szabolcs Nagy |
d18f44 |
{
|
|
Szabolcs Nagy |
d18f44 |
int r = sh(cmd);
|
|
Szabolcs Nagy |
d18f44 |
TEST(WIFSIGNALED(r), "child did not get killed\n");
|
|
Szabolcs Nagy |
d18f44 |
TEST(WTERMSIG(r) == sig, "child is killed by %d, expected %d\n", WTERMSIG(r), sig);
|
|
Szabolcs Nagy |
d18f44 |
}
|
|
Szabolcs Nagy |
d18f44 |
|
|
Szabolcs Nagy |
d18f44 |
int main() {
|
|
Szabolcs Nagy |
d18f44 |
test_exit(0);
|
|
Szabolcs Nagy |
d18f44 |
test_exit(1);
|
|
Szabolcs Nagy |
d18f44 |
test_shell_exit("exit 0", 0);
|
|
Szabolcs Nagy |
d18f44 |
test_shell_exit("exit 1", 1);
|
|
Szabolcs Nagy |
c185a5 |
test_shell_kill("kill -9 $$", 9);
|
|
Szabolcs Nagy |
d18f44 |
return t_status;
|
|
Szabolcs Nagy |
d18f44 |
}
|