Created
October 14, 2018 16:51
-
-
Save PetarKirov/536eb8b456cc365b7ee05133ec452627 to your computer and use it in GitHub Desktop.
Example usage of posix_spawn in D
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import core.sys.posix.sys.types : mode_t, pid_t; | |
import core.sys.posix.signal : sigset_t; | |
import core.sys.posix.sched : sched_param; | |
import core.stdc.stdio : perror, printf; | |
import core.stdc.errno : errno; | |
import core.stdc.stdlib : exit, EXIT_FAILURE; | |
void checkErrno(int err, const char* msg) | |
{ | |
if (!err) return; | |
errno = err; | |
perror(msg); | |
exit(EXIT_FAILURE); | |
} | |
void ensure(bool cond, const char* msg) | |
{ | |
if (cond) return; | |
printf("%s\n", msg); | |
exit(EXIT_FAILURE); | |
} | |
extern (C) extern __gshared char** environ; | |
extern (C) void main(int argc, const char** argv) | |
{ | |
import core.sys.posix.unistd : getopt, optind, STDOUT_FILENO; | |
int s; | |
posix_spawnattr_t attr; | |
posix_spawnattr_t* attrp; | |
posix_spawn_file_actions_t file_actions; | |
posix_spawn_file_actions_t* file_actionsp; | |
/* Parse command-line options, which can be used to specify an | |
attributes object and file actions object for the child. */ | |
while (true) | |
{ | |
int opt = getopt(argc, argv, "sc"); | |
if (opt == -1) break; | |
switch (opt) | |
{ | |
default: | |
break; | |
case 'c': // -c: close standard output in child | |
/* Create a file actions object and add a "close" | |
action to it */ | |
s = posix_spawn_file_actions_init(&file_actions); | |
checkErrno(s, "posix_spawn_file_actions_init"); | |
s = posix_spawn_file_actions_addclose(&file_actions, STDOUT_FILENO); | |
checkErrno(s, "posix_spawn_file_actions_addclose"); | |
file_actionsp = &file_actions; | |
break; | |
case 's': // -s: block all signals in child | |
/* Create an attributes object and add a "set signal mask" | |
action to it */ | |
s = posix_spawnattr_init(&attr); | |
checkErrno(s, "posix_spawnattr_init"); | |
s = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK); | |
checkErrno(s, "posix_spawnattr_setflags"); | |
import core.sys.posix.sys.wait : sigfillset; | |
sigset_t mask; | |
sigfillset(&mask); | |
s = posix_spawnattr_setsigmask(&attr, &mask); | |
checkErrno(s, "posix_spawnattr_setsigmask"); | |
attrp = &attr; | |
break; | |
} | |
} | |
ensure(optind < argc, "Program to execute not specified"); | |
/* Spawn the child. The name of the program to execute and the | |
command-line arguments are taken from the command-line arguments | |
of this program. The environment of the program execed in the | |
child is made the same as the parent's environment. */ | |
pid_t child_pid; | |
s = posix_spawnp(&child_pid, argv[optind], | |
file_actionsp, | |
attrp, | |
&argv[optind], environ); | |
checkErrno(s, "posix_spawn"); | |
/* Destroy any objects that we created earlier */ | |
if (attrp != null) | |
{ | |
s = posix_spawnattr_destroy(attrp); | |
checkErrno(s, "posix_spawnattr_destroy"); | |
} | |
if (file_actionsp != null) | |
{ | |
s = posix_spawn_file_actions_destroy(file_actionsp); | |
checkErrno(s, "posix_spawn_file_actions_destroy"); | |
} | |
printf("PID of child: %ld\n", cast(long)child_pid); | |
/* Monitor status of the child until it terminates */ | |
import core.sys.posix.sys.wait : waitpid, | |
WUNTRACED, WCONTINUED, WIFEXITED, WEXITSTATUS, | |
WIFSIGNALED, WTERMSIG, WIFSTOPPED, WSTOPSIG, WIFCONTINUED; | |
int status; | |
do | |
{ | |
s = waitpid(child_pid, &status, WUNTRACED | WCONTINUED); | |
ensure(s != -1, "waitpid failed"); | |
printf("Child status: "); | |
if (WIFEXITED(status)) | |
printf("exited, status=%d\n", WEXITSTATUS(status)); | |
else if (WIFSIGNALED(status)) | |
printf("killed by signal %d\n", WTERMSIG(status)); | |
else if (WIFSTOPPED(status)) | |
printf("stopped by signal %d\n", WSTOPSIG(status)); | |
else if (WIFCONTINUED(status)) | |
printf("continued\n"); | |
} | |
while (!WIFEXITED(status) && !WIFSIGNALED(status)); | |
} | |
version (Posix): | |
extern(C): | |
@nogc: | |
nothrow: | |
int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t*, int); | |
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t*, int, int); | |
int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t*, int, const char*, int, mode_t); | |
int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t*); | |
int posix_spawn_file_actions_init(posix_spawn_file_actions_t*); | |
int posix_spawnattr_destroy(posix_spawnattr_t*); | |
int posix_spawnattr_getflags(const posix_spawnattr_t*, short*); | |
int posix_spawnattr_getpgroup(const posix_spawnattr_t*, pid_t*); | |
int posix_spawnattr_getschedparam(const posix_spawnattr_t*, sched_param*); | |
int posix_spawnattr_getschedpolicy(const posix_spawnattr_t*, int*); | |
int posix_spawnattr_getsigdefault(const posix_spawnattr_t*, sigset_t*); | |
int posix_spawnattr_getsigmask(const posix_spawnattr_t*, sigset_t*); | |
int posix_spawnattr_init(posix_spawnattr_t*); | |
int posix_spawnattr_setflags(posix_spawnattr_t*, short); | |
int posix_spawnattr_setpgroup(posix_spawnattr_t*, pid_t); | |
int posix_spawnattr_setschedparam(posix_spawnattr_t*, const sched_param*); | |
int posix_spawnattr_setschedpolicy(posix_spawnattr_t*, int); | |
int posix_spawnattr_setsigdefault(posix_spawnattr_t*, const sigset_t*); | |
int posix_spawnattr_setsigmask(posix_spawnattr_t*, const sigset_t*); | |
int posix_spawn(pid_t*pid, const char* path, | |
const posix_spawn_file_actions_t* file_actions, | |
const posix_spawnattr_t* attrp, | |
const char** argv, const char** envp); | |
int posix_spawnp(pid_t* pid, const char* file, | |
const posix_spawn_file_actions_t* file_actions, | |
const posix_spawnattr_t* attrp, | |
const char** argv, const char** envp); | |
enum | |
{ | |
POSIX_SPAWN_RESETIDS = 0x01, | |
POSIX_SPAWN_SETPGROUP = 0x02, | |
POSIX_SPAWN_SETSIGDEF = 0x04, | |
POSIX_SPAWN_SETSIGMASK = 0x08, | |
POSIX_SPAWN_SETSCHEDPARAM = 0x10, | |
POSIX_SPAWN_SETSCHEDULER = 0x20, | |
} | |
version (CRuntime_Glibc): | |
enum | |
{ | |
POSIX_SPAWN_USEVFORK = 0x40, | |
POSIX_SPAWN_SETSID = 0x80 | |
} | |
struct __spawn_action | |
{ | |
enum tag_t | |
{ | |
spawn_do_close, | |
spawn_do_dup2, | |
spawn_do_open | |
} | |
struct close_action_t | |
{ | |
int fd; | |
} | |
struct dup2_action_t | |
{ | |
int fd; | |
int newfd; | |
} | |
struct open_action_t | |
{ | |
int fd; | |
char*path; | |
int oflag; | |
mode_t mode; | |
} | |
tag_t tag; | |
union | |
{ | |
close_action_t close_action; | |
dup2_action_t dup2_action; | |
open_action_t open_action; | |
} | |
} | |
struct posix_spawn_file_actions_t | |
{ | |
int __allocated; | |
int __used; | |
__spawn_action* __actions; | |
int[16] __pad; | |
} | |
struct posix_spawnattr_t | |
{ | |
short __flags; | |
pid_t __pgrp; | |
sigset_t __sd; | |
sigset_t __ss; | |
sched_param __sp; | |
int __policy; | |
int[16] __pad; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment