Você está na página 1de 5

LINUX USER

Papo de Botequim

Curso de Shell Script

Papo de Botequim
Voc no agenta mais aquele seu amigo usurio de Linux enchendo o seu saco com aquela histria de que o sistema fantstico e o Shell uma ferramenta maravilhosa? A partir desta edio vai ficar mais fcil entender o porqu deste entusiasmo...
POR JULIO CEZAR NEVES
porque, em ingls, Shell significa concha, carapaa, isto , fica entre o usurio e o sistema operacional, de forma que tudo que interage com o sistema operacional, tem que passar pelo seu crivo.

O ambiente Shell
Bom j que para chegar ao ncleo do Linux, no seu kernel que o que interessa a todo aplicativo, necessria a filtragem do Shell, vamos entender como ele funciona de forma a tirar o mximo proveito das inmeras facilidades que ele nos oferece. O Linux, por definio, um sistema multiusurio no podemos nunca nos esquecer disto e para permitir o acesso de determinados usurios e barrar a entrada de outros, existe um arquivo chamado /etc/passwd, que alm de fornecer dados para esta funo de leo-de-chcara do Linux, tambm prov informaes para o incio de uma sesso (ou login, para os ntimos) daqueles que passaram por esta primeira barreira. O ltimo campo de seus registros informa ao sistema qual o Shell que a pessoa vai receber ao iniciar sua sesso. Lembra que eu te falei de Shell, famlia, irmo? Pois , vamos comear a entender isto: o Shell a conceituao de concha envolvendo o sistema operacional propriamente dito, o nome genrico para tratar os filhos desta idia que, ao longo dos muitos anos de exis-

ilogo entreouvido em uma mesa de um botequim, entre um usurio de Linux e um empurrador de mouse: Quem o Bash? o filho caula da famlia Shell. P cara! Ests a fim de me deixar maluco? Eu tinha uma dvida e voc me deixa com duas! No, maluco voc j h muito tempo: desde que decidiu usar aquele sistema operacional que voc precisa reiniciar dez vezes por dia e ainda por cima no tem domnio nenhum sobre o que esta acontecendo no seu computador. Mas deixa isso pr l, pois vou te explicar o que Shell e os componentes de sua famlia e ao final da nossa conversa voc dir: Meu Deus do Shell! Porque eu no optei pelo Linux antes?.

O ambiente Linux
Para voc entender o que e como funciona o Shell, primeiro vou te mostrar como funciona o ambiente em camadas do Linux. D uma olhada no grfico mostrado na Figura 1. Neste grfico podemos ver que a camada de hardware a mais profunda e formada pelos componentes fsicos do seu computador. Em torno dela, vem a camada do kernel que o cerne do Linux, seu ncleo, e quem pe o hardware para funcionar, fazendo seu gerenciamento e controle. Os programas e comandos que envolvem o kernel, dele se utilizam para realizar as tarefas para que foram desenvolvidos. Fechando tudo isso vem o Shell, que leva este nome

Quadro 1: Uma rapidinha nos principais sabores de Shell


Bourne Shell (sh): Desenvolvido por Stephen Bourne do Bell Labs (da AT&T, onde tambm foi desenvolvido o Unix), foi durante muitos anos o Shell padro do sistema operacional Unix. tambm chamado de Standard Shell por ter sido durante vrios anos o nico, e at hoje o mais utilizado. Foi portado para praticamente todos os ambientes Unix e distribuies Linux. Korn Shell (ksh): Desenvolvido por David Korn, tambm do Bell Labs, um superconjunto do sh, isto , possui todas as facilidades do sh e a elas agregou muitas outras. A compatibilidade total com o sh vem trazendo muitos usurios e programadores de Shell para este ambiente. Boune Again Shell (bash): Desenvolvido inicialmente por Brian Fox e Chet Ramey, este o Shell do projeto GNU. O nmero de seus adeptos o que mais cresce em todo o mundo, seja por que ele o Shell padro do Linux, seja por sua grande diversidade de comandos, que incorpora inclusive diversos comandos caractersticos do C Shell. C Shell (csh): Desenvolvido por Bill Joy, da Universidade de Berkley, o Shell mais utilizado em ambientes BSD. Foi ele quem introduziu o histrico de comandos. A estruturao de seus comandos bem similar da linguagem C. Seu grande pecado foi ignorar a compatibilidade com o sh, partindo por um caminho prprio. Alm destes Shells existem outros, mas irei falar somente sobre os trs primeiros, tratando-os genericamente por Shell e assinalando as especificidades de cada um.

