先上成果图

源代码

仅供技术点的分享,抄袭者就算了,所以main.c就不贴了

/*
* split_line.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mini_shell.h" #define is_delim(x) ((x)==' '||(x)=='\t') char *new_str(char *s, int l) {
char *rv = emalloc(l + 1);
rv[l] = '\0';
strncpy(rv, s, l);
return rv;
} // 返回shell中获取到的一行命令
char *next_cmd(char *prompt, FILE *fp) {
char *buf; /* the buffer */
int buf_size = 0; /* total size */
int pos = 0; /* current position */
int c; /* input char */ printf("%s", prompt); /* prompt user */
while ((c = getc(fp)) != EOF) { /* need space? */
if (pos + 1 >= buf_size) { /* 1 for \0 */
if (buf_size == 0) buf = emalloc(BUFSIZ); /* y: 1st time */
else buf = erealloc(buf, buf_size + BUFSIZ); /* or expand */
buf_size += BUFSIZ; /* update size */
} /* end of command? */
if (c == '\n') break; /* no, add to buffer */
buf[pos++] = c;
}
if (c == EOF && pos == 0) return NULL; /* EOF and no input */
buf[pos] = '\0';
return buf;
} // 将每个句子依空格再次拆分
char **split_sentence(char *line) {
char **args;
int spots; /* spots in table */
int buf_space; /* bytes in table */
int arg_num = 0; /* slots used */
char *cp = line; /* pos in string */
char *start;
int len; if (line == NULL) /* handle special case */
return NULL; args = emalloc(BUFSIZ); /* initialize array */
buf_space = BUFSIZ;
spots = BUFSIZ / sizeof(char *); while (*cp != '\0') {
while (is_delim(*cp)) /* skip leading spaces */
cp++;
if (*cp == '\0') /* quit at end-o-string */
break; /* make sure the array has room (+1 for NULL) */
if (arg_num + 1 >= spots) {
args = erealloc(args, buf_space + BUFSIZ);
buf_space += BUFSIZ;
spots += (BUFSIZ / sizeof(char *));
} /* mark start, then find end of word */
start = cp;
len = 1;
while (*++cp != '\0' && !(is_delim(*cp))) len++;
args[arg_num++] = new_str(start, len);
}
args[arg_num] = NULL;
return args;
} // 依管道符将命令拆分为几个句子,如果没有管道符,则只有一个句子
char ***split_line(char *line) {
if (!line) return NULL;
char ***orders = emalloc(BUFSIZ);
int buf_space = BUFSIZ;
int spots = BUFSIZ / sizeof(char **);
int sen_num = 0;
char *p = line;
do {
while (is_delim(*p)) /* skip leading spaces */
p++;
if (*p == '\0') /* quit at end-o-string */
break;
if (sen_num + 1 >= spots) {
orders = erealloc(orders, buf_space + BUFSIZ);
buf_space += BUFSIZ;
spots += BUFSIZ / sizeof(char **);
} char *end = p;
while (*end != '\0' && *end != '|') end++;
char *sentence = emalloc(end - p + 1); // 由管道符隔开的为一个sentence
strncpy(sentence, p, end - p);
sentence[end - p] = 0;
orders[sen_num++] = split_sentence(sentence);
if (*end) p = end + 1; // '|'
else p = end; // '\0'
} while (*p); orders[sen_num] = 0; return orders;
} // 释放在堆区申请的内存
void freelist(char ***list) {
for (char ***t = list; *t; t++)
for (char **tt = *t; *tt; tt++)
free(*tt);
for (char ***t = list; *t; t++)
free(*t);
free(list);
} void *emalloc(size_t n) {
void *rv;
if ((rv = malloc(n)) == NULL) fatal("out of memory", "", 1);
return rv;
} void *erealloc(void *p, size_t n) {
void *rv;
if ((rv = realloc(p, n)) == NULL)
fatal("realloc() failed", "", 1);
return rv;
}
/*
* execute.c - code used by mini shell to execute commands
*/ #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <glob.h> // 利用glob()函数进行*的匹配 int redirect(char **cmd) {
int ard = 0; // append redirect, 追加重定向
int rd = 0; // 非追加重定向
while (*cmd) {
char *p = *cmd;
int fd;
if (ard || rd) {
if (ard) fd = open(p, O_CREAT | O_APPEND | O_WRONLY, 0644);
else fd = open(p, O_CREAT | O_TRUNC | O_WRONLY, 0644);
dup2(fd, 1);
close(fd);
return 0;
}
while (*p && *p != '>') p++;
if (*p) { // 如果有重定向符 >
*p = '\0', p++;
if (*p == '>') ard = 1; // 追加重定向
else rd = 1; // 不是追加重定向
*cmd = NULL;
}
cmd++;
}
if (ard || rd) return -1;
else return 0;
} // 执行解析好的命令
int execute(char ***argv) {
pid_t pid;
int child_info = -1;
int fds[2], fd = 0; while (*argv) {
pipe(fds);
if ((pid = fork()) == -1) perror("fork");
else if (pid == 0) {
close(fds[0]);
dup2(fd, 0); if (*(argv + 1)) dup2(fds[1], 1);
else {
if (redirect(*argv) == -1) { // 重定向后无内容
printf("zsh: parse error near `\\n'\n");
exit(1);
}
} signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL); glob_t buf;
buf.gl_offs = buf.gl_pathc = 0; // 初始化 offset 和 path_count // 计算offset,即第一个命令和后续命令选项的个数
char **word = *argv;
word++, buf.gl_offs++; // 命令
while (*word && **word == '-') word++, buf.gl_offs ++ ; // 选项
// GLOB_NOCHECK的作用是没有匹配的文件名时,使用模式串。用在 grep txt 类的命令中对 "txt" 的处理上
if (*word) glob(*word++, GLOB_DOOFFS | GLOB_NOCHECK, NULL, &buf); // 第一个参数
while (*word) glob(*word++, GLOB_DOOFFS | GLOB_APPEND | GLOB_NOCHECK, NULL, &buf); // 后续参数 // 调用 glob() 会将 gl_pathv[] 的前offset个置为空,因此,要在调用 glob() 后对其赋值
word = *argv, buf.gl_offs = 0; // 重置
buf.gl_pathv[buf.gl_offs++] = *word++; // 命令
while (*word && **word == '-') buf.gl_pathv[buf.gl_offs++] = *word++; // 选项 if (buf.gl_pathc) execvp((*argv)[0], &buf.gl_pathv[0]); // 调用过glob()函数,即可能有*的情况
else execvp((*argv)[0], *argv); // 没调用过,则不会有*
perror("cannot execute command");
exit(1);
} else {
if (wait(&child_info) == -1) perror("wait");
close(fds[1]);
fd = fds[0];
argv++;
}
}
return child_info;
}

