Blog do Urubatan
msgbartop
Desenvolvedor, Palestrante, Escritor, Nerd Assumido e Pai do Marcus :D
msgbarbottom

19 Jan 09 Profiglacy – Nunca foi tão fácil escrever uma UI com Swing (Graças ao JRuby)

O nome é complicado mesmo, o nome da biblioteca é “Profiglacy“. O nome da biblioteca veio de um SPAM recebido pelo Zed Shaw e ele utiliza esta biblioteca para escrever um programa de nome iHate, que é um cliente para um protocolo parecido com IRC, mas com algumas coisas mais divertidas.

O JRuby é uma implementação da linguagem Ruby para rodar na JVM. Uma das vantagens de uma implementação de Ruby rodando em uma JVM é a possibilidade de tirar proveito de todas as outras coisas que também rodam na JVM.
Exemplos disto são o acesso a EJBs a partir de aplicações Ruby, utilização de código Legado Java, acesso a diversas bibliotecas que já existem para Java e ainda não existem para Ruby.
Outra grande vantagem é a possibilidade de escrever UIs utilizando SWING que é um dos frameworks para UI mais completos disponíveis hoje em dia, mas que quando utilizado com java, tem uma possibilidade muito grande de criar um código horrível.
E para solucionar este problema existe o Profiglacy, que é uma biblioteca Ruby para facilitar a utilização de SWING quando se esta trabalhando com o JRuby.

E neste pequeno tutorial vou criar uma aplicação simples utilizando esta biblioteca. A proposta é um Gerenciador de Tarefas bem simples, mas antes vamos ver do que estamos fugindo …

Criar UI em Java é muito flexível mas muito trabalhoso, o SWING é poderoso mas muito verboso, e a própria natureza do Ruby ja melhora um pouco isto, veja o código abaixo:

1
2
3
4
5
6
require 'java'
 
@frame = javax.swing.JFrame.new "Old Way, using only SWING from Ruby"
@frame.add(@lbl1 = javax.swing.JLabel.new("Master Title"))
@frame.pack
@frame.visible = true

Isto vai criar um jframe com um label, mas ainda assim iriamos precisar de todos aqueles gerenciadores de layout, além de ser necessário também atrelar a ordem de criação dos objetos a posição deles no layout, mas para tudo há uma solução.
O modo padrão de trabalho do Profiglacy melhora isto apenas um pouco, então vamos começar direto com a utilização da Layout Expression Language criada para utilização na biblioteca. É basicamente uma forma fácil de se utilizar um GridLayout …
O layout vai ser definido como uma String, o formato desta string é bastante simples:

  • [ .. ] – delimita o inicio e fim de uma linha
  • | – delimita uma celula da linha
  • label – qualquer nome utilizado dentro de uma celula se torna o nome da celula para referência posterior
  • _ – identifica uma celula em branco
  • (width) ou (width,height) – define a largura e/ou altura de um componente dentro da celula
  • * – Expande a celula
  • ^ ou . – Alinham o componente no topo ou na parte de baixo da celula respectivamente
  • < ou > – Alinham o componente a esquerda ou direita respectivamente

E é isto, simples assim …
Segue um exemplo para facilitar o entendimento:

1
2
3
4
5
[ <lbl_proj | cmb_project  ]
[ <lbl_activ | cmb_activ  ]
[ <lbl_date | inpt_date ]
[ <lbl_hour | inpt_hour ]
[ <lbl_description | (300,200)txt_description  ]

Este código define um Grid Layout de 5 linhas por duas colunas, todos os componentes da esquerda estão também alinhados a esquerda e o último componente da direita tem 300 pixels de largura por 200 de altura.

Agora algum de vocês se anima a escrever o código em java para montar isto? Não precisa nem usar o Grid Layout, garanto que vai ficar bem maior.

