Last active
December 14, 2020 19:49
-
-
Save fernandolopez/6564869 to your computer and use it in GitHub Desktop.
Ejemplo muy básico de un shell para ilustrar la diferencia de los comandos internos y comandos externos de los shells usados en sistemas operativos unix-like. El ejemplo no un estilo muy prolijo ni pythonico porque está pensado para ser fácil de entender para personas que no conocen el lenguaje.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
#-*- encoding: utf-8 -*- | |
# | |
# Ejemplo de un shell extremadamene rudimentario e incompleto | |
# para ilustrar la diferencia entre comandos internos | |
# y comandos externos | |
# | |
import os | |
########################## COMANDOS INTERNOS ######################### | |
# Implementación muy básica e incompleta de comandos internos... | |
# no importa si no se entiende la implementación de esta parte | |
def echo_cmd(args): | |
print(" ".join(args)) | |
def ls_cmd(arg): | |
if not arg: | |
arg = [os.getcwd()] | |
try: | |
print("\n".join(os.listdir(arg[0]))) | |
except OSError as ex: | |
print(ex) | |
def exit_cmd(arg): | |
if not arg: | |
arg = [0] | |
exit(int(arg[0])) | |
def help_cmd(arg): | |
print("Comandos internos:\n" + "\n".join(comandos_internos.keys())) | |
# Defino los comandos internos | |
comandos_internos = { | |
'echo': echo_cmd, | |
'ls': ls_cmd, | |
'exit': exit_cmd, | |
'help': help_cmd | |
} | |
################## INICIALIZANDO ALGUNAS VARIABLES ################## | |
# Obtengo la lista de directorios en los que se buscarán | |
# los comandos, para esto pido la variable de entorno $PATH | |
path = os.getenv('PATH').split(':') | |
# Si soy root la terminal muestra un numeral, sino un signo pesos | |
if os.getuid() == 0: | |
prompt = "# " | |
else: | |
prompt = "$ " | |
#################### LEYENDO Y EJECUTANDO COMANDOS ################## | |
while True: | |
comando = raw_input(prompt) # Leo un comando por teclado | |
argumentos = comando.split() # Separo la línea en "palabras" | |
if not argumentos: | |
# Si no se ingresó ningún comando vuelvo al principio | |
continue # Esto salta una iteración del while | |
nombre = argumentos[0] # Me quedo con la primer palabra | |
# Verifico si tengo una implementación interna del comando | |
if nombre in comandos_internos: | |
# Invoco el comando interno con todas las palabras de | |
# la línea excepto la primera (es decir con sus | |
# argumentos) | |
comandos_internos[nombre](argumentos[1:]) | |
else: | |
path_descubierto = None | |
# Probablemente el usuario haya indicado | |
# el path completo o el path relativo al | |
# comando, por ejemplo /bin/ls | |
# en ese caso no hace falta buscar | |
if os.path.exists(nombre): | |
path_descubierto = nombre | |
else: | |
# Busco el comando en los directorios listados en la | |
# variable de entorno PATH | |
for directorio in path: | |
# Por ejemplo si ls no fuera interno | |
# y PATH=/bin:/usr/bin:/usr/local/bin | |
# buscaría: /bin/ls, luego /usr/bin/ls, | |
# luego /usr/local/bin/ls | |
if os.path.exists(directorio + '/' + nombre): | |
path_descubierto = directorio + '/' + nombre | |
break # Salgo del for | |
if path_descubierto == None: | |
# Si no encontramos nada... | |
print("Comando " + comando + " no encontrado") | |
else: | |
# Si existe lo ejecuto (para eso | |
# creo un nuevo proceso) | |
pid = os.fork() | |
if pid == 0: | |
# Si entra por acá es | |
# porque estoy en el | |
# proceso hijo | |
# entonces ejecuto el comando | |
os.execvp( | |
path_descubierto, | |
argumentos | |
) | |
else: | |
# Si entra por acá es | |
# porque estoy en el | |
# proceso padre | |
# entonces espero que | |
# el hijo termine de ejecutarse | |
os.waitpid(pid, 0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment