Shellmod Introdução 11.. OO qquuee éé sshheellllmmoodd Shellmod é um módulo do Linuxconf bem como um utilitário para rodar em máquinas sozinhas. Seu objetivo é permitir a escrita simples de outros módulos e utilitários Linuxconf utilizando sh (/bin/sh, o interpretador shell). Os benefícios de se escrever módulos Linuxconf (ou simplesmente utilitários de administração) desta forma são: · Boa interface: Seu script funcionará tanto em modo texto como gráfico, com uma aparência muito melhor do que com um shell script comum. Quando usado como um módulo no Linuxconf, ele também funcionará em HTML, de forma completamente transparente. · Simplicidade: É possível escrever coisas úteis em um shell script de 10-15 linhas. É possível transformar um shell script não- interativo existente de 10-15 lines em ótimo script interativo de 15-20 linhas, sendo executado em modo texto, gráfico e mesmo em HTML. · Usado como um módulo, seu script será capaz de se agregar a vários menus do Linuxconf, fazendo-se totalmente integrado com o esquema de administração. · Não só o script pode aprimorar os menus do Linuxconf, como também pode participar como co-administrador em alguns diálogos. Isto significa que um simples script pode adicionar novos campos no diálogo de contas de usuário, por exemplo. O módulo Linuxconf C++ Normal pode, obviamente, fazer mais coisas, mas os scripts oferecem uma boa e eficiente solução para instalação personalizada e suporte no site. Um novo módulo Linuxconf pode ser desenvolvido com o usuário/amigo/cliente olhando por cima de seu ombro. 22.. PPrriinnccííppiiooss Nesta seção nós veremos o layout básico de um script shellmod, como usá-lo e como ele se comunica com o Linuxconf. 22..11.. CCoommppoonneenntteess ddoo ppaaccoottee sshheellllmmoodd O pacote shellmod fornece as seguintes partes: · O utilitário shellmod usado para executar o script shellmod sem o Linuxconf. Este utilitário está localizado em /usr/bin. · O módulo shellmod que permite ao script shellmod interagir com o Linuxconf. Observe que um script shellmod pode ser usado das duas formas, sozinho ou embutido no Linuxconf. · A biblioteca de funções shellmod-lib.sh. Ela está localizada em /usr/lib/linuxconf/lib. Ela contém funções de utilitários que simplificam os scripts shellmod. Este arquivo deve ser originado em todos os scripts. · Um script exemplo. · Em algum momento, o pacote irá conter alguns scripts de exemplo e um browser será escrito para encontrar com facilidade e testar esses scripts. Se você escreveu algo genérico e útil, mande para a lista de discussão do Linuxconf, para inclusão neste pacote. 22..22.. CCoommoo uussaarr ssccrriippttss sshheellllmmoodd Um script pode ser utilizado sozinho ou juntamente com o Linuxconf. Pode ser utilizado de ambas as formas. 22..22..11.. CCoommoo uumm uuttiilliittáárriioo ssoozziinnhhoo Para executar um script shellmod, você pode fazer shellmod rota_do_script [ argumentos ] Ou se o script iniciar com #!/usr/bin/shellmod, você simplesmente o executa como qualquer utilitário. Observe que em todos os casos, o script deve ser executável (chmod +x script). 22..22..22.. CCoommoo uumm mmóódduulloo ddoo LLiinnuuxxccoonnff Para ser utilizado desta forma, ele deve estar registrado no Linuxconf. Isto é feito interativamente ou utilizando uma linha especial de comando. O módulo shellmod registra seu menu de configuração no menu Sistemas e arquivos de controle. Você encontrará lá um diálogo para registrar seu script. Apenas entre com a rota de seu script e mais nada. O script será visível ao Linuxconf a partir da próxima execução. O script pode ser registrado utilizando a seguinte linha de comando. Isto é útil especialmente se você incluir seu script em um pacote e desejar registrar o script no Linuxconf como instalação de pacote. (Empacotadores RPM devem considerar a grande facilidade em se fazer isto). linuxconf --modulemain shellmod --setmod rota_do_script Observe que a construção linuxconf --modulemain é a forma normal de ceder o controle à linha de comando de um módulo: o shellmod não é diferente. Você pode remover o registro de um script do Linuxconf da seguinte forma: linuxconf --modulemain shellmod --unsetmod rota_do_script Observe que a sintaxe acima replica a forma normal (C++) que os módulos Linuxconf podem ser registrados ou removidos do registro, usando as linhas de comando linuxconf --setmod e linuxconf --unsetmod. 22..33.. EEssttrruuttuurraa ddee uumm ssccrriipptt sshheellllmmoodd Um script shellmod sempre terá este aspecto: #!/usr/bin/shellmod . /usr/lib/linuxconf/lib/shellmod-lib.sh register(){ # Coloque aqui as chamadas do regmenu e comanager } # Coloque aqui as várias funções referenciadas acima main(){ # Nós definimos um sub-menu ou um diálogo } # O script sempre termina com a chamada da função dispatch function call. Sempre. dispatch 22..33..11.. AA bbiibblliiootteeccaa ddee ffuunnççõõeess sshheellllmmoodd--lliibb..sshh 22..33..22.. AA ffuunnççããoo rreeggiisstteerr A função register é necessária se o script for utilizado como um módulo do Linuxconf. Linuxconf chamará a função esperando que o script retorne a lista de menus e diálogos nos quais ele deseja registrar. Eis aqui um exemplo de uma função de registro instalando dois sub- menus e um co-administrador (co-manager). # Registro no menu "miscellaneous service" echo regmenu main MENU_MISCSERV \"menu principal do módulo\" # Registro ao final do menu dnsconf echo regmenu function2 dnsconf \"Qualquer título\" # Registro como co-manager no diálogo de contas de usuário echo comanager function-prefix user 22..33..33.. AA ffuunnççããoo rreeggiisstteerr ppaarraa mmóódduullooss iissoollaaddooss oouu ssoozziinnhhooss ((ssttaanndd-- aalloonnee)) A função register não é necessária para módulos isolados. É uma boa idéia fornecer um mínimo para o caso de o usuário tentar registrar o módulo no Linuxconf. As linhas seguintes tornarão claro que um determinado script não foi feito para ser executado desta forma: register(){ echo error \"Este script shellmod não pode ser usado como um módulo\" } 22..33..44.. AA ffuunnççããoo mmaaiinn Se o script é usado sozinho, ele precisa de uma função chamada main. O utilitário shellmod chamará esta função cegamente. É uma boa idéia sempre fornecer uma. Na função register nós freqüentemente registramos a função main em um menu do Linuxconf. Desta forma, o script fornece uma interface consistente usada tanto sozinha como quando um módulo do Linuxconf. A função main geralmente define um menu ou um diálogo. Observe que a função main é aquela que receberá os argumentos do script. Os argumentos freqüentemente serão usados como valores padrão para os campos do diálogo. Observe o exemplo a seguir: main(){ echo DIALOG echo newf_str path \"Rota do Documento\" $1 echo newf_str mail \"Enviar este documento por e-mail para\" $2 echo newf_str fax \"Enviar este documento por fax para\" $3 echo edit \"Gerenciador de documentos\" \"Preencha os campos para enviar o documento\" dispatch echo end if [ "$CODE" = "accept" ] ; then if [ "$mail" != "" ] ; then cat $path | mail $mail fi if [ "$fax" != "" ] ; then spoolfax $fax $path fi fi } 22..33..55.. AA ffuunnççããoo ddiissppaattcchh Um módulo sempre termina com uma chamada à função dispatch. Um script shellmod pode ser visto como um conjunto de funções esperando ser chamado (uma biblioteca). Baseado neste contexto, o Linuxconf (ou shellmod para scripts sozinhos) chamará a função apropriada. Observe que o script pode executar alguma inicialização antes de chamar a função dispatch. Como explicado a seguir, um script pode ser visto como um pequeno servidor que mantém seu estado entre chamadas a suas várias funções. 22..44.. CCoommoo ffuunncciioonnaa Um script shellmod interage com o shellmod ou Linuxconf ecoando comandos em sua saída padrão. Ele recebe instuções simplesmente lendo sua entrada padrão. A função dispatch cuida de ler e processar (dispatch) o pedido que ela recebe. Nós podemos pensar no script como sendo um sanduíche entre dois processos shellmod, como a seguir: shellmod | script | shellmod Tudo que é ecoado pelo script é captado pelo shellmod e interpretado como comandos de protocolo. É importante redirecionar a saída do subcomando que você estiver usando tanto para o canal de erros (command >&2) ou para /dev/null. Se isto não for feito, aparecerão muitas mensagens de erro provenientes do shellmod. 33.. PPrroottooccoolloo Nós agora apresentamos os vários comandos editados pelo script. Estes commandos são divididos por tarefa. 33..11.. EEssttrruuttuurraa ddee ccoommaannddooss ee ccoollooccaaççããoo ddee aassppaass Todos os comandos são enviados ao shellmod através do comando echo. Eles sempre se parecem com: echo command arg1 arg2 arg3 Os argumentos podem ser palavras simples, ou várias palavras separadas por espaços. Para agrupar múltiplas palavras como um argumento simples, deve-se usar aspas. Apesar de isto ser uma prática comum em linhas de commando, existe um detalhe: as aspas irão afetar apenas o argumento conforme visto pelo comando echo. Uma vez processada, a linha inteira será recebida como um fluxo simples de palavras separadas por espaços e as aspas desaparecerão. As aspas devem ser parte da linha recebida pelo shellmod. Veja um exemplo: echo newf_str name \"Digite seu nome\" \"Tux, o pingüim\" A biblioteca shellmod-lib.sh define a função qecho que ajudará você a ter um comportamento de aspas padrão. O seguinte é um exemplo reescrito com qecho. qecho newf_str name "Digite seu nome" 'Tux, o pingüim' Como você pode ver, com qecho você pode misturar as diferentes sintaxes de aspas do shell. A função qecho assegura que as aspas agregam todos os argumentos. 33..22.. EEnnvviiaannddoo ppaarrââmmeettrrooss eemm vváárriiaass lliinnhhaass Scripts shell não são tão bons em manipular e entregar texto em várias linhas. O comando "defval" foi criado para consertar isso. Eis aqui uma forma típica de utlização: echo var1 "Esta é a primeira linha" echo var1 "Esta é a segunda linha" echo error =var1 Isto cria uma mensagem popup de erro com duas linhas. "defval" é usado repetidamente para definir o texto em várias linhas e é referenciado como um argumento utilizando o sinal = . O argumento não pode estar entre aspas. Deste modo, você não pode utilizar a função qecho usando um parâmetro defvar parameter, porque qecho necessita de aspas fechando todos os parâmetros. 33..33.. CCoonnssttrruuiinnddoo uumm ddiiáállooggoo.. 33..33..11.. eecchhoo DDIIAALLOOGG Um diálogo sempre inicia com este comando. Ele não requere nenhum argumento a mais. Depois você acrescenta definições de campos, adiciona botões opcionais e então você chama a função edit. Eis aqui um exemplo: echo DIALOG echo newf_str var \"título do campo\" value edho edit \"Título do diálogo\" \"Introdução do Diálogo\" dispatch echo end 33..33..22.. rroommaann }} Isto faz aparecer um diálogo. O controle do título da janela usando o primeiro argumento e a maior descrição de diálogo é realizado pelo campo da introdução. O último argumento é opcional e permite que você controle os botões apresentados na parte inferior do diálogo. O valor "0" indica que nenhum botão deve ser mostrado (útil para mostrar alguma saída de dados, por exemplo). Se o último argumento for omitido, os botões Aceitar e Cancelar são mostrados. 33..33..33.. eecchhoo sshhooww \\""ttííttuulloo\\"" \\""IInnttrroodduuççããoo\\"" Isto funciona do mesmo modo que o edit. Ele apresenta o diálogo com os mesmos argumentos, mas retorna imediatamente. Geralmente é usado com o comando ``newf_gauge''. 33..33..44.. ddiissppaattcchh Passa o controle para Linuxconf/shellmod e espera pelos resultados. As variáveis de campo são atualizadas e a variável CODE recebe o valor do botão selecionado pelo usuário: Pode ser tanto "accept" (aceitar) como "cancel" (cancelar). 33..33..55.. eecchhoo eenndd Isto apaga o diálogo. Ele é removido da tela e esquecido. Nós editamos freqüentemente o comando end logo após o comando dispatch. Mas diálogos mais complexos podem utilizar o comando end após um loop de validação. 33..33..66.. UUmm eexxeemmpplloo ccoommpplleettoo #!/usr/bin/shellmod . /usr/lib/linuxconf/lib/shellmod-lib.sh main(){ echo DIALOG echo newf_str name \"Nome de Usuário\" while true do echo edit \"Perguntas ao usuário\" \"Entre com o nome de usuário\" dispatch if [ "$CODE" = "cancel" ] ; then break elif [ "$name" = "" ] ; then echo error \"Por favor entre com um nome\" else echo notice \"Fazendo algo com a conta do usuário\" break fi done echo end } dispatch 33..44.. CCoonnssttrruuiinnddoo uumm mmeennuu Isto é manipulado pelos comandos DIALOG_MENU e new_menuitem. 33..44..11.. eecchhoo DDIIAALLOOGG__MMEENNUU Não requere nenhum argumento. 33..44..22.. eecchhoo nneeww__mmeennuuiitteemm ffuunnccttiioonn pprroommpptt ttiittuulloo Isto registra mais uma entrada no menu. Cada entrada de menu é associada com uma função de script (que deve ser definida). O prompt geralmente é uma palavra-chave. O título é o restante da entrada do menu. 33..44..33.. eecchhoo eeddiittmmeennuu \\""TTííttuulloo ddoo MMeennuu\\"" \\""IInnttrroodduuççããoo\\"" Isto faz o menu aparecer. É seguido por uma chamada a dispatch. 33..44..44.. ddiissppaattcchh Aqui é onde tudo é realizado para o menu. A função dispatch será executada até que o usuário selecione o botão "quit". A função correspondente é chamada sempre que uma entrada de menu for selecionada. Isto é manipulado transparentemente pela função dispatch. Observe que a função dispatch também termina se o usuário selecionar algum botão opcional (adicionados com o comando button). Deste modo é possível executar o controle em um loop como o diálogo do exemplo acima. 33..44..55.. eecchhoo eenndd Apaga o menu. 33..44..66.. UUmm eexxeemmpplloo ccoommpplleettoo #!/usr/bin/shellmod . /usr/lib/linuxconf/lib/shellmod-lib.sh menufunc1(){ echo notice \"menufunc1 selecionado\" } menufunc2(){ echo notice \"menufunc2 selecionado\" } main(){ echo DIALOG_MENU echo new_menuitem menufunc1 Select \"Primeira opção\" echo new_menuitem menufunc2 \"\" \"Segunda opção\" echo editmenu \"Menu principal\" \"Escolha uma opção\" dispatch echo end } dispatch 33..55.. GGeerreenncciiaannddoo uummaa lliissttaa ddee rreeggiissttrrooss 33..55..11.. eecchhoo DDIIAALLOOGG__LLIISSTT DIALOG_LIST é apenas uma variação de um menu. A principal diferença é que o número da entrada pode ser bem longo. Nesse caso, um diálogo de filtro será apresentado para restringir o número de registros mostrados. Você pode então lidar com uma lista muito grande de itens. DIALOG_LIST não requer nenhum argumento. 33..55..22.. eecchhoo nneewwff__hheeaadd \\""TTííttuulloo ddaa CCoolluunnaa 11\\"" \\""TTííttuulloo ddaa CCoolluunnaa 22\\"" ...... Você pode definir o cabeçalho da lista. Isto é opcional, mas fica com um aspecto muito melhor. 33..55..33.. eecchhoo nneeww__mmeennuuiitteemm \\""AArrgguummeennttooss ddaa ffuunnççããoo\\"" \\""VVaalloorr ddaa CCoolluunnaa 11\\"" \\""VVaalloorr ddaa CCoolluunnaa 22\\"" ...... Funciona como DIALOG_MENU, exceto por nós normalmente fornecermos mais colunas. Existe uma outra variação quando a função é definida com argumentos. Observe que este modo pode ser utilizado com DIALOG_MENU da mesma forma. Nós geralment definimos uma função por entrada de menu e uma função simples para processar cada registro da lista, usando o argumento para diferenciar o processamento. Observe também que você pode usar uma solução mista com o mesmo DIALOG_MENU ou DIALOG_LIST: você pode utilizar uma função simples para fornecer um processamento comum para alguns registros e uma função diferente para gerenciar exceções. 33..55..44.. eecchhoo eeddiittmmeennuu \\""TTííttuulloo ddaa lliissttaa\\"" \\""IInnttrroodduuççããoo\\"" Igual a DIALOG_MENU. 33..55..55.. ddiissppaattcchh Isto se comporta como DIALOG_MENU. 33..55..66.. eecchhoo eenndd Isto apaga a lista. 33..55..77.. UUmm eexxeemmpplloo ccoommpplleettoo Eis aqui um exemplo real onde nós apresentamos um diretório e permitimos que o usuário escolha um arquivo para fazer algo com ele. Nós vemos neste exemplo como é fácil analisar a saída do comando "ls -l" e apresentar o nome do arquivo, o tamanho e a data de revisão em um formato de três colunas. #!/usr/bin/shellmod . /usr/lib/linuxconf/lib/shellmod-lib.sh fileshow(){ echo notice \"Processando arquivo $1\" } main(){ echo DIALOG_LIST echo newf_head \"Nome do Arquivo\" Size \"Data de Revisão\" ls -l $1 | \ ( read total while read perm count user group size month day hour name do echo new_menuitem \"fileshow $name\" $name $size \"$month $day $hour\" done ) echo editmenu \"Diretório Atual\" \"Mostra todos os arquivos no diretório atual\" dispatch echo end } dispatch 33..66.. DDeeffiinniinnddoo ccaammppooss Todos os comandos que definem um campo de diálogo iniciam com o prefixo newf_. Nós usamos a mesma ordem de nome e de parâmetro (quando possível) conforme a API do módulo C++. O primeiro argumento é sempre o nome da variável shell a qual receberá o valor entrado pelo usuário. Você utilizará freqüentemente a seguinte construção para editar (corrigir o valor atual) de uma determinada variável. qecho newf_str var "title" "$var" . qecho edit ... dispatch if [ "$CODE" = "accept" ] ; then if [ "$var" = "..." ] ;then . . fi fi 33..77.. LLiissttaa ddee ccoommaannddooss Here is the list of all field definition commands: · ``newf_chk'' · ``newf_chkm'' · ``newf_combo'' · ``newf_dbl'' · ``newf_enum'' · ``newf_gauge'' · ``newf_hexnum'' · ``newf_list'' · ``newf_num'' · ``newf_pass'' · ``newf_radio'' · ``newf_slider'' · ``newf_str'' · ``newf_title'' 33..77..11.. eecchhoo nneewwff__cchhkk vvaarr \\""TTííttuulloo ddoo ccaammppoo\\"" \\""VVaalloorr iinniicciiaall 00 oouu 11\\"" \\""TTííttuulloo ddoo ssuuffiixxoo\\"" Define um campo de caixa de verificação (lig/des ou sim/não). A variável var será definida como 0 ou 1. Este campo tem dois títulos. Um na esquerda da caixa de verificação e um na direita. No Linuxconf, isto é freqüentemente usado da seguinte maneira: A seguinte característica [ ] está selecionada 33..77..22.. VVaarriiaaççõõeess ddaa ssiinnttaaxxee ddee nneewwff__cchhkk Quando você usar newf_chk, você deve passar valores 0 ou 1. A variável edit receberá esse valor como 0 ou 1. Isto não é muito útil, já que, com freqüência, scripts shell lidam com diferentes tipos de valores booleanos. Por exemplo, um script tratando com um servidor SQL pode se deparar com valores como Y e N. Para evitar a tradução de um sistema para o outro, a sintaxe do valor inicial foi expandida. · Para facilitar as coisas, o shellmod aceita como valor selecionado qualquer coisa entre 1, Y e Yes (maíusculas ou minúsculas). A menos que o contrário seja explicitado, estes valores serão traduzidos para 1. Todo o restante será traduzido para 0. · Utilizando um formato especial de três campos, pode-se especificar o valor real e o dicionário utilizado para interpretá-lo. O valor deve ser especificado da seguinte maneira: valor:valor_lig:valor_des Deste modo, se a sua aplicação está lidando com valores ON/OFF, você pode especificar o valor inicial desta forma: $var:ON:OFF Não só os valores ON e OFF serão aceitos pelo interpretador, como também o resultado final será enviado ao script usando uma daquelas palavras. 33..77..33.. eecchhoo nneewwff__cchhkkmm vvaarr \\""ttííttuulloo ddoo ccaammppoo\\"" \\""vvaalloorr nnuumméérriiccoo iinniicciiaall\\"" \\""vvaalloorr11\\"" \\""vvaalloorr22\\"" ...... Configuração de campos de seleção múltipla utilizando caixas de verificação. As caixas são apresentadas horizontalmente. Eis um exemplo seguido do campo produzido em modo texto: echo newf_chkm sel \"Qual posição\" 1 esquerda centro direita This produces: Qual posição ( ) esquerda (o) centro ( ) direita A variável var conterá o índice numérico do item selecionado, iniciando em 0. 33..77..44.. eecchhoo nneewwff__ccoommbboo vvaarr \\""ttííttuulloo ddoo ccaammppoo\\"" \\""VVaalloorr iinniicciiaall\\"" Configura uma linha simples + campo seletor. O usuário será capaz de selecionar um valor dentre uma lista de valores ou entrar com um outro manualmente. A variável var irá conter o valor textual seja ele digitado ou selecionado. newf_combo é usado com o comando comboitem. Você configura antes o campo combo e então você passa um por um os valores possíveis utilizando comboitem. Observe que os valores são seguidos por um texto descritivo (opcional). Segue abaixo um código exemplo: echo newf_combo port \"Qual porta\" ttyS1 echo comboitem ttyS0 \"COM1 no DOS\" echo comboitem ttyS1 \"COM2 no DOS\" echo comboitem ttyS2 \"COM3 no DOS\" A variável $port conterá o valor ttyS0, ttyS1, ttyS2 ou qualquer coisa que o usuário digite. Veja ``newf_enum'' e ``newf_list'' para variações deste campo de entrada. 33..77..55.. eecchhoo nneewwff__ddbbll vvaarr \\""ttííttuulloo ddoo ccaammppoo\\"" \\""vvaalloorr nnuumméérriiccoo iinniicciiaall\\"" nnuummeerroo--ddee--ccaassaass Configura um campo de entrada numérico com notação decimal. Funciona como ``newf_num'' exceto por permitir um ponto decimal. O parâmetro número-de-casas controla o número de dígitos permitidos após o ponto decimal bem como a formatação do campo. 33..77..66.. eecchhoo nneewwff__eennuumm vvaarr \\""ttííttuulloo ddoo ccaammppoo\\"" \\""VVaalloorr nnuumméérriiccoo iinniicciiaall\\"" Configura um campo seletor. O usuário será capaz de selecionar um valor dentre uma lista de seleção. A variável var conterá o índice dos itens selecionados. O usuário é limitado a escolher um único item da lista. newf_enum é usado com o comando enumitem. Você configura primeiro o campo enum e então passa um por um os valores possíveis utilizando enumitem. Segue abaixo um código exemplo: echo newf_enum no \"Qual porta\" 1 echo enumitem ttyS0 \"COM1 no DOS\" echo enumitem ttyS1 \"COM2 no DOS\" echo enumitem ttyS2 \"COM3 no DOS\" A variável $no conterá o valor 0, 1 ou 2. Veja ``newf_combo'' e ``newf_list'' para variações deste campo de entrada. 33..77..77.. eecchhoo nneewwff__ggaauuggee IIDD \\""ttííttuulloo ddoo ccaammppoo\\"" \\""VVaalloorr ddeecciimmaall iinniicciiaall\\"" \\""VVaalloorr mmááxxiimmoo\\"" Configura um indicador visual de medida, geralmente usada para mostrar o progresso de execução de um processo (carregamento, instalação). O estado do indicador é alterado à cada chamada a este comando. A primeira chamada define o campo, as próximas atualizam o indicador. Este widget é geralmente utilizado com o comando "show" de forma que o script nunca pára no estado "edit". Eis aqui um pequeno exemplo: echo DIALOG qecho newf_gauge ID "Status" 0 10 qecho show "Status" "" i=0 while [ "$i" != "10" ] ; do i=`expr $i + 1` sleep 1 qecho newf_gauge ID "Status" $i 10 qecho show "Status" "" done 33..77..88.. eecchhoo nneewwff__hheexxnnuumm vvaarr \\""ttííttuulloo ddoo ccaammppoo\\"" \\""VVaalloorr hheexxaaddeecciimmaall iinniicciiaall\\"" Configura um campo de entrada numérico (inteiro). Funciona como ``newf_num'' mas aceita dígitos numéricos e hexadecimais. 33..77..99.. eecchhoo nneewwff__lliisstt vvaarr \\""ttííttuulloo ddoo ccaammppoo\\"" \\""VVaalloorr iinniicciiaall\\"" Configura um campo seletor. O usuário poderá selecionar um valor dentre uma lista. A variável var irá conter o valor textual selecionado. newf_list é utilizado com o comando listitem. Você primeiro configura o campo de lista e então você passa um por um todos os valores possíveis usando listitem. Observe que os valores são seguidos por um texto descritivo (opcional). Segue um código exemplo: echo newf_list port \"Qual porta\" ttyS1 echo listitem ttyS0 \"COM1 no DOS\" echo listitem ttyS1 \"COM2 no DOS\" echo listitem ttyS2 \"COM3 no DOS\" A variável $port conterá o valor ttyS0, ttyS1 ou ttyS2. Veja ``newf_enum'' e ``newf_combo'' para variações neste campo de entrada. 33..77..1100.. eecchhoo nneewwff__nnuumm vvaarr \\""ttííttuulloo ddoo ccaammppoo\\"" \\""VVaalloorr nnuumméérriiccoo iinniicciiaall\\"" Configura um campo de entrada numérico (inteiro). Funciona como newf_str mas aceita apenas um dígito. 33..77..1111.. eecchhoo nneewwff__ppaassss vvaarr \\""ttííttuulloo ddoo ccaammppoo\\"" \\""VVaalloorr iinniicciiaall\\"" Configura um campo de senha. Funciona como o campo newf_str exceto pela entrada não ser ecoada (digitação invisível). 33..77..1122.. eecchhoo nneewwff__rraaddiioo vvaarr \\""ttííttuulloo ddoo ccaammppoo\\"" vvaalloorr--nnuumméérriiccoo vvaalloorr--ddaa-- iinnssttâânncciiaa \\""ttííttuulloo ddoo ssuuffiixxoo\\"" Configura um campo de botão de rádio. Vários campos de botão de rádio devem ser definidos para cada seleção possível. Todos os botões de rádio que compartilham a mesma variável de entrada (var, acima) operam juntos: ligar um desliga o outro e vice-versa. A variável var conterá o valor numérico do campo de botão de rádio selecionado. Botões de rádio selecionados podem ser colocados em qualquer lugar em um diálogo. Eles não precisam estar em seqüência nem mesmo na mesma página do diálogo. 33..77..1133.. eecchhoo nneewwff__sslliiddeerr vvaarr \\""ttííttuulloo ddoo ccaammppoo\\"" \\""VVaalloorr ddeecciimmaall iinniicciiaall\\"" \\""VVaalloorr mmíínniimmoo\\"" \\""VVaalloorr mmááxxiimmoo\\"" Isto funciona como newf_num, para editar um valor decimal. Mas é mostrado como um botão deslizante. Os valores mínimo e máximo representam as margens esquerda e direita do botão deslizante. qecho newf_slider var "Hora de Reunião" 15 9 16 33..77..1144.. eecchhoo nneewwff__ssttrr vvaarr \\""ttííttuulloo ddoo ccaammppoo\\"" \\""VVaalloorr iinniicciiaall\\"" Configura uma entrada de texto de uma linha. 33..77..1155.. eecchhoo nneewwff__ttiittllee ""TTííttuulloo ddaa PPáággiinnaa"" lleevveell ""TTííttuulloo EEssqquueerrddoo"" ""TTííttuulloo eemm mmooddoo tteexxttoo"" Isto não é um campo de entrada, mas é uma forma de organizar um grande diálogo em uma seção. O resultado final é bem diferente em modo gráfico do que em em texto ou HTML. Em modo gráfico, isto criará um diálogo em um bloco de notas e cada newf_title define uma página do bloco de notas. O primeiro argumento, o título da página, é usado apenas em modo gráfico. O segundo argumento é um número e representa o nível do bloco de notas. Isto permite diálogos muito complexos com blocos de notas dentro de blocos de notas. Em modos texto e HTML mode, este argumento não tem efeito. · Um valor de 0 adiciona uma divisão horizontal entre dois campos. o "Título em modo texto" é centrado nesta divisão. · Um valor de 1 cria o primeiro nível do bloco de notas. Um valor de 2 cria um sub-bloco de notas com o atual. O terceiro argumento, título esquerdo, é utilizado apenas em modo texto e HTML. Ele coloca um pequeno título à esquerda dos campos de entrada. O último argumento, Título em modo texto, aparece centrado entre dois campos de entrada. 33..88.. AAddiicciioonnaannddoo bboottõõeess Você pode adicionar botões opcionais usando simplesmente o comando button. Ele requer dois argumentos. O primeiro é a ID (identificação) do botão que será passada ao script utilizando a variável CODE. O segundo é o rótulo (título) do botão. Segue abaixo um exemplo: echo DIALOG echo newf_str name \"Nome de usuárioe\" $name echo button Add \"Adicionar novo usuário\" echo edit "title" \"Gerenciamento de usuários\" dispatch echo end if [ "$CODE" = "Add" ] ; then # Adicionando um novo usuário elif [ "$CODE" = "accept" ] ; then # Inspecionando um registro de usuário fi 33..99.. CCoonnffiigguurraa oo ccaammppoo aattuuaall ddee eennttrraaddaa O código de operação "setcurfield" coloca o foco do teclado em um campo específico. Você deve passar a ID (identificação) do campo como um argumento simples. Eis um exemplo: qecho DIALOG qecho newf_str uid "ID de Usuário" qecho newf_str name "Nome" qecho newf_str phone "Nome" qecho setcurfield name qecho edit "exemplo" "O foco agora está no nome" dispatch echo end 44.. CCoonnssttrruuiinnddoo ccoo--ggeerreenncciiaaddoorreess Co-gerenciadores são ótimos. Eles permitem que funcionalidades sejam adicionadas ao Linuxconf no exato lugar a que elas pertencem, ao invés de se adicionar novos sub-menus. 44..11.. PPrriinnccííppiiooss Um co-gerenciador é um componente que participa de um diálogo. Ele pode adicionar campos e validação. O caso mais comum é o diálogo de conta de usuário, onde vários co-gerenciadores participam. O mais visível deles é o módulo mailconf, que insere uma seção completa para manipular aliases de email. Um outro é o módulo pppdialin, o qual adiciona uma seção para lidar com parâmetros PPP. Um co-gerenciador deve fornecer 4 funções: · Adicionar campos ao diálogo. Aqui o co-gerenciador irá provavelmente adicionar uma nova seção e alguns campos. Ele não é forçado a adicionar nada. · Adicionar validação. O co-gerenciador pode fazer qualquer tipo de validação, não apenas em seus próprios campos. Ao administrador não é permitido efetuar qualquer mudança à conta do usuário até que todos os co-gerenciadores concordem. · Salvar as entradas. O co-gerenciador deve salvar o valor dos campos que ele gerencia. Co-gerenciadores de contas de usuário devem preservar informações indexadas por usuário. · Apagar informações associadas à conta do usuário/registro de informações quando for apagado. Observe que os co-gerenciadores foram criados com contas de usuário em mente, mas o conceito é mais geral que isso. Troque "conta de usuário" acima por "registro" e você terá um retrato mais geral. 44..22.. RReeggiissttrraannddoo oo ccoo--ggeerreenncciiaaddoorr Linuxconf deve ser notificado que um co-gerenciador existe paa um determinado diálogo. Diálogos são identificados por uma pequena chave. Por exemplo, a chave para a conta do usuário é "user". Um co-gerenciador shellmod deve fornecer quatro funções, utilizando o mesmo prefixo. Quando você registra o co-gerenciador, você deve fornecer o prefixo da função e a chave de diálogo. Isto é feito com a função register. Segue abaixo um exemplo: # Registra como um co-gerenciador no diálogo de conta de usuário echo comanager ufct user O prefixo da função é ufct. Deve-se criar quatro funções de acordo com este prefixo: · ufct-setupdia · ufct-validate · ufct-save · ufct-deluser 44..33.. AAss vváárriiaass ffuunnççõõeess 44..33..11.. sseettuuppddiiaa Esta função é chamada durante a construção do diálogo. Você pode usar qualquer código de operação normalmente para definir um diálogo. Você não precisa definir o diálogo por você próprio (echo DIALOG) já que ele está definido implicitamente. Enquanto você pode simplesmente adicionar campos no diálogo, algum geralmente definirá uma nova seção do diálogo. A menos que você faça isso, seu novo campo será anexado à seção atual, a qual pode ser qualquer seção. Você define uma seção com o código de operação newf_title. qecho newf_title "Listas de postagem" 1 - "Listas de postagem" 44..33..22.. vvaalliiddaattee Esta função recebe todo o valor do campo (digitado pelo usuário). Cada campo corresponde a uma variável shell, de forma que você pode testar diretamente os valores delas. Você deve utilizar o código "retcode" para verificar se a validação foi bem-sucedida. Veja o exemplo a seguir: echo retcode 0 Qualquer valor diferente de 0 é tomado como uma falha na validação. Qualquer erro deve ser reportado com o código de operação "error". Você também pode usar "setcurfield" para saltar a um campo específico. if [ "$a1" = "válida" ] ; then echo retcode 0 else echo setcurfield a1 echo retcode -1 echo error \"sample.sh: Valor inválido, entre com a palavra válida\" fi 44..33..33.. ssaavvee Todos os valores dos campos são retornados ao seu script como variáveis shell. A função save deve fazer várias coisas com as informações. Ela pode tanto salvar em um arquivo, ou executar algumas ações (enviar um mail a um administrador sobre as mudanças necessárias, por exemplo). Outras variáveis shell também contém informações relacionadas a este diálogo (veja abaixo o contexto do diálogo). 44..33..44.. ddeelluusseerr O nome desta função é um tanto ambígüo. Significa que o registro deve ser apagado (em geral, uma conta de usuário). Você deve usar a informação a partir do contexto do diálogo (veja abaixo) para executar o apagamento desejado. 44..44.. CCoonntteexxttoo ddoo DDiiáállooggoo Um co-gerenciador manipula uma parte de um grande diálogo. Para gerenciar propriamente sua parte, o co-gerenciador deve conhecer outras informações sobre o diálogo atual. Por exemplo, para aprimorar o diálogo de conta de usuário, deve-se conhecer a conta do usuário (identificação do usuário) sendo editada bem como o domínio (é uma conta de usuário de domínio virtual de mail?). Esta informação extra é passada como variáveis shell, prontamente utilizáveis. A informação disponível é dependente de diálogos. Para co-gerenciadores de contas de usuários, as seguintes variáveis são fornecidas: ddoommaaiinn É passado o domínio de mail virtual. Para o domínio principal, esta variável é configurada para /. iiss__nneeww Isto é um flag que mostra a você se esta é uma nova conta (o nome está vazio) ou não. nnaammee Esta é a identificação de usuário. Uma forma de aprender as informações disponíveis para seu script é executá-lo em modo de depuração sob o Linuxconf. Você pode ativar este modo a partir da interface de usuário do Linuxconf, no controle de sistema e arquivos/gerenciamento de módulos shell/configuração do shellmod. 55.. VViiddaa ddoo pprroocceessssoo ddoo ssccrriipptt Shellmod e Linuxconf executarão o script sempre que necessário. Usado como um módulo do Linuxconf, o script não é executado durante a inicialização do Linuxconf, mas apenas quando é selecionada uma entrada de um de seus menus ou co-gerenciadores. O script é iniciado e procede à sua função dispatch, onde ele espera por um pedido. Alguns pedidos engatilham a execução de uma das funções do script. Quando a função termina, a função dispatch original recomeça e continua a aguardar. Observe que dispatch pode ser utilizado recursivamente. Uma vez iniciado, o script permanece lá esperando por um pedido até que o Linuxconf termine. Desta forma, isto pode ser visto como um pequeno servidor compartilhando informações coletadas enquanto executa vários pedidos. Quando utilizado como um utilitário sozinho, o script terminará assim que terminar a função principal. 66.. CCoonnssttrruuttoorr ddee mmóódduullooss Um construtor de módulos shell está disponível para você fazer as coisas mais rápido. Você consegue acessar este construtor através do menu principal do shellmod ou com o utilitário shellmod: shellmod --build Aparece um diálogo simples. Você o preenche e é criada uma base para um novo módulo shell. Seguem abaixo os vários campos: 66..11.. RRoottaa ddoo mmóódduulloo Simplesmente entre com a rota completa ou relativa do novo script shell que você deseja criar. O construtor não é capaz de editar um módulo existente. 66..22.. IInnsseerriirr nnoo mmeennuu Você deve fornecer a ID (identificação) do menu no qual você deseja inserir o módulo (no Linuxconf). Um módulo pode ser inserido em vários menus do Linuxconf, mas o construtor apenas suporta um. A modificação posterior do código é fácil. Este campo tem uma lista para ajudar na seleção da ID correta. 66..33.. TTííttuulloo ddoo MMeennuu Entre com o texto da entrada de menu. 66..44.. IIssttoo éé uumm ccoo--ggeerreenncciiaaddoorr ddee ccoonnttaass ddee uussuuáárriioo Selecionando esta caixa de verificação, você instrui o construtor a gerar os modelos de função adequados para o co-gerenciador (setupdia, save, deluser, validate). Observe que um módulo pode ser um co-gerenciador e efetuar inserções em menus da mesma maneira. 66..55.. EEnnttrraaddaass ddoo mmeennuu pprriinncciippaall.. Simplesmente digite as várias entradas de menu. Para cada uma, o construtor irá gerar um modelo de função shell menufunc1, menufunc2. Ele também irá gerar o código do menu na função principal. Você terá que fornecer o código para as diversas funções menufunc. } Entradas do menu principal.