home *** CD-ROM | disk | FTP | other *** search
- /* dls.c - Descriptive ls
- *
- * Copyright (c) 1991 Tim Cook.
- * Non-profit distribution allowed. See README for details.
- */
-
- static char rcsid[] = "$Header: dls.c 1.0 91/03/22 $" ;
-
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/dir.h>
- #include <sys/stat.h>
- #include <sys/file.h>
- #include <sys/time.h>
- #ifdef NDBM
- #include <ndbm.h>
- #else
- #if defined(sequent) && defined(NULL)
- #undef NULL
- #endif
- #include <dbm.h>
- #endif
-
- #include <vclib.h>
- #include <list.h>
-
- #define UID_TYPE unsigned short
- #define GID_TYPE unsigned short
-
- extern time_t time () ;
- extern void *smalloc () ;
- extern int getuid () ;
- extern int getgroups () ;
-
- extern char *optarg ;
- extern int optind, opterr ;
-
- #define NULL_CP ((char *) 0)
- #define EOS '\0'
-
- static struct file_info {
- char *name ;
- ino_t inode ;
- u_short mode ;
- short nlink ;
- off_t size ;
- time_t mtime ;
- } ;
-
- /* options */
- static int show_date = FALSE ;
- static int sort_by_date = FALSE ;
- static int even_inaccessible = FALSE ;
- static int filename_columns = 14 ;
-
- /* other globals */
- #ifdef NDBM
- static DBM *desc_database ;
- #endif
- static time_t six_months_ago ;
- static struct file_info not_there ; /* Symbolic value */
- static int name_and_size_columns ;
- static int space = FALSE ; /* If TRUE, we need to print a blank
- line before anything else */
- static int printed_anything = FALSE ;
- static int uid ;
- static int no_groups ;
- static int groups[NGROUPS] ;
-
- static void *get_element_from_argv () ;
- static void build_and_sort_list () ;
- static struct file_info *get_file_info () ;
- static void list_file () ;
- static void list_directory () ;
-
-
- int main (argc, argv)
- int argc ;
- char **argv ;
- {
- int option ;
- struct list file_list ;
- struct file_info *file_info ;
-
- opterr = 0 ;
- while ((option = getopt (argc, argv, "detf:")) != EOF) {
- switch ((char) option) {
- case 'd' :
- show_date = TRUE ; break ;
- case 'e' :
- even_inaccessible = TRUE ; break ;
- case 't' :
- sort_by_date = TRUE ; break ;
- case 'f' :
- filename_columns = atoi (optarg) ; break ;
- case '?' :
- break ; } }
-
- name_and_size_columns = filename_columns + 8 ;
-
- if (show_date)
- six_months_ago = time ((time_t *) 0) - (182 * 24 * 60 * 60) ;
-
- if (! even_inaccessible) {
- uid = (UID_TYPE) getuid () ;
- no_groups = getgroups (NGROUPS, groups) ; }
-
- if (optind - argc == 0) {
- list_directory (".", FALSE) ;
- #ifdef NDBM
- dbm_close (desc_database) ;
- #else
- dbmclose () ;
- #endif
- exit (0) ; }
-
- list_init (&file_list) ;
- build_and_sort_list (&file_list, get_element_from_argv, (char *) argv,
- (char *) &optind) ;
-
- while ((file_info = get_file_info (&file_list))
- != (struct file_info *) NULL) {
- if (file_info != ¬_there) {
- if (file_info->mode & S_IFDIR)
- list_directory (file_info->name, TRUE) ;
- else {
- list_file (file_info, FALSE) ; } } }
- }
-
-
- static
- void *get_element_from_argv (param_1, param_2)
- char *param_1, *param_2 ;
- {
- int *argc ;
- char **argv ;
-
- argv = (char **) param_1 ;
- argc = (int *) param_2 ;
- return (void *) argv[(*argc)++] ;
- }
-
-
- static
- int file_info_date_cmp (info_1, info_2)
- struct file_info **info_1, **info_2 ;
- {
- return (int) ((*info_2)->mtime - (*info_1)->mtime) ;
- }
-
-
- static
- int compare_str (str_1, str_2)
- char **str_1, **str_2 ;
- {
- return strcmp (*str_1, *str_2) ;
- }
-
-
- static
- void build_and_sort_list (file_list, get_element, param_1, param_2)
- struct list *file_list ;
- void * (*get_element) () ;
- char *param_1, *param_2 ;
- {
- struct stat file_status ;
- struct file_info *file_info ;
- char *name ;
-
- if (sort_by_date) {
- while ((name = (char *) get_element (param_1, param_2)) != NULL_CP) {
- if (stat (name, &file_status) == -1)
- perror (name) ;
- else {
- file_info =
- (struct file_info *) smalloc (sizeof (struct file_info)) ;
- file_info->name = name ;
- file_info->inode = file_status.st_ino ;
- file_info->mode = file_status.st_mode ;
- file_info->nlink = file_status.st_nlink ;
- file_info->size = file_status.st_size ;
- file_info->mtime = file_status.st_mtime ;
- list_push (file_list, (void *) file_info) ; } }
- list_sort (file_list, file_info_date_cmp) ; }
-
- else { /* Sort by name */
- while ((name = (char *) get_element (param_1, param_2)) != NULL_CP) {
- list_push (file_list, (void *) name) ; }
- list_sort (file_list, compare_str) ; }
- }
-
-
- static
- struct file_info *get_file_info (file_list)
- struct list *file_list ;
- {
- static struct file_info file_info ;
- static struct stat status ; /* Tongue twister */
- char *name ;
- int listable ;
- int n ;
-
- if (sort_by_date)
- return (struct file_info *) list_shift (file_list) ;
- else {
- name = (char *) list_shift (file_list) ;
- if (name == (char *) NULL)
- return (struct file_info *) NULL ;
- else
- if (stat (name, &status) == -1) {
- perror (name) ;
- return ¬_there ; }
- else {
- if (! even_inaccessible) {
- if (status.st_uid == (UID_TYPE) uid)
- listable = status.st_mode & 0500 ;
- else {
- for (n = 0 ; n < no_groups ; n++) {
- if (status.st_gid == (GID_TYPE) groups[n]) {
- listable = status.st_mode & 050 ;
- n = no_groups + 1 ; } }
- if (n == no_groups)
- listable = status.st_mode & 05 ; } }
- else
- listable = TRUE ;
- if (! listable)
- return ¬_there ;
- else {
- file_info.name = name ;
- file_info.inode = status.st_ino ;
- file_info.mode = status.st_mode ;
- file_info.nlink = status.st_nlink ;
- file_info.size = status.st_size ;
- file_info.mtime = status.st_mtime ;
- return &file_info ; } } }
- }
-
-
- static void *get_element_from_dir () ;
-
-
- static
- void list_directory (name, show_directory)
- char *name ;
- int show_directory ;
- {
- DIR *directory ;
- struct list file_list ;
- struct file_info *file_info ;
-
- space = FALSE ;
- if (show_directory) {
- if (printed_anything) {
- printc ('\n') ; }
- printf ("%s:\n", name) ;
- printed_anything = TRUE ; }
-
- if ((directory = opendir (name)) == (DIR *) NULL) {
- perror (name) ; }
- else {
- list_init (&file_list) ;
- build_and_sort_list (&file_list, get_element_from_dir,
- (char *) directory, name) ;
- while ((file_info = get_file_info (&file_list))
- != (struct file_info *) NULL) {
- if (file_info != ¬_there)
- list_file (file_info, TRUE) ; }
- list_free (&file_list) ;
- closedir (directory) ; }
- space = TRUE ;
- }
-
-
- static
- void *get_element_from_dir (param_1, param_2)
- char *param_1 ;
- char *param_2 ;
- {
- char *p ;
- struct direct *dir_entry ;
- int n ;
-
- for (dir_entry = readdir ((DIR *) param_1) ;
- dir_entry != (struct direct *) NULL && dir_entry->d_name[0] == '.' ;
- dir_entry = readdir ((DIR *) param_1)) ;
- if (dir_entry == (struct direct *) NULL)
- return (void *) NULL ;
-
- n = strlen ((char *) param_2) + dir_entry->d_namlen + 2 ;
- p = (char *) smalloc ((size_t) n) ;
- strcpy (p, (char *) param_2) ;
- strcat (p, "/") ;
- strncat (p, dir_entry->d_name, dir_entry->d_namlen) ;
- p[n] = EOS ;
- return (void *) p ;
- }
-
-
- static
- char *get_description (pathname, inode_ptr)
- char *pathname ;
- ino_t *inode_ptr ;
- {
- static char desc_file[MAXNAMLEN+1] = "" ;
- static char new_desc_file[MAXNAMLEN+1] ;
- static char file_name[MAXNAMLEN+1] ;
- static datum key, value ;
- static int no_desc_file = TRUE ;
- static int desc_not_found ;
- struct stat status ;
- char *p ;
-
- split_pathname (pathname, new_desc_file, file_name) ;
-
- if (no_desc_file || strcmp (new_desc_file, desc_file) != 0) {
- strcpy (desc_file, new_desc_file) ;
- if (*new_desc_file != EOS)
- strcat (new_desc_file, "/") ;
- #ifdef NDBM
- strcat (new_desc_file, ".desc") ;
- dbm_close (desc_database) ;
- if ((desc_database = dbm_open (new_desc_file, O_RDONLY, 0))
- == (DBM *) NULL)
- desc_not_found = TRUE ;
- else
- no_desc_file = desc_not_found = FALSE ;
- #else
- strcat (new_desc_file, ".desc.pag") ;
- dbmclose () ;
- no_desc_file = TRUE ;
- /* Check this ourselves to prevent dbm from complaining */
- if (stat (new_desc_file, &status) == 0) {
- p = strrchr (new_desc_file, '.') ;
- *p = EOS ;
- dbminit (new_desc_file) ;
- no_desc_file = desc_not_found = FALSE ; }
- else {
- desc_not_found = TRUE ; }
- #endif /* NDBM */
- }
- if (desc_not_found) {
- return NULL_CP ; }
- else {
- /* Check for it by name */
- key.dptr = file_name ;
- key.dsize = strlen (file_name) ;
- if (key.dsize == sizeof (ino_t))
- key.dsize++ ;
- #ifdef NDBM
- value = dbm_fetch (desc_database, key) ;
- #else
- value = fetch (key) ;
- #endif
- if (value.dptr == NULL_CP) {
- /* Check for it by inode */
- key.dptr = (char *) inode_ptr ;
- key.dsize = sizeof (ino_t) ;
- #ifdef NDBM
- value = dbm_fetch (desc_database, key) ;
- #else
- value = fetch (key) ;
- #endif
- if (value.dptr != NULL_CP) {
- /* Now use the name we got using the inode */
- key.dptr = value.dptr ;
- key.dsize = value.dsize ;
- #ifdef NDBM
- value = dbm_fetch (desc_database, key) ;
- #else
- value = fetch (key) ;
- #endif
- } }
- return (char *) value.dptr ; }
- }
-
-
-
- static
- void list_file (file_info, doing_directory)
- struct file_info *file_info ;
- int doing_directory ;
- {
- static char month[][12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"} ;
- char *p ;
- static char file_name[MAXNAMLEN+1] ;
- char *desc ;
- static char size[12] ;
- static char date[16] ;
- int name_len, size_len, gap ;
- struct tm *tm_time ;
-
- strcpy (file_name, file_info->name) ;
- p = file_name ;
- if (! doing_directory && p[0] == '.' && p[1] == '/' && p[2] != EOS)
- p += 2 ;
- desc = get_description (p, &(file_info->inode)) ;
- if (doing_directory)
- p = strrchr (p, '/') + 1 ;
-
- name_len = strlen (p) ;
- /* If it is a directory, make it obvious */
- if (file_info->mode & S_IFDIR) {
- strcat (p, "/") ;
- name_len++ ;
- size[1] = EOS ;
- size_len = 1 ;
- if (file_info->nlink > 2) { /* Denotes a directory that contains */
- size[0] = '=' ; } /* one or more sub-directories */
- else {
- size[0] = '-' ; } }
- else {
- sprintf (size, "%d", file_info->size) ;
- size_len = strlen (size) ; }
- if (name_len + size_len < name_and_size_columns)
- gap = name_and_size_columns - name_len ;
- else {
- print (p) ;
- p[0] = '\n' ; p[1] = EOS ;
- gap = name_and_size_columns ; }
- if (show_date) {
- tm_time = localtime (&file_info->mtime) ;
- if (six_months_ago > file_info->mtime) {
- /* The bloody thing is more than 6 months old! */
- #ifdef US_DATE_FORMAT
- sprintf (date, " %s %2d %d ", month[tm_time->tm_mon],
- tm_time->tm_mday, tm_time->tm_year + 1900) ;
- #else
- sprintf (date, " %2d %s %d ", tm_time->tm_mday,
- month[tm_time->tm_mon], tm_time->tm_year + 1900) ;
- #endif
- }
- else {
- #ifdef US_DATE_FORMAT
- sprintf (date " %s %2d %02d:%02d ", month[tm_time->tm_mon],
- tm_time->tm_mday, tm_time->tm_hour, tm_time->tm_min) ;
- #else
- sprintf (date, " %2d %s %02d:%02d ", tm_time->tm_mday,
- month[tm_time->tm_mon], tm_time->tm_hour, tm_time->tm_min) ;
- #endif
- } }
- else {
- date[0] = ' ' ;
- date[1] = EOS ; }
-
- if (space) {
- printc ('\n') ;
- space = FALSE ; }
- printf ("%s %*s%s %s\n", p, gap, size, date, desc) ;
- printed_anything = TRUE ;
- }
-