打印
[嵌入式linux]

最小的shell实现,只有127行代码

[复制链接]
853|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 nicholasldf 于 2016-7-23 17:15 编辑

在《linux命令行与shell脚本编程大全》这本书提到了这个微型的shell,用来解释shell的原理。

http://www.samiam.org/software/yash.html

This is a simple thought experiment: How small can we make a usable *NIX command shell? This program, only 127 lines long (complete with documentation), is a very basic *NIX command shell. It can be downloaded here
Since the program is so small, I am including its source below. Note that there are ways to make this smaller by, say, using strtok to parse the line, and strcmp to handle the "cd" command. However, this code style makes extending the shell easier; the smallest shell that one can make is actually main(){char i[99];for(;;){gets(i);system(i);}}

Without further ado, the code:

/* Placed in the public domain 2009 by Sam Trenholme */

/* Yash: A usable command shell in under 4k (yet another shell)
*
* This is a simple thought experiment: How small can we make a *NIX command
* line shell?  This is as simple as it gets; it will run a command typed
* in if it's an external command like "ls" or "cc", with arguments separated
* by space; if one types in "-cd {directory}", it will go to that directory.
*
* CNTL-C exits the shell
*
* BUGS: CNTL-D reruns the previous command instead of exiting the shell.
*/

#define LINEMAX 80
#define ARGMAX 16

#include <stdio.h>
#include <unistd.h>

/* Given a pointer to arguments, destroy the string */
void yash_zap_args(char **zap) {
        int a = 0;

        if(zap == 0) {
                return;
        }

        for(a = 0; a < ARGMAX; a++) {
                if(zap[a] != 0) {
                        free(zap[a]);
                        zap[a] = 0;
                }
        }

        free(zap);
}

/* Given a line separated by whitespace, return an array of strings
* of the individual arguments */

char **yash_args(char *in) {
        char **out = 0;
        int a = 0, b = 0;

        /* Sanity checks */
        if(in == 0) {
                return 0;
        }

        out = malloc(ARGMAX * sizeof(char *));
        for(a = 0; a < ARGMAX; a++) {
                out[a] = 0;
        }
        a = 0;

        if(out == 0) {
                return 0;
        }

        while(*in != 0) {
                if(*in != ' ' && *in != '\n') {
                        if((out[a] = malloc(LINEMAX)) == 0) {
                                goto catch_yash_args;
                        }
                        b = 0;
                        while(b < LINEMAX - 2 && *in != ' ' && *in != 0 &&
                              *in != '\n') {
                                out[a] = *in;
                                b++;
                                in++;
                        }
                        out[a] = 0;
                        a++;
                        if(a >= ARGMAX) {
                                goto catch_yash_args;
                        }
                }
                in++;
        }        

        return out;
               
catch_yash_args:
        yash_zap_args(out);
        return 0;
}

/* Meta commands for yash; right now this is just the cd command */
void yash_meta(char **args) {
        if(args == 0 || args[0] == 0) {
                return;
        }

        if(args[0][1] == 'c' && args[0][2] == 'd') {
                if(args[1] == 0) {
                        chdir("/"); /* Should be $HOME, isn't */
                } else {
                        chdir(args[1]);
                }
                return;
        }
}
               
main() {
        char in[LINEMAX], **args = 0;

        for(;;) {
                printf("$ ");
                fgets(in,LINEMAX,stdin);
                args = yash_args(in);
                if(args != 0 && args[0] != 0) {
                        if(*args[0] == '-') {
                                yash_meta(args);
                        }
                        else if(fork()) {
                                wait(0);
                        } else {
                                execvp(args[0],args);
                                printf("Command not found\n");
                                exit(-1);
                        }
                }               
                yash_zap_args(args);
        }
}

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

261

帖子

10

粉丝