Claro que as vezes o LEL (Layout Expression Language) não é suficiente, mas para mim parece que isto torna 80% dos casos bastante simples, e quando for necessário isto sempre pode ser combinado com código padrão …

Deem uma olhada no código abaixo, é criada uma UI simples, combinando paineis.
O primeiro painel definido por “main_layout” organiza os grupos de componentes, o primeiro componente recebe um label e os outros dois recebem paineis, criados com LEL mas poderiam ser criados utilizando JPanel.new sem maiores problemas.
TaskManager.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
require 'java'
require 'rubygems'
require 'profligacy/swing'
require 'profligacy/lel'
 
module TaskManager
    class UI
      include_package 'javax.swing'
      include_package 'java.awt'
      include_package 'javax.swing.border'
      include Profligacy
 
      def initialize(title)
        main_layout = "[main_label][inputs][buttons]"
        layout = %Q{
        [ <lbl_proj | cmb_project  ]
        [ <lbl_activ | cmb_activ  ]
        [ <lbl_date | inpt_date ]
        [ <lbl_hour | inpt_hour ]
        [ <lbl_description | (300,200)txt_description  ]
        }
        @ui = Swing::LEL.new JFrame, main_layout do |c,i|
          c.main_label = JLabel.new "Information About  New Entry"
          c.inputs = Swing::LEL.new JPanel, layout do |d,i| 
            d.lbl_proj = JLabel.new "Project"
            d.cmb_project = JTextField.new
            d.lbl_activ = JLabel.new "Activity" 
            d.cmb_activ = JTextField.new 
            d.lbl_date = JLabel.new "Date"
            d.inpt_date = JTextField.new 
            d.lbl_hour = JLabel.new "Hour"
            d.inpt_hour = JTextField.new 
            d.lbl_description = JLabel.new "Description"
            d.txt_description = JTextArea.new
          end.build :auto_create_container_gaps => false
          c.buttons = Swing::LEL.new JPanel, "[button_save|button_cancel ]" do |e,i|
            e.button_save = JButton.new "Save"
            i.button_save = { :action => method(:save_clicked) }
            e.button_cancel = JButton.new "Cancel"
          end.build :auto_create_container_gaps => false
        end
        @ui.build(:args => "Simple LEL Example").default_close_operation = JFrame::EXIT_ON_CLOSE
      end
 
      def save_clicked(evt_type,event)
        puts "Test OK 2"
      end
 
      def self.start
        SwingUtilities.invoke_later proc { UI.new('My Test Frame with long title') }.to_runnable
      end
 
    end
end

Para executar o código precisamos apenas de um arquivo Ruby para chamar o método “start” definido na classe UI, claro que poderiamos ter utilizado o mesmo arquivo .rb, mas isto iria diminuir a possibilidadede reutilização daquele código, então criei o arquivo abaixo:
starter.rb

1
2
3
require 'TaskManager'
 
TaskManager::UI.start

Pronto, com este super mini tutorial, você ja pode escrever muito menos código para definir as suas interfaces Java de hoje em diante, para isto só precisa programar em Ruby :D

Cada vez mais me convenço que o melhor cenário é utilizar java como Plataforma em vez de como Linguagem :D

PS.: Eu sei que faltou explicar toda a parte de eventos, mas se não for possível inferir isto do exemplo apresentado, postem perguntas nos comentários que escrevo mais algo detalhado sobre isto (isto vai servir também pra ver se alguem lê o que eu escrevo aqui :D )

Tags: , , , , , , , ,

14 Feb 08 Escrevendo plugins para o Rails – dicas e truques – plugins com generators

Seguindo a seqüencia que eu iniciei aqui, mas alterando a ordem proposta, Vamos conversar um pouco sobre os Geradores de código do Rails.

Generators são uma das coisas mais legais do Rails!
Sim, você ja viu eles, lembra do primeiro screencast sobre rails que você viu? Sim, aquele mesmo em que um cara cria um CRUD em 1 minuto …

Generators são a “forma rails” de gerar código[bb] :D

Mas o código gerado não precisa ser apenas aquele CRUD, ele pode ser o que você quiser, e o Rails ja tem um suporte excelente para isto, pois este mesmo suporte ja é utilizado na base do Rails.

Beleza, mas por que eu iria querer escrever um gerador de código?
Pense sobre o projeto que você estaria começando hoje, lembre de todos aqueles formulários para CRUD que você precisara criar, ou aquela parte quase igual de todas as páginas da aplicação …
Agora pense em todas as aplicações da empresa que você trabalho …
Entendeu agora?

Sim, eu concordo que utilizar o “scaffold” padrão não é realmente útil, mas se esta geração de código inicial for feita seguindo os padrões da sua empresa, ela pode aumentar muito a velocidade de desenvolvimento inicial das aplicações …

Agora eu imagino que você esteja pensando: Legal, generators são show de bola, mas para de falar besteira e me mostre o código!

Então, vamos brincar um pouco[bb]
Vamos iniciar criando um novo projeto rails: rails plugins102
agora de dentro do diretório do projeto execute: script\generate plugin my_generator
(Se você esta pensando que você ja viu isto antes, provavelmente você leu o post anterior sobre escrita de plugins para o rails :D )

Agora que você a criou a estrutura para um novo plugin, vamos escrever algum código!
Para criar um novo generator, você precisa criar um diretório de nome “generators” dentro do diretório do plugin, um diretório com o nome do seu generator dentro deste, e um diretório de nome “templates” dentro do diretório do seu generator, por exemplo a minha estrutura ficou assim:

  • my_generator
    • lib
    • tasks
    • test
    • generators
      • test_gen
        • templates

Na verdade, você não precisa de um plugin para criar um generator, você pode colocar o seu novo generator dentro de qualquer um dos seguintes diretórios:

  • RAILS_ROOT/lib/generators
  • RAILS_ROOT/vendor/generators
  • RAILS_ROOT/vendor/plugins/plugin_name/generators
  • USER_HOME/.rails/generators
  • gems com nome terminado em _generator

Mas eu acho que um plugin é a orma mais fácil de começar, e vai ser mais fácil de utilizar nas suas aplicações também, mas claro que se você for utilizar isto em diversas aplicações um GEM seria melhor pois você teria apenas uma cópia do código para todo o servidor, mas como eu nunca criei um GEM vou continuar com o plugin pelo menos para este exemplo …

para o código do generator nos vamos criar um arquivo no diretório do generator de nome [nome_do_generator]_generator.rb, no meu caso o nome do arquivo ficou: my_generator/generators/test_gen/test_gen_generator.rb

Agora dentro deste arquivo precisamos criar a classe que define o generator, esta classe deve ter o nome de acordo com o nome do arquivo (seguindo os padrões do ruby), no meu caso o nome da classe precisa ser TestGenGenerator, e ela precisa extender uma das classes padrão para generators do rails (na verdade eu poderia não extender nada e implementar um monte de métodos, mas assim é bem mais fácil :D ), estas classes são:
Rails::Generator::Base ou Rails::Generator::NamedBase, eu vou utilizar NamedBase (A base para o controller generator do Rails), e vou criar um modelo de generator para uma migration apenas para mostrar como isto funciona …

NamedBase é uma ótima base para geradores que esperam parametros no formato: Nome [parametro1] [parametro2] …
Para todos os outros Base é uma melhor pedida …

O nosso código inicial é este:

1
2
3
4
5
6
7
class TestGenGenerator < Rails::Generator::NamedBase
  def manifest
    record do |m|
 
    end
  end
end

Nesta classe precisamos configurar o manifesto do generator e configurar quaisquer variáveis locais que utilizemos nos templates.

