Chinaunix首页 | 论坛 | 博客
  • 博客访问: 299216
  • 博文数量: 83
  • 博客积分: 3193
  • 博客等级: 中校
  • 技术积分: 1679
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-03 12:04
文章分类

全部博文(83)

文章存档

2013年(2)

2012年(6)

2011年(72)

2010年(2)

2009年(1)

分类: C/C++

2011-08-11 21:51:16

作业:编写一个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;
                }

}


阅读(6323) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~