Linux-linux下实现模拟shell命令行代码,编译通过,实现不了功能

Linux-linux下实现模拟shell命令行代码,编译通过,实现不了功能

泛泛之交 发布于 2017-08-10 字数 3504 浏览 1238 回复 1

代码如下:

#include<stdio.h>
#include<stdlib.h>
#define EOL 1/*行结束*/
#define ARG 2
#define AMPERSAND 3
#define SEMICOLON 4
#define MAXARG 512/*命令行参数最大值*/
#define MAXBUF 512/*输入行的最大长度*/
#define FOREGROUND 0
#define BACKGROUND 1

int inarg(char c);
void procline();
int runcommand(char **cline,int where);

static char inpbuf[MAXBUF],tokbuf[2*MAXBUF],*ptr=inpbuf,*tok=tokbuf;
/**************************************************
*
*
**************************************************/
int userin(char *p)
{
int c,count;

ptr=inpbuf;
tok=tokbuf;

printf("%s",p);
for(count=0;;)
{
if((c=getchar())==EOF)
return (EOF);
if(count<MAXBUF)
inpbuf[count++]=c;
if(c=='n'&&count<MAXBUF){
inpbuf[count]='';
return(count);
}
}
if(c=='n'){
printf("smallsh:input line too longn");
count=0;
printf("%s",p);
}

}

gettok(char outptr[])
{
int type;
outptr=tok;
/*去除空白字符*/
for(;*ptr==' '||*ptr=='t';ptr++)

{*tok++=*ptr;}
switch(*ptr++)
{
case 'n':
type=EOL;break;
case '&':
type=AMPERSAND;break;
case ';':
type=SEMICOLON;break;
default:
type=ARG;
while(inarg(*ptr))
{*tok++=*ptr++;}
}
*tok++='';
return (type);
}

static char special[]={' ','t','*',';','n',''};
int inarg(char c)
{
char *wrk;
for(wrk=special;*wrk!='';wrk++)
{
if(c==*wrk)
return (0);
}
return (1);

}

void procline()
{
char *arg[MAXARG+1];
int toktype;
int narg;
int type;

for(narg=0;;){
switch(toktype=gettok(arg[narg])){
case ARG:
if(narg<MAXARG)
narg++;
break;
case EOL:
case SEMICOLON:
case AMPERSAND:
type=(toktype==AMPERSAND)?BACKGROUND:FOREGROUND;
if(narg!=0){
arg[narg]=NULL;
runcommand(arg,type);
}
if(toktype==EOL)
return;
narg=0;
break;
}
}
}

int runcommand(char **cline,int where)
{
int pid,exitstat,ret;

if((pid=fork())<0)
{
perror("fork fail");
return (-1);
}
if(!pid)
{
execvp(*cline,cline);
perror("*cline");
exit(127);
}
/*父进程代码*/
/*后台进程代码*/
if(where==BACKGROUND){
printf("[process id %d]n",pid);
return (0);
}
/*前台进程代码*/
while((ret=wait(&exitstat))!=pid && ret!=-1);
return (ret==-1?-1:exitstat);

}

char *prompt="command>";

main()
{
while(userin(prompt)!=EOF)
procline();
}

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清晨说ぺ晚安 2017-10-01 1 楼

可以参考下我的shell简单实现~

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "pipe.h"
#include "redirect.h"

#define MAX_CMD 1024
#define MAX_HOSTNAME 1024
#define MAX_ARG 32
#define MAX_ARGS 32

void
parse_args(const char *cmd, char *args[]);
int
internal_cmd(char *args[]);
void
exec_cmd(char *args[]);
void
show_prompt();
void
get_hostname();

char hostname[MAX_HOSTNAME] = {''};

int
main(int argc, char *argv[])
{
char cmd[MAX_CMD] = {''};
char *args[MAX_ARGS] = {NULL};
/* 将CTRL+C信号处理方式设置为忽略 */
signal(SIGINT, SIG_IGN);

get_hostname();
show_prompt();
while(fgets(cmd, sizeof(cmd), stdin)) {
parse_args(cmd, args);
if(!internal_cmd(args)) {
exec_cmd(args);
}
show_prompt();
}
printf("n");
return 0;
}

void
parse_args(const char *cmd, char *args[])
/*
* 将长串命令行按空格分割为字符串数组
*/
{
/* 清理args数组 */
int i;
for(i = 0; i < MAX_ARGS; i++) {
if(args[i] != NULL) {
free(args[i]);
args[i] = NULL;
}
}

/* 分配args */
int idx = -1;
int offset = 0;
for(i = 0; i < strlen(cmd); i++) {
switch(cmd[i]) {
case ' ' :
case 'n':
case '':
offset = 0;
break;
default:
if(offset == 0) {
idx++;
if((args[idx] = (char *)malloc(MAX_ARG)) == NULL) {
perror("malloc()");
exit(errno);
}
memset(args[idx], '', MAX_ARG);
}
args[idx][offset++] = cmd[i];
break;
}
}
}

