Riapre i descrittori di file stdin e stdin dopo averli chiusi

Sto scrivendo una funzione, che, dato un argomento, reindirizzerà lo stdout a un file o leggerà lo stdin da un file. Per fare questo chiudo il descrittore di file associato allo stdout o allo stdin, in modo che quando apro il file si apra sotto il descrittore che ho appena chiuso. Funziona, ma il problema è che una volta fatto questo, ho bisogno di ripristinare lo stdout e lo stdin su cosa dovrebbero essere realmente.

Quello che posso fare per stdout è aperto (“/ dev / tty”, O_WRONLY); Ma non sono sicuro del perché funzioni e, cosa più importante, non so di una dichiarazione equivalente per stdin.

Quindi ho, per stdout

close(1); if (creat(filePath, O_RDWR) == -1) { exit(1); } 

e per stdin

 close(0); if (open(filePath, O_RDONLY) == -1) { exit(1); } 

Dovresti usare dup () e dup2 () per clonare un descrittore di file.

 int stdin_copy = dup(0); int stdout_copy = dup(1); close(0); close(1); int file1 = open(...); int file2 = open(...); < do your work. file1 and file2 must be 0 and 1, because open always returns lowest unused fd > close(file1); close(file2); dup2(stdin_copy, 0); dup2(stdout_copy, 1); close(stdin_copy); close(stdout_copy); 

Tuttavia, c’è un piccolo dettaglio che potresti voler fare attenzione (da man dup):

I due descrittori non condividono i flag dei descrittori di file (il close-on-execflag). Il flag close-on-exec (FD_CLOEXEC; vedi fcntl (2)) per il descrittore duplicato è distriggersto.

Se questo è un problema, potresti dover ripristinare il flag close-on-exec, possibilmente usando dup3 () invece di dup2 () per evitare condizioni di competizione.

Inoltre, tieni presente che se il tuo programma è multi-thread, altri thread potrebbero accidentalmente scrivere / leggere sul tuo rimappato stdin / stdout.

Penso che puoi “salvare” i descrittori prima di redirect :

 int save_in, save_out; save_in = dup(STDIN_FILENO); save_out = dup(STDOUT_FILENO); 

In seguito puoi usare dup2 per ripristinarli:

 /* Time passes, STDIN_FILENO isn't what it used to be. */ dup2(save_in, STDIN_FILENO); 

Non sto facendo alcun controllo degli errori in quell’esempio, dovresti.

È ansible creare un processo figlio e impostare il reindirizzamento solo all’interno del figlio. Quindi attendi che il bambino termini e continua a lavorare nel processo genitore. In questo modo non devi preoccuparti di invertire il tuo reindirizzamento.

Cerca solo esempi di codice usando fork () e wait ().