shellmod Introducción 11.. ¿¿QQuuéé eess sshheellllmmoodd?? Shellmod es un módulo Linuxconf como la utiliad stand-alone (autónoma). Su función es permitir con mayor facilidad la escritura de otros módulos de Linuxconf y de utilidades autónomas usando sh (/bin/sh, el intérprete de shell). La ventaja de escribir módulos Linuxconf (o simplemente utilidades del administrador) de esta formas es: · Interfaz agradable: su script trabajará tanto en modo texto como en gráfico, con un aspecto mejor que el script shell tradicional. Cuando se use como un módulo en Linuxconf, incluso trabajará en HTML, completamente transparente. · Simplicidad: es posible escribir info útil en un script shell de 10 o 15 líneas. Es posible convertir un script shell existente no interactivo de 10-15 línias en 15-20 líneas de script totalmente interactivo, ejecutándose tanto en modo texto, modo GUI e incluso modo HTML. · Usado como módulo, su script será capaz de "colgarse" de diferentes menús de Linuxconf, haciendo que esté totalmente integrado en el esquema de administración. · No sólo el script puede aumentar los menús de Linuxconf, puede incluso participar como co-administrador en algunos cuadros de diálogo. Ésto significa que un simple script puede añadir nuevos campos de edición en el diálogo de cuenta de usuario, por ejemplo. El módulo de Linuxconf normal para C++ puede hacer muchas más cosas, pero los scripts ofrecen una buena y eficiente solución para personalizar la instalación y soporte en el sitio. Un nuevo módulo Linuxconf puede ser desarrollado con user/friend/customer supervisándolo. 22.. PPrriinncciippiiooss En esta sección veremos el esquema básico de un script shellmod, cómo usarlo y cómo comunicarse con Linuxconf. 22..11.. CCoommppoonneenntteess ddeell ppaaqquueettee sshheellllmmoodd El paquete shellmod proporciona las siguientes partes: · La utilidad shellmod utilizada para ejecutar el script shellmod sin Linuxconf. Esta utilidad está localizada en /usr/bin. · El módulo shellmod que permite al script interactuar con Linuxconf. Nótese que un script shellmod puede utilizarse de dos formas: autónomo o incrustado en Linuxconf. · La librería de funciones shellmod-lib.sh. Está en /usr/lib/linuxconf/lib. Contiene funciones de utlidades para simplificar scripts shellmod. Este archivo se debe originar en todos los scripts. · Algunos ejemplos de script. · En algún punto, el paquete contendrá algunos scripts contrib y se designará un navegador para facilitar su búsqueda y probarlos. Si ha escrito algo general y útil, envíelo a la lista de correo de Linuxconf para poderlo incluir en este paquete. 22..22.. CCóómmoo uussaarr sshheellllmmoodd ssccrriippttss Un script puede usarse de manera autónoma o incluido en Linuxconf. 22..22..11.. CCoommoo uuttlliiddaadd aauuttóónnoommaa ((ssttaanndd--aalloonnee))...... Para ejecutarlo, haga: shellmod ruta_del_script [ argumentos ] O si el script empieza con #!/usr/bin/shellmod, simplemente ejecútelo como cualquier otra utilidad. Nótese que en ambos casos, el script debe ser ejecutable (chmod +x script). 22..22..22.. CCoommoo uunn mmóódduulloo LLiinnuuxxccoonnff Para usarlo de esta manera, debe ser registrado en Linuxconf. Esto se hace tanto interactivamente como usando una línea especial de comando. El módulo shellmod registra su menú de configuración en el menú Control de archivos y sistemas. Encontrará allí un cuadro de diálogo para registrar su script. Simplemente introduzca la ruta y éste estará visible en Linuxconf en la próxima ejecución. El script se puede registrar usando la siguiente línea de comando. Ésta es especialmente útil si lo incluye en un paquete y quisiera registrarlo en Linuxconf en la instalación de paquetes (los empaquetadores RPM pueden tener en cuenta la utilidad de trigger para hacerlo). linuxconf --modulemain shellmod --setmod ruta_del_script Nótese que el constructor linuxconf --modulemain es la manera normal de ceder el control a una línea de comando propia del módulo: en este aspecto shellmod no es diferente. Puede darlo de baja de Linuxconf haciendo lo siguiente: linuxconf --modulemain shellmod --unsetmod ruta_del_script Nótese que la sintaxis de arriba reproduce exactamente el funcionamiento normal (C++) de los módulos de Linuxconf deben ser registrados y dados de baja, mediante las líneas linuxconf --setmod y linuxconf --unsetmod . 22..33.. EEssqquueemmaa ddee uunn ssccrriipptt sshheellllmmoodd Un script shellmod siempre tiene este aspecto: #!/usr/bin/shellmod . /usr/lib/linuxconf/lib/shellmod-lib.sh register(){ # Poner las llamadas a regmenu y comanager aquí } # Poner las distintas funciones mencionadas arriba main(){ # Definimos un submenú o un diálogo } # El script siempre termina con una llamada a la función dispatch. Siempre dispatch. 22..33..11.. LLaa lliibbrreerrííaa ddee ffuunncciioonneess sshheellllmmoodd--lliibb..sshh 22..33..22.. LLaa ffuunncciióónn rreeggiissttrroo Se necesita la función registro si el script es utilizado como un módulo Linuxconf, que llamará a la función que espera que el script le devuelva la lista del menú y el diálogo en el que se quiere registrar. Aquí tiene un ejemplo de una función de registro que instala dos submenús y un co-administrador: # Registrar el menú "miscellaneous service" echo regmenu main MENU_MISCSERV \"menú principal del módulo\" # Registrar al final del menú de dnsconf echo regmenu función2 dnsconf \"Algún título\" # Registrar como co-administradorr en el diálogo de cuentas de usuario echo comanager prefijo-función user 22..33..33.. LLaa ffuunncciióónn rreeggiissttrroo ppaarraa mmóódduullooss aauuttóónnoommooss La función registro no se necesita para módulos autónomos. Es buena idea proporcionar una función mínima similar en caso de que un usuario intentase registrar este módulo en Linuxconf. La siguiente lo aclara, aunque no se pretende que el script se use así: register(){ echo error \"Este script shellmod no se puede registar\" } 22..33..44.. LLaa ffuunncciióónn pprriinncciippaall ((mmaaiinn)) Si el script se usa de forma autónoma, requiere de una función llamada main. La utilidad shellmod llamará ciegamente a esta función. Es necesario implementar siempre una función main. En la función register a menudo se añade una función main a los menús de Linuxconf. Hecho así, el script proporciona una interfaz consistente usado tanto de forma autónoma como en forma de módulo Linuxconf. La función main generalmente definirá un menú o diálogo. Nótese que dicha función es la que recibe los argumentos del script, que a menudo se usan como valores por definición para los campos de diálogo. Aquí se presenta un pequeño ejemplo: main(){ echo DIALOG echo newf_str path \"Ruta del documento\" $1 echo newf_str mail \"Enviar este documento a\" $2 echo newf_str fax \"Enviar por fax este documento a\" $3 echo edit \"Administrador de documentos\" \"Rellene este formulario para enviar el documento\" dispatch echo end if [ "$CODE" = "aceptar" ] ; then if [ "$mail" != "" ] ; then cat $path | mail $mail fi if [ "$fax" != "" ] ; then spoolfax $fax $path fi fi } 22..33..55.. LLaa ffuunncciióónn ddiissppaattcchh Un módulo siempre termina con una llamada a una función dispatch. Un script shellmod puede verse como un conjunto de funciones esperando a ser llamadas (una librería). Basado en este contexto, Linuxconf (o shellmod para scripts autónomos) llamará a la función apropiada. Nótese que el script puede realizar algunas tareas previas de configuración antes de llamar a la función dispatch. Como se explicará posteriormente, un script puede verse como un pequeño servidor que mantiene su estado entre llamadas a sus distintas funciones. 22..44.. CCóómmoo ffuunncciioonnaa Un script shellmod interactúa con shellmod o Linuxconf mostrando comandos por la salida estándar. La función dispatch se cuida de leer y procesar (dispatching) la petición que recibe. Podemos imaginarnos que el script es la parte del medio de un "sandwich" como este: shellmod | script | shellmod Todo lo que muestra el script se capta mediante shellmod y se interpreta como comandos de protocolos. Es importante redirigir la salida del sub-comando que está utilizando tanto hacia el canal de error (command &2) como a /dev/null. La falta de ésto puede originar multitud de mensajes de error de shellmod. 33.. PPrroottooccoolloo ahora presentaremos los diferentes comandos tratados por el script. Estos comandos se dividen por tareas. 33..11.. EEssqquueemmaa ddee ccoommaannddooss yy ccoommiillllaass Todos los comandos enviados a shellmod se hacen a parir del comando de shell echo (mostrar). Siempre tienen este aspecto: echo command arg1 arg2 arg3 Los argumentos son tanto simples como múltiples palabras (separadas por blancos). Para agrupar múltiples palabras como un único argumento, se puede utilizar las comillas. Aunque ésta sea la práctica estándar de dicha línea de comando, tiene un inconveniente: usar comillas sólo afectará al argumento tal y como se ve mediante el comando echo. Una vez procesado, la línea entera se recibirá como una cadena de palabras separadas por blancos y las comillas desaparecerán. Las comillas deben ser parte de la línea recibida por shellmod. Aquí hay un ejemplo: echo newf_str name \"Introduzca su nombre\" \"Tux el pingüino\" shellmod-lib.sh define la función de ayuda qecho que puede usar para obtener un comportamiento más estándar de las comillas de shell. Aquí aparece el mismo ejemplo reescrito pero conqecho. qecho newf_str name "Introduzca su nombre" 'Tux el pingüino' Como puede observar, con qecho puede mezclar las distintas sintaxis de comillas de shell. La función qecho se asegura de que tenga las comillas dobles correspondientes en todos los argumentos. 33..22.. EEnnvviiaannddoo ppaarráámmeettrrooss mmuullttii--llíínneeaass Los scripts de shell no son tan buenos soportando y pasando texto en formato multi-línea. El comando defval se creó para corregir este defecto. Aquí tenemos un uso típico: echo var1 "Esta es la primera línea" echo var1 "Esta es la segunda línea" echo error =var1 Ésto crea un mensaje emergente de error con dos líneas. "defval"se usa repetidamente para definir el texto multi-línea y se relaciona como un argumento, usando el signo =. El argumento no deber estar entre comillas, así que no puede usar la función de ayuda qecho cuando utilice un parámetro defvar, ya que, qecho se asegura de todos los parámetros estén entre comillas. 33..33.. CCoonnttrruuiirr uunn ccuuaaddrroo ddee ddiiáállooggoo 33..33..11.. eecchhoo DDIIAALLOOGG Un diálogo siempre empieza con este comando. No requiere muchos argumentos. Después lo arregla con definiciones de campo, añade botones opcionales y entonces llama a la función edit. Aquí hay un ejemplo: echo DIALOG echo newf_str var \"Campo de título\" value edho edit \"Título de diálogo\" \"Introducción de diálogo\" dispatch echo end 33..33..22.. rroommaann }} Ésto muestra el diálogo. El control del título de la ventana que usa el primer argumento y la descripción del diálogo más largo, se controla mediante el campo de introducción. El último argumento es opcinal y le permite controlar los botones mostrados en la parte inferior del diálogo. Un valor "0" significa no mostrar ningún botón (útil para mostrar algunos indicadores, por ejemplo). Cuando el último argumento se omite aparecen en el diálogo los botones Aceptar y Cancelar. 33..33..33.. eecchhoo sshhooww \\""ttííttuulloo\\"" \\""IInnttrroodduucccciióónn\\"" Esto funciona como "edit", muestra diálogos con los mismos argumentos. Pero termina inmediatamente. Esto se usa generalmente con el comando ``newf_gauge''. 33..33..44.. ddiissppaattcchh Ésto cede el control a Linuxconf/shellmod y espera los resultados. Las variables de campo son traducidas y actualizadas y la variable CODE se configura con el valor del botón seleccionado por el usuario, ya sea "Aceptar"o "Cancelar". 33..33..55.. eecchhoo eenndd Ésto elmina el cuadro. Se borra de la pantalla y se olvida. A veces usamos el comando end justo después del comando dispatch, pero en cuadros más complicados puede usar el comando end después de un bucle de verificación. 33..33..66.. UUnn eejjeemmpplloo ccoommpplleettoo #!/usr/bin/shellmod . /usr/lib/linuxconf/lib/shellmod-lib.sh main(){ echo DIALOG echo newf_str name \"Nombre de usuario\" while true do echo edit \"Pregunta de usuario\" \"Introduzca su nombre de usuario\" dispatch if [ "$CODE" = "cancelar" ] ; then break elif [ "$name" = "" ] ; then echo error \"Por favor, introduzca un nombre\" else echo notice \"Haciendo lo que sea con la cuenta de usuario\" break fi done echo end } dispatch 33..44.. CCoonnssttrruuyyeennddoo uunn mmeennúú Esto está contemplado por DIALOG_MENU y por los comandos new_menuitem. 33..44..11.. eecchhoo DDIIAALLOOGG__MMEENNUU No requiere ningún argumento. 33..44..22.. ffuunncciióónn pprroommpptt ttiittllee ddee eecchhoo nneeww__mmeennuuiitteemm Esto almacena una entrada de menú. Cada entrada del menú se asocia a una función script (que debe estar definida). La señal es generalmente una clave. El título es el resto de la entrada del menú. 33..44..33.. eecchhoo eeddiittmmeennuu \\""TTííttuulloo ddee mmeennúú\\"" \\""IInnttrroodduucccciióónn\\"" Esto muestra el menú seguida de una llamada a dispatch. 33..44..44.. ddiissppaattcchh Aquí es donde se acaba todo lo relacionado con el menú. La función duspatch se ejecutará hasta que el usuario aprete el botón "salir" (quit). La correspondiente función será llamada en el momento que se selecciones una entrada de menú, cosa que se realiza de forma transparente por dicha función. Nótese que la función dispatch también termina si el usuario selecciona botones opcionales (añadidos con el comando button). Así que es posible gestionar esto en un bucle como el anterior. 33..44..55.. eecchhoo eenndd Esto borra el menú. 33..44..66.. UUnn eejjeemmpplloo ccoommpplleettoo #!/usr/bin/shellmod . /usr/lib/linuxconf/lib/shellmod-lib.sh menufunc1(){ echo notice \"menufunc1 seleccionado\" } menufunc2(){ echo notice \"menufunc2 seleccionado\" } main(){ echo DIALOG_MENU echo new_menuitem menufunc1 Select \"Primera opción\" echo new_menuitem menufunc2 \"\" \"Segunda opción\" echo editmenu \"Main menu\" \"Elegir una opción\" dispatch echo end } dispatch 33..55.. GGeessttiioonnaannddoo uunnaa lliissttaa ddee ccooppiiaass 33..55..11.. eecchhoo DDIIAALLOOGG__LLIISSTT Un DIALOG_LIST es sólo una variación de un menú. La diferencia principal estriba en que el número de la entrada puede ser muy largo. En tal caso un diálogo de filtro aparecerá y restringirá la cantidad de copias mostrada. Puede llegar a tener listas enormes de items. DIALOG_LIST no requiere ningún argumento. 33..55..22.. eecchhoo nneewwff__hheeaadd \\""CCoolluummnn11 ttííttuulloo\\"" \\""CCoolluummnn22 ttííttuulloo\\"" ...... Puede definir el encabezado de la lista. Esto es opcional pero es resultón. 33..55..33.. eecchhoo nneeww__mmeennuuiitteemm \\""aarrggss ddee llaa ffuunncciióónn\\"" \\""CCoolluummnn11 vvaalloorr\\"" \\""CCoolluummnn22 vvaalloorr\\"" ...... Funciona como DIALOG_MENU salvo que se suelen proporcionar más columnas. Existe otra variación ya que la función está definida con argumentos. Nótese que esto puede ser usado con DIALOG_MENU también. Generalmente definimos una función por entrada de menú y una única función para procesar cada copia de la lista, usando el argumento para diferenciar el proceso. Nótese también que se puede usar una solución mixta dentro del mismo DIALOG_MENU o DIALOG_LIST: puede usar una única función para proveer un proceso común para algunas copias y diferentes funciones para gestionar cada excepción. 33..55..44.. eecchhoo eeddiittmmeennuu \\""TTííttuulloo ddee lliissttaa\\"" \\""IInnttrroodduucccciióónn\\"" Lo mismo que con DIALOG_MENU. 33..55..55.. ddiissppaattcchh Se comporta como DIALOG_MENU. 33..55..66.. eecchhoo eenndd Borra la lista. 33..55..77.. UUnn eejjeemmpplloo ccoommpplleettoo Aquí hay un verdadero ejemplo donde se muestra un directorio y se permite al usuario elegir un archivo y hacer algo con él. Vemos en el ejemplo cúan sencillo es analizar la salida del comando "ls -l" y presentar el nombre de archivo, el tamaño y la data de revisión en tres columnas con formato. #!/usr/bin/shellmod . /usr/lib/linuxconf/lib/shellmod-lib.sh fileshow(){ echo notice \"Procesando archivo $1\" } main(){ echo DIALOG_LIST echo newf_head \"Nombre de archivo\" Tamaño \"Fecha de revisión\" 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 \"Directorio Actual\" \"Esto muestra todos los archivos en el directorio actual\" dispatch echo end } dispatch 33..66.. DDeeffiinniieennddoo ccaammppooss Todos los comandos que definen un campo de diálogo empiezan con el prefijo newf_. Hemos usado el mismo nombre y el mismo orden de parámetros (cuando ha sido posible) como en el módulo de C++ API. El primer argumento es siempre el nombre de la variable shell que recibirá el valor introducido por el usuario. A menudo se usará el siguiente contructor para editar (corregir el valor actual) de una variable dada. qecho newf_str var "título" "$var" . qecho edit ... dispatch if [ "$CODE" = "aceptar" ] ; then if [ "$var" = "..." ] ;then . . fi fi 33..77.. LLiissttaa ddee ccoommaannddooss Aquí hay una lista de todos los comandos de campos de definición: · ``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 ddeell ccaammppoo\\"" \\""VVaalloorr iinniicciiaall 00 oo 11\\"" \\""ttííttuulloo ddee ssuuffiijjoo\\"" Configure un campo de una casilla de verificación (on/off o sí/no). La variable var se configurará a 0 o 1. Este campo tiene dos títulos. Uno a la izquierda de la casilla de comprobación y otro a la derecha. Esto a menudo se usa como sigue: La siguiente característica [] está seleccionada 33..77..22.. VVaarriiaacciióónn ddee llaa ssiinnttaaxxiiss ddee nneewwff__cchhkk ssyynnttaaxx Cuand use newf_chk, debe pasar 0 o 1 como valor. La variable edit recibirá el resultado como 0 o 1. Esto no es útil ya que a menudo los shell script trabajan con diferentes tipos de valores booleanos. Por ejemplo, un script que trata con un servidor SQL puede encontrar que debe lidiar con valores Y y N. Para evitar tener que traducir de un sistema a otro se amplió la sintaxis referente al valor inicial. · Para facilitar las cosas, shellmod aceptará los valores sea en el formato que sea: 1, Y y Yes...A menos que se le diga lo contrario, todos esos valores se interpretarán como un 1. Sus homólogos de negación se considerarán 0. · Mediante el uso de un formato especial de tripletas, se puede especificar el valor real y el diccionario utilizado para traducirlo, especififcando el valor así: value:on_value:off_value Así que, si su aplicación trabaja con valores ON/OFF, puede especi­ ficar el valor inicial como sigue: $var:ON:OFF No solo se aceptará ON y OFF sinó que el resultado se enviará en este mismo formato, usando una de las dos palabras. 33..77..33.. eecchhoo nneewwff__cchhkkmm vvaarr \\""CCaammppoo ddee ttííttuulloo\\"" \\""VVaalloorr nnuumméérriiccoo iinniiccaall\\"" \\""vvaalloorr11\\"" \\""vvaalloorr22\\"" ...... Configurar múltiples campos de selección usando casillas de verificación. Las casillas se presentan horizontalmente. Aquí hay un ejemplo seguido del campo que produce en modo texto: echo newf_chkm sel \"Qué posición\" 1 left center right Produciendo: Qué posición ( ) left (o) center ( ) right La variable var tomará el índice numérico del item sleccionado, empezando desde 0. 33..77..44.. eecchhoo nneewwff__ccoommbboo vvaarr \\""CCaammppoo ddee ttííttuulloo\\"" \\""VVaalloorr iinniicciiaall\\"" Configurar una única línea + slector de campo. El usuario será capaz de elegir un valor de entre una lista o introducir uno a mano. La variable var contendrá el valor literal introducido o seleccionado. newf_combo se usa con el comando comboitem. Primero debe configrar el campo de edición del combo y después pasar uno a uno los posibles valores usando comboitem. Nótese que los valores van seguidos de un texto explicativo (opcional). Aquí hay un ejemplo de código: echo newf_combo port \"Qúe puerto\" ttyS1 echo comboitem ttyS0 \"COM1 en DOS\" echo comboitem ttyS1 \"COM2 en DOS\" echo comboitem ttyS2 \"COM3 en DOS\" La variable $port tomará los valores ttyS0, ttyS1, ttyS2 o cualquier otro valor que el usuario quiera darle. Véase ``newf_enum'' y ``newf_list'' para una variación de este campo de entrada. 33..77..55.. eecchhoo nneewwff__ddbbll vvaarr \\""TTííttuulloo ddeell ccaammppoo\\"" \\""VVaalloorr nnuumméérriiccoo iinniicciiaall\\"" nnúúmmeerroo ddee ddeecciimmaalleess Configurando un campo de entrada numérico con notación decimal. Se escribe así ``newf_num'' salvo por la coma decimal que está permitida. El número de parámetro decimal controla el número de dígitos decimales permitidos después de la coma así como el formato del campo. 33..77..66.. eecchhoo nneewwff__eennuumm vvaarr \\""TTííttuulloo ddee ccaammppoo\\"" \\""VVaalloorr nnuumméérriiccoo iinniicciiaall\\"" Configurando un selector de campo. El usuario puede elegir un valor de entre una lista. La variable var contendrá el índice del ítem seleccionado. El usario se limita a escoger un item de la lista. newf_enum se usa con el comando menuitem. Primero configure el campo enum y entonces pase uno a uno los posibles valores usando enumitem. Aquí hay un ejemplo de código: echo newf_enum no \"Qué puerto\" 1 echo enumitem ttyS0 \"COM1 en DOS\" echo enumitem ttyS1 \"COM2 en DOS\" echo enumitem ttyS2 \"COM3 en DOS\" La variable $no tomará el valor 0, 1 o 2. Vea ``newf_combo'' y ``newf_list'' para variar un campo de entrada. 33..77..77.. eecchhoo nneewwff__ggaauuggee IIDD \\""TTííttuulloo ddee ccaammppoo\\"" \\""VVaalloorr ddeecciimmaall iinniicciiaall\\"" \\""VVaalloorr mmááxxiimmoo\\"" Configurar un indicador gráfico, generalmente para mostrar el estado de progresión de un proceso (cargando, instalando). El estado del indicador se cambia utilizando de nuevo este comando. La primera llamada define el campo y la siguiente actualiza el indicador. Este widget se usa generalmente con el comando "show" para que el script nunca pare en el estado "edit". Aquí mostramos un pequeño ejemplo: echo DIALOG qecho newf_gauge ID "Estado" 0 10 qecho show "Estado" "" i=0 while [ "$i" != "10" ] ; do i=`expr $i + 1` sleep 1 qecho newf_gauge ID "Estado" $i 10 qecho show "Estado" "" done 33..77..88.. eecchhoo nneewwff__hheexxnnuumm vvaarr \\""TTííttuulloo ddee ccaammppoo\\"" \\""VVaalloorr iinniicciiaall hheexxaaddeecciimmaall\\"" Configurando un campo de entrada numérico (entero). Funciona así: ``newf_num'' pero acepta dígitos y dígitos hexadecimales. 33..77..99.. eecchhoo nneewwff__lliisstt vvaarr \\""TTííttuulloo ddee ccaammppoo\\"" \\""VVaalloorr iinniicciiaall\\"" Configurando un selector de campo. El usuario podrá escoger un valor de entre una lista. La variable var contendrá el valor literal seleccionado. newf_list se usa con el comando listitem. Primero configure el campo de la lista y después pase uno a uno los posibles valores usando listitem. Nótese que los valores van seguidos de un texto explicativo (opcional). Aquí hay un ejemplo de código: echo newf_list port \"Qué puerto\" ttyS1 echo listitem ttyS0 \"COM1 en DOS\" echo listitem ttyS1 \"COM2 en DOS\" echo listitem ttyS2 \"COM3 en DOS\" La variable $port tomará los valores ttyS0, ttyS1 or ttyS2. Vea ``newf_enum'' y ``newf_combo'' para variar el campo de entrada. 33..77..1100.. eecchhoo nneewwff__nnuumm vvaarr \\""TTííttuulloo ddee ccaammppoo\\"" \\""VVaalloorr nnuumméérriiccoo iinniicciiaall\\"" Configurar un campo de entrada numérico (entero). Funciona como newf_str pero sólo acepta dígitos. 33..77..1111.. eecchhoo nneewwff__ppaassss vvaarr \\""TTííttuulloo ddee ccaammppoo\\"" \\""VVaalloorr iinniicciiaall\\"" Configurando un campo de contraseña. Funciona como un campo newf_str pero la entrada no se muestra (escritura invisible). 33..77..1122.. eecchhoo nneewwff__rraaddiioo vvaarr \\""TTííttuulloo ddee ccaammppoo\\"" vvaalloorr--nnuumméérriiccoo vvaalloorr--eejjeemmpplloo \\""TTííttuulloo ddee ssuuffiijjoo\\"" Configurando un campo de botón radio. Algunos campos de botones radio deben ser definidos para cada posible selección. Todos estos botones comparten las mismas variables de entrada (var de arriba) y operan conjuntamente. La variable var tomará el valor numérico del campo del botón radio seleccionado. Los botones radio que estén relacionados pueden colocarse en cualquier lugar del diálogo. No necesitan estar de forma secuencial o incluso en la misma página del cuadro de diálogo de libreta. 33..77..1133.. eecchhoo nneewwff__sslliiddeerr vvaarr \\""TTííttuulloo ddee ccaammppoo\\"" \\""VVaalloorr ddeecciimmaall iinniicciiaall\\"" \\""vvaalloorr mmíínniimmoo\\"" \\""vvaalloorr mmááxxiimmoo\\"" Funciona como newf_num para editar un valor decimal, pero se muestra como un proyector de diapositivas gráfico. El valor máximo y mínimo representan el extremo izquierdo y el derecho del proyector. qecho newf_slider var "Hora de la cita" 15 9 16 33..77..1144.. eecchhoo nneewwff__ssttrr vvaarr \\""TTííttuulloo ddee ccaammppoo\\"" \\""VVaalloorr iinniicciiaall\\"" Configurar una entrada de línea de texto. 33..77..1155.. eecchhoo nneewwff__ttiittllee ""TTííttuulloo ddeell bblloocc"" lleevveell ""TTííttuulloo iizzqquuiieerrddoo"" ""TTííttuulloo ddeell mmooddoo tteexxttoo"" Esto no es un campo de entrada sinó una manera de organizar un diálogo grande en la sección. Es lresultado final es bien distinto en modo gráfico qu en texto y HTML. En el primero, creará un diálogo de bloc de notas y cada newf_title define una página de la libreta. El primer argumento, título del bloc, sólo se usa en modo gráfico. El segundo argumento es un número y representa el nivel del bloc de notas. Ésto permite diálogos muy complejos con bloc de notas dentro de los mismos. En modo texto y HTML, este argumento no tiene efecto. · Un valor de 0 añade una división horizontal entre dos campos. El "Título en modo texto"se centrará en esta división. · Un valor de 1 creará el primer nivel del bloc de notas, mientras que un valor 2 creará un sub-bloc con el actual. El tercer argumento, título izquierdo, se usa sólo en modo texto y HTML. Coloca un pequeño título a la izquierda de los campos de entrada. El último argumento, título en modo texto, aparece centrado entre dos campos de entrada. 33..88.. AAññaaddiieennddoo bboottoonneess Puede añadir botones opcionales simplemente usando el comndo button. Requiere dos argumentos. El primero es la Id del botón que se pasará al script la variable CODE. El segundo es la etiqueta (título) del botón. Aquí hay un ejemplo: echo DIALOG echo newf_str name \"Nombre de usuario\" $name echo button Agregar \"Agregar un nuevo usuario\" echo edit "título" \"Gestión de usuarios\" dispatch echo end if [ "$CODE" = "Agregar" ] ; then # Añadir un nuevo usuario elif [ "$CODE" = "aceotar" ] ; then # Inspeccionar apariciones anteriores de usuario fi 33..99.. AAjjuussttaarr eell ccaammppoo ddee eennttrraaddaa aaccttuuaall El opcode "setcurfield" ajusta la zona activa del teclado hacia un determinado campo. Debe pasar la ID del campo como un único argumento. Aquí tiene un ejemplo: qecho DIALOG qecho newf_str uid "id de usuario" qecho newf_str name "Nombre" qecho newf_str phone "Nombre" qecho setcurfield name qecho edit "ejemplo" "La zona activa está sobre el nombre" dispatch echo end 44.. CCoonnssttrruuyyeennddoo ccoo--mmaannaaggeerrss Los co-managers permiten añadir funciones a Linuxconf justo donde se precisa, en vez de agregar nuevos submenús. 44..11.. PPrriinncciippiiooss Un co-manager es un componente que participa en un diálogo. Puede añadir campos y validaciones. El caso más común es el diálogo de cuenta de usuario, donde participan más de uno de ellos. El más visible es el módulo mailconf, que inserta una sección completa para gestionar los áliases de correo. Otro caso es el módulo pppdialin que agrega una sección para tratar con parámetros PPP. Un co-manager debe proporcionar 4 funciones: · Añadir campos al diálogo. Aquí el co-manager probablemente añadirá una nueva sección y algunos campos. No es forzado a agregar nada. · Agregar validación. El co-manager puede realizar todo tipo de validaciones también en otros campo que no sean los suyos. No se permite al administrador cometer ningún cambio sobre la cuenta de usuario hasta que todos los co-mangers den el visto bueno. · Salvar las entradas. El co-manager debe salvar los valores de los campos que gestiona. Los relativos a cuentas de usuario tienen que preservar la información en unas bases para usuario. · Borra información asociada al registro de cuenta/información cuando ésta se borra. Nótese que los co-managers fueron creados en base a cuentas de usuario, pero el concepto es más genérico que eso. Cambie "cuenta de usuario" por "registro" y tendrá una visión más general. 44..22.. RReeggiissttrraannddoo aall ccoo--mmaannaaggeerr Linuxconf debe ser notificado de que existe un co-manager para un diálogo dado, identificado por una pequeña clave. Por ejemplo, la clave para el diálogo de cuenta de usuario es üsuario". Un co-manager shellmod debe proveer cuatro funciones que usen el mismo prefijo. Al registrarlo proporcione la función prefijo y la clave del diálogo. Ésto se hace con la función register. Aquí tiene un ejemplo: # Registrar como co-manager en el diálogo de cuenta de usuario echo comanager ufct user La función prefijo es ufct. Se deben crear cuatro funciones according to this prefix: · ufct-setupdia · ufct-validate · ufct-save · ufct-deluser 44..33.. LLaass ddiissttiinnttaass ffuunncciioonneess 44..33..11.. sseettuuppddiiaa Esta función es llamdada al construir un diálogo. Puede usar cualquier opcode de los normalmente utilizados para definir un diálogo. No tiene que definir el diálodo ud. mismo (echo DIALOG) ya que está implícitamente definido. Mientras ud. puede añadir simplemente campos en el diálogo, uno definirá generalmente una nueva sección de diálogo. A menos que haga ésto, su nuevo campo se anexará a la sección actual que puede ser cualquiera. Definició de una sección con el opcode newf_title qecho newf_title "Listas de correo" 1 - "Listas de correo" 44..33..22.. vvaalliiddaattee Esta función recibe todos los valores de los campos (introducidos por el usuario). Cada campo corresponde a una variable shell, así que ud. puede comprobar sus valores directamente. Debe usar "retcode" para decir que la validación se ha realizado con éxito. Como ejemplo: echo retcode 0 Cualquier valor distinto de 0 se toma como una validación fallida. Todos los errores deben ser informados con el opcode "error". También puede usar "setcurfield" para ir a un campo específico. if [ "$a1" = "válido" ] ; then echo retcode 0 else echo setcurfield a1 echo retcode -1 echo error \"sample.sh: Valor no válido, introduzca la palabra correcta\" fi 44..33..33.. ssaavvee Todos los valores del campo se retornan a su script como una variable shell. La función save debe hacer varias cosas con la información. Puede salvarlo en un archivo o realizar algunas acciones (enviar un mensaje al adminitrador acerca de los cambios requeridos, por ejemplo). Otra variable shell contiene información relacionada con este diálogo (véase el contexto de diálogo abajo). 44..33..44.. ddeelluusseerr Este nombre de función es un poco engañoso. Significa que el registro debe ser borrado (en general, una cuenta de usuario). Debe usar la información del contexto del diálogo (ver abajo) para realizar la eliminación pretendida. 44..44.. CCoonntteexxttoo ddee ddiiáállooggoo Un co-manager gestiona una parte de un diálogo mayor. Para gestionarlo adecuadamente, el co-manager debe saber otra información acerca del diálogo actual. Por ejemplo, para aumentar el diálogo de cuenta de usuario, se debe conocer la cuenta de usuario (id de usuario) que va a ser editada así como su dominio (¿es una cuenta de usario de dominio virtual de correo?). Esta información extra se pasa como una variable shell, utilizable para lectura. La información disponible depende del diálogo. Para co- managers de cuentas de usuario, se proporcionan las siguientes variables: ddoommiinniioo Se pasa el dominio virtual de correo. Para el dominio principal, esta variable se pone a /. iiss__nneeww Esta el identificador que le dice si es una cuenta nueva (el nombre está vació) o no. nnaammee Esta es la id de usuario. Una manera de aprender la información disponible para su script es mediante su ejecución en modo depurado bajo Linuxconf. Active este modo de la interfaz de usuario Linuxconf, en controlar archivo y sistema/gestión de módulo shell/configuración shellmod. 55.. VViiddaa ddee uunn pprroocceessoo ssccrriipptt Shellmod y Linuxconf iniciará el script siempre que sea preciso. Usado como módulo Linuxconf, el script no inicia al arrancar Linuxconf sinó sólo cuando uno de sus menús o alguna entrada de co-manager se seleccionan. El script se inicia y le sucede su función dispatch, donde espera una petición. Algunas de éstas disparan la ejecución de una de las funciones del script. Cuando acaba, la función original dispatch continúa y sigue esperando. Nótese que dispatch puede ser utilizado recursivamente. Una vez iniciado, el script se queda esperando una petición hasta que Linuxconf termine. Así que puede verse como si fuera un pequeño servidor compartiendo la información recogida al realizar varias peticiones. Cuando se usa como utilidad autónoma, elscript se terminará en cuanto exista una función main. 66.. CCoonnssttrruuccttoorr ddee mmóódduullooss Un constructor de módulos shell está disponible para coger soltura en estos menesteres. Puede acceder a este constructor desde el menú principal de shellmod o con la utilidad shellmod: shellmod --build Aparece aquí un único diálogo. Rellénelo y se creará el modelo para un módulo shell nuevo. Aquí hay varios campos. 66..11.. RRuuttaa ddeell mmóódduulloo Simplemente introduzca la ruta relativa o completa del nuevo script de shell que quiere crear. El constructor no es capaz de editar un módulo ya existente. 66..22.. IInnsseerrttee eenn mmeennúú Debe especificar el id del menú en que quiere insertar el módulo (Linuxconf). Un módulo puede insertarse en distintos menús de Linuxconf, pero el constructor sólo soporta uno. Modificar el código más tarde es muy sencillo. Este campo tiene una lista de ayuda para elegir el ID correcto. 66..33.. TTííttuulloo ddee mmeennúú Simplemente introduzca el texto del menú. 66..44.. EEssttoo eess uunn ccoo--mmaannaaggeerr ddee ccuueennttaa ddee uussuuaarriioo Seleccionando esta casilla de verificación, ordena la constructor a generar los ejemplos de funciones de co-manager apropiadas (setupdia, save,deluser,validate). Nótese que un módulo puede ser co-manager e insertarse en menús también. 66..55.. EEnnttrraaddaass ddeell mmeennúú pprriinncciippaall Simplemente introduzca las diferentes entradas del menú. Para cada una, el constructor generará un ejemplo de función shell: menufunc1,menufunc2. También creará el código del menú en la función main. Deberá proveer el código para las distintas funciones menufunc. } Entradas del menú principal