C语言 编写一个基本的 Shell
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4788374/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Writing a Basic Shell
提问by Bobby S
For my class I have to create a basic shell similar to bash that will allow the user to call commands like ls, sleep, etc. I am looking for resources on how to do this: tutorials, help text, sample code or even just some general information on how to get started. Does anyone have an links or info to help me out?
对于我的课程,我必须创建一个类似于 bash 的基本 shell,它允许用户调用 ls、sleep 等命令。我正在寻找有关如何执行此操作的资源:教程、帮助文本、示例代码,甚至只是一些关于如何开始的一般信息。有没有人有链接或信息来帮助我?
回答by jcoffland
It really depends on how simple your shell has to be. If you don't need job control (i.e. backgrounding) or pipes then it is very simple. Here is an example:
这实际上取决于您的外壳必须有多简单。如果您不需要作业控制(即后台)或管道,那么它非常简单。下面是一个例子:
#include <stdio.h>
#include <stdlib.h>
#define MAX_LENGTH 1024
int main(int argc, char *argv[]) {
char line[MAX_LENGTH];
while (1) {
printf("$ ");
if (!fgets(line, MAX_LENGTH, stdin)) break;
system(line);
}
return 0;
}
You can exit from the above example with CTRL-D. To add built-in commands like exitor cdyou would have to tokenize the line using strtok()and look at the first token. Here is a more complicated example with those commands added:
您可以使用 CTRL-D 退出上述示例。要添加诸如exit或cd 之类的内置命令,您必须使用strtok()对该行进行标记并查看第一个标记。这是一个更复杂的示例,添加了这些命令:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef _WIN32
#include <windows.h>
#define chdir _chdir
#else
#include <unistd.h>
#endif
#define MAX_LENGTH 1024
#define DELIMS " \t\r\n"
int main(int argc, char *argv[]) {
char *cmd;
char line[MAX_LENGTH];
while (1) {
printf("$ ");
if (!fgets(line, MAX_LENGTH, stdin)) break;
// Parse and execute command
if ((cmd = strtok(line, DELIMS))) {
// Clear errors
errno = 0;
if (strcmp(cmd, "cd") == 0) {
char *arg = strtok(0, DELIMS);
if (!arg) fprintf(stderr, "cd missing argument.\n");
else chdir(arg);
} else if (strcmp(cmd, "exit") == 0) {
break;
} else system(line);
if (errno) perror("Command failed");
}
}
return 0;
}
You could extend this by adding more build-in commands or by supporting things like cdwith out arguments to change to your home directory. You could also improve the command prompt by adding information such as the current directory.
您可以通过添加更多内置命令或支持诸如cd 之类的不带参数的内容来扩展它以更改到您的主目录。您还可以通过添加诸如当前目录之类的信息来改进命令提示符。
As a side note, an easy way to add a command history and line editing features is to use the GNU readlinelibrary.
作为旁注,添加命令历史记录和行编辑功能的一种简单方法是使用GNU readline库。
回答by Tim Post
I wrote a very basic shell for the HelenOS project. It has the following features:
我为HelenOS 项目编写了一个非常基本的 shell 。它具有以下特点:
- Line editing / history
- Buit in commands / loadable commands
- Search path to find external commands
- EXTREMELY basic scripting
- Dumbed down implementations of most of the GNU core utilities (done from scratch) as built in functions.
- 行编辑/历史
- 内置命令/可加载命令
- 查找外部命令的搜索路径
- 非常基本的脚本
- 将大多数 GNU 核心实用程序(从头开始)的实现简化为内置函数。
Most of it is implemented on a very simple re-usable framework built around function pointers. At the minimum, you'll need a built in 'exit' or 'quit' so someone can actually get out of the shell, plus 'cd' and 'pwd'. An 'export' / 'declare' built in would also make sense.
其中大部分是在围绕函数指针构建的非常简单的可重用框架上实现的。至少,您需要一个内置的“exit”或“quit”,这样有人才能真正离开外壳,再加上“cd”和“pwd”。内置的“导出”/“声明”也有意义。
You can look at the code (BSD) licensed here. Or download the repo, it's in uspace/app/bdsh. I can probably dig up the last working Linux version, prior to when I ported it if you need it. The biggest difference is the HelenOS version uses a home grown line editor, task_spawn() instead of execve() / posix_spawn(), etc. The rest is portable. It was originally designed just to make testing of features easy and interactive. I didn't implement job control, as it wasn't needed. That could be achieved trivially, however.
您可以在此处查看许可的代码 (BSD) 。或者下载 repo,它在 uspace/app/bdsh 中。如果你需要的话,我可能会在我移植它之前挖掘出最后一个可用的 Linux 版本。最大的不同是 HelenOS 版本使用了自产的行编辑器,task_spawn() 而不是 execve() / posix_spawn() 等,其余的是可移植的。它最初的设计只是为了使功能测试变得简单和交互。我没有实施作业控制,因为它不需要。然而,这可以轻而易举地实现。
If you want to study a 'real' shell, I highly recommend looking at dash, you'll find it much simpler to grasp than diving straight into the code of bash.
如果您想研究“真正的”shell,我强烈建议您查看dash,您会发现它比直接深入研究 bash 代码更容易掌握。
Anecdotally, 'bdsh' stands for 'brain dead shell'.
有趣的是,“bdsh”代表“脑死壳”。
回答by R.. GitHub STOP HELPING ICE
回答by Laschet Jain
If you are starting , try http://stephen-brennan.com/2015/01/16/write-a-shell-in-c/and further for detailed knowledge http://www.gnu.org/software/libc/manual/html_node/Data-Structures.html#Data-Structures.
如果您正在开始,请尝试http://stephen-brennan.com/2015/01/16/write-a-shell-in-c/并进一步了解详细知识http://www.gnu.org/software/libc /manual/html_node/Data-Structures.html#Data-Structures。
Also , while learning how to program a shell using C/C++ make a habit to refer man pages of commands.
此外,在学习如何使用 C/C++ 编写 shell 时,请养成参考命令手册页的习惯。
回答by chrisaycock
Bash provides very few commands on its own: cd, pushd, popd, the variable handling routines (setand $x), and all of the control flow items like loops and conditionals. Almost all other commands are found in the $PATH.
Bash 本身提供的命令很少:cd、pushd、popd、变量处理例程(set和$x),以及所有控制流项,如循环和条件。几乎所有其他命令都可以在$PATH.
Unless the assignment states otherwise, ignore variables and control flow. Just provide a REPLthat looks in $PATHand executes whatever the user enters (presumably through posix_spawn()) and pass along the command-line arguments.
除非赋值另有说明,否则忽略变量和控制流。只需提供一个REPL,它会查看$PATH并执行用户输入的任何内容(大概是通过posix_spawn())并传递命令行参数。
回答by agx
Lowball answer:
低球答案:
If the program is very simple, then simple system calls can be implemented script-like with the command "system("putdesiredcommandhere");"
如果程序很简单,那么简单的系统调用就可以像脚本一样用命令“ system("putdesiredcommandhere");”来实现
When you install "printf" in a program, you are doing a simple system call, with the help of stdio.h.
当您printf在程序中安装“ ”时,您正在执行一个简单的系统调用,借助 stdio.h。
Small code sample follows.
小代码示例如下。
#include <stdio.h>
#include <stdlib.h>
main ()
{
system ("clear");
system ("echo this is an example of a basic system call");
printf ("just as you've always done.\n");
return 0;
}
Using that method, you could transcribe bash or csh scripts into a c program. It would require using a system call for each line in the script.
使用该方法,您可以将 bash 或 csh 脚本转录为 ac 程序。它需要对脚本中的每一行使用系统调用。

