[comp.os.minix] Diffs for an even better ls

hgm@beta.UUCP (Harry McGavran) (05/11/87)

I previously posted the diffs for an improved ls. Here are the diffs
for one that is a bit better yet. For one thing, I had done a real
hoaky replacement for isatty, because I found that isatty(stdout)
didn't work. Alan Bishop was kind enough to write me that of course
that won't work. isatty takes file descriptors not pointers. He is
certainly correct, and I wish to thank him very much for discreetly
pointing it out to me. I have recovered from that stupidity
and replaced the hoaky code with isatty(1).

I also added one minor enhancement to my previous posting. When one
specified directories on the ls execute line, he would get an
extra blank line at the end of the listing due to the recursion in "print".
One point in having ls default to single column when not going to the tty
is to pipe its output to wc and such. The extra blank line can mess that
up, so I fixed that possibility.

These diffs below are the previous enhancements plus what is described above.
Start with the ORIGINAL ls source.  The remaining enhancement description is
included below in case you didn't see the original article.

		  - - - - - - - -

This ls prints multiple columns sorted DOWN rather than across.

When it detects that stdout is not the tty, it defaults to a single column.

By default it also appends a "*" to the executables and a "/"
to the directories.

I have added to options to disable the above features. "-1" causes single
column output, and "-m" cause multiple column output when stdout is not
to the tty.

"-n" will turn off the addition of "*" and "/".

I make no claims as to the suitability of these changes for anything.

I extend my appreciation to Ed Nather, whose "ls" for MS-DOS gave me
the ideas and some of the code for this. I believe he doesn't mind
redistribution of it, as long as he gets credit.

Hope you find this useful.

To install it, move your ORIGINAL ls source to some system with the
latest version of "patch".  Cut the diffs below out into a file
called "ls.pat". Then type "patch -l ls.c <ls.pat" to get your
new ls.c.

------------------------------Cut here----------------------------------
*** ls.c	Mon May 11 11:45:45 1987
--- ls.new	Mon May 11 11:42:46 1987
***************
*** 11,17 ****
  #define NFILE            256    /* max files in arg list to ls */
  #define MAXPATHLEN       256    /* max chars in a path name */
  #define NDIRBLOCKS        16    /* max length of a directory */
! #define LEGAL      0x1E096DL    /* legal flags to ls */
  
  struct file {
    char *name;
--- 11,17 ----
  #define NFILE            256    /* max files in arg list to ls */
  #define MAXPATHLEN       256    /* max chars in a path name */
  #define NDIRBLOCKS        16    /* max length of a directory */
! #define LEGAL      0x1E396DL    /* legal flags to ls */
  
  struct file {
    char *name;
***************
*** 48,55 ****
  extern char *getuidgid();
  extern int errno;
  
  
- 
  main(argc, argv)
  int argc;
  char *argv[];
--- 48,57 ----
  extern char *getuidgid();
  extern int errno;
  
+ int cc;                         /* column count */
+ int multcol;                    /* flag for multiple columns */
+ #define COLSIZ  16              /* width of field in multi-column mode */
  
  main(argc, argv)
  int argc;
  char *argv[];
***************
*** 59,64 ****
--- 61,68 ----
  
    setbuf(stdout, buffer);
    expand_flag = 1;
+   cc = 0;
+   multcol = 1;
    flags = get_flags(argc, argv);
    expand_args(argc, argv);
  
***************
*** 67,73 ****
          exp_dir(&file[NFILE]);
          expand_flag = 0;
    }
!   if (present('f')) flags = 0x21;       /* -f forces other flags on and off */
    sort(0, nrfiles, expand_flag);
  
    if (present('l')) {
--- 71,81 ----
          exp_dir(&file[NFILE]);
          expand_flag = 0;
    }
!   /* if (present('f')) flags = 0x21; */ /* -f forces other flags on and off */
!   if (present('f')) flags &= (~(0x1A0004L));
!   if (!present('m'))
!         if (!isatty(1))         /* if stdout is a file, use one column */
!                 multcol = 0;
    sort(0, nrfiles, expand_flag);
  
    if (present('l')) {
***************
*** 97,103 ****
    k = argc - topfiles;
    statflag = (topfiles == 0 ? 0 : 1);
    if (present('c') || present('t') || present('u')) statflag = 1;
!   if (present('s') || present('l')) statflag = 1;
    while (k < argc) fill_file("", argv[k++], statflag);
  }
  
--- 105,111 ----
    k = argc - topfiles;
    statflag = (topfiles == 0 ? 0 : 1);
    if (present('c') || present('t') || present('u')) statflag = 1;
!   if (present('s') || present('l') || !present('n')) statflag = 1;
    while (k < argc) fill_file("", argv[k++], statflag);
  }
  
***************
*** 110,116 ****
  {
  /* Sort the elements file[index] ... file[index+count-1] as needed. */
  
!   int i, j, tmp;
  
    if (count == 0) return;
    for (i = index; i < index + count; i++) sort_index[i] = i;
--- 118,125 ----
  {
  /* Sort the elements file[index] ... file[index+count-1] as needed. */
  
!   int i, j, m, n, tmp;
!   short tmp_index[5];
  
    if (count == 0) return;
    for (i = index; i < index + count; i++) sort_index[i] = i;
***************
*** 125,130 ****
--- 134,140 ----
                          sort_index[i] = tmp;
                  }
          }
+ 
  }
  
  
