环境:
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;
}