terça-feira, 27 de janeiro de 2015

Redirecionar saída do terminal para arquivo usando C

Oi, hoje vou postar uma dica bem simples aqui, e que talvez seja útil para alguém , redirecionar stdout para um arquivo usando C.

vou mostrar duas formas de fazer isso, a primeira eu aprendi nesse link: www.vivaolinux.com.br

No linux, sempre que executamos algo existem 3 fds que já estão abertos, são eles:

0 - stdin - entrada do teclado
1 - stdout - saida padrao do terminal
2 - stderr - saida de erro

quando usamos, por exemplo:
printf("blahblahbla");
É a mesma coisa de usar a system call write, e passar como primeiro parâmetro o numero 1 (stdout), você pode comprovar isso usando o strace.
[mmxm@hc0d3r tmp]$ cat tutorial1.c
#include <stdio.h>
 
int main(void){
    printf("Chuck norris\n");
    return 0;
}

[mmxm@hc0d3r tmp]$ gcc tutorial1.c -o tutorial1
[mmxm@hc0d3r tmp]$ strace -e write ./tutorial1
write(1, "Chuck norris\n", 13Chuck norris
)          = 13

Viram ?

Continuando ... , ai vai um exemplo igual o do link do vivaolinux, mas no lugar de printf vou usar a função system que manda o resultado do comando para stdout, ou stderr, para enviar tudo para o stdout vou usar 2>&1, pra redirecionar qualquer saida de erro para o stdout
#include <stdlib.h> // int system(const char *command);
#include <fcntl.h> // int open(char *filename, int access, int permission);
#include <unistd.h> // int  close(int handle);
 
int main(void){
 
	close(1);
 
	open("teste.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);
	system("echo system | figlet 2>&1");
 
	return 0;
}

a função open, usada no exemplo, equivale à:
fopen("teste.txt","w");

Testando:
[mmxm@hc0d3r tmp]$ gcc tutorial2.c -o tutorial2
[mmxm@hc0d3r tmp]$ ./tutorial2
[mmxm@hc0d3r tmp]$ cat teste.txt
               _                 
 ___ _   _ ___| |_ ___ _ __ ___  
/ __| | | / __| __/ _ \ '_ ` _ \ 
\__ \ |_| \__ \ ||  __/ | | | | |
|___/\__, |___/\__\___|_| |_| |_|
     |___/                       

Caso você não tenha o figlet instalado o conteudo do arquivo teste.txt vai ser algo como:
sh: figlet: comando não encontrado

por isso redirecionei o stderr pro stdout, caso alguém não tenha o figlet o output ainda vai ir pro arquivo teste.txt.

O segundo método é usando a função dup2.
#include <stdlib.h> // int system(const char *command);
#include <fcntl.h> // int open(char *filename, int access, int permission);
#include <unistd.h> // int  close(int handle);
 
int main(void){
 
	close(1);
 
	open("teste.txt", O_WRONLY|O_CREAT|O_TRUNC, 0665+1);
	system("echo system | figlet 2>&1");
 
	return 0;
}

Executando:
[mmxm@hc0d3r tmp]$ gcc tutorial3.c -o tutorial3
[mmxm@hc0d3r tmp]$ ./tutorial3
[mmxm@hc0d3r tmp]$ cat teste.txt
Uhhhh baby babyy, whatever you do now... dont ever go away

Bem, é isso ai, até mais.

Referencias:

[1] Em C, escrever em arquivo fácil [Dica] (Acessado em Janeiro/2015)
http://www.vivaolinux.com.br/dica/Em-C-escrever-em-arquivo-facil
[2] File descriptor (Acessado em Janeiro/2015)
http://en.wikipedia.org/wiki/File_descriptor
[3] Files: open(), read(), write(), close() (Acessado em Janeiro/2015)
http://gd.tuwien.ac.at/languages/c/programming-bbrown/c_075.htm
[4] dup (Acessado em Janeiro/2015)
http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
[5] open(3): open file - Linux man page (Acessado em Janeiro/2015)
http://linux.die.net/man/3/open
[6] dup2(3): duplicate open file descriptor - Linux man page (Acessado em Janeiro/2015)
http://linux.die.net/man/3/dup2

Nenhum comentário:

Postar um comentário