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_spawn
funçõ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_pid
rescisão do contrato.
posix_spwan
é um ponteiro do tipoposix_spawn_file_actions_t
(que você forneceu comoNULL
).posix_spawn
abrirá, fechará ou duplicará descritores de arquivo herdados do processo de chamada, conforme especificado peloposix_spawn_file_actions_t
objeto. Asposix_spawn_file_actions_{addclose,adddup2}
funções são usadas para indicar o que acontece com qual fd.