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_spawnfunciones 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_pidla terminación.
posix_spwanes un puntero de tipoposix_spawn_file_actions_t(uno que ha dado comoNULL).posix_spawnabrirá, cerrará o duplicará los descriptores de archivos heredados del proceso de llamada según lo especificado por elposix_spawn_file_actions_tobjeto. Lasposix_spawn_file_actions_{addclose,adddup2}funciones se utilizan para indicar qué sucede con qué fd.