Creando una shell de Linux (IV)


Estamos muy cerca de dotar de una funcionalidad muy útil a nuestra shell. Hemos sentado las bases en la entrada anterior y ya falta solo el colofón para poder listar los contenidos de una carpeta, y tendríamos así un programa capaz de navegar por el árbol de directorios y mostrarnos lo que hay en ellos. Prácticamente con un par de cosas más sería una shell muy apañada!

En Linux disponemos de funciones como “opendir()” y “readdir()” para acceder a un directorio y a sus contenidos. Como puedes ver en el manual, ambas dependen de la librería “dirent” así que vamos a incorporarla a nuestro programa:

Además, “readdir()” nos detalla que devuelve una estructura llamada “dirent” que tiene este patrón:

Vamos con la implementación. Por argumentos nos llega lo que escriba el usuario, que puede ser una ruta, el flag “s” (para solo mostrar el nombre de los elementos) y el flag “a” (para mostrar todos los elementos, incluyendo ocultos).
Por eso, comenzamos definiendo unas variables que serán las que luego nos permitan ver qué opciones ha activado y qué ruta nos está pidiendo ver.
La variable “dir” es la que va a darnos acceso al directorio, y la “dirent” será la que nos permita ir referenciando cada uno de sus archivos o carpetas. El string “path” será la ruta a listar.

Lo que haremos será un bucle que recorra los argumentos con los que “ls” ha sido invocado para comparar si alguno se corresponde con “-s” o “-a”, y ponemos el valor de las variables “simple” y/o “all” a 1.
Si nos encontramos algo más, será una ruta. Si no hay más argumentos o si no había ninguno, le asignaremos el directorio actual llamando a la función “cwd” que habíamos programado en la segunda parte de esta serie.

La segunda parte de la función es muy sencilla de entender.
Intentamos abrir el directorio (lanzamos un error si no es posible). Ahora, cada vez que invoquemos “readdir()”, se nos devolverán de forma secuencial los elementos que contenga, así que hagamos un bucle para recorrerlos todos hasta que la función devuelva NULL, que significa que ya no quedan más elementos.
Con el “if” nos saltamos los archivos que empiecen por un punto (es decir, los archivos ocultos o los enlaces al directorio actual y superior) si la variable “all” no está activada; y si la variable “simple” lo está, entonces solo hacemos un printf con el nombre de la entrada (accesible mediante la estructura dirent que hemos visto antes). En caso contrario… aquí viene la magia de todo el post anterior: llamamos a la función getFileMetadata para obtener el string con los permisos, el grupo, el propietario, etc. etc. 🙂
Una vez terminadas todas estas operaciones, cerramos el directorio. Con “closedir()”.

Ya podemos añadir nuestro “ls” a la lista de comandos que acepta nuestra shell, descartando ya el primer argumento que es precisamente el nombre del comando:

Y por último podemos compilar y hacer alguna prueba para comprobar su buen funcionamiento:

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