Creando una shell de Linux (II)


Vamos empezar a dar funcionalidad a la Shell que comencé en el post anterior. Hasta ahora hemos visto cómo se comporta el bucle principal, como leer las órdenes del usuario y como finalizar la ejecución del programa de forma segura. A continuación, vamos a implementar un procedimiento muy sencillo para mostrar el autor, y sabiendo como hacer esto, tres procedimientos más que nos permitan movernos por la estructura de directorios de nuestro sistema y saber en qué directorio nos encontramos. ¡Vamos allá!

En primer lugar atacaremos el procedimiento más sencillo. Quiero que cuando el usuario teclee la orden:
#-> auth
El programa imprima un pequeño texto con mi nombre, el año y la dirección del blog. De modo que en nuestra función “cmdcall”, que era donde distinguíamos la orden que ha introducido el usuario, voy a definir que si ha escrito “auth”, se llame a la función “printauth”.

Sencillo, verdad? Pues ya puedo definir la función “printauth”, que sólo son un puñado de “printf”:

Pasemos a las dos funciones de directorios que quiero implementar. La primera es “pwd” y hace exactamente lo mismo que hace el comando de Linux: muestra en qué directorio estoy. La segunda será “cd” y como la original, me permite cambiar a otro directorio. Voy a añadirlas a mi lista de comandos que ahora tiene esta pinta:

Para implementarlos, voy a utilizar primero un procedimiento adicional, que me devuelve la cadena con la ruta del directorio donde me encuentro. Lo llamaré “cwd” (por las siglas de “Current Working Directory”) y su implementación es muy sencilla: creo un buffer de caracteres (voy a aprovechar y darle un tamaño máximo para evitar problemas) y llamo a la función “getcwd” que vuelca en este buffer la ruta local, de nuevo hasta el maximo de caracteres que hemos establecido.
Antes de continuar, fíjate en el manual de getcwd:
$ man getcwd
Pertenece a una librería del sistema, de modo que habrá que importarla en la cabecera del programa:
#include <unistd.h>
Ahora que podemos obtener la ruta a partir de esta función, la implementación de pwd es trivial. Basta con almacenarla en una cadena e imprimir su contenido, sin más. Solo debemos vigilar que la función no nos haya devuelto NULL o que haya habido un error; y en ese caso lo enviamos a la salida de errores con “perror”. Aquí puedes ver ambas funciones:

Una vez hecho esto, pasemos a una función con algo más de trabajo. Quiero que el comando “cd” me permita cambiar de directorio, o que no haga nada si no le indico una ruta. Es decir, la cadena con la que se lanza este comando es:
#-> cd [una_ruta]
Donde el argumento de la ruta puede aparecer o no. Por eso, en “cmdcall” lo invocamos pasándole el resto de la orden introducida por el usuario, ya que ahí estarán los argumentos. Vamos a implementarlo.

El procedimiento comienza precisamente preguntando si hay argumentos o no. Si los hay es que el usuario nos ha escrito una ruta y en ese caso llamamos a la función “chdir” (que por suerte también es parte de “unistd.h” indicándole esa ruta. Si el sistema no puede cambiar de directorio (porque la ruta no es valida o el procedimiento provoca un error), lo enviamos a la salida estandar. Un efecto colateral de hacer la llamada a la función dentro del propio if que comprueba su resultado es que, si todo ha ido bien, no necesitamos hacer nada más. Es posible que esto nos arroje algún warning, pero nada grave si entendemos que es por este motivo:

Y habiendo hecho esto, nuestra shell ya está lista para que la compilar y probar:

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s