Linux shell命令解析器(二),命令

环境:

Ubuntu14-4   内核 4.4.0-135

vim编辑器 7.4 

gcc  4.8.4 

1.1 知识点

  • Shell 的基本概念
  • 文件相关函数,内存相关函数

 1  ls命令语法

ls [选项] [目录或文件名] 
参数: 
-a:--all的缩写,显示所有的文件,包括隐藏文件(以.开头的文件),参考示例1。(常用) 
-A:--almost-all的缩写,显示所有的文件,包括隐藏文件,但不包括表示当前目录.和上级目录..这两个文件,参考示例2。 
-c:和-lt一起使用:显示列表并且以ctime(文件状态最后改变时间)排序。和-l一起使用:显示ctime并且以文件名排序。其他情况,以ctime排序。参考示例3。 
-d:--directory的缩写,仅列出目录本身,而不是列出目录里的内容列表,参考示例4。(常用) 
-f:直接列出结果,而不进行排序(ls默认会以文件名排序) 
--color[=WHEN]:是否根据文件类型显示颜色,WHEN可以为never、always或者auto 
--full-time:以完整的实际模式显示(包含年月日时分),类似与ls -l --time-style=full-iso,参考示例5。 
-g:列表显示结果,和-l类似,但是不显示文件所属者。 
-h:将文件内容大小以GB、KB等易读的方式显示,参考示例6。 
-i:结合-l参数,列出每个文件的inode,参考示例7。 
-l:列出长数据串,显示出文件的属性与权限等数据信息(常用) 
-n:和-l类似,只是显示的所属用户和组不是名称而是对应的id,参考示例8。 
-r:--reverse,将排序结果以倒序方式显示,参考示例9。 
-S:以文件大小排序,参考示例9。 
-t:以修改时间排序 
--help:显示帮助信息
 