Mas com o código que nos temos, você ja pode executar: ruby script\generate test_gen asdas_dasda asd:ash (letras aleatórias como parâmetros por hora).
NamedBase ja vai configurar algumas variáveis para nós quando executarmos este comando:

  • class_name -> AsdasDasda
  • class_nesting ->
  • class_nesting_depth -> 0
  • class_path ->
  • file_path -> asdas_dasda
  • name -> asdas_dasda
  • plural_name -> asdas_dasdas
  • singular_name -> asdas_dasda
  • table_name -> asdas_dasdas
  • attributes -> #<Rails::Generator::GeneratedAttribute:0×3716418>
  • args -> asd:ash

Claro que por enquanto não estamos gerando absolutamente nada, por que o manifesto do gerador esta em branco, então vamos criar um exemplo simples para ver como isto realmente funciona …
Vamos criar um diretório de nome “dummy” dentro do diretório “template” e um arquivo em branco de nome “log.log” dentro deste, e vamos fazer as seguintes alterações no manifesto:

1
2
3
4
5
  def manifest
    record do |m|
      m.file 'dummy/log.log', "log/#{file_path}.log"
    end
  end

Este código vai dizer para o gerador copiar o nosso arquivo em branco para $APP_ROOT/log/asdas_dasda.log se executarmos o gerador com os mesmos parâmetros que antes …
Mas apenas copiar arquivos de um lugar para outro não é uma coisa muito divertida, então vamos brincar um pouco com o ERB, e vamos criar uma migration para o nosso plugin, para isto vamos alterar novamente o manifesto como no seguinte exemplo:

1
2
3
4
5
6
7
8
  def manifest
    @migration_name = "Create#{class_name}"
    @migration_action = "add"
    record do |m|
      m.file 'dummy/log.log', "log/#{file_path}.log"
      m.migration_template 'lib/mymigration.rb',"db/migrate", :migration_file_name => "create_#{file_path}"
    end
  end

Como você pode ver no código, estou informando ao gerador que eu tenho um arquivo de nome mymigration.rb dentro do diretório templates/lib, este template vai ser processado pelo ERB e o código gerado vai ser colocado no diretório “db/migrate”e vai ser chamado XXX_create_asdas_dasda.rb (XXX vai ser o número da migration gerado automaticamente pelo rails)

O conteúdo do arquivo mymigration.rb é o seguinte:

1
2
3
4
5
6
7
8
9
10
11
class <%= migration_name.underscore.camelize %> < ActiveRecord::Migration
  def self.up<% attributes.each do |attribute| %>
    <%= migration_action %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'add' %>, :<%= attribute.type %><% end -%>
  <%- end %>
  end
 
  def self.down<% attributes.reverse.each do |attribute| %>
    <%= migration_action == 'add' ? 'remove' : 'add' %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'remove' %>, :<%= attribute.type %><% end -%>
  <%- end %>
  end
end

este é um template ERB que vai gerar código ruby.

Agora que ja temos um plugin razoavelmente útil , vamos ver o que mais é possível fazer …
para responder esta pergunta, vou copiar parte da documentação da classe Rails::Generator::Commands::Create, ou seja, todas as possibilidades de comandos para o manifesto do gerador:

  • class_collisions – Check whether the given class names are already taken by Ruby or Rails. In the future, expand to check other namespaces such as the rest of the user‘s app.
  • directory – Create a directory including any missing parent directories. Always directories which exist.
  • file – Copy a file from source to destination with collision checking.
  • identical? – Checks if the source and the destination file are identical. If passed a block then the source file is a template that needs to first be evaluated before being compared to the destination.
  • migration_template – When creating a migration, it knows to find the first available file in db/migrate and use the migration.rb template.
  • readme – Display a README.
  • route_resources – add a route to the routes.rb
  • template – Generate a file for a Rails application using an ERuby template. Looks up and evaluates a template by name and writes the result.

Acho que era isto, você pode fazer perguntas nos comentários se quiser, vou tentar responder todas (se é que alguem vai perguntar :D )

