skip to content
==> tests/spawn.c <==
1/* Spawning: descriptors land where asked, the environment is extended and
2 * overridden, a process group of its own, statuses described. */
3#include "mesh/check.h"
4#include "mesh/spawn.h"
5
6#include <signal.h>
7#include <stdlib.h>
8#include <string.h>
9#include <sys/wait.h>
10#include <unistd.h>
11
12int main(void) {
13    int out[2];
14    char *err = NULL;
15    CHECK(mesh_pipe_cloexec(out, &err));
16    setenv("MESH_SPAWN_A", "old", 1);
17    char *argv[] = {"sh", "-c", "echo \"$MESH_SPAWN_A $MESH_SPAWN_B $(ps -o pgid= -p $$ | tr -d ' ') $$\" >&5", NULL};
18    char *env[] = {"MESH_SPAWN_A=new", "MESH_SPAWN_B=b", NULL};
19    mesh_spawn_fd fds[] = {{out[1], 5}};
20    pid_t pid;
21    CHECK(mesh_spawn(argv, env, fds, 1, &pid, &err));
22    close(out[1]);
23    char buf[128] = {0};
24    ssize_t n = read(out[0], buf, sizeof buf - 1);
25    int st;
26    waitpid(pid, &st, 0);
27    CHECK(n > 0);
28    char a[16], b[16];
29    long pgid, self;
30    CHECK(sscanf(buf, "%15s %15s %ld %ld", a, b, &pgid, &self) == 4);
31    CHECK_S(a, "new");
32    CHECK_S(b, "b");
33    CHECK_I(pgid, self);
34    CHECK(mesh_status_success(st));
35    char *d = mesh_describe_status(st);
36    CHECK_S(d, "exit 0");
37    free(d);
38    /* Exit codes and signals. */
39    char *e3[] = {"sh", "-c", "exit 3", NULL};
40    CHECK(mesh_spawn(e3, NULL, NULL, 0, &pid, &err));
41    waitpid(pid, &st, 0);
42    d = mesh_describe_status(st);
43    CHECK_S(d, "exit 3");
44    free(d);
45    CHECK_U(mesh_exit_word(st), 3 << 8);
46    char *k9[] = {"sh", "-c", "kill -9 $$", NULL};
47    CHECK(mesh_spawn(k9, NULL, NULL, 0, &pid, &err));
48    waitpid(pid, &st, 0);
49    d = mesh_describe_status(st);
50    CHECK_S(d, "signal 9 (Killed)");
51    free(d);
52    CHECK_U(mesh_exit_word(st), 9);
53    char *nope[] = {"/nonexistent/x", NULL};
54    CHECK(!mesh_spawn(nope, NULL, NULL, 0, &pid, &err));
55    CHECK_S(err, "posix_spawn /nonexistent/x: No such file or directory (os error 2)");
56    free(err);
57    return mesh_check_done();
58}