Chinaunix首页 | 论坛 | 博客
  • 博客访问: 93850
  • 博文数量: 20
  • 博客积分: 777
  • 博客等级: 军士长
  • 技术积分: 287
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-22 18:53
文章存档

2011年(1)

2009年(19)

我的朋友

分类: LINUX

2009-05-05 20:00:28

服务器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(sockfd<0)
    {
        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(connfd<0)
        {
            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[i]=='\n')
                    {
                        outbuf[i]='\r';
                        i++;
                        outbuf[i]='\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[i]=='\n')
                    {
                        outbuf[i]='\r';
                        i++;
                        outbuf[i]='\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[i]!=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[i]=='\n')
                    {
                        outbuf[i]='\r';
                        i++;
                        outbuf[i]='\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[i]!=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[i]=='\n')
                    {
                        outbuf[i]='\r';
                        i++;
                        outbuf[i]='\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[i]=start;
            count++;
            break;
        }
        
        *pos='\0';
        if(*start)
        {
            result[i]=start;
            i++;
            count++;
        }
        start=pos+strlen(sour);
        start=trim(start);    
    }
    
    result[count]=NULL;
    return count;
}

阅读(5015) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~