82

Agosto 2004

www.linuxmagazine.com.br

Papo de Botequim

LINUX USER

tncia do sistema operacional Unix, foram aparecendo. Atualmente existem diversos sabores de Shell (veja Quadro 1 na pgina anterior).

Com que Shell eu vou?


Quando digo que o ltimo campo do arquivo /etc/passwd informa ao sistema qual o Shell que o usurio vai usar ao se logar, isto deve ser interpretado ao p-da-letra. Se este campo do seu registro contm o termo prog, ao acessar o sistema o usurio executar o programa prog. Ao trmino da execuo, a sesso do usurio se encerra automaticamente. Imagine quanto se pode incrementar a segurana com este simples artifcio.

redirecionamento, que pode ser de entrada (stdin), de sada (stdout) ou dos erros (stderr), conforme vou explicar a seguir. Mas antes precisamos falar de...

Como funciona o Shell


O Shell o primeiro programa que voc ganha ao iniciar sua sesso (se quisermos assassinar a lngua portuguesa podemos tambm dizer ao se logar) no Linux. ele quem vai resolver um monte de coisas de forma a no onerar o kernel com tarefas repetitivas, poupando-o para tratar assuntos mais nobres. Como cada usurio possui o seu prprio Shell interpondo-se entre ele e o Linux, o Shell quem interpreta os comandos digitados e examina as suas sintaxes, passando-os esmiuados para execuo. pa! Esse negcio de interpretar comando no tem nada a ver com interpretador no, n? Tem sim: na verdade o Shell um interpretador que traz consigo uma poderosa linguagem com comandos de alto nvel, que permite construo de loops, de tomadas de deciso e de armazenamento de valores em variveis, como vou te mostrar. Vou explicar as principais tarefas que o Shell cumpre, na sua ordem de execuo. Preste ateno, porque esta ordem fundamental para o entendimento do resto do nosso bate papo.

Substituio de Variveis
Neste ponto, o Shell verifica se as eventuais variveis (parmetros comeados por $), encontradas no escopo do comando, esto definidas e as substitui por seus valores atuais.

volvidos (inclusive o prprio programa), e retorna um erro caso o usurio que chamou o programa no esteja autorizado a executar esta tarefa.
$ ls linux linux

Substituio de MetaCaracteres
Se algum meta-caracter (ou coringa, como *, ? ou []) for encontrado na linha de comando, ele ser substitudo por seus possveis valores. Supondo que o nico item no seu diretrio corrente cujo nome comea com a letra n seja um diretrio chamado nomegrandeprachuchu, se voc fizer:
$ cd n*

Neste exemplo o Shell identificou o ls como um programa e o linux como um parmetro passado para o programa ls.

Atribuio
Se o Shell encontra dois campos separados por um sinal de igual (=) sem espaos em branco entre eles, ele identifica esta seqncia como uma atribuio.
$ valor=1000

como at aqui quem est manipulando a linha de comando ainda o Shell e o programa cd ainda no foi executado, o Shell expande o n* para nomegrandeprachuchu (a nica possibilidade vlida) e executa o comando cd com sucesso.

Anlise da linha de comando


Neste exame o Shell identifica os caracteres especiais (reservados) que tm significado para a interpretao da linha e logo em seguida verifica se a linha passada um comando ou uma atribuio de valores, que so os tens que vou descrever a seguir.

Neste caso, por no haver espaos em branco (que um dos caracteres reservados), o Shell identificou uma atribuio e colocou 1000 na varivel valor.

Entrega da linha de comando para o kernel


Completadas todas as tarefas anteriores, o Shell monta a linha de comando, j com todas as substituies feitas e chama o kernel para execut-la em um novo Shell (Shell filho), que ganha um nmero de processo (PID ou Process IDentification) e fica inativo, tirando uma soneca durante a execuo do programa. Uma vez encerrado este processo (e o Shell filho), o Shell pai recebe novamente o controle e exibe um prompt, mostrando que est pronto para executar outros comandos.