Para mais documentação sobre generators do rails siga os seguintes links:
http://wiki.rubyonrails.org/rails/pages/UnderstandingGenerators
http://www.aidanf.net/node/33
http://api.rubyonrails.org/classes/Rails/Generator/Base.html
http://api.rubyonrails.org/classes/Rails/Generator/NamedBase.html
http://api.rubyonrails.org/classes/Rails/Generator/Commands/Create.html

Espero que este passo a passo ajude alguem!
O próximo vai ser sobre testar o seu plugin! e o quarto eu ainda não pensei sobre o que vai ser, sugestões são bem vindas :D

Tags: , , , , , ,

16 Jan 08 Escrevendo plugins para o Rails – dicas e truques – plugins com view helpers

Uma das coisas mais legais no Rails[bb] é o suporte a Plugins …
O Ruby On Rails em si já é um excelente framework, mas a combinação dos Plugins do Rails com as classes abertas do Ruby é uma combinação explosiva!
Esta combinação é o que permite a criação de “tags” customizadas para utilizar nas suas aplicações RoR nas views e nos layouts.
E é realmente fácil de criar estes “view helpers” no Rails.

A forma padrão (sem plugins) de se criar estas “tags” é simplesmente criar um método em uma das classes Helper (as que ficam em app/helpers), por exemplo, se todos os forms na sua aplicação ficam dentro de tabelas, com uma coluna para o label e uma para o campo real, você pode criar um método helper para diminuir bastante a quantidade de código a ser digitada seguindo estes passos:

  1. rails plugins101
  2. cd plugins101
  3. ./script/generate scaffold example name:string url:string

O formulário padrão, bastante simples e feio, para o model “Example” que criamos, nesta aplicação seria algo parecido com:

1
2
3
4
5
6
7
<% form_for(@example) do |f| %>
  <table>
    <tr><td><label for="example_name">Name</label></td><td><%= f.text_field :name %></td></tr>
    <tr><td><label for="example_name">Url</label></td><td><%= f.text_field :url %></td></tr>
    <tr><td colspan="2"><%= f.submit "Update" %></td></tr>
  </table>
<% end %>

mas se editarmos o arquivo app/helpers/application_helper.rb e adicionarmos o seguinte método:

1
2
3
   def textfield label, object, property, options = {}
    %Q{<tr><td><label for="#{object.to_s}_#{property.to_s}">#{label}</label></td><td>#{text_field object, property, options}</td></tr>}
  end

o código da view ficaria muito mais simples como podemos ver abaixo.

1
2
3
4
5
6
7
<% form_for(@example) do |f| %>
  <table>
    <%= textfield "Name", :example, :name %>
    <%= textfield "Url", :example, :url %>
    <tr><td colspan="2"><%= f.submit "Update" %></td></tr>
  </table>
<% end %>

Se você pensar apenas neste pequeno formulário, pode parecer muita complicação para pouca coisa, mas pensando na aplicação inteira isto poupa bastante trabalho :D

Agora pensando um pouco maior, imagine que este padrão de layout (bem feio por sinal) que eu defini para esta aplicação, seja o padrão de todas as aplicações de toda a empresa!

e todos os desenvolvedores estão trabalhando da primeira forma que eu descrevi, codificando o HTML direto em todas as páginas.
Um belo dia, um designer novo, contratado pelo dono da empresa, diz que em todos os TR de todos os forms, é necessário adicionar uma classe CSS.
Nesta situação, o negócio é sentar e chorar …

Mas se você escolheu trabalhar da segunda forma, utilizando um helper, no máximo você precisara alterar uma linha de código por aplicação!
Você pode se considerar um herói! Certo?

Mas considere a opção de você ser ainda mais esperto do que isto! Que tal criar um plugin que vai conter estas tags para facilitar o trabalho, e utilizar este plugin em todas as aplicações da empresa?
Desta forma você precisaria alterar apenas uma linha de código, testar apenas uma vez, e todas as aplicações da empresa ja estariam corrigidas!

E como sempre, com o Rails, esta é uma tarefa muito fácil de ser completada :D
Apenas siga estes passos simples:

  1. ./script/generate plugin life_saver
  2. Edite o arquivo vendor/plugins/life_saver/lib/life_saver.rb e adicione o seguinte código nele:
    1
    2
    3
    4
    5
    6
    
    # LifeSaver
    module LifeSaver
      def textfield label, object, property, options = {}
        %Q{<tr><td><label for=#{object.to_s}_#{property.to_s}>#{label}</label></td><td>#{text_field object, property, options}</td></tr>}
      end
    end
  3. Edite o arquivo vendor/plugins/life_saver/init.rb e inclua o seguinte código:
    1
    2
    
    # Include hook code here
    ActionView::Base.send :include, LifeSaver
  4. Remova o método helper que adicionamos no arquivo app/helpers/application_helper.rb

Ok, você acabou de criar o seu primeiro plugin para o Rails[bb]!
E sim, o código é exatamente o mesmo utilizado no application_helper.rb, o único truque esta no init.rb, aquela linha de código, inclui todos os métodos do module “LifeSaver” na classe base de todas as views do Rails, a ActionView::Base.

Agora, se você escolheu esta terceira opção, va falar com o seu chefe, conte uma historia parecida com a que eu contei aqui, e peça um aumento, por que você merece, você acabou de poupar diversas horas de trabalho de umas 3 pessoas pelo menos :D

Espero que este pequeno passo a passo ajude alguem :D

Este é o primeiro post de uma série sobre escrita de plugins para RoR, o próximo vai ser sobre testes unitários para o código dos seus plugins, o terceiro vai falar de plugins com generators, e o quarto vocês vão ter que voltar aqui para descobrir sobre o que vai ser :D

Tags: , , , , ,

05 Jan 08 Claro 3g com modem traveller D301 funciona no linux :D – passo a passo para configuração e compartilhamento de acesso a internet

Como escrevi no outro post, estou utilizando o Claro 3g aqui em casa, e estava com um problema grave pois não conseguia conectar utilizando o Kubuntu do meu linux, e graças ao link indicado pelo Walter Gomes, segue um passo a passo para utilizar a conexão no linux, e ainda ativar o compartilhamento de internet, que no meu caso é útil pois são duas maquinas aqui :D
E como passei trabalho para descobrir como fazer isto, resolvi compartilhar com vocês (na verdade é bem simples depois de descobrir como fazer :D )

Primeiro, vamos instalar todo o software necessário para a conexão:

sudo apt-get install wvdial pppd

Espere o final da instalação e tudo pronto …

No meu caso o wvdialconf não detectou o modem da claro, ou pelo menos ele detectou primeiro o modem onboard e desistiu de procurar, mas a configuração do wvdial que eu escrevi ficou assim:

[Dialer Defaults]
Modem = /dev/ttyACM0
ISDN = off
Modem Type = USB Modem
Baud = 115200
Init = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 =
Init4 =
Init5 =
Init6 =
Init7 =
Init8 =
Init9 =
Phone1 =
Phone2 =
Phone3 =
Phone4 =
Dial Prefix =
Dial Attempts = 3
Dial Command = ATM1L3DT
Ask Password = off
Abort on Busy = off
Auto Reconnect = on
Carrier Check = on
Check Def Route = on
Abort on No Dialtone = on
Stupid Mode = off
Idle Seconds = 0
Auto DNS = on

; display modem information
[Dialer info]
Init9 = AT&V

[Dialer claro3g]
Password = claro
Username = claro
Phone = *99***10#
Auto Reconnect = off
Stupid Mode = on

O modem USB da claro esta no dispositivo /dev/ttyACM0, se você copiar e colar o texto acima e digitar:

sudo wvdial claro3g

você deve conectar a internet sem problemas, aqui aconteceu do wvdial não configurar a rota padrão, então tive que executar também:

sudo route add -net 0.0.0.0 dev ppp0

depois disto a internet[bb] passou a funcionar beleusa :D

Agora o negocio é fazer tudo funcionar usando o PPPD, para isto eu criei um arquivo de nome /etc/ppp/peers/claro3g com o seguinte conteúdo (não esqueça de derrubar o wvdial para terminar a conexão antes de continuar):

noauth
name wvdial
connect "/usr/bin/wvdial --chat claro3g"
/dev/ttyACM0
115200
modem
crtscts
defaultroute
usehostname
user claro
noipdefault
#usepeerdns
#demand
idle 0
logfd 6

Isto vai fazer com que você possa conectar utilizando o comando: pon claro3g, e desconectar com o comando poff claro3g
Agora estou procurando uma forma de fazer descomentar o demand e ativar o “pon claro3g” no momento em que o linux detectar que o modem USB foi inserido, e a linha peerdns esta desabilitada na por que eu prefiro utilizar o meu bind9 local, vocês podem descomentar esta linha se não quiserem utilizar um DNS local, mas sem o DNS local o próximo passo não vai funcionar muito bem …

Agora vamos compartilhar a conexão a internet[bb], para isto precisamos de mais alguns softwares instalados:

sudo apt-get install dhcp3-server iptables

e vamos precisar configurar o servidor DHCP e um IP estático para a placa de rede da rede local …
Configurar um IP estático para a placa de rede local é fácil, basta editar o arquivo /etc/network/interfaces, localizar a ehtrada correspondente a eth0 e faze-la parecida com isto:

auto eth0
iface eth0 inet
address 192.168.57.1
netmask 255.255.255.0

e a configuração do servidor DHCP também não é exatamente complexa, edite o arquivo cat /etc/dhcp3/dhcpd.conf e adicione a seguinte configuração ao final do arquivo:

subnet 192.168.57.0 netmask 255.255.255.0 {
range 192.168.57.10 192.168.57.100;
option routers 192.168.57.1;
}

reinicie o servidor (sudo /etc/init.d/dhcp3-server restart) e tudo pronto, falta só compartilhar a conexão a internet, se você não tiver ainda um firewall configurado, basta executar isto:

#/sbin/iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
#echo 1 > /proc/sys/net/ipv4/ip_forward

A primeira linha habilita mascaramento de IP (NAT) para todo o trafego saindo pela interface ppp0 e a segunda linha habilita o forwarding de pacotes IP.

Tudo pronto, esta conectando ao claro3g e compartilhando a sua conexão a internet em casa :D
Agora é só você falar para os seus amigos deste post, e publicar um link para ele em algum lugar para facilitar para os novos usuários da claro, assim eles vão encontrar este passo a passo e não vão perder quase duas semanas como eu perdi :D

Abraço e espero que este post seja útil para mais alguem …
PS.: uma outra idéia legal é fazer um script para subir as configurações do firewall automagicamente quando ligar a maquina e salvar quando desligar, para isto eu criei um arquivo /etc/init.d/iptables com o seguinte conteúdo:

#!/bin/sh
# Start/stop the iptables configuration
#
### END INIT INFO
test -f /sbin/iptables-save || exit 0
. /lib/lsb/init-functions
case "$1" in
start) log_daemon_msg "Reading iptables configuration" "iptables"
/sbin/iptables-restore < /etc/iptables.conf
log_end_msg $?
;;
stop) log_daemon_msg "Saving iptables configuration" "iptables"
/sbin/iptables-save > /etc/iptables.conf
log_end_msg $?
;;
*) log_action_msg "Usage: /etc/init.d/iptables {start|stop}"
exit 2
;;
esac
exit 0

e executei o comando update-rc.d iptables defalts 90

Tags: , , , , , , , , , ,