作业:编写一个myls程序,能实现ls 的一些基本功能
注:这个作业我花费了不少时间,先前蹭听老牛的课的时候,用了4天 * 2小时/天左右的时间完成了一个半成品。后来上了周末班老刘的课,还是这个作业,可见是个经典的练习。所以在旧有代码的基础上,又花费了5~6个小时进行了一些改进,并增添了一些以前我没来得及实现的功能:
1.带有4个可选参数:
Usage:./myls [option]...[file]...
-a do not ignore entries starting with .
-l use a long listing format
-i print the index number of each file
-n Same as '-l', but add UID and GID
2. 通过颜色显示来区分普通文件,可执行文件,目录和suid文件
3. 实现了属组和属主用户名显示功能,既 真正的ls -l 功能。
介绍完毕,上代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PATHSIZE 255
#define NAMESIZE 50
static struct MYLS_DATA
{
char c;
time_t mtime;
char remote_path[PATHSIZE];
char permission[11];
off_t st_size;
ino_t st_ino;
uid_t uid;
gid_t gid;
nlink_t st_nlink;
int count;
int fileflag;
int localfile_flag;
int exec_flag;
int dir_flag;
int sid_flag;
char filename[PATHSIZE];
char d_name[PATHSIZE];
char username[NAMESIZE];
char groupname[NAMESIZE];
}ls_data;
static struct tm *my_time;
static struct dirent *dirp;
void usage(char *name)
{
printf("Usage:%s [option]...[file]...\n", name);
printf("-a do not ignore entries starting with .\n");
printf("-l use a long listing format\n");
printf("-i print the index number of each file\n");
printf("-n Same as '-l', but add UID and GID\n");
}
int check_dir(char *pathname,char *c)
{
FILE *fp;
fp = fopen(pathname, "rb");
if (fp==NULL) {
// perror("fopen()");
return errno;
// exit(1);
}
struct stat statres;
if(fstat(fileno(fp), &statres) <0)
{
perror("fstat()");
exit(1);
}
switch (statres.st_mode & S_IFMT){
case S_IFSOCK:
*c='s';
break;
case S_IFLNK:
*c='l';
break;
case S_IFREG:
*c='-';
break;
case S_IFBLK:
*c='b';
break;
case S_IFDIR:
*c='d';
return 0;
break;
case S_IFIFO:
*c='p';
break;
default:
*c='?';
break;
}
return -1;
}
int show_fstype(char *pathname,char *c)
{
FILE *fp;
ls_data.dir_flag = 0;
fp = fopen(pathname, "rb");
if (fp==NULL) {
// perror("fopen()");
return errno;
// exit(1);
}
struct stat statres;
if(fstat(fileno(fp), &statres) <0)
{
perror("fstat()");
exit(1);
}
switch (statres.st_mode & S_IFMT){
case S_IFSOCK:
*c='s';
break;
case S_IFLNK:
*c='l';
break;
case S_IFREG:
*c='-';
break;
case S_IFBLK:
*c='b';
break;
case S_IFDIR:
ls_data.dir_flag = 1;
*c='d';
break;
case S_IFIFO:
*c='p';
break;
default:
*c='?';
break;
- }
fclose(fp);
return 0;
}
void save_permission(mode_t st_mode, char *permission)
{
ls_data.exec_flag = 0;
ls_data.sid_flag = 0;
if (S_IRUSR & st_mode) {
permission[0]='r';
} else {
permission[0]='-';
}
if (S_IWUSR & st_mode) {
permission[1]='w';
} else {
permission[1]='-';
}
if (S_IXUSR & st_mode) {
if (S_ISUID & st_mode) {
permission[2]='s';
ls_data.sid_flag = 1;
} else {
ls_data.exec_flag = 1;
permission[2]='x';
}
} else {
permission[2]='-';
}
if (S_IRGRP & st_mode) {
permission[3]='r';
} else {
permission[3]='-';
}
if (S_IWGRP & st_mode) {
permission[4]='w';
} else {
permission[4]='-';
}
if (S_IXGRP & st_mode) {
if (S_ISGID & st_mode) {
ls_data.sid_flag = 1;
permission[5]='s';
} else {
ls_data.exec_flag = 1;
permission[5]='x';
}
} else {
permission[5]='-';
}
if (S_IROTH & st_mode) {
permission[6]='r';
} else {
permission[6]='-';
}
if (S_IWOTH & st_mode) {
permission[7]='w';
} else {
permission[7]='-';
}
if (S_ISVTX & st_mode) {
permission[8]='t';
} else if (S_IXOTH & st_mode) {
ls_data.exec_flag = 1;
permission[8]='x';
} else {
permission[8]='-';
}
}
int show_fspermission(char *pathname, char *permission, time_t *mtime, off_t *st_size, uid_t *uid, g
id_t *gid, ino_t *st_ino, nlink_t *st_nlink)
{
FILE *fp;
fp = fopen(pathname, "rb");
if (fp==NULL) {
// perror("fopen()");
return errno;
// exit(1);
}
struct stat statres;
if(fstat(fileno(fp), &statres) <0)
{
perror("fstat()");
exit(1);
}
*mtime = statres.st_mtime;
*st_size = statres.st_size;
*uid = statres.st_uid;
*gid = statres.st_gid;
*st_ino = statres.st_ino;
*st_nlink = statres.st_nlink;
int i;
save_permission(statres.st_mode,permission);
permission[9]='\0';
fclose(fp);
return 0;
}
int detach_name(char *pathname, char *filename)
{
int i,j,k;
int path_len,name_len;
for(i=0;pathname[i]!='\0';i++);
path_len=i;
for(name_len=1,i=i-1;(i>0)&& (pathname[i]!='/');name_len++,i--);
if(i==0)
{
strcpy(filename,pathname);
return -1;
}
for(i=0;i filename[i]=pathname[path_len-name_len+1+i];
filename[i]='\0';
return 0;
}
int get_username(uid_t uid, char *username)
{
FILE *fp;
char *buf;
char num[20];
int i,j,count;
int n=0;
int len;
fp = fopen("/etc/passwd","r");
while(len=getline(&buf,&n,fp)!=-1)
{
count=0;
for(i=0;count!=1;i++)
{
if(buf[i]==':')
{
buf[i]='\0';
count++;
}
}
for(i;count!=2;i++)
{
if(buf[i]==':')
count++;
}
for(i,j=0;count!=3;i++,j++)
{
num[j]=buf[i];
if(buf[i]==':')
{
num[j]='\0';
count++;
}
}
if(atoi(num) == uid)
{
strcpy(username,buf);
break;
}
}
if(buf)
free(buf);
fclose(fp);
return 0;
}
int get_groupname(gid_t gid, char *groupname)
{
FILE *fp;
char *buf;
char num[20];
int i,j,count;
int n=0;
int len;
fp = fopen("/etc/group","r");
while(len=getline(&buf,&n,fp)!=-1)
{
count=0;
for(i=0;count!=1;i++)
{
if(buf[i]==':')
{
buf[i]='\0';
count++;
}
}
for(i;count!=2;i++)
{
if(buf[i]==':')
count++;
}
for(i,j=0;count!=3;i++,j++)
{
num[j]=buf[i];
if(buf[i]==':')
{
num[j]='\0';
count++;
}
}
if(atoi(num) == gid)
{
strcpy(groupname,buf);
break;
}
}
if(buf)
free(buf);
fclose(fp);
return 0;
}
void myls_for_file(char option)
{
int ret;
ret = show_fstype(ls_data.d_name,&ls_data.c);
if(ret != 0)
{
fprintf(stderr,"%s\n",strerror(ret));
return;
}
show_fspermission(ls_data.d_name, ls_data.permission, &ls_data.mtime, &ls_data.st_si
ze, &ls_data.uid, &ls_data.gid, &ls_data.st_ino, &ls_data.st_nlink);
my_time = localtime(&ls_data.mtime);
// printf("%c%s\t%s\n",c,permission, dirp->d_name);
if((ls_data.fileflag==1)&&(ls_data.localfile_flag == 1))
strcpy(ls_data.d_name,ls_data.filename);
get_username(ls_data.uid,ls_data.username);
get_groupname(ls_data.gid,ls_data.groupname);
// printf("user:%s group:%s\n",ls_data.username,ls_data.groupname);
switch(option){
case 'l':
printf("%c%s %4d %5s %5s %8d %d-%.2d-%.2d %.2d:%.2d",ls_data.c,ls_da
ta.permission,ls_data.st_nlink, ls_data.username, ls_data.groupname, (int)ls_data.st_size, my_time->
tm_year+1900, my_time->tm_mon+1, my_time->tm_mday, my_time->tm_hour, my_time->tm_min);
case 'n':
if(option == 'n')
printf("%c%s %4d %4d %4d %8d %d-%.2d-%.2d %.2d:%.2d",ls_data
.c,ls_data.permission,ls_data.st_nlink, ls_data.uid, ls_data.gid, (int)ls_data.st_size, my_time->tm_
year+1900, my_time->tm_mon+1, my_time->tm_mday, my_time->tm_hour, my_time->tm_min);
if(ls_data.exec_flag == 1)
printf("\33[32m");
if(ls_data.sid_flag == 1)
printf("\33[41m");
else if(ls_data.dir_flag == 1)
printf("\33[34m");
printf(" %s",ls_data.d_name);
printf("\33[49m");
printf("\33[30m");
printf("\n");
break;
case 'a':
case '#':
if(ls_data.exec_flag == 1)
printf("\33[32m");
if(ls_data.sid_flag == 1)
printf("\33[41m");
else if(ls_data.dir_flag == 1)
printf("\33[34m");
printf("%s",ls_data.d_name);
printf("\33[49m");
printf("\33[30m");
printf("\t");
break;
case 'i':
ls_data.count++;
printf("%8ld",(long)ls_data.st_ino);
if(ls_data.exec_flag == 1)
printf("\33[32m");
if(ls_data.sid_flag == 1)
printf("\33[41m");
else if(ls_data.dir_flag == 1)
printf("\33[34m");
printf(" %.10s",ls_data.d_name);
printf("\33[49m");
printf("\33[30m");
printf("\t");
if(ls_data.count %3 ==0)
printf("\n");
break;
default:
break;
}
}
int myls_default(char *pathname, char option){
DIR *p;
ls_data.count=0;
ls_data.fileflag=0;
int ret;
if(pathname == NULL)
strcpy(ls_data.remote_path,"./");
else
strcpy(ls_data.remote_path,pathname);
ret = check_dir(pathname,ls_data.permission);
if(ret == -1)
{
strcpy(ls_data.d_name,pathname);
ls_data.fileflag=1;
myls_for_file(option);
}
else if(ret == 0)
{
p = opendir(ls_data.remote_path);
if(p==NULL)
{
perror("Open dir error");
return errno;
}
while((dirp=readdir(p))!=NULL)
{
if((option != 'a') && (strncmp(dirp->d_name,".",1) == 0 ))
continue;
if(chdir(ls_data.remote_path) < 0)
{
printf("remote_path : %s\n",ls_data.remote_path);
perror("failed to enter");
return errno;
}
strcpy(ls_data.d_name,dirp->d_name);
myls_for_file(option);
}
closedir(p);
}
else
{
fprintf(stderr,"%s:%d\n",strerror(ret),ret);
return ret;
}
if((option == 'a')||(option == 'i')||(option == '#'))
printf("\n");
return 0;
}
char *filter_pathname(int n, char **ch)
{
int i;
for(i=1;i {
if(*ch[i] != '-')
{
return ch[i];
}
}
return NULL;
}
char filter_parameter(int n, char **ch)
{
int i;
for(i=1;i {
if(*ch[i] == '-')
return *(ch[i]+1);
}
return '#';
}
int getpwd(char *path)
{
if(getcwd(path, PATHSIZE) == NULL)
return -1;
return 0;
}
int check_pathname(char *pathname)
{
int i;
if(pathname == NULL)
return -1;
for(i=0;pathname[i]!='\0';i++)
{
if(pathname[i]=='/')
return 0;
}
return -1;
}
char *whole_path(char *path, char *pathname)
{
int i,j,k;
char *newpath;
for(i=0;path[i]!='\0';i++);
if(pathname != NULL)
for(j=0;pathname[j]!='\0';j++);
else
j=0;
newpath = malloc(sizeof(char)*(i+j+2));
for(k=0;k newpath[k]=path[k];
newpath[k++] = '/';
for(k,i=0;i newpath[k]=pathname[i];
newpath[k]='\0';
return newpath;
}
int main(int argc, char **argv)
{
char path[PATHSIZE];
char *pathname=NULL;
if((argc != 1) && (strcmp(argv[1], "--help")==0))
{
usage(argv[0]);
exit(1);
}
if(argc > 1)
pathname=filter_pathname(argc, argv);
if(check_pathname(pathname) == -1)
{
if((pathname != NULL)&& detach_name(pathname,ls_data.filename)==-1)
ls_data.localfile_flag=1;
getpwd(path);
pathname=whole_path(path,pathname);
}
// printf("pathname = %s\n",pathname);
switch(filter_parameter(argc,argv)){
case 'l':
return myls_default(pathname,'l');
break;
case 'i':
return myls_default(pathname,'i');
break;
case 'n':
return myls_default(pathname,'n');
break;
case 'a':
return myls_default(pathname,'a');
break;
case '#':
return myls_default(pathname,'#');
break;
default:
break;
}
}
阅读(6551) | 评论(0) | 转发(0) |