Resoluo de Redirecionamentos
Aps identificar os componentes da linha que voc digitou, o Shell parte para a resoluo de redirecionamentos. O Shell tem incorporado ao seu elenco de habilidades o que chamamos de

Comando
Quando um comando digitado no prompt (ou linha de comando) do Linux, ele dividido em partes, separadas por espaos em branco: a primeira parte o nome do programa, cuja existncia ser verificada; em seguida, nesta ordem, vm as opes/parmetros, redirecionamentos e variveis. Quando o programa identificado existe, o Shell verifica as permisses dos arquivos en-

Shell Programas e Comandos Ncleo ou Kernel Hardware

Cuidado na Atribuio
Jamais faa:

$ valor = 1000 bash: valor: not found


Neste caso, o Bash achou a palavra valor isolada por espaos e julgou que voc estivesse mandando executar um programa chamado valor, para o qual estaria passando dois parmetros: = e 1000.

Figura 1: Ambiente em camadas de um sistema Linux

www.linuxmagazine.com.br

Agosto 2004

83

LINUX USER

Papo de Botequim

Decifrando a Pedra de Roseta


Para tirar aquela sensao que voc tem quando v um script Shell, que mais parece uma sopa de letrinhas ou um conjunto de hierglifos, vou lhe mostrar os principais caracteres especiais para que voc saia por a como Champollion decifrando a Pedra de Roseta.

$ echo \* $ echo *

Caracteres para remoo do significado.


isso mesmo, quando no desejamos que o Shell interprete um caractere especfico, devemos escond-lo dele. Isso pode ser feito de trs maneiras diferentes, cada uma com sua peculiaridade: Apstrofo (): quando o Shell v uma cadeia de caracteres entre apstrofos, ele retira os apstrofos da cadeia e no interpreta seu contedo.
$ ls linuxm* linuxmagazine $ ls 'linuxm*' bash: linuxm* no such file U or directory

Viu a diferena? Aspas (): exatamente iguais ao apstrofo, exceto que, se a cadeia entre aspas contiver um cifro ($), uma crase (`), ou uma barra invertida (\), estes caracteres sero interpretados pelo Shell. No precisa se estressar, eu no te dei exemplos do uso das aspas por que voc ainda no conhece o cifro ($) nem a crase (`). Daqui para frente veremos com muita constncia o uso destes caracteres especiais; o mais importante entender seu significado.

esperando pelo teclado (Entrada Padro) e como tambm no citei a sada, o que eu teclar ir para a tela (Sada Padro), criando desta forma como eu havia proposto um programa gago. Experimente!

Redirecionamentop da Sada Padro


Para especificarmos a sada de um programa usamos o smbolo > ou o >>, seguido do nome do arquivo para o qual se deseja mandar a sada. Vamos transformar o programa anterior em um editor de textos:
$ cat > Arq

Caracteres de redirecionamento
A maioria dos comandos tem uma entrada, uma sada e pode gerar erros. Esta entrada chamada Entrada Padro ou stdin e seu dispositivo padro o teclado do terminal. Analogamente, a sada do comando chamada Sada Padro ou stdout e seu dispositivo padro a tela do terminal. Para a tela tambm so enviadas normalmente as mensagens de erro oriundas dos comandos, chamada neste caso de Sada de Erro Padro ou stderr. Veremos agora como alterar este estado de coisas. Vamos fazer um programa gago. Para isto digite (tecle Enter ao final de cada linha comandos do usurio so ilustrados em negrito):
$ cat E-e-eu sou gago. Vai encarar? E-e-eu sou gago. Vai encarar?

O cat continua sem ter a entrada especificada, portanto est aguardando que os dados sejam teclados, porm a sua sada est sendo desviada para o arquivo Arq. Assim sendo, tudo que esta sendo teclado esta indo para dentro de Arq, de forma que fizemos o editor de textos mais curto e ruim do planeta. Se eu fizer novamente:
$ cat > Arq

No primeiro caso o Shell expandiu o asterisco e descobriu o arquivo linuxmagazine para listar. No segundo, os apstrofos inibiram a interpretao do Shell e veio a resposta que no existe o arquivo linuxm*. Contrabarra ou Barra Invertida (\): idntico aos apstrofos exceto que a barra invertida inibe a interpretao somente do caractere que a segue. Suponha que voc, acidentalmente, tenha criado um arquivo chamado * (asterisco) o que alguns sabores de Unix permitem e deseja remov-lo. Se voc fizesse:
$ rm *

