[comp.os.minix] More ls fixes

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

I previously posted two sets of diffs for an improved ls.
Here are the diffs for yet another one that fixes yet another problem
that seems to have arisen with the original ls, and therefore is still
present in the one with my diffs. It seems that files whose names are
14 characters long, will occasionally print with garbage after the end of
the name. This seems to have to do with the structure containing the name
having no room for an end of string mark in the name. I added some more
code to deal with this. I also added some code to fix a problem with
directory headings when specific files and directories are
listed on the command line. That problem resulted in
a column misalignment of the first line of one of the directory
listings on occasion.

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	Tue May 19 09:28:11 1987
--- ls.new	Tue May 19 09:28:31 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,258 ----
  {
  /*  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;
+   cc = 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) {
--- 286,292 ----
    }
    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) {
***************
*** 310,316 ****
  print_line(fp)
  struct file *fp;
  {
!   int blks, m, prot, s;
    char *p1, *p2, *p3, c;
  
    if (present('i')) fprintf(stdout, "%5d ", fp->inumber);
--- 336,342 ----
  print_line(fp)
  struct file *fp;
  {
!   int blks, cnt, m, prot, s;
    char *p1, *p2, *p3, c;
  
    if (present('i')) fprintf(stdout, "%5d ", fp->inumber);
***************
*** 355,362 ****
          date(fp->modtime);
    }
  
!         /* Print file name. */
!         fprintf(stdout, "%s\n",fp->name);
  }
  
  
--- 381,416 ----
          date(fp->modtime);
    }
  
!   /* Print file name. */
!   while(cc % COLSIZ) {          /* pad to columnarize */
!         fputc(' ', stdout);
!         cc++;
!   }
! 
!   m = 0;
!   cnt = 0;
!   while((m < MAX_PATH) && ((c = (fp->name)[m]) != 0)) {
!         if (cnt < DIRNAMELEN) {
!                 fputc(c, stdout);
!                 cc++;
!         }
!         if (c == '/')
!                 cnt = 0;
!         else
!                 cnt++;
!         m++;
!   }
! 
!   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 ****
--- 506,516 ----
          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 ****
--- 529,536 ----
  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;
--- 641,653 ----
    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 ****
--- 702,706 ----
    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