C语言模拟Shell

Linux大作业

newshell.c 

#include"command_comm.h"
#include"err_msg.h"
#include"file_isexist.h"
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<memory.h>
#include<math.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<sys/param.h>
#include<sys/times.h>
#include<sys/time.h>
#include<pwd.h>
#include<errno.h>
#include<time.h>
#include<fcntl.h>
#include<dirent.h>
#include<signal.h>
#include<grp.h>
#include<getopt.h>
#include<utmp.h>
/*和长度有关的宏定义*/
#define MAX_LINE 80//最大命令长度
#define MAX_NAME_LEN 100//最大用户名长度
#define MAX_PATH_LEN 1000//最大路径长度

/*more*/
#define PAGELEN 24
#define LINELEN 514

/*time*/
#define err_exit(m) {perror(m); exit(1);}

/*全局变量申明*/
extern char **environ;//必须用extern申明,否则会报错
char *cmd_array[MAX_LINE/2+1];//保存命令输入,就是原框架的char* args[]
int pipe_fd[2];//和管道有关的数组,作为pipe()的参数
int cmd_cnt;//命令中字符串的个数

void readcommand();//读取用户输入
int is_internal_cmd();//处理内部命令

int is_pipe();//分析管道命令
void do_redirection();//分析重定向,对内部命令无效

void welcome();//打印欢迎信息,带有颜色
void printprompt();//打印提示符,必须包含当前路径名
int getcommandlen();//计算命令长度
void do_pipe(int pos);//执行管道命令
void run_external_cmd(int pos);//执行外部命令
int is_bg_cmd();//判断是否有后台运行符号&

void myquit();//quit,退出myshell
void myexit();//exit,直接退出
void myclr();//clr

void print_continue_info();//打印"continue"相关信息

void mypwd();//pwd,打印当前工作目录
void myecho();//echo,必须支持重定向
void myecho_redirect();//带重定向的echo
void mytime();//time,和"date"类似
void myenviron();//environ,和env一样,必须支持重定向
void myenviron_redirect();//带重定向的environ
void mycd();//cd,切换到某个目录
void myhelp();//help,必须支持重定向
void myhelp_redirect();//带有重定向的help
void print_manual();//打印用户手册,是myhelp()的子函数
void print_cmdinfo(char* cmdname);//打印每个命令的帮助信息,是myhelp()的子函数
void myexec();//exec,开启一个新进程并替换当前进程
void mytest();//test,检查文件类型,支持-l,-b,-c,-d四个选项
void myumask();//umask,查看默认的umask值或者重置umask
void myjobs();//jobs,查看正在运行的=进程
void myfg(pid_t pid);//fg,切换进程到前台
void mybg(pid_t pid);//bg,切换进程到后台
void mybatch();//实现命令批处理,一次性执行保存在文件里的命令
void mydir();//dir,显示当前目录下的所有文件
void mydir_redirect();//带有重定向的dir


/***************************功能:wc ********************************/
struct wc_option
{
    unsigned char           c;      /*  显示字节数  */
    unsigned char           l;      /*  显示行数    */
    unsigned char           w;      /*  显示单词数  */
};

struct wc_count
{
    unsigned int            c;
    unsigned int            l;
    unsigned int            w;
};

struct wc_option            g_option;
struct wc_count             g_count;

static int char_is_in(char c, const char *str, size_t len)
{
    size_t                  i;

    for(i = 0; i < len; ++i)
        if(str[i] == c)
            return 1;

    return 0;
}

static unsigned int
getwordcount(char *buf)
{
    const char              *word_sep = " \r\f\t\v\n";
    unsigned int            word_count = 0;
    char                    *token;
    size_t                  total_size = strlen(buf);

    if(buf == NULL || buf[0] == 0)
        return 0;
    /*  去前面的无关字符    */
    {
        while(total_size > 0 && char_is_in(buf[0], word_sep, strlen(word_sep)))
        {
            --total_size;
            buf++;
        }

    }

    /*  去掉后面的无关字符  */
    {
        while(total_size > 0 && char_is_in(buf[total_size], word_sep, strlen(word_sep)))
        {
            buf[total_size] = 0;
            --total_size;
        }
    }

    token = strtok(buf, word_sep);
    while(token)
    {
        ++word_count;
        token = strtok(NULL, word_sep);
    }

    return word_count;
}

