Sí tu puedes. Definir la lista correcta de acciones de archivo de generación posix definitivamente es el camino a seguir.
Ejemplo:
#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;
}
Compilar y probar:
$ 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
Tenga en cuenta que las posix_spawn
funciones no establecen errno, en cambio, a diferencia de la mayoría de las otras funciones de UNIX, devuelven un código de error. Por lo tanto, no podemos usar, perror()
pero tenemos que usar algo como strerror()
.
Utilizamos dos acciones de generación de archivos: addopen y addup2. El addopen es similar a un normal open()
pero también especifica un descriptor de archivo que se cierra automáticamente si ya está abierto (aquí 1, es decir, stdout). El addup2 tiene efectos similares a dup2()
, es decir, el descriptor del archivo de destino (aquí 2, es decir, stderr) se cierra atómicamente antes de que 1 se duplique a 2. Esas acciones solo se ejecutan en el elemento secundario creado por posix_spawn
, es decir, justo antes de ejecutar el comando especificado.
Me gusta fork()
, posix_spawn()
y posix_spawnp()
volver inmediatamente a los padres. Por lo tanto, tenemos que usar waitid()
o waitpid()
esperar explícitamente child_pid
la terminación.
posix_spwan
es un puntero de tipoposix_spawn_file_actions_t
(uno que ha dado comoNULL
).posix_spawn
abrirá, cerrará o duplicará los descriptores de archivos heredados del proceso de llamada según lo especificado por elposix_spawn_file_actions_t
objeto. Lasposix_spawn_file_actions_{addclose,adddup2}
funciones se utilizan para indicar qué sucede con qué fd.