欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux C语言 shell

程序员文章站 2022-03-04 15:52:57
...
#include "wrapper.h"
#include <time.h>
int MAXARGS=10;
int parseline(char *buf, char **argv) { 
 char *delim; /* 指向第1个分隔符 */
 int argc; /* 字符串数组args中命令行参数个数 */
 int bg; /* 后台作业 */ 
 buf[strlen(buf)-1] = ' '; /* 用空格替换行末换行符 */ 
 while (*buf && (*buf == ' ')) /* 删除行首空格 */
 buf++; /* 创建 argv数组 */
 argc = 0;
 while ((delim = strchr(buf, ' '))) {
   argv[argc++] = buf; *delim = '\0'; 
   buf = delim + 1;
   while (*buf && (*buf == ' ')) /* 忽略空格,查找下一个参数起始位置 */ 
   buf++; 
  }
 argv[argc] = NULL;
if (argc == 0) /* 忽略空行*/
 return 1; /* 命令是否应在后台执行 */ 
if ((bg = (*argv[argc-1] == '&')) != 0) 
argv[--argc] = NULL; 
return bg;
 }

void execute(char *cmdline) { 
char *argv[MAXARGS]; /* execve()参数表 */ 
char buf[MAXLINE]; /* 保存修改后的命令行 */
 int bg; /* 是否在后台执行 */ 
int fd;
pid_t pid; /* 子进程PID */ 
strcpy(buf, cmdline);
 bg = parseline(buf, argv); /* 解析命令行 */ 
if (argv[0] == NULL) return; /* 如果第1个参数为空,则忽略命令 */ 
if (!builtin_command(argv))
 { if ((pid = fork()) == 0) 
{ /* 创建子进程 */ 
if(!strcmp(argv[3],">>")||!strcmp(argv[3],">")){
fd=open(argv[4],O_RDWR,0);     /*重定向功能*/
dup2(fd,1);              /*execvp的输出在1而不在0,把1指向fd*/
}
if (execvp(argv[0], argv) < 0) { printf("%s: Command not found.\n", argv[0]); 
close(fd);     /*记得保存*/   /*agrv[0][1]...是解析好的各参数*/ /*execvp不用bin目录的路径*/
exit(0); 
}
 }if (!bg) { /* 前台执行 */ int status;
if (waitpid(pid, &status, 0) < 0) perror("waitpid error");
 }
else printf("%d %s", pid, cmdline);
 }
return; 
}

int builtin_command(char **argv) { 
if (!strcmp(argv[0], "exit")) /* 内置命令exit */ exit(0); 
if (!strcmp(argv[0], "logout")) /* 内置命令logout */ exit(0); 
if (!strcmp(argv[0], "&")) /* 忽略由&开始的命令串 */
 return 1; 
return 0; /* 非内置命令 */ 
}


int main() { 
char cmdline[MAXLINE]; /* 命令行缓冲区 */ 
while (1) { printf("%% ");  /*一个百分号是转义的,得两个*/
fgets(cmdline, MAXLINE, stdin); /* 读取命令行 */ 
if (feof(stdin)) exit(0); execute(cmdline); 
/* 执行命令 */ }
 }

想说的都在注释里