Os dados contidos em Arq sero perdidos, j que antes do redirecionamento o Shell criar um Arq vazio. Para colocar mais informaes no final do arquivo eu deveria ter feito:
$ cat >> Arq

Redirecionamento da Sada de Erro Padro


Assim como por padro o Shell recebe os dados do teclado e envia a sada para a tela, os erros tambm vo para a tela se voc no especificar para onde eles devem ser enviados. Para redirecionar os erros, use 2> SaidaDeErro. Note que entre o nmero 2 e o sinal de maior (>) no existe espao em branco. Vamos supor que durante a execuo de um script voc pode, ou no (dependendo do rumo tomado pela execuo do programa), ter criado um arquivo chamado /tmp/seraqueexiste$$. Como no quer ficar com sujeira no disco rgido, ao final do script voc coloca a linha a seguir:
rm /tmp/seraqueexiste$$

Voc estaria na maior encrenca, pois o rm removeria todos os arquivos do diretrio corrente. A melhor forma de fazer o servio :
$ rm \*

O cat um comando que lista o contedo do arquivo especificado para a Sada Padro (stdout). Caso a entrada no seja definida, ele espera os dados da stdin (a entrada padro). Ora como eu no especifiquei a entrada, ele a est

Redirecionamento Perigoso
Desta forma, o Shell no interpreta o asterisco, evitando a sua expanso. Faa a seguinte experincia cientfica:
$ cd /etc $ echo '*'
Como j havia dito, o Shell resolve a linha e depois manda o comando para a execuo. Assim, se voc redirecionar a sada de um arquivo para ele prprio, primeiramente o Shell esvaziaeste arquivo e depois manda o comando para execuo! Desta forma, para sua alegria, voc acabou de perder o contedo de seu querido arquivo.

84

Agosto 2004

www.linuxmagazine.com.br

Papo de Botequim

LINUX USER

Dados ou Erros?
Preste ateno! No confunda >> com 2>. O primeiro anexa dados ao final de um arquivo, e o segundo redireciona a Sada de Erro Padro (stderr) para um arquivo que est sendo designado. Isto importante!

Caso o arquivo no existisse seria enviado para a tela uma mensagem de erro. Para que isso no acontea faa:
rm /tmp/seraqueexiste$$ 2> U /dev/null

caprichamos, n? Ento ao invs de sair redigindo o mail direto no prompt, de forma a tornar impossvel a correo de uma frase anterior onde, sem querer, voc escreveu um ns vai, voc edita um arquivo com o contedo da mensagem e aps umas quinze verificaes sem constatar nenhum erro, decide envi-lo e para tal faz:
$ mail chefe@chefia.com.br < U arquivocommailparaochefe

Etiquetas Erradas
Um erro comum no uso de labels (como o fimftp do exemplo anterior) causado pela presena de espaos em branco antes ou aps o mesmo. Fique muito atento quanto a isso, por que este tipo de erro costuma dar uma boa surra no programador, at que seja detectado. Lembre-se: um label que se preze tem que ter uma linha inteira s para ele.

Para que voc teste a Sada de Erro Padro direto no prompt do seu Shell, vou dar mais um exemplo. Faa:
$ ls naoexiste bash: naoexiste no such file U or directory $ ls naoexiste 2> arquivodeerros $ $ cat arquivodeerros bash: naoexiste no such file U or directory

e o chefe receber uma mensagem com o contedo do arquivocommailparaochefe. Outro tipo de redirecionamento muito louco que o Shell permite o chamado here document. Ele representado por << e serve para indicar ao Shell que o escopo de um comando comea na linha seguinte e termina quando encontra uma linha cujo contedo seja unicamente o label que segue o sinal <<. Veja o fragmento de script a seguir, com uma rotina de ftp:
ftp -ivn hostremoto << fimftp user $Usuario $Senha binary get arquivoremoto fimftp

Neste exemplo, vimos que quando fizemos um ls em naoexiste, ganhamos uma mensagem de erro. Aps redirecionar a Sada de Erro Padro para arquivodeerros e executar o mesmo comando, recebemos somente o prompt na tela. Quando listamos o contedo do arquivo para o qual foi redirecionada a Sada de Erro Padro, vimos que a mensagem de erro tinha sido armazenada nele. interessante notar que estes caracteres de redirecionamento so cumulativos, isto , se no exemplo anterior fizssemos o seguinte:
$ ls naoexiste 2>> U arquivodeerros