static void
pr_wc(const char *file)
{
    if(g_option.c == 0 && g_option.l == 0 && g_option.w == 0)
    {
        printf("%u\t%u\t%u\t%s\n", g_count.l, g_count.w, g_count.c, file);
        return;
    }

    if(g_option.l != 0)
        printf("%u\t", g_count.l);
    if(g_option.w != 0)
        printf("%u\t", g_count.w);
    if(g_option.c != 0)
        printf("%u\t", g_count.c);

    printf("%s\n", file);
}

static int
wc(const char *file)
{
    FILE            *fp;
    char            buf[MAX_LINE_BUF_SIZE];

    if(!file_isreg(file))
    {
        pr_msg("file [%s] is not access or is not a simple file\n", file);
        return 1;
    }

    if((fp = fopen(file, "r")) == NULL)
    {
        pr_msg("open file [%s] error [%s]\n", file, strerror(errno));
        return 1;
    }

    memset(&g_count, 0, sizeof(g_count));
    while(fgets(buf, MAX_LINE_BUF_SIZE, fp) != NULL)
    {
        ++g_count.l;
        g_count.c += strlen(buf);
        g_count.w += getwordcount(buf);
    }


    pr_wc(file);
    return 0;
}

/******************************************************************/

/*******************功能:ls -l *************************************/
void show_file_info(char* filename, struct stat* info_p)
{
    char* uid_to_name(), *ctime(), *gid_to_name(), *filemode();
    void mode_to_letters();
    char modestr[11];

    mode_to_letters(info_p->st_mode, modestr);

    printf("%s", modestr);
    printf(" %4d", (int) info_p->st_nlink);
    printf(" %-8s", uid_to_name(info_p->st_uid));
    printf(" %-8s", gid_to_name(info_p->st_gid));
    printf(" %8ld", (long) info_p->st_size);
    printf(" %.12s", 4 + ctime(&info_p->st_mtime));
    printf(" %s\n", filename);
}

void mode_to_letters(int mode, char str[])
{
    strcpy(str, "----------");

    if (S_ISDIR(mode))
    {
        str[0] = 'd';
    }

    if (S_ISCHR(mode))
    {
        str[0] = 'c';
    }

    if (S_ISBLK(mode))
    {
        str[0] = 'b';
    }

    if ((mode & S_IRUSR))
    {
        str[1] = 'r';
    }

    if ((mode & S_IWUSR))
    {
        str[2] = 'w';
    }

    if ((mode & S_IXUSR))
    {
        str[3] = 'x';
    }

    if ((mode & S_IRGRP))
    {
        str[4] = 'r';
    }

    if ((mode & S_IWGRP))
    {
        str[5] = 'w';
    }

    if ((mode & S_IXGRP))
    {
        str[6] = 'x';
    }

    if ((mode & S_IROTH))
    {
        str[7] = 'r';
    }

    if ((mode & S_IWOTH))
    {
        str[8] = 'w';
    }

    if ((mode & S_IXOTH))
    {
        str[9] = 'x';
    }
}

char* uid_to_name(uid_t uid)
{
    struct passwd* getpwuid(),* pw_ptr;
    static char numstr[10];

    if((pw_ptr = getpwuid(uid)) == NULL)
    {
        sprintf(numstr,"%d",uid);

        return numstr;
    }
    else
    {
        return pw_ptr->pw_name;
    }
}

char* gid_to_name(gid_t gid)
{
    struct group* getgrgid(),* grp_ptr;
    static char numstr[10];

    if(( grp_ptr = getgrgid(gid)) == NULL)
    {
        sprintf(numstr,"%d",gid);
        return numstr;
    }
    else
    {
        return grp_ptr->gr_name;
    }
}

void dostat(char* filename)
{
    struct stat info;

    if (stat(filename, &info) == -1)
    {
        perror(filename);
    }
    else
    {
        show_file_info(filename, &info);
    }
}

void do_ls(char dirname[])
{
    DIR* dir_ptr;
    struct dirent* direntp;

    if ((dir_ptr = opendir(dirname)) == NULL)
    {
        fprintf(stderr, "ls2: cannot open %s \n", dirname);
    }
    else
    {
        while ((direntp = readdir(dir_ptr)) != NULL)
        {
            dostat(direntp->d_name);
        }

        close(dir_ptr);
    }
}

