Lotus 1-2-3 para Linux
(lock.cmpxchg8b.com)- O Lotus 1-2-3, uma planilha proprietária de 30 anos, passou a rodar nativamente no Linux após a recuperação acidental de materiais e hacking de binários, mesmo que o sistema não existisse na época do lançamento
- A descoberta do SDK de add-ins LPL dado como perdido e do Lotus 1-2-3 for UNIX em backups de BBS dos anos 1990 tornou possível compilar plugins de exemplo e analisar os binários UNIX
- A distribuição UNIX incluía o objeto COFF Intel 80386 compactado
123.o, e cerca de 20.000 símbolos e informações de debug revelaram a estrutura interna - O port não se resumiu a converter COFF para ELF; foi preciso contornar as diferenças de ABI de chamadas de sistema e estruturas entre Linux e UNIX com
coffsyrupe funções wrapper - Atualmente o port roda sem travar e está 100% utilizável, mas ainda restam alguns problemas e o port do driver de terminal, então a versão DOS em emulação ainda parece melhor
O ponto de partida para levar um app proprietário de 30 anos ao Linux
- O Lotus 1-2-3 permanecia como um abandonware de 30 anos, mas várias descobertas e hacks tornaram possível um port nativo para Linux
- O alvo do port é o clássico Lotus 1-2-3 R3, embora o próprio Lotus 1-2-3 tenha recebido lançamentos até 2002
- O projeto começou a partir da manutenção do driver lotusdrv, feito para que o Lotus 1-2-3 funcione bem em sistemas modernos
- A API do driver foi entendida por engenharia reversa, e os drivers existentes funcionam bem em sistemas modernos
O SDK LPL perdido e os backups de BBS
- O Lotus 1-2-3 foi projetado para ser expandido com plugins, ou add-ins, mas eles precisavam ser escritos em uma linguagem especial chamada LPL
- O compilador LPL e o SDK haviam desaparecido, e a Lotus não distribuía o SDK gratuitamente: ele era vendido por US$ 395
- O SDK foi recuperado em forma de warez por meio de um ex-sysop que guardava backups em fita de sistemas BBS dos anos 1990
- O ADK recuperado pode ser baixado em 123DADK.ZIP
- Um programa de exemplo em LPL foi publicado como modern.pl
- Esses mesmos backups de BBS também continham uma cópia warez do Lotus 1-2-3 for UNIX, amplamente considerada perdida
Análise das imagens de disco do Lotus 1-2-3 for UNIX
- A versão UNIX sobreviveu em um conjunto de arquivos TD0 de
123UNIX1.TD0até123UNIX5.TD0 - Foi confirmado que TD0 é um formato antigo de imagem de disco compactada dos anos 1980, e a conversão para imagem de disco raw foi feita com samdisk
- Entre as imagens convertidas, a primeira era um
tar archive, e as demais eram archives cpio ASCII no formato pre-SVR4 ou odc - O conjunto completo das imagens de disco foi enviado para o Internet Archive
- Depois da descompactação, surgiram em
lotus/123.v10o executável, ajuda, keymaps, dados de drivers de impressora e vídeo, arquivos de exemplo, manuais e mais- A estrutura total tinha cerca de 35 diretórios e 338 arquivos
A pista decisiva: 123.o
- No diretório
sysV386/lib, foi encontrado um arquivo grande dividido em123.o.z_1e123.o.z_2 - Após juntar as duas partes e descompactar,
123.ofoi identificado como um arquivo objeto COFF Intel 80386- arquivo objeto sem strip
- 5 seções
- offset de símbolos
0x1efbdc -
19.755 símbolos
- tamanho do optional header: 28
- Esse arquivo incluía símbolos privados e informações de debug, o que ajudou muito a entender a estrutura interna do Lotus 1-2-3
- A resposta recebida em
alt.folklore.computerssugeriu que esse arquivo não foi incluído por engano - Como o
dlopen()não era amplamente usado no UNIX do início dos anos 1990, é provável que tenha sido um objeto parcialmente ligado para extensão de recursos e relinkedição
A estrutura interna revelada pelas informações de debug
- A versão UNIX era próxima de um port direto do código-fonte da versão DOS, então a maior parte do funcionamento era igual
- As informações de debug incluídas esclareceram várias dúvidas sobre o interior do Lotus 1-2-3
- Para melhorar a saída de gráficos, queria-se colocar um hook no rasterizador a partir do driver, mas era difícil entender o funcionamento apenas com a documentação
- Com as informações de debug, foi possível descobrir que o rasterizador gera dinamicamente pequenos programas em bytecode, que o motor gráfico interpreta
- Depois de identificar os opcodes, isso passou a poder ser desmontado e alterado em raster.c para melhorar a saída
Convertendo de COFF para ELF
- O
objcopyconsegue converter arquivos objeto COFF para o formato ELF usado no Linux - O comando
objcopy -I coff-i386 -O elf32-i386 123.o 123elf.ofoi usado para converter123.oem123elf.o - O resultado foi identificado como
ELF 32-bit LSB relocatable, Intel 803386, version 1 (SYSV), not stripped - Segundo o
objdump, o horário de compilação do arquivo objeto original era 8 de setembro de 1990 às 06:23:50, ou seja, antes da primeira versão do Linux
Lidando com as diferenças de ABI entre Linux e UNIX
- O primeiro problema era que Linux e UNIX não usam interfaces de chamadas de sistema compatíveis entre si
- A versão UNIX usava a interface
lcall7; por exemplo,open()fazia uma chamada de callgate no formatocall 0x7:0x0 - Como o Linux não dá suporte a esse callgate, a execução travava se fosse mantido como estava
- O Linux já teve suporte de compatibilidade para
lcall7elcall27, mas isso não existe mais
- O Linux já teve suporte de compatibilidade para
- O objetivo era eliminar essas chamadas e redirecionar tudo para passar pela glibc
Relocação e coffsyrup
- A tentativa inicial foi remover o símbolo com
objcopy --strip-symbol open, mas oobjcopyrecusou porqueopenera usado em uma relocation - Um arquivo objeto relocável inclui referências simbólicas e informações de relocação para funcionar independentemente do endereço em que for carregado
- Para remover um símbolo, também é preciso alterar junto a informação de relocação que o referencia
- Para isso, foi criada a pequena ferramenta coffsyrup
- Ela consegue remover símbolos COFF que o
objcopyse recusa a retirar - Como exemplo, ela localiza e trata o símbolo
opene as relocations associadas
- Ela consegue remover símbolos COFF que o
Funções UNIX que não são binariamente compatíveis
- Muitas funções UNIX padrão são compatíveis em nível de código-fonte, mas não binariamente compatíveis
- Um exemplo representativo é
struct stat- O mesmo código C pode ser compilado em várias famílias UNIX
- Mas o arquivo objeto compilado pode quebrar em outro sistema por diferenças no tamanho de
struct statou no offset dest_size
- As principais funções que precisaram ser tratadas foram
stat(),times(),uname(),fcntl(),ioctl()e outras - A abordagem foi renomear símbolos com
objcopy, marcá-los como undefined comcoffsyrupe escrever funções wrapper que convertem estruturas Linux em estruturas UNIX termiosfoi um obstáculo particularmente grande, porque os detalhes do comportamento variam de forma sutil entre sistemas UNIX e não são compatíveis, o que dificultou o debug
Verificação de licença e resultado da execução
- Depois de vários hacks, o programa passou a rodar sem travar, mas não funcionava sem uma licença
- Ao colocar um breakpoint em
exit(), descobriu-se que o símbolo interno responsável por validar a licença eralic_init() - A análise do código no IDA mostrou que a checagem de licença procura o arquivo
LICENSE.000e verifica se a data de expiração, o nome do usuário e o nome do sistema batem com os valores informados pelo sistema - No fim, o Lotus 1-2-3 foi portado para um novo sistema operacional: o Linux
- O estado atual é o seguinte
- roda sem travar
-
100% utilizável
- alguns problemas ainda precisam ser ajustados
- o port do driver de terminal ainda está pendente
- por enquanto, a versão DOS rodando em emulação ainda parece melhor, mas isso pode ser corrigido
- o código do port está disponível no github
1 comentários
Opiniões no Hacker News
É quase inacreditável que tenham recuperado uma cópia warez do SDK a partir de um backup em fita de um antigo sistema BBS e ainda compilado até o plugin de exemplo
Isso me lembrou Why History Needs Software Piracy
Esses equipamentos são hardwares que continuarão existindo por décadas, então haveria grande valor público em ter um repositório centralizado e duradouro que toda a comunidade pudesse usar, indo além de cada fabricante guardar tudo em sua própria nuvem pessoal
Também pensei em distribuir o arquivo todos os anos, ou vender um archival Blu-ray em mídia física capaz de durar uns 100 anos
Assim, quando alguém precisasse recuperar o firmware corrompido de um módulo Eurorack com DSP baseado em ARM, a probabilidade de alguém ter o último e raro arquivo
.binnecessário ficaria próxima de 1Meu pai guardava um monte de arquivos Lotus 1-2-3 importantes em um notebook secundário com uma versão antiga do Windows, e às vezes precisava abri-los, então aquela situação era bem preocupante
Recentemente descobri que o LibreOffice consegue converter arquivos Lotus para ODF/ODS, até pela linha de comando, e converti tudo com um script bash simples
Fiz upload em lote dos arquivos convertidos para um Nextcloud com Collabora, criei uma conta para meu pai e expliquei o uso básico; agora ele consegue ver os arquivos online, e eles também entram na rotina normal de backup do servidor
Sou muito grato a arqueólogos de dados como o OP e aos contribuidores do LibreOffice
Lembro de quando eu tinha 7 anos e pedi um Nintendo; meu pai comprou em vez disso um PC 286 com Lotus 1-2-3 e a aventura de texto Indiana Jones
Por isso minha primeira linguagem foi BASIC, não LISP, e pretendo culpar essa tragédia por todos os fracassos da minha vida, sem aceitar contestações
Mesmo que o Spectrum já estivesse em declínio naquela época
Estou fazendo um trabalho parecido, mas acrescentando uma etapa que primeiro transforma partes do programa em arquivos-objeto
Assim, não fico preso apenas aos arquivos-objeto existentes que sobreviveram, embora seja necessária certa engenharia reversa para fazer funcionar
Fiz uma prova de conceito com
aln, o linker do Atari Jaguar, separando um executável Linux x86a.outem arquivos-objeto ELF e depois fazendo o link novamente como um executável ELF x86, contornando as diferenças de ABIhttps://forums.atariage.com/topic/354341-porting-the-original-atari-jaguar-sdk-to-elf/
Foi interessante em vários aspectos
O processo de levar um binário UNIX para um binário Linux sem código-fonte, sem o compilador original e sem a linguagem original pareceu muito legal; esse é o tipo de conteúdo que combina com o HN
Também serve para lembrar que, em 2023, a Usenet ainda é usada para coisas além da simples distribuição de arquivos rar
E também traz à memória a cultura dos BBS antes da popularização da internet, quando entusiasmo e ótimas distribuições shareware chegavam ao público
Ainda mais vendo o colapso do Twitter e de outras redes sociais; a Geração Z mais velha está mergulhando no retrô dos anos 80 e 90 e até baixando sons de negociação de modem como toque de celular
Meu sobrinho de 23 anos fez isso recentemente, e obras como American Horror Story e Stranger Things continuam alimentando essa nostalgia
A velha máxima de que, se você esperar tempo suficiente, tudo volta à moda acaba estando certa
Também houve uma boa discussão em maio de 2022 do ano passado
https://news.ycombinator.com/item?id=31455968
O site https://scenelist.org/ linkado neste excelente texto foi exatamente a bomba de nostalgia de que eu precisava esta manhã
É uma ótima viagem ao passado, recomendo muito
Links relacionados
Lotus 1-2-3 for Linux - https://news.ycombinator.com/item?id=35807639 - maio de 2023, 73 comentários
Lotus 1-2-3 - https://news.ycombinator.com/item?id=35872758 - maio de 2023, 117 comentários
Lotus 1-2-3 For Linux - https://news.ycombinator.com/item?id=31455968 - maio de 2022, 83 comentários
Lotus 1-2-3 arbitrary resolution - https://news.ycombinator.com/item?id=26316637 - março de 2021, 123 comentários
Eu tinha esquecido completamente do 1-2-3, apesar de tê-lo usado rapidamente no ano passado
O binário
123ainda roda muito bem no Linux, e é um feito e tanto que um software desaparecido há tanto tempo simplesmente funcioneSempre quis algo assim. Como não uso muito fontes ou imagens em planilhas, uma planilha baseada em terminal é perfeita
Fico feliz que finalmente tenha surgido, e seria ótimo se fosse portada para Mac e Windows
https://lock.cmpxchg8b.com/spreadsheet.html
Nunca usei, mas vale conferir
Além disso, o Org-Mode do Emacs é uma ferramenta para explorar sem fim, e também há uma forma de usar células de tabelas do org-mode como planilha junto com o recurso
Calcdo Emacshttps://www.youtube.com/watch?v=15aDIvb5LJs
Parece bem poderoso e, como é típico do Emacs, roda tanto no terminal quanto em ambiente de janelas
sc: https://www.unix.com/man-page/linux/1/sc/