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

C语言实现Linux代码解释器

程序员文章站 2022-03-04 15:53:51
...

一.设计目的:熟悉Linux编程环境,加强对Linux命令的理解及函数的运用

二.设计内容:在Linux环境下模拟实现简单命令解释器(即定义一个命令使它具有Linux中某些命令的功能)
例如:定义mydir使它具有dir 的功能
即在Linux环境中 $ mydir 和 $dir 作用一样
就实现了dir命令的解释。
(1)要求实现的基本命令包括:
定义 mypwd 具有 pwd //显示当前所在目录的路径名
定义 mylist 具有 list //列出指定目录名中的所有目录及文件
定义 mycd 具有 cd //改变当前工作目录
定义 mymkdir 具有 mkdir //新建目录
定义 myrmdir 具有 rmdir //删除目录
定义 myexit 具有 exit //退出命令解释程序
(2)可选做的扩展命令包括:
定义 myrename 具有 rename <旧文件名> <新文件名> //重命名一个文件或目录
定义mycopy 具有 copy <已存在的文件名> <副本文件名或路径> //复制一个已存在的文件
定义myfind 具有 find <目录> -name <待查找的文件名> //在指定的目录及其子目录中查找指定的文件(输入文件名),并输出查找到的文件的绝对路径。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
/*
 *           实现dir功能的函数
 */
void do_ls(char dirname[])
{
              DIR* dir_ptr;   /* the dirname */
              struct dirent* direntp; /* each entry */
              if ((dir_ptr = opendir(dirname)) == NULL)
             {
                        fprintf(stderr, "ls1: cannot open %s\n", dirname);
              }
              else
              {
                         while ((direntp = readdir(dir_ptr)) != NULL)
                         {
                             printf("%s\n", direntp->d_name);
                          }
                         closedir(dir_ptr);
                     }
}
/*
*      实现mycd功能的函数
*/
bool mycd(char path[])  {
                if(chdir(path)==0)
                  {
                              return true;
                    }
                  else
                     {
                              return false;
                     }
}
/*
*         实现mycopy功能的函数
*/
#define BUFFERSIZE 4096//定义存储器容量
#define COPYMODE 0644//定义复制的长度

void mycopy(int argc, char *argv[])
{
                         int in_fd, out_fd, n_chars;//三个描述符值
                         char buf[BUFFERSIZE];//存储器位置

                         /*cp的参数有两个,分别是要复制的文件,和目的目录,这样一共应该是有三个操作数
                           所以要先检查argc的值是否为三,如果不是,返回标准错误*/
                          if (argc != 3){
                                    fprintf(stderr, "usage: %s source destination\n", *argv);
                                     exit(1);
                           }
                          /*检查cp的第一个参数,要复制的文件,用open打开,in_fd为open返回的描述符
                          如果返回-1,代表打开失败,提示错误*/
                         if ((in_fd = open(argv[1], O_RDONLY)) == -1)
                                      printf("Cannot open %s\n", argv[1]);
                                /*检查cp的第二个参数,复制的目的地址,用create在目的地址创建新文件,out_fd为open返回的描述符
                                   如果返回-1,代表创建失败,提示错误*/
                         if ((out_fd = creat(argv[2], COPYMODE)) == -1)
                                            printf("Cannot creat %s\n", argv[2]);
                       /*cp指令的动作就是读取一个文件的内容到存储器,在新的地址创建空白文件,再从存储器将内容写入新文件。
                           这里判断复制是否成功:
                           如果能读取顺利,而读取的位数和写的位数不同,是写错误;
                           如果读取失败,是读错误。*/
                           while ((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0)
                                         if (write(out_fd, buf, n_chars) != n_chars)
                                                  printf("Write error to %s\n", argv[2]);
                            if (n_chars == -1)
                                         printf("Read error from %s\n", argv[1]);
                         /*这里执行的是关闭文件的动作,in_fd和out_fd两个文件描述符
                               所指向的文件只要有一个关闭错误,就提示关闭错误。*/
                           if (close(in_fd) == -1 || close(out_fd) == -1)
                                      printf("Error closing files\n");
}
/*这个是用来输出错误信息的函数*/
void oops(char *s1, char *s2)
{
                             fprintf(stderr, "Error: %s ", s1);
                             perror(s2);//用来将上一个函数发生错误的原因输出到标准设备(stderr)
                             exit(1);
}
/*
*      实现mydel功能的函数
*/
bool mydel(char dir[]) {
                    if(rmdir(dir)==0)
                       {
                            return true;
                        }
                    else {
                              return false;
                         }
}
/*
*      实现pwd功能的函数
*/
ino_t get_inode(char *filename);
void printpathto(ino_t);
void inum_to_name(ino_t inode_to_find, char *namebuf, int buflen);

/*
* prints path leading down to an object with this inode
* kind of recursive
*/
void printpathto(ino_t this_inode)
{
                            ino_t my_inode;
                            char its_name[BUFSIZ];
                            if (get_inode("..") != this_inode)
                            {
                                  chdir("..");       /* up one dir */
                                  inum_to_name(this_inode, its_name, BUFSIZ);     /* get its name */
                                  my_inode = get_inode(".");       /* print head */
                                  printpathto(my_inode);      /* recursively */
                                  printf("/%s", its_name);        /* now print name of this */
                             }
}
void inum_to_name(ino_t inode_to_find, char *namebuf, int buflen)
{
           DIR *dir_ptr;   /* the directory */
           struct dirent *direntp; /* each entry */
           dir_ptr = opendir(".");
           if (dir_ptr == NULL)
           {
             perror(".");
             exit(1);
            }
              /* search directory for a file with specified inum */
            while ((direntp = readdir(dir_ptr)) != NULL)
            {
                        if (direntp->d_ino == inode_to_find)
                        {
                             strncpy(namebuf, direntp->d_name, buflen);
                             namebuf[buflen - 1] = '\0'; /* just in case */
                             closedir(dir_ptr);
                             return;
                         }
            }
            fprintf(stderr, "error looking for inum %ld\n", inode_to_find);
            exit(1);
}

/*
*      returns inode number of the file
*/
ino_t get_inode(char *filename)
{
        struct stat info;
        if (stat(filename, &info) == -1)
        {
                  fprintf(stderr, "Cannot stat");
                  perror(filename);
                  exit(1);
         }
         return info.st_ino;
}
//主程序
int main(int argc, char *argv[])
{
               char command[20];
               char c;
               int i=1;
               do{
                       printf("请输入命令:");
                       scanf("%s",&command);
                       if(strcmp(command,"mydir") == 0)
                       {
                               if (argc == 1)
                                            do_ls(".");
                               else
                               {
                              while (--argc)
                              {
                               printf("%s:\n", *(++argv));
                               do_ls(*argv);
                               }
                         }
                    }
else if(strcmp(command,"mycd") == 0)
{
              char path[20];
              scanf("%s",&path);
              if(!mycd(path))
              {
                           printf("mycd:%s:没有那个目录\n",path);
               }
}
else if(strcmp(command,"mycopy") == 0)
{
                     char filename1[20];
                     char filename2[20];
                     scanf("%s",&filename1);
                     scanf("%s",&filename2);
                     argc=3;
                     argv[1]=filename1;
                     argv[2]=filename2;
                     argv[3]=NULL;
                     mycopy(argc,argv);
}
else if(strcmp(command,"mydel") == 0)
{
                 char dir[20];
                 scanf("%s",&dir);
                 if(!mydel(dir))
                 {
                          printf("mydel:无法删除%s:没有那个目录\n",dir);
                  }
}
else if(strcmp(command,"mypwd") == 0)
{
                  printpathto(get_inode("."));    /* print path to here */
                  putchar('\n');  /* then add newline */
}
else
{
                  printf("input error!\n");
}
printf("是否继续操作(Y/N)?");
fflush(stdin);
scanf("\n%c",&c);
if(c=='N' || c=='n')
{
          i=0;
}
printf("\n");
}while(i!=0);
           return 0;
}