home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / c / snippets / lsd.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  7KB  |  268 lines

  1. /*
  2. ** LSD - A simple directory lister
  3. ** A public domain C demo program by Bob Stout
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include <dos.h>
  11.  
  12. char *sprintfc(char *, long);
  13. char *capitalize(const char *);
  14.  
  15. /* For portability, make everything look like MSC 6+ */
  16.  
  17. #if defined(__TURBOC__)
  18.  #include <dir.h>
  19.  #define _dos_findfirst(f,a,b) findfirst(f,b,a)
  20.  #define _dos_findnext(b) findnext(b)
  21.  #define find_t ffblk
  22.  #define _A_SUBDIR FA_DIREC
  23.  #define attrib ff_attrib
  24.  #define name ff_name
  25.  #define size ff_fsize
  26.  #define wr_time ff_ftime
  27.  #define wr_date ff_fdate
  28.  #define _dos_getdiskfree getdfree
  29.  #define diskfree_t dfree
  30.  #define avail_clusters df_avail
  31.  #define sectors_per_cluster df_sclus
  32.  #define bytes_per_sector df_bsec
  33. #else                                     /* assume MSC/QC              */
  34.  #include <errno.h>
  35. #endif
  36.  
  37. #ifdef TRUE
  38.  #undef TRUE
  39. #endif
  40. #ifdef FALSE
  41.  #undef FALSE
  42. #endif
  43. #ifdef ERROR
  44.  #undef ERROR
  45. #endif
  46.  
  47. enum LOGICAL {ERROR = -1, SUCCESS, FALSE = 0, TRUE};
  48.  
  49. #ifndef CAST
  50.  #define CAST(new_type,old_object) (*((new_type *)&(old_object)))
  51. #endif
  52.  
  53. #define LAST_CHAR(s) (((char *)s)[strlen(s) - 1])
  54.  
  55. struct DOS_TIME {
  56.         unsigned int ss : 5;
  57.         unsigned int mm : 6;
  58.         unsigned int hh : 5;
  59.         } ;
  60. #define dos_time(t) CAST(struct DOS_TIME, (t))
  61.  
  62. struct DOS_DATE {
  63.         unsigned int da : 5;
  64.         unsigned int mo : 4;
  65.         unsigned int yr : 7;
  66.         } ;
  67. #define dos_date(t) CAST(struct DOS_DATE, (t))
  68.  
  69. /*
  70. **  DOS DIR improved work-alike w/ improved formatting & attribute display
  71. **
  72. **  supports /W switch
  73. */
  74.  
  75. main(int argc, char *argv[])
  76. {
  77.       int i, files = 0, dirs = 0, argptr = 0, errflag = FALSE, cols, drive;
  78.       long siz_tot = 0L;
  79.       char *p, *fname, *ext, name[13], buf[67], numbuf[12];
  80.       struct find_t ff;
  81. #ifndef __ZTC__
  82.       struct diskfree_t df;
  83. #endif
  84.       int one_column(), five_column();
  85.       int (*display)(char *, char *, long, unsigned, unsigned, unsigned)
  86.             = one_column;
  87.       char *sprintfc(char *, long);
  88.       char *capitalize(const char *);
  89.  
  90.       strcpy(buf, fname = "*.*");
  91.       if(argc != 1)   for (i = 1; i < argc; ++i)
  92.       {
  93.             if ('/' == argv[i][0])
  94.             {
  95.                   if ('W' == toupper(argv[i][1]))
  96.                         display = five_column;
  97.                   else
  98.                   {
  99.                         puts("\aUsage: LSD [/W] [file]");
  100.                         errflag = TRUE;
  101.                   }
  102.             }
  103.             else if (!argptr)
  104.                   argptr = i;
  105.       }
  106.       if (argptr)
  107.       {
  108.             fname = argv[argptr];
  109.             strcpy(buf, fname);
  110.             if ('\\' == LAST_CHAR(buf) || ':' == LAST_CHAR(buf))
  111.                   strcat(buf, "*.*");
  112.             else
  113.             {
  114.                   if (SUCCESS == _dos_findfirst(buf, _A_SUBDIR, &ff))
  115.                   {
  116.                         if (ff.attrib & _A_SUBDIR && '.' != *ff.name)
  117.                         {
  118.                               if ('\\' != LAST_CHAR(buf))
  119.                                     strcat(buf, "\\");
  120.                               strcat(buf, "*.*");
  121.                         }
  122.                   }
  123.                   else  errflag = TRUE;
  124.             }
  125.       }
  126.       if (':' == buf[1])
  127.             drive = toupper(*buf) - '@';
  128.       else  drive = 0;
  129.       if (!errflag && !(_dos_findfirst(buf, 0xff, &ff))) do
  130.       {
  131.             siz_tot += ff.size;
  132.             if (ff.attrib & _A_SUBDIR)
  133.                   ++dirs;
  134.             else  ++files;
  135.             strcpy(name, ff.name);
  136.             if (NULL != (p = strchr(name, '.')) && p != name)
  137.             {
  138.                   *p  = '\0';
  139.                   ext = ++p;
  140.             }
  141.             else  ext = "";
  142.             cols = (*display)(name, ext, ff.size,
  143.                   ff.attrib, ff.wr_date, ff.wr_time);
  144.       } while (SUCCESS == _dos_findnext(&ff));
  145.       else
  146.       {
  147.             fprintf(stderr, "Cannot do directory on '%s'\n", fname);
  148.             exit(-1);
  149.       }
  150.       if (cols)
  151.             fputc('\n', stdout);
  152.       sprintfc(numbuf,siz_tot);
  153.       printf("\n%3d Files totalling %s bytes\n", files, numbuf);
  154.       printf("%3d Director%s\n", dirs, (1 == dirs) ? "y" : "ies");
  155. #ifndef __ZTC__
  156.       _dos_getdiskfree(drive, &df);
  157.       sprintfc(numbuf, (long)df.avail_clusters * df.sectors_per_cluster *
  158.             df.bytes_per_sector);
  159. #else /* if ZTC */
  160.       sprintfc(numbuf, dos_getdiskfreespace(drive));
  161. #endif
  162.       printf("%s bytes free\n", numbuf);
  163.       return 0;
  164. }
  165.  
  166. /*
  167. **  The single column directory entry display function
  168. */
  169.  
  170. int one_column(char    *name,
  171.                char    *ext,
  172.                long     size,
  173.                unsigned attribs,
  174.                unsigned date,
  175.                unsigned time)
  176. {
  177.       register int i, mask;
  178.       static char *atr = "RHSVDA", szbuf[12];
  179.  
  180.       sprintfc(szbuf, size);
  181.       printf("%-8s %-3s %12s  ", capitalize(name), capitalize(ext), szbuf);
  182.  
  183.       for (i = 0, mask = 1; i < 6; ++i, mask <<= 1)
  184.             fputc((attribs & mask) ? atr[i] : '.', stdout);
  185.  
  186.       printf("%4d-%02d-%02d%4d:%02d:%02d\n",
  187.             dos_date(date).mo,
  188.             dos_date(date).da,
  189.             (dos_date(date).yr + 80) % 100,
  190.             dos_time(time).hh,
  191.             dos_time(time).mm,
  192.             dos_time(time).ss);
  193.  
  194.       return 0;
  195. }
  196.  
  197. /*
  198. **  The five column directory entry display function
  199. */
  200.  
  201. int five_column(char    *name,
  202.                 char    *ext,
  203.                 long     size,
  204.                 unsigned attribs,
  205.                 unsigned date,
  206.                 unsigned time)
  207. {
  208.       static int cols = 0;
  209.  
  210.       printf("%-8s %-3s%s", capitalize(name), capitalize(ext),
  211.             (5 > ++cols) ? "    " : "");
  212.       if (0 == (cols %= 5))
  213.             putchar('\n');
  214.       return (cols);
  215. }
  216.  
  217. /*
  218. **  Display a long int using commas as thousands separators
  219. */
  220.  
  221. char *sprintfc(char *string, long num)
  222. {
  223.       if (num > 999999L)
  224.       {
  225.             sprintf(string, "%d,%03d,%03d",
  226.                   (int)(num / 1000000L),
  227.                   (int)((num % 1000000L) / 1000L),
  228.                   (int)(num % 1000L));
  229.       }
  230.       else
  231.       {
  232.             if (num > 999L)
  233.             {
  234.                   sprintf(string, "%d,%03d",
  235.                         (int)(num / 1000L),
  236.                         (int)(num % 1000L));
  237.             }
  238.             else  sprintf(string, "%d", (int)num);
  239.       }
  240.       return string;
  241. }
  242.  
  243. /*
  244. **  Capitalize a name or extension in place
  245. */
  246.  
  247. char *capitalize(const char *string)
  248. {
  249.       int flag = 0;
  250.       char *ptr = (char *)string;
  251.  
  252.       do
  253.       {
  254.             if (isalpha(*ptr))
  255.             {
  256.                   if (flag)
  257.                         *ptr = (char)tolower(*ptr);
  258.                   else
  259.                   {
  260.                         flag = 1;
  261.                         *ptr = (char)toupper(*ptr);
  262.                   }
  263.             }
  264.             else  flag = 0;
  265.       } while (*++ptr);
  266.       return (char *)string;
  267. }
  268.