- 论坛徽章:
- 0
|
服务器server端平台:Redhat9 、gcc-3.2.2、vim-6.1.320
客服端平台client: windows xp、超级终端
实现功能:常用内部命令,外部命令、重定向、管道、历史命令记录
Shell是系统的用户,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。
实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核。不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序。Shell编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编写的Shell程序与其他应用程序具有同样的效果。本程序就是模拟redhat9终端实现远程shell命令解析器
一、main函数模块
//===============================================================================
//文件名称:main.c
//功能描述:用socket实现基于tcp/ip的远程shell命令解析器
//包含文件:strsplit.h command.h clicmd.h redirect.h
//维护日期:
//================================================================================
#include stdio.h>
#include stdlib.h>
#include string.h>
#include unistd.h>
#include sys/socket.h>
#include netinet/in.h>
#include arpa/inet.h>
#include fcntl.h>
#include "strsplit.h"
#include "command.h"
#include "clicmd.h"
#include "redirect.h"
//=================================================================================
//函数名称:main
//功能描述:实现远程shell的命令解析器
//函数参数:
//返回值:
//==================================================================================
int main(int argc,char *argv[])
{
char recvbuf[2048];
int sockfd;
struct sockaddr_in servAddr;
unsigned short port=8000;
char mycmd[20];
if(argc>1)
{
port=atoi(argv[1]);
}
printf("tcp server start at port %d\n",port);
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd0)
{
perror("Invalid socket\n");
exit(1);
}
bzero(&servAddr,sizeof(servAddr));//服务器地址初始化
servAddr.sin_family=AF_INET;//设置协议为IPv4
servAddr.sin_port=htons(port);//设置服务器端口
servAddr.sin_addr.s_addr=htonl(INADDR_ANY); //设置服务器ip地址为本机ip
printf("Binding server to port %d\n",port);
if(bind(sockfd,(struct sockaddr*)&servAddr,sizeof(struct sockaddr))!=0)//ip邦定
{
close(sockfd);
perror("binding err!\n");
exit(1);
}
if(listen(sockfd,1)!=0) //开始端口侦听
{
close(sockfd);
perror("listen err!\n");
exit(1);
}
printf("waiting client...\n");
while(1)
{
char cliIp[INET_ADDRSTRLEN];
size_t recvLen;
struct sockaddr_in cliAddr;
size_t cliAddrLen=sizeof(cliAddr);
int connfd=accept(sockfd,(struct sockaddr*)&cliAddr,&cliAddrLen);
if(connfd0)
{
close(sockfd);
perror("accept err!\n");
exit(1);
}
inet_ntop(AF_INET,&cliAddr.sin_addr.s_addr,cliIp,INET_ADDRSTRLEN);
printf("client ip=%s\n",cliIp);
memset(mycmd,0,sizeof(mycmd));
while((recvLen=read(connfd,recvbuf,2048))>0)
{
if(strstr(recvbuf,"\n"))
{
//strcat(mycmd,"\r\n");
clicmd(mycmd); //执行client端命令
strcat((outbuf+strlen(outbuf)),"\rMYSHELL>>");
write(connfd,outbuf,strlen(outbuf));
memset(mycmd,0,sizeof(mycmd));
memset(recvbuf,0,2048);
memset(outbuf,0,2048);
}
strcat(mycmd,recvbuf);//获得命令行
}
close(connfd);//命令执行完毕,关闭连接
printf("client closed\n");
}
close(sockfd);
return 0;
}
二、命令执行模块
#ifndef __clicmd_h_
#define __clicmd_h_
#include "command.h"
#include "strsplit.h"
#include "redirect.h"
extern void clicmd(char *clicmd);
#endif
//========================================================================
//函数名称: clicmd
//功能描述: 判断输入命令的类型,并执行命令
//参 数: clicmd 指向输入命令指针变量
//返 回 值: 无
//=========================================================================
#include "clicmd.h"
void clicmd(char *clicmd)
{
char *cmd_option[10];
int cmd_type=0;
//fgets(inputbuf,sizeof(inputbuf),stdin);
if(strstr(clicmd,"\n"))
{
clicmd[strlen(clicmd)-1]='\0';
}
cmd_type=get_cmd_type(clicmd,cmd_option);//提取命令信息
if(!cmd_type)
{
iner_cmd_addr(cmd_option);
}
else if(cmd_type==1)
{
printf("redirect\n");
redirect_rewrite(cmd_option);
printf("after redirect\n");
}
else if(cmd_type==2)
{
redirect_rewrite(cmd_option);
}
else if(cmd_type==4)
{
comm_cmd_addr(cmd_option);
}
else
{
printf("this cmd is not finshed\n");
}
}
三、命令分析模块
#ifndef __command_h_
#define __command_h_
#include stdio.h>
#include stdlib.h>
#include string.h>
#include unistd.h>
#include sys/wait.h>
#include sys/types.h>
extern char outbuf[2048];
extern int get_cmd_type(char *inputbuf,char *cmd_option[]);
extern void iner_cmd_addr(char *cmd_option[]);
extern void comm_cmd_addr(char *cmd_option[]);
#endif
//==========================================================================
//模块名称: shell命令模块
//功能描述:判断输入的命令信息
//
//==========================================================================
#include "command.h"
#include "strsplit.h"
char cd_path_his[50];
char outbuf[2048];
//========================================================================================================
//function name : getcmd_info
//description: split input command and get it's info
//parameter:
//return value: int,the command's type
//========================================================================================================
int get_cmd_type(char *inputbuf,char *cmd_option[])
{
int cmd_type;
if(inputbuf==NULL)
{
perror("in function get_cmd_tpye() error!\n");
exit(-1);
}
if((strstr(inputbuf,"cd")!=NULL) || (strstr(inputbuf,"exit")!=NULL)||(strstr(inputbuf,"jobs")!=NULL)||(strstr(inputbuf,"bg")!=NULL)||(strstr(inputbuf,"fg")!=NULL))
{
cmd_type=0; //内部命令
strsplit(inputbuf," ",cmd_option);
return cmd_type;
}
else if( strstr(inputbuf,">") )//rewrite方式重定向
{
cmd_type=1;
strsplit(inputbuf,">",cmd_option);
return cmd_type;
}
else if( strstr(inputbuf,">>"))//append方式重定向
{
cmd_type=2;
strsplit(inputbuf,">>",cmd_option);
return cmd_type;
}
else if( strstr(inputbuf,"|") )//pipe 管道命令
{
cmd_type=3;
strsplit(inputbuf,"|",cmd_option);
return cmd_type;
}
else //普通命令
{
cmd_type=4;
strsplit(inputbuf," ",cmd_option);
return cmd_type;
}
return -1;
}
//==============================================================================================================
//function name: iner_cmd_addr
//description: execute iner command address
//parameter:
//return value: null
//==============================================================================================================
void iner_cmd_addr(char *cmd_option[])
{
char temp[50];
char path[50];
char cmdbin[20];
int fd[2];
int i=0;
pid_t pid;
printf("in 66 line");
strcpy(cmdbin,cmd_option[0]);
printf("in 68 line");
if(pipe(fd)0)
{
perror("pipe error!\n");
exit(1);
}
if((pid=fork())0)
{
perror("fork error in comm_cmd addr\n");
exit(-1);
}
if(pid==0)
{
close(fd[0]);
dup2(fd[1],1);
if(strcmp(cmdbin,"cd")==0)
{
memset(temp,0,50);
memset(path,0,50);
if(cmd_option[1]!=NULL)
strcpy(path,cmd_option[1]);
// strcpy(cd_cmd_his,cd_cur_path);
getcwd(temp,sizeof(temp));
if(strcmp(path,"~")==0)
{
strcpy(path,"/home");
}
else if(strcmp(path,"-")==0)
{
strcpy(path,cd_path_his);
}
//printf("path=%s",path);
chdir(path);
strcpy(cd_path_his,temp);
}
else if(strcmp(cmdbin,"jobs")==0)
{
;
}
else if(strcmp(cmdbin,"bg")==0)
{
;
}
else if(strcmp(cmdbin,"fg")==0)
{
;
}
else if(strcmp(cmdbin,"exit")==0)
{
printf("Bye bye!\n");
exit(1);
}
}
else
{
close(fd[1]);
waitpid(pid,NULL,0);
while(read(fd[0],outbuf+i,1)!=0)
{
if(outbuf=='\n')
{
outbuf='\r';
i++;
outbuf='\n';
}
i++;
}
}
}
//==============================================================================================================
//function name: comm_cmd_addr
//description:
//parameter:
//return value:
//=========================================================================================================
void comm_cmd_addr(char *cmd_option[])
{
pid_t pid;
char cmdbin[20];
int fd[2];
int i=0;
strcpy(cmdbin,cmd_option[0]);
if(pipe(fd)0)
{
perror("pipe error!\n");
exit(1);
}
if((pid=fork())0)
{
perror("fork error in comm_cmd addr\n");
exit(-1);
}
if(0==pid)
{
close(fd[0]);
dup2(fd[1],1);
execvp(cmdbin,cmd_option);
}
else
{
close(fd[1]);
//dup2(fd[0],0);
waitpid(pid,NULL,0);
while(read(fd[0],outbuf+i,1)!=0)
{
if(outbuf=='\n')
{
outbuf='\r';
i++;
outbuf='\n';
}
i++;
}
}
}
三、重定向模块
#ifndef __redirect_h_
#define __redirect_h_
#include unistd.h>
#include stdio.h>
#include stdlib.h>
#include string.h>
#include sys/wait.h>
#include fcntl.h>
#include sys/stat.h>
#include sys/types.h>
extern char outbuf[2048];
extern int redirect_rewrite(char *cmd_option[]);
extern int redirect_append(char *cmd_option[]);
#endif
#include "redirect.h"
#include "strsplit.h"
//=================================================================================================================
//function name: redirect()
//function description: redirect oupput to filename
//function parameter: filename
//return value: int, file fd
//==================================================================================================================
int redirect_rewrite(char *cmd_option[])
{
int fd,i=1;
char cmdbin[20];
char *rewrite[10];
pid_t pid;
strcpy(cmdbin,cmd_option[0]);
strsplit(cmdbin," ",rewrite);
if((pid=fork())0)
{
perror("fork error!\n");
exit(1);
}
if(0==pid)
{
while(cmd_option!=NULL)
{
if((fd=open(cmd_option[i++],O_CREAT|O_RDWR|S_IREAD))0)
{
perror("open file error\n");
exit(0);
}
}
dup2(fd,1);
execvp(cmdbin,rewrite);
printf("dgsfs");
}
else
{
i=0;
waitpid(pid,NULL,0);
printf("wait rewrite\n");
memset(outbuf,0,sizeof(outbuf));
while(read(fd,outbuf+i,1)>0)
{
if(outbuf=='\n')
{
outbuf='\r';
i++;
outbuf='\n';
}
i++;
printf("i=%d\n",i);
}
}
return 1;
}
//==================================================================================================================
//function name:
//description:
//parameter:
//return value:
//==================================================================================================================
int redirect_append(char *cmd_option[])
{
int fd,i=1;
pid_t pid;
char cmdbin[20];
char *append[10];
strcpy(cmdbin,cmd_option[0]);
strsplit(cmdbin," ",append);
trim(cmdbin);
if((pid=fork())0)
{
perror("fork error\n");
exit(0);
}
if(0==pid)
{
while(cmd_option!=NULL)
{
if((fd=open(cmd_option[i++],O_CREAT|O_RDWR|O_APPEND|S_IREAD))0)
{
perror("open file error\n");
exit(1);
}
}
dup2(fd,1);
execvp(cmdbin,append);
}
else
{
i=0;
waitpid(pid,NULL,0);
while(read(fd,outbuf+i,1)>0)
{
if(outbuf=='\n')
{
outbuf='\r';
i++;
outbuf='\n';
}
i++;
}
}
return 1;
}
四、预处理模块
#ifndef __strsplit_h__
#define __strsplit_h__
#include stdio.h>
#include stdlib.h>
#include string.h>
extern char *trim(char *string);
extern int strsplit(char *split,const char *sour,char *result[]);
#endif
#include "strsplit.h"
char *trim(char *string)
{
char *phead=string;
char *ptail;
if(string==NULL)
{
perror("del space error!\n");
exit(0);
}
ptail=string+strlen(string)-1;
while((phead!=NULL) && (*(phead)==' '))
{
*(phead)='\0';
phead++;
}
while((ptail!=NULL) && (*(ptail)==' '))
{
*(ptail)='\0';
ptail--;
}
return phead;
}
//==============================================================================================================
//function name: strsplit
//function description: split a string
//function parameter:
//return value: int ,the segments of result
//===============================================================================================================
int strsplit(char *split,const char *sour,char *result[])
{
char *pos,*start;
int i=0,count=0;
//split=trim(split);
pos=start=split;
while(pos!=NULL)
{
pos=strstr(start,sour);//ls |
if(pos==NULL)
{
result=start;
count++;
break;
}
*pos='\0';
if(*start)
{
result=start;
i++;
count++;
}
start=pos+strlen(sour);
start=trim(start);
}
result[count]=NULL;
return count;
}
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/94835/showart_1919067.html |
|