这个命令主要利用opendir函数读出DIR结构体,然后用readdir函数读出struct dirent结构体,最后利用dirent结构体里面的d_name来用lstat函数读出文件的各种属性,最后格式化输出,下面的代码主要实现了无参数的默认文件名输出,还有实现了带‘-l’参数的属性输出,目前只是实现了‘-l’参数,以后再努力实现其他参数。
/********************************************************
Program:
List all the file of the directory.
History:
2013/04/08 dingdong First release
2013/05/21 dingdong Second release[not finish]
2013/05/24 dingdong Third release[finish '-l']
*********************************************************/
#include "apue.h"
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
void parameters_l(char *temp);/*'-l' parameter*/
int
main(int argc,char *argv[])
{
DIR *dp;
struct dirent *dirp;
int i,j,k=0,count=0;/*count for format,per 5 d_name print '\n'*/
int flag1=0,flag2=0;/*flag2 for extra parameters
flag1 check have parameters or not,
*/
char buf[10];
if(argc==1)/*current directory by default*/
argv[1]=".";
else if(argc>=2)
{
if(argv[1][0]=='-')flag1=1;
else flag1=0;
}
if(flag1&&argc==2)/*have no parameters and argc==2*/
argv[2]=".";
if(flag1)/*have parameters*/
{
for(i=1;i<argc;i++)
{
for(j=0;argv[i][j]!='\0';j++)
{
if(argv[i][j]!='-')/*collect the parameters*/
{
buf[k]=argv[i][j];
k++;
}
}
}
buf[k]='\0';
for(k=0;buf[k]!='\0';k++)
{
switch(buf[k])
{
case 'l':parameters_l(argv[2]);break;
default :flag2=1;
printf("%s: extra operand %s\n",argv[0],argv[1]);
break;
}
if(flag2)break;/*if have extra operand then break*/
}
}/*if(flag2)*/
else if(!flag1)/*not parameters*/
{
if((dp=opendir(argv[1]))==NULL)
err_sys("can't open %s",argv[1]);
while((dirp=readdir(dp))!=NULL)
{
printf("%-12s ",dirp->d_name);
count++;
if(count==7)
{
count=0;
printf("\n");
}
}
printf("\n");
closedir(dp);
}
exit(0);
}
void parameters_l(char *temp)
{
DIR *dp;
struct dirent *dirp;
struct stat buf;
struct passwd *uid;
struct group *gid;
char *time;/*for ctime */
if((dp=opendir(temp))==NULL)
err_sys("can't open %s",temp);
while((dirp=readdir(dp))!=NULL)
{
char mode[]="----------.";
if(lstat(dirp->d_name,&buf)<0)
err_ret("lstat error");
/*file type*/
if(S_ISDIR(buf.st_mode))mode[0]='d';/*directory*/
if(S_ISCHR(buf.st_mode))mode[0]='b';/*block special file*/
if(S_ISBLK(buf.st_mode))mode[0]='c';/*character special file*/
if(S_ISFIFO(buf.st_mode))mode[0]='f';/*FIFO*/
if(S_ISLNK(buf.st_mode))mode[0]='s';/*socket*/
if(S_ISSOCK(buf.st_mode))mode[0]='l';/*symbolic link*/
/*the mode of the file*/
if(buf.st_mode&S_IRUSR)mode[1]='r';
if(buf.st_mode&S_IWUSR)mode[2]='w';
if(buf.st_mode&S_IXUSR)mode[3]='x';
if(buf.st_mode&S_IRGRP)mode[4]='r';
if(buf.st_mode&S_IWGRP)mode[5]='w';
if(buf.st_mode&S_IXGRP)mode[6]='x';
if(buf.st_mode&S_IROTH)mode[7]='r';
if(buf.st_mode&S_IWOTH)mode[8]='w';
if(buf.st_mode&S_IXOTH)mode[9]='x';
/*user and group*/
if((uid=getpwuid(buf.st_uid))==NULL)
err_sys("getpwuid error");
if((gid=getgrgid(buf.st_gid))==NULL)
err_sys("getgrgid error");
/*ctime for file*/
time=ctime(&buf.st_ctime);
time[strlen(time)-1]='\0';/*ignore the '\n'*/
printf("%s %-2d %-8s %-8s %-5d %-1s %-5s\n",mode,buf.st_nlink,
uid->pw_name,gid->gr_name,buf.st_size,time,dirp->d_name);
}
closedir(dp);
}