/*************************************************************************
> File Name: ls.c
> Author:
> Mail:
> Created Time: 2018年10月19日 星期五 07时44分47秒
************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<dirent.h>
#include<grp.h>
#include<pwd.h>
#include<dirent.h>
#define STRLEN 128
#define MAXDIR 10  //支持可最多查询的目录
#define START_FLAG 1
#define FLAG_L 1
#define FLAG_A 2
#define FLAG_I 4
#define FLAG_S 8
#define FLAG_K 16
#define FLAG_B 32
#define FLAG_R 64    //R,递归
#define FLAG_UMASK 
int get_total(const char *root)
{
	int total = 0;
	DIR *dir = NULL;
	dir = opendir(root);
	if (dir == NULL)
	{
		perror("opendir error");
		exit(1);
	}
	struct dirent *ptr = NULL;
	while ((ptr = readdir(dir)) != NULL)
	{
		if (strcmp(".", ptr->d_name) == 0 || strcmp("..", ptr->d_name) == 0)
		{
			printf("%s\n", ptr->d_name);
			continue;
		}
		if (ptr->d_type == DT_REG)
		{
			total++;
		}
		if (ptr->d_type == DT_DIR)
		{
			printf("%s\n", ptr->d_name);
			char path[128] = { 0 };
			sprintf(path, "%s/%s", root, ptr->d_name);
			total += get_total(path);
		}
	}
	closedir(dir);
	return total;
}
void AlayPath(int argc, char*argv[], char path[][STRLEN], char para[], int *num)
{
	int length = argc;
	int i = 0;
	int count = 0;
	int j = 0;
	DIR *dir = NULL;
	for (i = 0; i < length; i++)
	{
		if (strncmp(argv[i], "-", 1) != 0)
		{
			if ((dir = opendir(argv[i])) != NULL)
			{
				strcpy(path[count++], argv[i]);
				//printf("alaypara %s\n",path[count-1]);
			}
		}
		else
		{
			strcat(para, argv[i]);
		}
	}
	*num = count;
}
void PrintFileName(int mode, char *name)
{
	if (S_ISDIR(mode))    //判断是否为目录
	{
		printf("\033[1;34m%s\033[0m   ", name);//文件名显示为蓝色
	}
	else if (S_ISREG(mode)) //判断是否为普通文件
	{
		if (mode & S_IXUSR || mode & S_IXGRP || mode & S_IXOTH)//判断是否为可执行文件
		{
			printf("\033[1;32m%s\033[0m    ", name);//文件名显示为绿色
		}
		else
		{
			printf("%s   ", name);
		}
	}
	else
	{
		printf("%s   ", name);
	}

}
//w e y z  无效
//i block
//a 所有文件
//s 磁盘空间值
//d 当前文件
//f 所有文件
//h 单位以k显示
//k 文件大小以k值为单位向上取整
//n 文件所有者及所属组以整数值表示
//m 逗号分割
//l 详细信息
int  AlayPara(char para[], char errpara[], int length, int *flag)
{
	int i = 0;
	int pos = 0;
	*flag = 0;
	int sign = 1;
	for (; i < length; ++i)
	{
		if (para[i] == '-')
		{
			continue;
		}
		else if (para[i] == 'l')
		{
			*flag |= START_FLAG << 0;
		}
		else	if (para[i] == 'a')
		{
			*flag |= START_FLAG << 1;
		}
		else if (para[i] == 'i')
		{
			*flag |= START_FLAG << 2;
		}
		else if (para[i] == 's')
		{
			*flag |= START_FLAG << 3;
		}
		else if (para[i] == 'k')
		{
			*flag |= START_FLAG << 4;
		}
		else if (para[i] == 'b')
		{
			*flag |= START_FLAG << 5;
		}
		else if (para[i] == 'R')
		{
			*flag |= START_FLAG << 6;
		}
		else
		{
			errpara[pos++] = para[i];
			sign = 0;
			break;
		}

	}
	return sign;
}

int main(int argc, char *argv[])
{
	char dirpath[MAXDIR][STRLEN] = { 0 }; //存所传入的路径
	char curpath[STRLEN] = { 0 };   //存当前路径
	char para[STRLEN] = { 0 };      //存参数
	char errpara[STRLEN] = { 0 };   //存非法参数
	struct dirent *ptr = NULL;
	struct dirent *pptr = NULL;
	DIR *dir = NULL;
	int dir_num = 0;                //路径数目
	int i;
	int ret;
	int t;
	int flag = 0;                  //得到所输入的路径的参数
	int length = 0;                //参数长度
	int total = 0;
	struct stat st;
	int inode = 0;
	int blocks = 0;
	int blksize = 0;
	int linkNum = 0;
	char *fileUser = NULL;
	char *fileGrp = NULL;
	int fileSize = 0;
	char *time = NULL;
	char mtime[STRLEN] = { 0 };
	char realtime[STRLEN] = { 0 };
	char buff[1024];
	char perms[12] = { 0 };   // dwrxwrxwrx. 比这11位多一位存‘/0’
	getcwd(curpath, STRLEN - 1);
	if (argc < 2)
	{
		dir = opendir(curpath);
		if (dir != NULL)
		{
			while ((ptr = readdir(dir)) != NULL)
			{
				ret = stat(ptr->d_name, &st);
				if (ret == -1)
				{
					perror("stat");
					exit(1);
				}

				if (strcmp(".", ptr->d_name) == 0 || strcmp("..", ptr->d_name) == 0)
				{
					continue;
				}
				PrintFileName(st.st_mode, ptr->d_name);

			}
		}
	}
	else
	{
		AlayPath(argc, argv, dirpath, para, &dir_num);
		length = strlen(para);
		t = AlayPara(para, errpara, length, &flag);
		//	printf("t==%d flag==%d\n",t,flag);
		if (t == 0)
		{
			printf("ls:invalid option --'%s'\n", errpara);
			printf("Try 'ls -help' for more infomation.\n");
			exit(0);
		}
		for (i = 0; i < dir_num; i++)
		{
			//printf("i===%d dir=%s\n",i,dirpath[i]);
			chdir(curpath);
			getcwd(curpath, STRLEN - 1);
			dir = opendir(dirpath[i]);
			if (dir == NULL)
			{
				perror("opendir fail");
				continue;
			}
			chdir(dirpath[i]);
			while ((pptr = readdir(dir)) != NULL)
			{
				ret = stat(pptr->d_name, &st);
				if (ret == -1)
				{
					perror("stat");
					break;
				}
				if ((strcmp(".", pptr->d_name) == 0 || strcmp("..", pptr->d_name) == 0) && (flag & 2) != 2)
				{
					continue;
				}
				total += st.st_blocks / 2;
			}
			if (flag & 1 == 1 || flag & 8 == 8)
			{
				printf("total %d\n", total);
			}
			total = 0;
			closedir(dir);
			chdir(curpath);
			dir = opendir(dirpath[i]);
			chdir(dirpath[i]);
			while ((ptr = readdir(dir)) != NULL)
			{
				ret = stat(ptr->d_name, &st);
				if (ret == -1)
				{
					perror("stat");
					break;
				}
				blocks = st.st_blocks / 2;
				inode = st.st_ino;
				switch (st.st_mode & S_IFMT)
				{
				case S_IFLNK:perms[0] = 'l';	break;
				case S_IFDIR:perms[0] = 'd';  break;
				case S_IFREG:perms[0] = '-';	break;
				case S_IFBLK:perms[0] = 'b';	break;
				case S_IFCHR:perms[0] = 'c';	break;
				case S_IFSOCK:perms[0] = 's';	break;
				case S_IFIFO:perms[0] = 'p';  break;
				default:break;
				}
				//use
				perms[1] = (st.st_mode & S_IRUSR) ? 'r' : '-';
				perms[2] = (st.st_mode & S_IWUSR) ? 'w' : '-';
				perms[3] = (st.st_mode & S_IXUSR) ? 'x' : '-';
				//group
				perms[4] = (st.st_mode & S_IRGRP) ? 'r' : '-';
				perms[5] = (st.st_mode & S_IWGRP) ? 'w' : '-';
				perms[6] = (st.st_mode & S_IXGRP) ? 'x' : '-';
				//other
				perms[7] = (st.st_mode & S_IROTH) ? 'r' : '-';
				perms[8] = (st.st_mode & S_IWOTH) ? 'w' : '-';
				perms[9] = (st.st_mode & S_IXOTH) ? 'x' : '-';
				perms[10] = '.';
				//link number
				linkNum = st.st_nlink;
				//fileUser
				fileUser = getpwuid(st.st_uid)->pw_name;
				//fileGrp
				fileGrp = getgrgid(st.st_gid)->gr_name;
				//fileSize
				fileSize = (int)st.st_size;
				//modifyTime
				time = ctime(&st.st_mtime);
				strncpy(mtime, time, strlen(time) - 1);
				memmove(realtime, mtime + 4, 12);
				sprintf(buff, "%s " "%d " "%s " "%s " "%d " "%s ", perms, linkNum, fileUser, fileGrp, fileSize, realtime);
				//	printf("%8s  %4d  %4s  %8s  %8d  %8s %8s",perms,linkNum,fileUser,fileGrp,fileSize,realtime,dirpath);
				printf("%s", buff);
				PrintFileName(st.st_mode, ptr->d_name);
				printf("\n");
				//		closedir(dir);
				//chdir(curpath);
			}
			closedir(dir);
		}
	}
	printf("\n");
	return 0;
}

2 su命令语法

-f , –fast:不必读启动文件(如 csh.cshrc 等),仅用于csh或tcsh两种Shell。

-l , –login:加了这个参数之后,就好像是重新登陆一样,大部分环境变量(例如HOME、SHELL和USER等)都是以该使用者(USER)为主,并且工作目录也会改变。如果没有指定USER,缺省情况是root。

-m, -p ,–preserve-environment:执行su时不改变环境变数。

-c command:变更账号为USER的使用者,并执行指令(command)后再变回原来使用者。

–help 显示说明文件
–version 显示版本资讯

/*************************************************************************
	> File Name: su.c
	> Author: 
	> Mail: 
	> Created Time: 2018年10月19日 星期五 07时47分05秒
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<shadow.h>
#include<pwd.h>
#include<sys/stat.h>
#include<sys/types.h>

int main(int argc,char *argv[])
{
    char *user="root";
    if(argv[1]!=NULL)
    {
        user=argv[1];
    }
    printf("Password:");
    fflush(stdout);    //字符串刷到终端
    char password[128]={0};
    fgets(password,128,stdin);
    password[strlen(password)-1]=0;

    //根据用户名获取系统存储用户的密码信息
    struct spwd *pwd=getspnam(user);
    assert(pwd!=NULL);

    //根据用户密码信息获取加密算法ID以及密钥
    char *p=pwd->sp_pwdp;
    char salt[128]={0};
    int count=0,i=0;
    printf("%s\n",p);
    while(1)
    { 
        salt[i]=*p;
        if(salt[i]=='$')
        {
            count++;
        }
        if(count==3)
        {
            break;
        }
        i++,p++;
    }

    //根据获取的算法ID以及密钥,对输入的明文加密
    char *s=strcpy(password,salt);
    if(strcmp(s,pwd->sp_pwdp)!=0)
    {
        perror("password is error");
        exit(0);
    }
    pid_t n=fork();
    assert(n!=-1);
    if(n==0)
    {
        struct passwd *pw=getpwnam(user);
        assert(pw!=NULL);
        setenv("HOME",pw->pw_dir,1);//设置环境变量
        setuid(pw->pw_uid);//修改用户
        execl("a.out",pw->pw_shell,NULL);
        printf("su is fail\n");
        exit(0);
    }
    else

    {
        wait(NULL);
    }

}

3 cp命令语法

-a:此选项通常在复制目录时使用,它保留链接、文件属性,并复制目录下的所有内容。其作用等于dpR参数组合。

-d:复制时保留链接。这里所说的链接相当于Windows系统中的快捷方式。

-f:覆盖已经存在的目标文件而不给出提示。

-i:与-f选项相反,在覆盖目标文件之前给出提示,要求用户确认是否覆盖,回答"y"时目标文件将被覆盖。

-p:除复制文件的内容外,还把修改时间和访问权限也复制到新文件中。

-r:若给出的源文件是一个目录文件,此时将复制该目录下所有的子目录和文件。

-l:不复制文件,只是生成链接文件。

-help:显示说明文件

/*************************************************************************
	> File Name: c.c
	> Author: 
	> Mail: 
	> Created Time: 2018年10月19日 星期五 07时43分27秒
 ************************************************************************/

