Sim você pode. Definindo a lista correta de ações do arquivo posix spawn definitivamente é o caminho a percorrer.
Exemplo:
#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 e testar:
$ 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
Observe que as posix_spawnfunções não definem errno; ao contrário da maioria das outras funções UNIX, elas retornam um código de erro. Assim, não podemos usar, perror()mas temos que usar algo parecido strerror().
Usamos duas ações de arquivo de reprodução: addopen e addup2. O addopen é semelhante ao normal, open()mas você também especifica um descritor de arquivo que é fechado automaticamente se já estiver aberto (aqui 1, isto é, stdout). O addup2 tem efeitos semelhantes a dup2(), ou seja, o descritor do arquivo de destino (aqui 2, ou seja, stderr) é fechado atomicamente antes de 1 ser duplicado para 2. Essas ações são executadas apenas no filho criado por posix_spawn, ou seja, antes de executar o comando especificado.
Como fork(), posix_spawn()e posix_spawnp()retornar imediatamente para o pai. Portanto, temos que usar waitid()ou waitpid()aguardar explicitamente a child_pidrescisão do contrato.
posix_spwané um ponteiro do tipoposix_spawn_file_actions_t(que você forneceu comoNULL).posix_spawnabrirá, fechará ou duplicará descritores de arquivo herdados do processo de chamada, conforme especificado peloposix_spawn_file_actions_tobjeto. Asposix_spawn_file_actions_{addclose,adddup2}funções são usadas para indicar o que acontece com qual fd.