a mensagem de erro oriunda do ls seria anexada ao final de arquivodeerros.

neste pedacinho de programa temos um monte de detalhes interessantes: As opes usadas para o ftp (-ivn) servem para ele listar tudo que est acontecendo (opo -v de verbose), para no ficar perguntando se voc tem certeza que deseja transmitir cada arquivo (opo -i de interactive) e finalmente a opo -n serve para dizer ao ftp para ele no solicitar o usurio e sua senha, pois estes sero informados pela instruo especfica (user); Quando eu usei o << fimftp, estava dizendo o seguinte para o interpretador: Olha aqui Shell, no se meta em

nada a partir deste ponto at encontrar o label fimftp. Voc no entenderia droga nenhuma, j que so instrues especficas do ftp. Se fosse s isso seria simples, mas pelo prprio exemplo d para ver que existem duas variveis ($Usuario e $Senha), que o Shell vai resolver antes do redirecionamento. Mas a grande vantagem deste tipo de construo que ela permite que comandos tambm sejam interpretados dentro do escopo do here document, o que, alis, contraria o que acabei de dizer. Logo a seguir te explico como esse negcio funciona. Agora ainda no d, esto faltando ferramentas. O comando user do repertrio de instrues do ftp e serve para passar o usurio e a senha que haviam sido lidos em uma rotina anterior a este fragmento de cdigo e colocados respectivamente nas duas variveis: $Usuario e $Senha. O binary outra instruo do ftp, que serve para indicar que a transferncia de arquivoremoto ser feita em modo binrio, isto o contedo do arquivo no ser inteerpretado para saber se est em ASCII, EBCDIC, O comando get arquivoremoto diz ao cliente ftp para pegar este arquivo no servidor hostremoto e traz-lo para a nossa mquina local. Se quisssemos enviar um arquivo, bastaria usar, por exemplo, o comando put arquivolocal.

Redirecionamento da Entrada Padro


Para fazermos o redirecionamento da Entrada Padro usamos o < (menor que). E pra que serve isso?, voc vai me perguntar. Deixa eu dar um exemplo, que voc vai entender rapidinho. Suponha que voc queira mandar um mail para o seu chefe. Para o chefe ns

Direito de Posse
O $$ contm o PID,isto ,o nmero do seu processo. Como o Linux multiusurio, bom anexar sempre o $$ ao nome dos seus arquivos para no haver problema de propriedade,isto ,caso voc batizasse o seu arquivo simplesmente como seraqueexiste,a primeira pessoa que o usasse (criando-o ento) seria o seu dono e a segunda ganharia um erro quando tentasse gravar algo nele.

Redirecionamento de comandos
Os redirecionamentos de que falamos at agora sempre se referiam a arquivos, isto , mandavam para arquivo, recebiam de arquivo, simulavam arquivo local, O que veremos a partir de agora, redireciona a sada de um comando para a entrada de outro. utilssimo e, apesar de no ser macaco gordo, sempre quebra os

www.linuxmagazine.com.br

Agosto 2004

85

LINUX USER

Papo de Botequim

maiores galhos. Seu nome pipe (que em ingls significa tubo, j que ele canaliza a sada de um comando para a entrada de outro) e sua representao a | (barra vertical).
$ ls | wc -l 21

$ echo "Existem who | wc -l U usuarios conectados" Existem who | wc -l usuarios U conectados

$ (pwd ; cd /etc ; pwd) /home/meudir /etc $ pwd /home/meudir

O comando ls passou a lista de arquivos para o comando wc, que quando est com a opo -l conta a quantidade de linhas que recebeu. Desta forma, podemos afirmar categoricamente que no meu diretrio existiam 21 arquivos.
$ cat /etc/passwd | sort | lp

Hi! Olha s, no funcionou! mesmo, no funcionou e no foi por causa das aspas que eu coloquei, mas sim por que eu teria que ter executado o who | wc -l antes do echo. Para resolver este problema, tenho que priorizar a segunda parte do comando com o uso de crases:
$ echo "Existem `who | wc -l` U usuarios conectados" Existem 8 usuarios U conectados