int
internal_cmd(char *args[])
/*
* 判断是否为shell内部命令,如果是则执行对应内部命令
*/
{
if(strcmp(args[0], "exit") == 0) {
if(args[1] == NULL) {
exit(0);
} else {
exit(atoi(args[1]));
}
return 1;
}
if(strcmp(args[0], "cd") == 0) {
const char *path;
if(args[1] == NULL) {
path = getenv("HOME");
} else {
path = args[1];
}
if(-1 == chdir(path)) {
perror("cd");
} else {
setenv("PWD", path, 1);
}
return 2;
}
return 0;
}

void
exec_cmd(char *args[])
/*
* 运行输入的shell命令
*/
{
pid_t pid;
int status;
if((pid = fork()) == -1) {
perror("fork()");
exit(errno);
} else if(pid == 0) {
/* 将CTRL+C信号处理方式设置为默认 */
signal(SIGINT, SIG_DFL);
parse_pipe(args);
parse_redirect(args);
execvp(args[0],args);
perror("execvp()");
exit(errno);
}
if(-1 == waitpid(pid, &status, 0)) {
perror("waitpid()");
exit(errno);
}
}

void
show_prompt()
/*
* 显示shell提示符
*/
{
printf("%s", getenv("LOGNAME"));
printf("@%s", hostname);
printf(":");
printf("%s", getenv("PWD"));
printf("$ ");
}

void
get_hostname()
/*
* 获取主机名字的字符串
*/
{
FILE *fp;
int len;
if((fp = fopen("/etc/hostname", "r")) == NULL) {
perror("fopen()");
exit(errno);
}
if(fgets(hostname, MAX_HOSTNAME, fp) == NULL) {
perror("fgets()");
}
fclose(fp);
len = strlen(hostname);
if(hostname[len - 1] == 'n') {
hostname[len - 1] = '';
}
}

 #include "pipe.h"

int p[2] = {-1, -1};

void
parse_pipe(char *args[])
/*
* 解析命令行参数中的管道参数
*/
{
int i, start = 0;
int have_pipe = 0;
for(i = 0; args[i] != NULL; i++) {
if(strcmp(args[i], "|") == 0) {
have_pipe = 1;
make_pipe(args, start, i);
start = i + 1;
}
}
if(have_pipe) {
for(i = 0; i < start; i++) {
free(args[i]);
args[i] = NULL;
}
for(i = 0; ; i++) {
if(args[start] == NULL) {
break;
}
args[i] = args[start];
args[start++] = NULL;
}
}
return;
}

void
make_pipe(char *args[], int start, int max)
/*
* 建立管道
*/
{
pid_t pid;
args[max] = NULL;
if(pipe(p) == -1) {
perror("pipe()");
exit(errno);
}
if(-1 == dup2(p[0], STDIN_FILENO)) {
perror("dup2()");
exit(errno);
}
if((pid = fork()) == -1) {
perror("fork()");
exit(errno);
} else if(pid == 0) {
if(-1 == dup2(p[1], STDOUT_FILENO)) {
perror("dup2()");
exit(errno);
}
close(p[0]);
close(p[1]);
parse_redirect(args);
execvp(args[start], &args[start]);
perror("execvp()");
exit(errno);
}
close(p[0]);
close(p[1]);
}

 #include "redirect.h"

void
parse_redirect(char *args[])
/*
* 解析命令行参数中的重定向参数
*/
{
int fd;
int i, j;
int fd_to_redirect, flags;
int need_redirect;

for(i = 0; args[i] != NULL; i++) {
flags = 0;
need_redirect = 1;
if(strcmp(args[i], "<") == 0) {
fd_to_redirect = STDIN_FILENO;
flags = O_RDONLY;
} else if(strcmp(args[i], ">") == 0) {
fd_to_redirect = STDOUT_FILENO;
flags = O_TRUNC|O_WRONLY|O_CREAT;
} else if(strcmp(args[i], ">>") == 0) {
fd_to_redirect = STDOUT_FILENO;
flags = O_APPEND|O_WRONLY|O_CREAT;
} else if(strcmp(args[i], "2>") == 0) {
fd_to_redirect = STDERR_FILENO;
flags = O_TRUNC|O_WRONLY|O_CREAT;
} else if(strcmp(args[i], "2>>") == 0) {
fd_to_redirect = STDERR_FILENO;
flags = O_APPEND|O_WRONLY|O_CREAT;
} else {
need_redirect = 0;
}

if(need_redirect) {
if(fd_to_redirect != STDIN_FILENO) {
if((fd = open(args[i + 1], flags, S_IRUSR | S_IWUSR)) == -1) {
perror("open()");
exit(errno);
}
} else {
if((fd = open(args[i + 1], flags)) == -1) {
perror("open()");
exit(errno);
}
}
if(-1 == dup2(fd, fd_to_redirect)) {
perror("dup2()");
exit(errno);
}
close(fd);

args[i] = NULL;
args[i + 1] = NULL;
for(j = i; args[j + 2] != NULL; j++) {
args[j] = args[j + 2];
args[j + 2] = NULL;
}
}
}
}