项目结构
代码实现
程序入口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| [shell.py] []
import sys import shlex import os
from ysh.constants import *
from ysh.builtins.cd import * from ysh.builtins.exit import *
def register_command(name, func): built_in_cmds[name] = func
def init(): register_command('cd', cd) register_command('exit', exit)
built_in_cmds = {}
def shell_loop(): status = SHELL_STATUS_RUN while status == SHELL_STATUS_RUN:
sys.stdout.write('$'+os.getlogin()+' '+os.getcwd() + '> ') sys.stdout.flush()
cmd = sys.stdin.readline()
cmd_tokens = tokenize(cmd)
status = execute(cmd_tokens)
def tokenize(string): return shlex.split(string)
def execute(cmd_tokens): cmd_name = cmd_tokens[0] cmd_args = cmd_tokens[1:] if cmd_name in built_in_cmds: return built_in_cmds[cmd_name](cmd_args) pid = os.fork() if pid == 0: os.execvp(cmd_tokens[0], cmd_tokens) elif pid > 0: while True: wpid, status = os.waitpid(pid, 0) if os.WIFEXITED(status) or os.WIFSIGNALED(status): break return SHELL_STATUS_RUN
def main(): init() shell_loop()
if __name__ == '__main__': main()
|
常量
1 2 3 4
| [constants.py] []
SHELL_STATUS_RUN = 1 SHELL_STATUS_STOP = 0
|
内建命令
我们fork了一个子进程去执行命令,执行命令的过程没有发生在父进程上.比如cd命令,这样只是改变了子进程的当前目录,而没有改变父进程的.所以像这种与shell自己相关的命令必须是内置命令.他必须在shell进程中执行,而不是分叉中!
1 2 3 4 5 6 7 8 9 10 11 12 13
| [cd.py] []
import os from ysh.constants import *
def cd(args): if len(args) == 0: os.chdir(os.environ['HOME']) else: os.chdir(args[0]) return SHELL_STATUS_RUN
|
1 2 3 4 5 6 7 8
| [exit.py] []
import os from ysh.constants import *
def exit(args): return SHELL_STATUS_STOP
|