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;
}
上一篇: 原生js实现打印部分页面
下一篇: js 打印,预览页面的部分元素