Si, puoi. Definire la giusta lista di azioni di file spawn posix è sicuramente la strada da percorrere.
Esempio:
#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;
}
Compilare e testare:
$ 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
Si noti che le posix_spawnfunzioni non impostano errno, invece, a differenza della maggior parte delle altre funzioni UNIX, restituiscono un codice di errore. Pertanto, non possiamo usare perror()ma dobbiamo usare qualcosa di simile strerror().
Utilizziamo due azioni del file di spawn: addopen e addup2. L'adopen è simile a un normale open()ma si specifica anche un descrittore di file che viene automaticamente chiuso se già aperto (qui 1, cioè stdout). L'addup2 ha effetti simili a dup2(), ovvero il descrittore del file di destinazione (qui 2, ovvero stderr) viene chiuso atomicamente prima che 1 sia duplicato su 2. Tali azioni vengono eseguite solo nel figlio creato da posix_spawn, ovvero proprio prima che esegua il comando specificato.
Mi piace fork(), posix_spawn()e posix_spawnp()torna immediatamente al genitore. Pertanto, dobbiamo utilizzare waitid()o waitpid()attendere esplicitamente child_pidla risoluzione.
posix_spwanè un puntatore di tipoposix_spawn_file_actions_t(uno che hai dato comeNULL).posix_spawnaprirà, chiuderà o duplicerà i descrittori di file ereditati dal processo di chiamata come specificatoposix_spawn_file_actions_tdall'oggetto. Leposix_spawn_file_actions_{addclose,adddup2}funzioni sono usate per indicare cosa succede a quale fd.