Ja, du kannst. Das Definieren der richtigen Liste von Aktionen für Posix-Spawn-Dateien ist definitiv der richtige Weg.
Beispiel:
#include <errno.h>
#include <fcntl.h>
#include <spawn.h>
#include <stdio.h>
#include <string.h>
#define CHECK_ERROR(R, MSG) do { if (R) { fprintf(stderr, "%s: %s\n",
(MSG), strerror(R)); return 1; } } while (0)
extern char **environ;
int main(int argc, char **argv)
{
if (argc < 3) {
fprintf(stderr, "Call: %s OUTFILE COMMAND [ARG]...\n", argv[0]);
return 2;
}
const char *out_filename = argv[1];
char **child_argv = argv+2;
posix_spawn_file_actions_t as;
int r = posix_spawn_file_actions_init(&as);
CHECK_ERROR(r, "actions init");
r = posix_spawn_file_actions_addopen(&as, 1, out_filename,
O_CREAT | O_TRUNC | O_WRONLY, 0644);
CHECK_ERROR(r, "addopen");
r = posix_spawn_file_actions_adddup2(&as, 1, 2);
CHECK_ERROR(r, "adddup2");
pid_t child_pid;
r = posix_spawnp(&child_pid, child_argv[0], &as, NULL,
child_argv, environ);
CHECK_ERROR(r, "spawnp");
r = posix_spawn_file_actions_destroy(&as);
CHECK_ERROR(r, "actions destroy");
return 0;
}
Kompilieren und testen:
$ cc -Wall -g -o spawnp spawnp.c
$ ./spawnp log date -I
$ cat log
2018-11-03
$ ./a.out log dat
spawnp: No such file or directory
Beachten Sie, dass die posix_spawn
Funktionen nicht errno setzen, sondern im Gegensatz zu den meisten anderen UNIX-Funktionen einen Fehlercode zurückgeben. Daher können wir nicht verwenden, perror()
sondern müssen so etwas verwenden strerror()
.
Wir verwenden zwei Aktionen für Spawn-Dateien: addopen und addup2. Das Addopen ähnelt einem normalen, open()
aber Sie geben auch einen Dateideskriptor an, der automatisch geschlossen wird, wenn er bereits geöffnet ist (hier 1, dh stdout). Das Addup2 hat ähnliche Auswirkungen wie dup2()
, dh der Zieldateideskriptor (hier 2, dh stderr) wird atomar geschlossen, bevor 1 zu 2 dupliziert wird. Diese Aktionen werden nur in dem von erstellten untergeordneten Element ausgeführt posix_spawn
, dh unmittelbar bevor es den angegebenen Befehl ausführt .
Wie fork()
, posix_spawn()
und posix_spawnp()
sofort wieder an die Eltern. Daher müssen wir die Kündigung verwenden waitid()
oder waitpid()
explizit darauf warten child_pid
.
posix_spwan
ist ein Zeiger vom Typposix_spawn_file_actions_t
(einer, den Sie als angegeben habenNULL
).posix_spawn
öffnet, schließt oder dupliziert Dateideskriptoren, die vom aufrufenden Prozess geerbt wurden, wie vomposix_spawn_file_actions_t
Objekt angegeben. Dieposix_spawn_file_actions_{addclose,adddup2}
Funktionen werden verwendet, um anzuzeigen, was mit welchem fd passiert.