当前位置:首页 » 《资源分享》 » 正文

Linux——简单的Shell程序

25 人参与  2024年03月23日 15:05  分类 : 《资源分享》  评论

点击全文阅读


在这里插入图片描述


?北尘_:个人主页
?个人专栏:《Linux操作系统》《经典算法试题 》《C++》 《数据结构与算法》

☀️走在路上,不忘来时的初心

文章目录

一、Shell程序思路二、Shell代码展示


一、Shell程序思路

用下图的时间轴来表示事件的发生次序。其中时间从左向右。shell由标识为sh的方块代表,它随着时间的流逝从左向右移动。shell从用户读入字符串"ls"。shell建立一个新的进程,然后在那个进程中运行ls程序并等待那个进程结束。
在这里插入图片描述
然后shell读取新的一行输入,建立一个新的进程,在这个进程中运行程序 并等待这个进程结束。

获取命令行解析命令行建立一个子进程(fork)替换子进程(execvp)父进程等待子进程退出(wait)
根据这些思路,和我们前面的学的技术,就可以自己来实现一个shell了。

二、Shell代码展示

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>#define NUM 1024#define SIZE 64#define SEP " "//#define Debug 1char cwd[1024];char enval[1024]; // for testint lastcode = 0;char *homepath(){    char *home = getenv("HOME");    if(home) return home;    else return (char*)".";}const char *getUsername(){    const char *name = getenv("USER");    if(name) return name;    else return "none";}const char *getHostname(){    const char *hostname = getenv("HOSTNAME");    if(hostname) return hostname;    else return "none";}const char *getCwd(){    const char *cwd = getenv("PWD");    if(cwd) return cwd;    else return "none";}int getUserCommand(char *command, int num){    printf("[%s@%s %s]# ", getUsername(), getHostname(), getCwd());    char *r = fgets(command, num, stdin); // 最终你还是会输入\n    if(r == NULL) return -1;    // "abcd\n" "\n"    command[strlen(command) - 1] = '\0'; // 有没有可能越界?不会    return strlen(command);}void commandSplit(char *in, char *out[]){    int argc = 0;    out[argc++] = strtok(in, SEP);    while( out[argc++] = strtok(NULL, SEP));#ifdef Debug    for(int i = 0; out[i]; i++)    {        printf("%d:%s\n", i, out[i]);    }#endif}int execute(char *argv[]){    pid_t id = fork();    if(id < 0) return -1;    else if(id == 0) //child    {        // exec command        execvp(argv[0], argv); // cd ..        exit(1);    }    else // father    {        int status = 0;        pid_t rid = waitpid(id, &status, 0);        if(rid > 0){            lastcode = WEXITSTATUS(status);        }    }    return 0;}void cd(const char *path){    chdir(path);    char tmp[1024];    getcwd(tmp, sizeof(tmp));    sprintf(cwd, "PWD=%s", tmp); // bug    putenv(cwd);}// 什么叫做内键命令: 内建命令就是bash自己执行的,类似于自己内部的一个函数!// 1->yes, 0->no, -1->errint doBuildin(char *argv[]){    if(strcmp(argv[0], "cd") == 0)    {        char *path = NULL;        if(argv[1] == NULL) path=homepath();        else path = argv[1];        cd(path);        return 1;    }    else if(strcmp(argv[0], "export") == 0)    {        if(argv[1] == NULL) return 1;        strcpy(enval, argv[1]);        putenv(enval); // ???        return 1;    }    else if(strcmp(argv[0], "echo") == 0)    {        if(argv[1] == NULL){            printf("\n");            return 1;        }        if(*(argv[1]) == '$' && strlen(argv[1]) > 1){             char *val = argv[1]+1; // $PATH $?            if(strcmp(val, "?") == 0)            {                printf("%d\n", lastcode);                lastcode = 0;            }            else{                const char *enval = getenv(val);                if(enval) printf("%s\n", enval);                else printf("\n");            }            return 1;        }        else {            printf("%s\n", argv[1]);            return 1;        }    }    else if(0){}    return 0;}int main(){    while(1){        char usercommand[NUM];        char *argv[SIZE];        // 1. 打印提示符&&获取用户命令字符串获取成功        int n = getUserCommand(usercommand, sizeof(usercommand));        if(n <= 0) continue;        // 2. 分割字符串        // "ls -a -l" -> "ls" "-a" "-l"        commandSplit(usercommand, argv);        // 3. check build-in command        n = doBuildin(argv);        if(n) continue;        // 4. 执行对应的命令        execute(argv);    }}


点击全文阅读


本文链接:http://zhangshiyu.com/post/84362.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1