如何用c语言写一个shell

用c语言编写如下程序:编写一个简单的shell,可以运行不带参数的外部命令,支持标准I/O重定向,可以通过管道连接两个命令。(外部命令的路径可以是固定路径)。求示例代码。... 用c语言编写如下程序:
编写一个简单的shell,可以运行不带参数的外部命令,支持标准I/O重定向,可以通过管道连接两个命令。(外部命令的路径可以是固定路径)。

求示例代码。翻遍鸟哥都只找到shell的脚本编程,哪位大牛知道用c语言写一个shell解释器要怎么弄啊?求大神指点啊!!!
展开
 我来答
Spowoor
2012-05-20
知道答主
回答量:13
采纳率:0%
帮助的人:6.5万
展开全部
鸟哥是不会有这个的,可以这样想(感觉这样很麻烦,只用一对管道应该也可以,流程也能简单,控制好进程顺序就行。这个编得过):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>

#define CMD_LINE 1024
#define PIPE_MAX 16
#define ARG_MAX 10

typedef struct {
char *arg[ARG_MAX];
char *in;
char *out;
} cmd_t;

extern int parse_token(char *buf, cmd_t cmd[]);
extern int parse(char *buf, cmd_t * cmd);
extern int test_parse(cmd_t cmd[], int len);

int main(int argc, char *argv[])
{
char buf[CMD_LINE];
cmd_t cmd[PIPE_MAX + 1];
int fd[PIPE_MAX][2];
int j, i;
int cmd_len, pipe_len;
pid_t pid;

while (1) {
printf("my_shell#");

fgets(buf, CMD_LINE, stdin);
buf[strlen(buf) - 1] = '\0';
cmd_len = parse_token(buf, cmd);

pipe_len = cmd_len - 1;
if (pipe_len > PIPE_MAX)
continue;

for (i = 0; i < pipe_len; ++i)
pipe(fd[i]);

for (i = 0; i < cmd_len; ++i)
if ((pid = fork()) == 0)
break;

if (pid == 0) {
if (pipe_len) {
if (i == 0) {
close(fd[i][0]);
dup2(fd[i][1], 1);
close(fd[i][1]);
for (j = 1; j < pipe_len; ++j)
close(fd[j][0]),
close(fd[j][1]);
} else if (i == pipe_len) {
close(fd[i - 1][1]);
dup2(fd[i - 1][0], 0);
close(fd[i - 1][0]);
for (j = 0; j < pipe_len - 1; ++j)
close(fd[j][0]),
close(fd[j][1]);
} else {
dup2(fd[i - 1][0], 0);
close(fd[i][0]);
dup2(fd[i][1], 1);
close(fd[i][1]);
for (j = 0; j < pipe_len; ++j) {
if ((j != i - 1)
|| (j != i))
close(fd[j][0]),
close(fd[j]
[1]);
}
}
}
if (cmd[i].in) {
int fd = open(cmd[i].in, O_RDONLY);
dup2(fd, STDIN_FILENO);
close(fd);
}
if (cmd[i].out) {
int fd =
open(cmd[i].out,
O_RDWR | O_CREAT | O_TRUNC, 0644);
dup2(fd, STDOUT_FILENO);
close(fd);
}
execvp(cmd[i].arg[0], cmd[i].arg);
fprintf(stderr, "Failed exec\n");
exit(127);
}
/* parent */
for (i = 0; i < pipe_len; ++i)
close(fd[i][0]), close(fd[i][1]);
for (i = 0; i < cmd_len; ++i)
wait(NULL);
}

return 0;
}

int parse_token(char *buf, cmd_t cmd[])
{
int n = 0;
#if 1
char *save_p;
char *p = strtok_r(buf, "|", &save_p);
while (p != NULL) {
parse(p, &cmd[n++]);
p = strtok_r(NULL, "|", &save_p);
}

#else
cmd[n].arg[0] = "ls";
cmd[n].arg[1] = "-l";
cmd[n].arg[2] = NULL;

#endif
return n;
}

int test_parse(cmd_t cmd[], int len)
{
int i;
for (i = 0; i < len; ++i) {
printf("cmd[%d]:", i);
int j = 0;
while (cmd[i].arg[j])
printf(" %s", cmd[i].arg[j++]);
if (cmd[i].in)
printf("\tin:%s", cmd[i].in);
if (cmd[i].out)
printf("\tout:%s", cmd[i].out);
printf("\n");
}
return 0;
}

int parse(char *buf, cmd_t * cmd)
{
int i = 0;
cmd->in = NULL;
cmd->out = NULL;
char *p = strtok(buf, " ");
while (p) {
if (*p == '<') {
if (*(p + 1))
cmd->in = p + 1;
else
cmd->in = strtok(NULL, " ");
} else if (*p == '>') {
if (*(p + 1))
cmd->out = p + 1;
else
cmd->out = strtok(NULL, " ");
} else
cmd->arg[i++] = p;
p = strtok(NULL, " ");
}
cmd->arg[i] = NULL;
return 0;
}
星月小木木
推荐于2017-09-04 · TA获得超过3.2万个赞
知道大有可为答主
回答量:2.4万
采纳率:0%
帮助的人:1亿
展开全部
#include <stdio.h>
#include <unistd.h>

int main() {

// exec 系列函数出错时会返回 -1,平常返回 0,所以可以
// 据此来打印错误信息
// 第一个 ls 是命令的名称,execlp 函数会自动在 $PATH
// 中寻找这个命令。
// 后面一个 ls 是要在 shell 中输入的第一个参数
//(也就是命令名称本身)
// 使用 NULL 作为参数结尾标记是 exec 系列函数的要求。
if (execlp("ls", "ls", "-l", NULL) == -1)
perror("Error Executing Command.\n");
return 0;
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
幻湖葬月
2012-05-22 · TA获得超过306个赞
知道答主
回答量:290
采纳率:0%
帮助的人:189万
展开全部
bash源码放哪干嘛的?
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式