Fiquei devendo a alguns da lista uma explicação detalhada de como eu
gerei aquela mensagem, aparentemente criptografada. Não enviei antes
pois pretendia fazê-lo com riqueza de detalhes. Pensei até em escrever
um artigo no Viva o Linux (onde contribuo) e talvez ainda o faça.
O dc, para quem não conhece, é uma calculadora de notação polonesa.
Como qualquer aluno de programação sabe, pois certamente já teve que
implementar algo em Linguagem de Programação ou Estrutura de Dados, a
notação polonesa funciona sobre uma pilha.
Se para somar 200 com 500 se faz no bc (outra calculadora):
echo "200 + 300" | bc
No dc é um pouco diferente:
echo "200 300 + p" | dc
Onde se lê:
- Empilha o 200
- Empilha o 300
- Operador + precisa de dois parâmetros. Desempilha dois parâmetros
e soma (200 e 300)
- Empilha o resultado da operação (500)
- Imprime (sem desempilhar) o valor do topo da pilha (comano 'p').
No caso 500
Ao final da operação a pilha está vazia
Um exemplo mais completo para ilustrar de vez o conceito:
echo "200 3 4 5 6 7 + * - + + p" | dc
- "200 3 4 5 6 7" são todos EMPILHADOS. A pilha está com o 7 sendo
o TOPO
- Operador de +, desempilha o 7 e o 6 e soma: 7+6 = 13. Empilha o
13. A pilha está agora com "200 3 4 5 13"
- Operador de *, desempilha o 13 e o 5 e multiplica: 13*5 = 65.
Empilha. A pilha agora está com "200 3 4 65"
- Operador de -, desempilha o 65 e o 4 e faz 4-65= -61. Empilha. A
pilha está agora com "200 3 -61"
- Operador de +, desempilha o 3 e o -61 e soma: 3+ (-61) = -58.
Empilha. A Pilha está agora com "200 -58"
- Operador de +, desempilha o 200 e o -58 e soma: 200 + (-58) =
142. Empilha. A pilha está agora com "142"
- Operador p, imprime o valor do topo. Imprime 142
Ok. Isto quanto ao dc.
Lembrando o mais importante neste caso: o comando 'p', minúsculo,
apenas imprime o que está no topo da pilha. Apenas um valor, não
importa quantos estão na pilha.
Já o comando P (Maiúsculo) faz uma impressão diferente. Ele imprime
interpretando ASCII.
Veja:
echo "65 p" | dc # irá imprimir 65
echo "65 P" | dc # irá imprimir a letra A
O dc é um interpretador de comandos. Se você apenas digitar "dc" ele
irá aguardar comandos. Por isto que se usa o echo junto com o pipe para
evitar que ele aguarde que você digite algo.
Ou então pode-se usar o parâmetro -e, passando o que se quer digitar
como parâmetro:
dc -e "65p"
dc -e "65P"
O último dc, se você está me acompanhando e reproduziu em seu terminal,
imprimiu um A perdido, quase não notado antes do prompt.
Seria interessante ter uma quebra de linha, certo?
No mundo Unix a quebra de linha é reproduzida apenas com o caractere LF
(Line Feed) que na tabela ASCII corresponde ao valor 10.
No mundo DOS uma quebra de linha precisa de LF+CR (Line Feed + Enter)
que na tabela ASCCI é 10 e 13. Para quem não entendeu, isto explica
porque o teu código em bash feito no Linux não abre corretamente no
(sic) notepad. Isto é tão comum que já existem nas distribuições
aplicativos como dos2unix e unix2dos apenas para converter de e para o
formato de texto DOS.
Então para termos a nossa quebra de linha:
dc -e "65 P 10 P"
Meu nome neste formato:
dc -e "69P 108P 103P 105P 111P 32P 83P 99P 104P 108P 101P 109P 101P
114P 10P"
Deixei espaço em branco para facilitar, mas ele não é necessário:
dc -e "69P108P103P105P111P32P83P99P104P108P101P109P101P114P10P"
Isto já é um pouco nerd, mas ainda não tem graça. Tem muito 'P' ai e
quem conhece ASCII logo iria sacar: "69 => 'E'
A grande vantagem o comando P é que ele pode pegar um inteiro qualquer
e ler como uma string!!
Vamos com um exemplo pequeno: o 'A' seguido de quebra de linha:
dc -e "65P10P"
Se a gente pensar no 65 na memória (UM BYTE) e o 10 na memória (UM
BYTE), porém pegar estes DOIS bytes juntos e ver qual inteiro dá, o que
teríamos?
O caminho mais prático para isto é transformar em HEXA:
65 => 0x41
10 => 0x0A
(usei a notação 0x por ser a notação do C)
Então teriamos 0x410A como a junção da letra 'A' (65) com um LF (10).
Qualquer calculadora me diz que 0x410A = 16650 em decimal.
Então:
dc -e "16650P"
Voalá!
Agora vem a parte divertida: fazendo a mesma coisa com o meu nome
(estou usando agora fonte FIXA para dar uma ideia de tabela)
'E' lgio Schlemer
STRING => 'E' 'l' 'g' 'i' 'o' ' ' 'S' 'c' 'h' 'l' 'e' 'm' 'e'
'r' LF
DECIMAL=> 69 108 103 105 111 32 83 99 104 108 101 109 101 114 10
HEXA => 45 6C 67 69 6F 20 53 63 68 6C 65 6D 65 72 0A
Agora temos que pegar este ENORME número em HEXA
(456C67696F205363686C656D65720A) e ver qual é o ENORME inteiro que ele
representa.
Tem várias maneiras de fazer isto. Neste tutorial irei sugerir o bc que
é muito versátil na conversão de bases:
echo -ne "ibase=16\n456C67696F205363686C656D65720A\n"|bc
(indico que a entrada, ibase, é na 16).
Isto me dá o simpático número 360467176607105907189923076131615242
Então:
dc -e "360467176607105907189923076131615242P"
A medida que a string aumenta em caracteres, o número inteiro atinge
proporções ALARMANTES.
dc -e "
277201296679637797555446024759571638996189735149437200489138275766068595461885161373164910801694181693794226357412355299879133847920069570025933844008821898437588589611533P"
Para evitar problemas com os contes, linhas muito longas, pode-se usar
o contra barra. No bash, assim como no C, a contra barra indica que a
linha ainda não acabou, continuando na linha de baixo.
dc -e "277201296679637797555446024759571638996\
1897351494372004891382757660685954618851613731\
6491080169418169379422635741235529987913384792\
0069570025933844008821898437588589611533P"
Você pode, agora, simplesmente copiar o trecho acima e colar no seu
terminal. Nem precisa colocar em um arquivo. Só dê um ENTER final para
enviar o comando.
Como o # é comentário, isto também é aceito:
# INICIO. Copie a partir daqui
dc -e "277201296679637797555446024759571638996\
1897351494372004891382757660685954618851613731\
6491080169418169379422635741235529987913384792\
0069570025933844008821898437588589611533P";\
# FIM. Copie ate aqui
Além dos caracteres em ASCII eu também coloquei na string sequências de
ESCAPE que indicam limpar a tela e imprimir em colorido.
Isto pode ser demonstrado com qualquer echo:
echo -e "\033[2JLimpei a tela. \033[0;31;1mVermelho\033[m Normal\n"
A sequência ESC [0;31;1m configura o terminal para um vermelho negrito.
No caso do echo o ESCAPE foi representado por \033, ou seja, o octal
33. Se for colocado do decimal do ESC mesmo não precisaria o -e do echo.
O \033[m volta o terminal a configuração normal.
Assim como o Rafael Jeffman mostrou um código em python que transforma
uma string em um inteiro gigante que a representa, eu tenho um
programinha em bash mesmo para fazer isto.
Bem, era isto. Escrevi este email em um só fôlego, portanto é possível
que tenham erros (não o revisei).
Por fim:
dc -e "2570P47124526397124574873853331168207446777\
76557321296532173690633106694284207747615688075869\
0137565983871170813168141P2570P"
--
Elgio Schlemer - ULBRA - http://gravatai.ulbra.tche.br/~elgio
Coordenador do curso de Ciência da Computação Ulbra Gravataí
http://www.vivaolinux.com.br/perfil/verPerfil.php?login=elgio
***** "Eu sei que foi pago um alto preço" (Asaph Borba) *****