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;
}