/*
模擬ls命令,實現參數-tariRl.有些代碼重復出現,可改進
可以在該程序的基礎上增加參數,該程序思路清晰,容易擴展
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<dirent.h>
#include<sys/ioctl.h>
#include<pwd.h>
#include<grp.h>
#define LL (1<<0) /*帶l參數標志*/
#define IL (1<<1) /*帶i參數標志*/
#define RU (1<<2) /*帶R參數標志*/
#define TL (1<<16) /*帶t參數標志*/
#define AL (1<<17) /*帶a參數標志*/
#define RL (1<<18) /*帶r參數標志*/
#define LENGTH 500 /*字符串最大長度*/
#define MAX_FILE_COUNT 500/*文件列表最大長度*/
/*函數聲明*/
void error(char* error_message,int line);
void display(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);
int file_list(char* path,struct stat* stalist,char (*namelist)[LENGTH],int mode);
void display_simply(char (*namelist)[LENGTH],int n);
void display_LL(struct stat * stalist,char (*namelist)[LENGTH],int n);
void display_IL(struct stat * stalist,char (*namelist)[LENGTH],int n);
void display_LL_IL(struct stat * stalist,char (*namelist)[LENGTH],int n);
void display_RU(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);
void display_RU_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode);
void display_RU_IL(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);
void display_RU_IL_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode);
/*主函數*/
int main(int argc,char **argv)
{
int i,j;
/*mode的前16個位用來標志那些能影響顯示的參數,16位之後的位用來標志不影響輸出格式的參數。這個程序只用到了0-3位,16-18位,如果要在該程序的基礎上增加參數,可以用其他沒有使用的位。
mode的第0位為1表示帶l參數,mode的第1位為1表示帶i參數,mode的第2位為1表示帶R參數,mode的第16位為1表示帶t參數,mode的第17位為1表示帶a參數,mode的第18位為1表示帶r參數*/
int mode=0;
char error_message[LENGTH]={0};/*錯誤信息*/
char path[LENGTH]={0};/*路徑*/
struct stat stalist[MAX_FILE_COUNT];/*文件詳細信息數組*/
char namelist[MAX_FILE_COUNT][LENGTH];/*文件名數組*/
int flag=0;/*判斷是否指定了目錄*/
int count;/*文件個數*/
/*解析參數*/
for(i=1;i<argc;i++){
if(argv[i][0]=='-'){/*如果是選項參數*/
for(j=1;j<strlen(argv[i]);j++){
if(argv[i][j]=='l')
mode=mode|LL;
else if(argv[i][j]=='i')
mode=mode|IL;
else if(argv[i][j]=='R')
mode=mode|RU;
else if(argv[i][j]=='r')
mode=mode|RL;
else if(argv[i][j]=='a')
mode=mode|AL;
else if(argv[i][j]=='t')
mode=mode|TL;
else{
snprintf(error_message,LENGTH,"no option of %c",argv[i][j]);
error(error_message,__LINE__);
}
}
}else{/*參數為目錄或文件*/
if(flag==1)
error("can not specify more then two dir or file",__LINE__);
else
flag=1;
if(argv[i][0]!='/'){/*相對路徑*/
strcat(path,get_current_dir_name());
strcat(path,"/");
strncat(path,argv[i],strlen(argv[i]));
}else/*絕對路徑*/
strcpy(path,argv[i]);
}
}
if(flag==0)/*未指定任何目錄或文件,則使用默認當前目錄*/
strcat(path,get_current_dir_name());
/*根據mode獲取指定目錄下的文件*/
count=file_list(path,stalist,namelist,mode);
/*根據mode顯示文件*/
display(stalist,namelist,count,mode);
return 0;
}
/*獲取文件列表*/
int file_list(char* path,struct stat* stalist,char (*namelist)[LENGTH],int mode)
{
int i=0,index,j,k;
DIR *dir;
struct dirent *ptr;
char str[LENGTH];
char nametemp[LENGTH];
struct stat statemp;
if(stat(path,&stalist[0])<0){
// puts(path);
error("the specify file is not exist",__LINE__);
}
if(S_ISDIR(stalist[0].st_mode)){/*如果該路徑指向的是一個目錄*/
if((dir=opendir(path))==NULL){/*打開目錄*/
sprintf(str,"can not open %s",path);
error(str,__LINE__);
}
chdir(path);/*改變當前工作目錄到path*/
i=0;
while((ptr=readdir(dir))!=NULL){/*依次讀取目錄下的所有文件*/
if(ptr->d_name[0]=='.' && !(mode & AL))/*忽略隱藏文件*/
continue;
/*按字母順序插入到stalist數組及namelist數組*/
for(j=i;j>0;j--){
if(strcmp(ptr->d_name,namelist[j-1])>0)
break;
}
for(k=i;k>j;k--){
strcpy(namelist[k],namelist[k-1]);
stalist[k]=stalist[k-1];
}
strcpy(namelist[j],ptr->d_name);
stat(ptr->d_name,&stalist[j]);
i++;
if(i==MAX_FILE_COUNT)
error("file count beyond MAX_FILE_COUNT",__LINE__);
}
closedir(dir);
}else{
j=strlen(path)-1;
while(j>=0 && path[j]!='/'){
j--;
}
if(j<0)
error("path error",__LINE__);
j++;
k=0;
while(path[j]){
namelist[0][k]=path[j];
j++;
k++;
}
namelist[0][k]=0;
return 1;
}
if(mode & TL){/*按文件修改時間排序*/
for(j=0;j<i;j++){
index=j;
for(k=j+1;k<i;k++)
if(stalist[index].st_mtime<stalist[k].st_mtime){
index=k;
}
statemp=stalist[j];
stalist[j]=stalist[index];
stalist[index]=statemp;
strcpy(nametemp,namelist[j]);
strcpy(namelist[j],namelist[index]);
strcpy(namelist[index],nametemp);
}
}
if(mode & RL){/*反序排列*/
for(j=0;j<i/2;j++){
strcpy(nametemp,namelist[j]);
strcpy(namelist[j],namelist[i-j-1]);
strcpy(namelist[i-j-1],nametemp);
statemp=stalist[j];
stalist[j]=stalist[i-j-1];
stalist[i-j-1]=statemp;
}
}
return i;
}
/*根據mode選擇不同的函數進行顯示*/
void display(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode)
{
/*使mode的高16位為0*/
int m = mode & ((1<<16)-1);
switch(m){
case 0:
display_simply(namelist,n);
break;
case 1:
display_LL(stalist,namelist,n);
break;
case 2:
display_IL(stalist,namelist,n);
break;
case 3:
display_LL_IL(stalist,namelist,n);
break;
case 4:
display_RU(stalist,namelist,n,mode);
break;
case 5:
display_RU_LL(stalist,namelist,n,mode);
break;
case 6:
display_RU_IL(stalist,namelist,n,mode);
break;
case 7:
display_RU_IL_LL(stalist,namelist,n,mode);
break;
}
}
/*不帶顯示選項,簡單顯示文件名*/
void display_simply(char (*namelist)[LENGTH],int n)
{
int i,maxlength=0,cols;
struct winsize ts;
for(i=0;i<n;i++)
if(strlen(namelist[i])>maxlength)
maxlength=strlen(namelist[i]);
/*獲取終端的大小*/
ioctl(STDIN_FILENO,TIOCGWINSZ,&ts);
cols=ts.ws_col;
cols/=(maxlength+1);
//lines=ts.ws_row;
for(i=0;i<n;i++){
if(i!=0 && i%cols==0)
puts("");
printf("%*s",-(maxlength+1),namelist[i]);
}
putchar('n');
}
/*-l 參數,顯示詳細文件信息*/
void display_LL(struct stat * stalist,char (*namelist)[LENGTH],int n)
{
int i,mode;
char* str;
for(i=0;i<n;i++){
mode=stalist[i].s