最新文章

  1. &lt;实训|第八天&gt;超级管理员管理linux用户行为权限附监控主机状态
  2. 我的PhoneGap安装配置经历
  3. my.cnf详解
  4. python学习笔记24(路径与文件 (os.path包, glob包))
  5. 使用 EPUB 制作数字图书
  6. BOM 浏览器对象模型学习
  7. configure.ac
  8. 信号处理——Hilbert端点效应浅析
  9. JAVA获取客户端IP地址和MAC地址
  10. Java基础知识回顾之五 ----- 多线程
  11. Python使用Plotly绘图工具,绘制饼图
  12. Html,CSS和盒子
  13. linux 常用命令积累
  14. Linux usb子系统(二) _usb-skeleton.c精析
  15. bzoj 3924 点分
  16. Spring boot之SpringApplicationBuilder,@@Configuration注解,@Component注解
  17. 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法
  18. 使用screen后台实时执行命令
  19. Asp.Net 远程连接Oracle数据库
  20. ZT 父子进程共享文件描述符

热门文章

  1. 电脑无法自动获取ip地址
  2. 有备无患!DBS高性价比方案助力富途证券备份上云
  3. WCH沁恒 CH37系列芯片选型以及常见问题的处理(CH376/CH378)
  4. [OpenCV实战]8 深度学习目标检测网络YOLOv3的训练
  5. 如何用 30s 给面试官讲清楚什么是 Token
  6. Openmp Runtime 库函数汇总(上)
  7. C 语言初学者必备开发工具——Dev-Cpp [ 图文安装教程 ]
  8. 狂神——SpringSecurity入门例子(设置不同用户访问权限)
  9. 刷题笔记——1267.A+B Problem
  10. Codeforces Round #845 (Div. 2) and ByteRace 2023 A-D