Pregunta

Estoy escribiendo mi propio shell en C.Debe poder mostrar el directorio actual de los usuarios y ejecutar comandos basados ​​en la ruta completa (debe usar execv), y permitir al usuario cambiar el directorio con cd.

Esta ES tarea.El profesor sólo nos dio una introducción básica a C y un resumen muy breve de cómo debería funcionar el programa.Como no soy de los que se dan por vencidos fácilmente, he estado investigando cómo hacer esto durante tres días, pero ahora estoy perplejo.

Esto es lo que tengo hasta ahora:

  • Muestra el nombre de usuario, el nombre de la computadora y el directorio actual del usuario (el valor predeterminado es el directorio de inicio).
  • Solicita al usuario información y obtiene la información
  • Divide la entrada del usuario por " " en una serie de argumentos
  • Divide la variable de entorno PATH por ":" en una matriz de tokens

No estoy seguro de cómo proceder desde aquí.Sé que tengo que usar el comando execv pero en mi investigación en Google no encontré un ejemplo que entienda.Por ejemplo, si el comando es bin/ls, ¿cómo sabe execv que se muestran todos los archivos/carpetas del directorio de inicio?¿Cómo le digo al sistema que cambié el directorio?

He estado usando mucho este sitio y ha sido útil: http://linuxgazette.net/111/ramankutty.html pero, de nuevo, estoy perplejo.

Gracias por tu ayuda.Avíseme si debería publicar parte de mi código existente, aunque no estoy seguro de si era necesario.

¿Fue útil?

Solución

Para implementar el comando cd solo necesitas la llamada al sistema chdir.

#include <unistd.h>

int chdir(
    const char *path /* the path name */
);

Entonces puedes llamar a algo como:

int ret1 = chdir("../foo/bar");

El valor de retorno de chdir es 0 cuando fue posible cambiar a ese directorio y -1 si ocurrió un error.Para el error, debe consolidar la página de manual.

El directorio actual puede ser verificado por cualquier programa, por lo que si ejecuta ls sin ningún argumento, ls comprueba en qué directorio se está ejecutando y utiliza este directorio como único argumento.Esta es una característica de ls y no del execv llamar.

Para la segunda parte.

#include <unistd.h>
int execv(
     const char *path, /* programm path*/
     char *const argv[]/* argument vector*/
);

execv ejecuta un archivo ejecutable en el momento dado path y con los argumentos dados en argv.Así que si quieres ejecutar /bin/ls ../foo /bar, necesitas algo similar a

char *cmd_str = "/bin/ls";
char *argv[] = {cmd_str, "../foo", "/bar", NULL };
if (execv(cmd_str, argv) == -1 ){
    /* an error occurred */
}

El error devuelto por execv es -1.Si desea saber por qué no ejecutó el comando, consulte las páginas del manual.

El NULL en char *argv[] = {cmd_str, "../foo", "/bar", NULL }; está ahí para indicar que no hay otros argumentos después de la NULL.

La tercera parte.Los sistemas basados ​​en Unix normalmente tratan los comandos que contienen / como comandos que se pueden ejecutar directamente.Lo que significa que primero verifica si hay una barra diagonal en la cadena de comando dada.

int ret_value;
if (strchr(cmd_str, '/')
    if (execv(cmd_str, argv) == -1 ){
        /* an error occurred */
    }

Si no hay una barra, entonces deberá revisar todos los directorios en PATH y compruebe si puede ejecutar el comando.Entonces el comando dado es ls ../foo /bar y supongamos el valor de PATH es ".:/sbin:/bin:/usr/bin".Entonces intentaríamos ejecutar primero ./ls ../foo /bar entonces /usr/bin/ls ../foo /bar y por ultimo /bin/ls ../foo /bar.

Espero que esto ayude.

Otros consejos

Por ejemplo, si el comando es bin/ls, cómo execv ¿Sabe cómo mostrar todos los archivos/carpetas del directorio de inicio?¿Cómo le digo al sistema que cambié el directorio?

Cada proceso tiene un directorio de trabajo actual, que puede modificarse usando chdir.Los procesos secundarios heredarán el directorio de trabajo de sus padres.Entonces, en general, su shell administrará su directorio de trabajo actual en respuesta a cd comandos introducidos por el usuario.Cuando se ingresa un comando que no es incorporado, entonces fork para crear un proceso hijo y luego llamar execv allí para ejecutar el binario.

Si quieres tomar el PATH en cuenta para nombres de programas que no contienen ninguna parte de directorio, entonces debería probar todas las combinaciones posibles de un PATH elemento y el nombre del programa.Puede verificar si el archivo nombrado existe o simplemente intentar ejecutarlo y continuar con el siguiente si falla.Me caigo execv las llamadas fallaron, tendrás que llamar _exit para finalizar el proceso hijo.

Tenga en cuenta que la mayoría de los shells tratarán cualquier comando que contenga un / como un camino que se pasa a execv directamente.Si el camino no comenzar con un /, entonces es una ruta relativa y el sistema operativo la resolverá con respecto al directorio de trabajo actual.En otras palabras, el bin/ls de su ejemplo se referiría a la ls binario en el bin directorio que es un subdirectorio del directorio de trabajo actual.Sólo comandos que no contienen ningún / en absoluto se interpretan como un comando incorporado (como cd) o el nombre de algún binario ubicado en el PATH.

El primer argumento para execv es el camino tal como lo calculaste.El primer elemento del argv La lista tradicionalmente es igual al nombre tal como se ingresó, es decir.sin añadido PATH directorio.Después de ese primer argumento, se pasan todos los parámetros de línea de comando adicionales, seguidos de un NULL para terminar la lista.

Creo que el problema es que cree que la concha es responsable de hacer el trabajo de ls.ls no es realmente una "parte" de la cáscara (en este caso, al menos).El Shell ejecuta un programa llamado ls.La mayoría de los comentarios parecen explicar cómo encontrar ls, pero no creo que eso se confunde.

Debe considerar cuidadosamente cuál es el punto de la cáscara antes de escribirlo.Los comentarios han señalado indirectamente el hecho de que el shell "simplemente" tiene que "llamar" programas como ls y chdir, no realice sus tareas.

ls sabe por sí mismo que, si no se le dan ningún argumento, se supone que debe enumerar los archivos en el directorio de trabajo actual según lo devuelto por getcwd

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top