A linha de comandos acima manda a listagem do arquivo /etc/passwd para a entrada do comando sort. Este a classifica e envia para o lp que o gerenciador da fila de impresso.

Para eliminar esse monte de brancos antes do 8 que o wc -l produziu, basta retirar as aspas. Assim:
$ echo Existem `who | wc -l` U usuarios conectados Existem 8 usuarios conectados

Caracteres de ambiente
Quando queremos priorizar uma expresso, ns a colocamos entre parnteses, no ? Pois , por causa da aritmtica normal pensarmos deste jeito. Mas em Shell o que prioriza mesmo so as crases (`) e no os parnteses. Vou dar exemplos para voc entender melhor. Eu quero saber quantos usurios esto logados no computador que eu administro. Eu posso fazer:
$ who | wc -l 8

Quequeiiisso minha gente? Eu estava no /home/meudir, mudei para o /etc, constatei que estava neste diretrio com o pwd seguinte e quando o agrupamento de comandos terminou, eu vi que continuava no /etc/meudir! Hi! Ser que tem coisa do mgico Mandrake por a? Nada disso. O interessante do uso de parnteses que eles invocam um novo Shell para executar os comandos que esto em seu interior. Desta forma, fomos realmente para o diretrio /etc, porm aps a execuo de todos os comandos, o novo Shell que estava no diretrio /etc morreu e retornamos ao Shell anterior que estava em /home/meudir. Que tal usar nossos novos conceitos?
$ mail suporte@linux.br << FIM Ola suporte, hoje as `date U +%hh:mm` ocorreu novamente U aquele problema que eu havia U reportado por telefone. De U acordo com seu pedido segue a U listagem do diretorio: `ls -l` Abracos a todos. FIM

As aspas protegem da interpretao do Shell tudo que est dentro dos seus limites. Como para o Shell basta um espao em branco como separador, o monte de espaos ser trocado por um nico aps a retirada das aspas. Outra coisa interessante o uso do ponto-e-vrgula. Quando estiver no Shell, voc deve sempre dar um comando em cada linha. Para agrupar comandos em uma mesma linha, temos que separ-los por ponto-e-vrgula. Ento:
$ pwd ; cd /etc; pwd ;cd -;pwd /home/meudir /etc /home/meudir

O comando who passa a lista de usurios conectados ao sistema para o comando wc -l, que conta quantas linhas recebeu e mostra a resposta na tela. Muito bem, mas ao invs de ter um nmero oito solto na tela, o que eu quero mesmo que ele esteja no meio de uma frase. Ora, para mandar frases para a tela eu s preciso usar o comando echo; ento vamos ver como que fica:

Buraco Negro
Em Unix existe um arquivo fantasma. Chama-se /dev/null.Tudo que enviado para este arquivo some. Assemelha-se a um Buraco Negro. No caso do exemplo, como no me interessava guardar a possvel mensagem de erro oriunda do comando rm, redirecionei-a para este arquivo.

Neste exemplo, listei o nome do diretrio corrente com o comando pwd, mudei para o diretrio /etc, novamente listei o nome do diretrio e finalmente voltei para o diretrio onde estava anteriormente (cd -), listando seu nome. Repare que coloquei o ponto-e-vrgula de todas as formas possveis, para mostrar que no importa se existem espaos em branco antes ou aps este caracter. Finalmente, vamos ver o caso dos parnteses. No exemplo a seguir, colocamos diversos comandos separados por ponto-e-vrgula entre parnteses:

Finalmente agora podemos demonstrar o que conversamos anteriormente sobre here document. Os comandos entre crases tem prioridade, portanto o Shell os executar antes do redirecionamento do here document. Quando o suporte receber a mensagem, ver que os comandos date e ls foram executados antes do comando mail, recebendo ento um instantneo do ambiente no momento de envio do email. - Garom, passa a rgua! s
Julio Cezar Neves Analista de Suporte de Sistemas desde 1969 e trabalha com Unix desde 1980, quando fez parte da equipe que desenvolveu o SOX, sistema operacional, similar ao Unix, da Cobra Computadores. professor do curso de Mestrado em Software Livre das Faculdades Estcio de S, no Rio de Janeiro.

86

Agosto 2004

www.linuxmagazine.com.br

SOBRE O AUTOR

Você também pode gostar