***************
*** 203,232 ****
  {
  /*  If an entry is a file, print it; if a directory, process it. */
  
!   int k, m, nrf;
    struct file *fp;
  
    nrf = nrfiles;
!   for (k = index; k < index + count; k++) {
!         fp = &file[sort_index[k]];
!         if (present('l') || present('s') || present('i'))
!                 if (fp->size == -1L)    /* -1 means stat not done */
!                         if (stat_file(dirname, fp) < 0) continue;
  
!         m = fp->mode & I_TYPE;  /* 'm' may be junk if 'expand' = 0 */
!         if (present('f')) m = I_DIRECTORY;
!         if (m != I_DIRECTORY || present('d') || expand == 0) {
!                 /* List a single line. */
!                 print_line(fp);
!         } else {
!                 /* Expand and print directory. */
!                 exp_dir(fp);
!                 sort(nrf, nrfiles - nrf, 0);
!                 if (topfiles > 1) fprintf(stdout, "\n%s:\n", fp->name);
!                 print_total(nrf, nrfiles - nrf);
!                 print(nrf, nrfiles - nrf, 0, fp->name); /* recursion ! */
!                 nrfiles = nrf;
          }
    }
  }
  
--- 213,257 ----
  {
  /*  If an entry is a file, print it; if a directory, process it. */
  
!   int k, l, m, n, nrf;
!   int recursion;
    struct file *fp;
  
+   recursion = 0;
+ 
+   if(present('1') || present('i') || present('s') || present ('l'))
+         n = count;              /* set for 1-column listing */
+   else
+         n = (count + 4)/5;      /* or 5-column */
+ 
    nrf = nrfiles;
!   for (k = index; k < (index+n); k++) {
!         for(l = 0; (k+l) < (index+count); l += n) {
!                 fp = &file[sort_index[k+l]];
!                 if (present('l') || present('s') || present('i'))
!                         if (fp->size == -1L)    /* -1 means stat not done */
!                                 if (stat_file(dirname, fp) < 0) continue;
  
!                 m = fp->mode & I_TYPE;  /* 'm' may be junk if 'expand' = 0 */
!                 if (present('f')) m = I_DIRECTORY;
!                 if (m != I_DIRECTORY || present('d') || expand == 0) {
!                         /* List a single line. */
!                         print_line(fp);
!                 } else {
!                         /* Expand and print directory. */
!                         exp_dir(fp);
!                         sort(nrf, nrfiles - nrf, 0);
!                         if (topfiles > 1) fprintf(stdout, "\n%s:\n", fp->name);
!                         print_total(nrf, nrfiles - nrf);
!                         print(nrf, nrfiles - nrf, 0, fp->name); /* recursion ! */
!                         recursion++;
!                         nrfiles = nrf;
!                 }
          }
+         if (!recursion) {
+                 cc = 0;
+                 fputc('\n',stdout);
+         }
    }
  }
  
***************
*** 260,266 ****
    }
    statflag = 0;
    if (present('c') || present('t') || present('u')) statflag = 1;
!   if (present('s') || present('l')) statflag = 1;
  
    for (k = 0; k < klim; k++) {
          if (dir[k].inum != 0) {
--- 285,291 ----
    }
    statflag = 0;
    if (present('c') || present('t') || present('u')) statflag = 1;
!   if (present('s') || present('l') || !present('n')) statflag = 1;
  
    for (k = 0; k < klim; k++) {
          if (dir[k].inum != 0) {
***************
*** 355,362 ****
          date(fp->modtime);
    }
  
!         /* Print file name. */
!         fprintf(stdout, "%s\n",fp->name);
  }
  
  
--- 380,407 ----
          date(fp->modtime);
    }
  
!   /* Print file name. */
!   while(cc % COLSIZ) {          /* pad to columnarize */
!         fputc(' ', stdout);
!         cc++;
!   }
! 
!   m = 0;
!   while((c = (fp->name)[m++]) != 0) {
!         fputc(c, stdout);
!         cc++;
!   }
! 
!   if (!present('n')) {          /* add entry type */
!         if ((fp->mode & I_TYPE) == I_DIRECTORY) {
!                 fputc('/', stdout);
!                 cc++;
!         } else if (fp->mode & 0111) {
!                 fputc('*', stdout);
!                 cc++;
!         }
!   }
! 
  }
  
  
***************
*** 452,457 ****
--- 497,507 ----
          ptr++;
  
          while (*ptr != 0) {
+                 if (*ptr == '1') {
+                         multcol = 0;
+                         ptr++;
+                         continue;
+                 }
                  k = *ptr - 'a';
                  t = 1L << k;
                  if (*ptr < 'a' || *ptr > 'z' || (t|LEGAL) != LEGAL) {
***************
*** 470,475 ****
--- 520,527 ----
  present(let)
  char let;
  {
+   if (let == '1')
+         return (!multcol);
    return  (flags >> (let - 'a')) & 01;
  }
  
***************
*** 580,590 ****
    char lbuf[100], *ptr, *ptr1;
    int bin;
  
    if (usrid == lastuid) return(lastname);
    lseek(passwd, 0L, 0);         /* rewind the file */
    linenext = 0;
    linelimit = 0;
!   
    /* Scan the file. */
    while (1) {
          ptr = lbuf;
--- 632,644 ----
    char lbuf[100], *ptr, *ptr1;
    int bin;
  
+   extern long lseek();
+ 
    if (usrid == lastuid) return(lastname);
    lseek(passwd, 0L, 0);         /* rewind the file */
    linenext = 0;
    linelimit = 0;
! 
    /* Scan the file. */
    while (1) {
          ptr = lbuf;
***************
*** 639,642 ****
--- 693,697 ----
    blocks += (fileb + NR_INDIRECTS - 1)/NR_INDIRECTS;
    return(blocks);
  }
+ 
  
-----------------------------Cut here---------------------------------

Harry McGavran
hgm@LANL.GOV
Los Alamos National Laboratory
MS-B294, Group C-8
Los Alamos, New Mexico 87545
505/667-4050