#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
    if(argc < 2)
    {
        printf("cp: missing file operand\n");
        printf("Try 'cp --help' for more information.\n");
        exit(0);
    }
    if(argc == 2)
    {
        printf("cp: missing destination file operand after '%s'\n",argv[1]);
        printf("Tryy 'cp --help' for more infot=rmation\n");
        exit(0);
    }
    if(argc == 3)
    {
        
    }
    int fd_src=open(argv[1],O_RDONLY);
    if(fd_src==-1)
    {
        perror("open");
        exit(1);
    }
    int fd_dest=open(argv[2],O_WRONLY|O_CREAT|O_EXCL,0644);
    if(fd_dest==-1&&errno==EEXIST)
    {
        printf("recover it?");
        char choose;
        scanf("%c",&choose);
        if(choose=='y'||choose=='Y')
        {
            fd_dest=open(argv[2],O_WRONLY);
        }
        else
        {
            exit(1);
        }
    }
     while(1)
    {
        char buf[1024]={};
        memset(buf,0x00,sizeof(buf));
        int r=read(fd_src,buf,1024);
        if(r==-1)
        {
            perror("read");
            exit(1);
        }
        if(r==0)
        {
             break;     
        }
        write(fd_dest,buf,r);  
    }
    close(fd_src);
    close(fd_dest);                 
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值