/*****************************************************************/


/*************************cat,more*******************************/
void do_more(FILE *fp)
{
    char line[LINELEN];
    //int see_more();
    int reply;
    int number_line = 0;
    while(fgets(line, LINELEN, fp) != NULL)
    {
        if(number_line == PAGELEN)
        {
            reply = see_more();
            if(reply == 0)
              break;
            number_line -= reply;
        }
        if( fputs(line, stdout) == EOF)
          exit(1);
        number_line ++;
    }
}

int see_more()
{
    int c;
    printf("\033[7m more? \033[m");
    while( (c = getchar()) != EOF )
    {
        if(c == 'q')
          return 0;
        if(c == ' ')
          return PAGELEN;
        if(c == '\n')
          return 1;
    }
    return 0;
}

/*****************************************************************/


/**********************who instruction*****************************/
int pr_who()
{
    struct utmp         *u;
    char                timebuf[128];

    // getutent()用来从utmp 文件(/var/run/utmp)中读取一项登录数据, 该数据以utmp 结构返回。
    // 第一次调用时会取得第一位用户数据, 之后每调用一次就会返回下一项数据, 直到已无任何数据时返回NULL。
    while((u = getutent()))
    {
        /*  去除一些不需要显示的项  */
        if(u->ut_type != USER_PROCESS)
            continue;
        ctime_r(&(u->ut_tv.tv_sec), timebuf);
        if(timebuf[0] != 0)
            timebuf[strlen(timebuf)-1] = 0; /*去掉'\n'*/
        printf("%-12s%-12s%-20.20s  (%s)\n",
               u->ut_user,
               u->ut_line,
               timebuf,
               u->ut_host);
    }

    endutent();
    return 1;
}
/*****************************************************************/


/********************将指令写入历史文件*****************************/
int CommWriteHisFile(char *comm)    //将command指令存入history文件
{
    FILE *fp = NULL;
    if((fp=fopen("history.txt","at+"))==NULL)
    {
        printf("cannot open file\n");
        return 0;
    }
    fputs(comm,fp);
    fputs("\n",fp);
    //putchar(str);
    fclose(fp);
    fp = NULL;
    return 0;
}
/*****************************************************************/


/********************从历史文件中读出指令*****************************/
void FileReadComm()    //读取文件中的指令
{
FILE *stream;
   char line[10];

   if( (stream = fopen( "history.txt", "r" )) != NULL )
   {
       while(fgets(line,10,stream)!=NULL)
       {
         printf( "%s", line);
       }
       printf("\n");
      fclose( stream );
   }
}
/*****************************************************************/

void readcommand(){//用来读取用户输入
    int exit_status = 0;
    int cnt=0;//记录cmd_array[]中字符串的个数
    char str[MAX_LINE]; //用户输入的字符串
    char* helper;
    memset(cmd_array,0,MAX_LINE/2+1);//每次必须清空!
    //cmd_array
    fgets(str,MAX_LINE,stdin);//用fgets代替gets,因为gets不检查溢出,比较危险
    if(str[strlen(str)-1]=='\n'){
        str[strlen(str)-1]='\0';//fgets会补'\n',这里必须把'\n'替换成'\0'
    }
    helper=strtok(str," ");//用空格分割这个命令
    while(helper!=NULL){//将分割后得到的结果写进cmd_array
            cmd_array[cnt]=(char*)malloc(sizeof(*helper));
            strcpy(cmd_array[cnt++],helper);//注意:即便直接回车cmd_cnt也是1
            helper=strtok(NULL," "); //返回被空格分开的下一个单词的首地址
    }
    cmd_cnt=cnt;//cmd_cnt的值就是cnt的值
}

int is_internal_cmd(){
    //这个函数用来解析内部命令
    //根据不同的结果来调用不同函数来达到目的
    if(cmd_array[0]==NULL){//如果没有命令(只是回车)
        return 0;//返回0使得主函数的continue不执行
    }
    else if(strcmp(cmd_array[0],"ls")==0){
        CommWriteHisFile("ls");
        printf("--------------rewrite\n");
        do_ls(".");
        return 1;
    }
    else if(strcmp(cmd_array[0],"cat")==0){//cat和more功能
        CommWriteHisFile("cat");
        printf("--------------rewrite\n");
        FILE 
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值