Newsgroup: it.comp.lang.c
Titolo: strerr e stdout

ciao, dopo aver eseguito un comando con file=popen(cmd,"r");
devo leggere l'output in file.
ma io ho bisogno che sia stderr e stdout siano ENTRAMBI in stdout, perche'
popen+r mi legge solo quello.
allora mi sono chiesta:
1) posso far si che popen legga sia stderr che stdout ?
2) come posso far si che stdout e stderr siano entrambi nello stesso
flusso ? cosi' ho provato a usare freopen:
freopen("stderr",r,stdout);
ma non va' cmq. (e nemmeno freopen("stdout",r,stderr); )
potete aiutarmi ? 
Ciao Ciao e Grazie.
Raffaella Monteclerici


Ciao.
Purtroppo non conosco molto bene popen e freopen, ma credo di
poter rispondere alla tua domanda n. 2.
In genere in ambiente Unix per individuare piu' flussi con un unico descrittore
si puo' usare dup o dup2.
Riporto di seguito un banale programma di esempio
file a.c
#include <stdio.h>
#include <unistd.h>
int main(void) {
    fprintf(stdout,"topogigio1\n");
    fflush(stdout);
/*  close(1);
    dup(2); */
    fprintf(stdout,"topogigio2\n");
    fflush(stdout);
    return 0;
}
Per capire come funziona ti consiglierei di provare a compilare ad esempio
con
cc a.c -o a
e provare a vedere cosa succede con a > pippo.
Se lasci commentate le close e la dup dovresti trovare nel file pippo
sia topogigio 1 che topogigio2, mentre a video non dovresti vedere alcuna
scritta. Se togli i commenti, ricompili
e riprovi a > pippo dovresti vedere una scritta a video (topogigio2) mentre
nel file c'e' solo topogigio1. Questo perche' la close chiude lo standard
output (identificato da 1. In realta` c'e` un identificatore standard POSIX
per lo stdout, qualcosa tipo STDOUT_FILENO, pero' non mi ricordo in quale
file header e'). La dup semplicemente duplica l'identificatore 2 (associato
a stderr. Anche qui dovrebbe esserci qualcosa tipo STDERR_FILENO. Con un
grep dovresti trovarli agevolmente) nel primo posto disponibile nell'array
di identificatori di file (Stevens li chiama "file descriptors" anziche'
identificatori di file) di cui il S.O. terra' traccia. Dopo che la
dup e' stata eseguita avrai che nel'array di identificatori di file non
compare mai l'identificatore dello stdou (1) mentre compare due volte
l'identificatore dello stderr (2)
prima di eseguire close e dup:
array degli identificatori di file
---------------------------
    0 = stdin             |
__________________________|
    1 = stdout            |
__________________________|
    2 = stderr            |
__________________________|
     ...                  |
   altri identificatori   |
dopo aver eseguito close e dup:
array degli identificatori di file
---------------------------
    0 = stdin             |
__________________________|
    2 = stderr            |
__________________________|
    2 = stderr            |
__________________________|
     ...                  |
   altri identificatori   |
In questo modo quando il task che invoca main "pensa" di scrivere
su stdout, utilizzera' l'identificatore
'array degli identificatori di file'[1]
che questa volta sara' uguale all'identificatore di stderr.
Risultato: il processo che "pensa" di scrivere su stdout, scrivera' in realta'
su stderr (dopo close e dup).
Comunque consiglierei la lettura di Stevens : "Advanced programming in the
Unix environment".
Tieni presente che dup e' conforme allo standard POSIX ma non a quello
ANSI/ISO. Dato che usi popen spero che questo non ti crei problemi.
Marco Guidi
 

 potete aiutarmi ?
  Se la tua shell lo consente, prova la redirezione. Altrimenti, dicci
che sistema operativo usi, che magari si trova una soluzione
alternativa.
	Alla prossima,
		Marco

popen+r mi legge solo quello.
Non rispondo al tuo problema, ma, comunque, di default stderr e stdout sono
lo stesso canale (lo schermo). Penso tu stia facendo un po' di
confusione
--
Francesco Trotta
http://space.tin.it/computer/ftrotta
Elimina "x_" dal mio indirizzo per mandarmi
un messaggio direttamente
-

 
Non e' esatto. stdout e stderr puntano di default allo stesso file ma non
sono la stessa cosa. Infatti se intercetti stdout, le scritture su stderr
continuano ad essere inviate al file originale (al terminale, nel caso di
un programma interattivo). Ogni programma ha una tabella di file descriptor
di dimensione limitata (FOPEN_MAX). Ad ogni file descriptor del programma
e' associato un file del sistema. Piu' descrittori possono puntare allo
stesso file (come nel caso stdout e stderr) ma se associo un descrittore ad
un nuovo file, solo le operazioni di I/O relative a quel descrittore
verranno inviare al nuovo file, quelle sui descrittori connessi al file
originale continueranno ad essere inviate al vecchio file. La popen()
chiude lo stdout e lo riapre su un file temporaneo o su un lato di una pipe
ma lo stderr rimane invariato.

 lo stesso canale (lo schermo)
Questo non e` del tutto vero, nel senso che gli identificatori dei descrittori
che il S.O. usa per stdout e stderr differiscono (vedere ad esempio il mio post
precedente)
Marco Guidi
 


Prova con file=popen("cmd 2>&1", "r")
in UNIX dovrebbe funzionare.
Raffaele.

you wrote :
#Non rispondo al tuo problema, ma, comunque, di default stderr e stdout sono
#lo stesso canale (lo schermo).
Non vorrei alimentare una conversazione poco utile all'autrice del
messaggio originale ma, scusami, questo che c'entra ?
stdout e stderr sono *a priori* diversi.
Vengono *indirizzati* sullo stesso canale di default (il video, ma non
e' detto che sia per forza un "video") nel caso non ci sia
reindirizzamento, ma nessuno ci dice che per lei sia cosi'...
...o mi sbaglio ? ;)
"Penso tu stia facendo un po' di confusione" ;)
--------------------------------------------------------
. Andrea Laforgia        (
andrea_...@bigfoot.com
) .
--------------------------------------------------------

 wrote:
[ snip ]
AC>    {
AC>      close(fd[1]);
AC>      return fdopen(fd[0], "r");
AC>    }
AC>  /* Children */
Anche un 
     close(fd[0]);
qui starebbe bene.
AC>  close(1);	/* stdout */
AC>  dup(fd[1]);
[ snip ]
AC>  if ((f=popen_stderr(argv[1], &pid)))
Qui sicuramente intendevi
     if((f=popen_stderr(argv[1], &pid)) == (FILE *)0)
altrimenti esce subito.
A voler essere pignoli, mancherebbero un po' di #include ;)
Ciao ciao,
Andrea
-- 
"...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and 
 the Ugly)."
(by Matt Welsh)

"Penso tu stia facendo un po' di confusione" ;)
Il messaggio non mi sembrava poi chiarissimo.
Comunque, per fortuna che ci sei tu ;-)



Questo e' strano, il compilatore non mi ha dato nessun warning sui
prototipi...
Mi riservo di verificare...
Ciao, Alberto.

 
....che manca <unistd.h> (oltre all'abilitazione dei Warning)!. Sorry.
Saluti, Alberto.

 wrote:
[ snip ]
A>Questo e' strano, il compilatore non mi ha dato nessun warning sui
A>prototipi...
Neanche il mio, se non gli dico di essere puntiglioso ;)
D'altra parte
[bigfok@fokhouse /tmp]$ gcc -o tubo tubo.c -Wall -pedantic
tubo.c: In function `popen_stderr':
tubo.c:11: warning: implicit declaration of function `pipe'
tubo.c:17: warning: implicit declaration of function `fork'
tubo.c:19: warning: implicit declaration of function `close'
tubo.c:25: warning: implicit declaration of function `dup'
tubo.c:29: warning: implicit declaration of function `execlp'
tubo.c: In function `main':
tubo.c:36: warning: unused variable `fd'
saremo entrambi d'accordo, penso, sul fatto che le funzioni di cui 
mancano i prototipi non sono in 'stdio.h' ;)
