home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / hamradio / s920603.zip / DIRUTIL.C < prev    next >
C/C++ Source or Header  |  1992-06-01  |  9KB  |  422 lines

  1. /* dirutil.c - MS-DOS directory reading routines
  2.  *
  3.  * Bdale Garbee, N3EUA, Dave Trulli, NN2Z, and Phil Karn, KA9Q
  4.  * Directory sorting by Mike Chepponis, K3MC
  5.  * New version using regs.h by Russell Nelson.
  6.  * Rewritten for Turbo-C 2.0 routines by Phil Karn, KA9Q 25 March 89
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <dir.h>
  11. #include <dos.h>
  12. #include <stdlib.h>
  13. #include "global.h"
  14. #include "dirutil.h"
  15. #include "proc.h"
  16. #include "commands.h"
  17.  
  18. struct dirsort {
  19.     struct dirsort *next;
  20.     struct ffblk de;
  21. };
  22. #define    NULLSORT (struct dirsort *)0
  23.  
  24. static void commas __ARGS((char *dest));
  25. static int fncmp __ARGS((char *a, char *b));
  26. static void format_fname_full __ARGS((FILE *file,struct ffblk *sbuf,int full,
  27.     int n));
  28. static void free_clist __ARGS((struct dirsort *this));
  29.  
  30. #ifdef    notdef
  31. static int getdir_nosort __ARGS((char *path,int full,FILE *file));
  32. #endif
  33. static int nextname __ARGS((int command, char *name, struct ffblk *sbuf));
  34. static void print_free_space __ARGS((FILE *file,int n));
  35. static void undosify __ARGS((char *s));
  36. static char *wildcardize __ARGS((char *path));
  37.  
  38. #define REGFILE    (FA_HIDDEN|FA_SYSTEM|FA_DIREC)
  39.  
  40. #define    insert_ptr(list,new)    (new->next = list,list = new)
  41.  
  42.  
  43. /* Create a directory listing in a temp file and return the resulting file
  44.  * descriptor. If full == 1, give a full listing; else return just a list
  45.  * of names.
  46.  */
  47. FILE *
  48. dir(path,full)
  49. char *path;
  50. int full;
  51. {
  52.     FILE *fp;
  53.  
  54.     if((fp = tmpfile()) != NULLFILE){
  55.         getdir(path,full,fp);
  56.         rewind(fp);
  57.     }
  58.     return fp;
  59. }
  60.  
  61. /* find the first or next file and lowercase it. */
  62. static int
  63. nextname(command, name, sbuf)
  64. int command;
  65. char *name;
  66. struct ffblk *sbuf;
  67. {
  68.     int found;
  69.  
  70.     switch(command){
  71.     case 0:
  72.         found = findfirst(name,sbuf,REGFILE);
  73.         break;
  74.     default:
  75.         found = findnext(sbuf);
  76.     }
  77.     found = found == 0;
  78.     if(found)
  79.         strlwr(sbuf->ff_name);
  80.  
  81.     return found;
  82. }
  83.  
  84. /* wildcard filename lookup */
  85. int
  86. filedir(name,times,ret_str)
  87. char *name;
  88. int times;
  89. char *ret_str;
  90. {
  91.     static struct ffblk sbuf;
  92.     int rval;
  93.  
  94.     switch(times){
  95.     case 0:
  96.         rval = findfirst(name,&sbuf,REGFILE);
  97.         break;
  98.     default:
  99.         rval = findnext(&sbuf);
  100.         break;
  101.     }
  102.     if(rval == -1){
  103.         ret_str[0] = '\0';
  104.     } else {
  105.         /* Copy result to output */
  106.         strcpy(ret_str, sbuf.ff_name);
  107.     }
  108.     return rval;
  109. }
  110. /* do a directory list to the stream 
  111.  * full = 0 -> short form, 1 is long
  112. */
  113. int
  114. getdir(path,full,file)
  115. char *path;
  116. int full;
  117. FILE *file;
  118. {
  119.     struct ffblk sbuf;
  120.     int command = 0;
  121.     int n = 0;
  122.     struct dirsort *head, *here, *new;
  123.  
  124.     path = wildcardize(path);
  125.  
  126.     head = NULLSORT;    /* No head of chain yet... */
  127.     for(;;){
  128.         if (!nextname(command, path, &sbuf))
  129.             break;
  130.         command = 1;    /* Got first one already... */
  131.         if (sbuf.ff_name[0] == '.')    /* drop "." and ".." */
  132.             continue;
  133.  
  134.         new = (struct dirsort *) mallocw(sizeof(struct dirsort));
  135.         new->de = sbuf;    /* Copy contents of directory entry struct */
  136.  
  137.         /* insert it into the list */
  138.         if (!head || fncmp(new->de.ff_name, head->de.ff_name) < 0) {
  139.             insert_ptr(head, new);
  140.         } else {
  141.             register struct dirsort *this;
  142.             for (this = head;
  143.                 this->next != NULLSORT;
  144.                 this = this->next)
  145.                 if (fncmp(new->de.ff_name, this->next->de.ff_name) < 0)
  146.                     break;
  147.             insert_ptr(this->next, new);
  148.         }
  149.     } /* infinite FOR loop */
  150.  
  151.     for (here = head; here; here = here->next)
  152.         format_fname_full(file,&here->de,full,++n);
  153.  
  154.     /* Give back all the memory we temporarily needed... */
  155.     free_clist(head);
  156.  
  157.     if(full)
  158.         print_free_space(file, n);
  159.  
  160.     return 0;
  161. }
  162. static int
  163. fncmp(a,b)
  164. register char *a, *b;
  165. {
  166.         int i;
  167.  
  168.     for(;;){
  169.         if (*a == '.')
  170.             return -1;
  171.         if (*b == '.')
  172.             return 1;
  173.         if ((i = *a - *b++) != 0)
  174.             return i;
  175.         if (!*a++)
  176.             return -1;
  177.     }
  178. }
  179. /* Change working directory */
  180. int
  181. docd(argc,argv,p)
  182. int argc;
  183. char *argv[];
  184. void *p;
  185. {
  186.     char dirname[128];
  187.  
  188.     if(argc > 1){
  189.         if(chdir(argv[1]) == -1){
  190.             printf("Can't change directory\n");
  191.             return 1;
  192.         }
  193.     }
  194.     if(getcwd(dirname,128) != NULLCHAR){
  195.         undosify(dirname);
  196.         printf("%s\n",dirname);
  197.     }
  198.     return 0;
  199. }
  200. /* List directory to console */
  201. int
  202. dodir(argc,argv,p)
  203. int argc;
  204. char *argv[];
  205. void *p;
  206. {
  207.     char *path;
  208.     FILE *fp;
  209.  
  210.     if(argc >= 2)
  211.         path = argv[1];
  212.     else
  213.         path = "*.*";
  214.  
  215.     fp = tmpfile();
  216.     getdir(path,1,fp);
  217.     newproc("view",512,view,0,(void *)fp,(void *)strdup(path),0);
  218.     return 0;
  219. }
  220. /* Create directory */
  221. int
  222. domkd(argc,argv,p)
  223. int argc;
  224. char *argv[];
  225. void *p;
  226. {
  227.     if(mkdir(argv[1]) == -1)
  228.         perror("Can't mkdir");
  229.     return 0;
  230. }
  231. /* Remove directory */
  232. int
  233. dormd(argc,argv,p)
  234. int argc;
  235. char *argv[];
  236. void *p;
  237. {
  238.     if(rmdir(argv[1]) == -1)
  239.         perror("Can't rmdir");
  240.     return 0;
  241. }
  242.  
  243. /*
  244.  * Return a string with commas every 3 positions.
  245.  * the original string is replace with the string with commas.
  246.  *
  247.  * The caller must be sure that there is enough room for the resultant
  248.  * string.
  249.  *
  250.  *
  251.  * k3mc 4 Dec 87
  252.  */
  253. static void
  254. commas(dest)
  255. char *dest;
  256. {
  257.     char *src, *core;    /* Place holder for malloc */
  258.     unsigned cc;        /* The comma counter */
  259.     unsigned len;
  260.  
  261.     len = strlen(dest);
  262.     /* Make a copy, so we can muck around */
  263.     core = src = strdup(dest);
  264.  
  265.     cc = (len-1)%3 + 1;    /* Tells us when to insert a comma */
  266.  
  267.     while(*src != '\0'){
  268.         *dest++ = *src++;
  269.         if( ((--cc) == 0) && *src ){
  270.             *dest++ = ','; cc = 3;
  271.         }
  272.     }
  273.     free(core);
  274.     *dest = '\0';
  275. }
  276. /* fix up the filename so that it contains the proper wildcard set */
  277. static char *
  278. wildcardize(path)
  279. char *path;
  280. {
  281.     struct ffblk sbuf;
  282.     static char ourpath[64];
  283.  
  284.     /* Root directory is a special case */
  285.     if(path == NULLCHAR ||
  286.        *path == '\0' ||
  287.        strcmp(path,"\\") == 0 ||
  288.        strcmp(path,"/") == 0)
  289.         path = "\\*.*";
  290.  
  291.     /* if they gave the name of a subdirectory, append \*.* to it */
  292.     if (nextname(0, path, &sbuf) &&
  293.         (sbuf.ff_attrib & FA_DIREC) &&
  294.         !nextname(1, path, &sbuf)) {
  295.  
  296.         /* if there isn't enough room, give up -- it's invalid anyway */
  297.         if (strlen(path) + 4 > 63) return path;
  298.         strcpy(ourpath, path);
  299.         strcat(ourpath, "\\*.*");
  300.         return ourpath;
  301.     }
  302.     return path;
  303. }
  304.  
  305. static void
  306. format_fname_full(file, sbuf, full, n)
  307. FILE *file;
  308. struct ffblk *sbuf;
  309. int full, n;
  310. {
  311.     char line_buf[50];        /* for long dirlist */
  312.     char cbuf[20];            /* for making line_buf */
  313.  
  314.     strcpy(cbuf,sbuf->ff_name);
  315.     if(sbuf->ff_attrib & FA_DIREC) strcat(cbuf, "/");
  316.     if (full) {
  317.         /* Long form, give other info too */
  318.         sprintf(line_buf,"%-13s",cbuf);
  319.         if(sbuf->ff_attrib & FA_DIREC)
  320.             strcat(line_buf,"           ");/* 11 spaces */
  321.         else {
  322.             sprintf(cbuf,"%ld",sbuf->ff_fsize);
  323.             commas(cbuf);
  324.             sprintf(line_buf+strlen(line_buf),"%10s ",cbuf);
  325.         }
  326.         sprintf(line_buf+strlen(line_buf),"%2d:%02d %2d/%02d/%02d%s",
  327.           (sbuf->ff_ftime >> 11) & 0x1f,    /* hour */
  328.           (sbuf->ff_ftime >> 5) & 0x3f,    /* minute */
  329.           (sbuf->ff_fdate >> 5) & 0xf,    /* month */
  330.           (sbuf->ff_fdate ) & 0x1f,        /* day */
  331.           (sbuf->ff_fdate >> 9) + 80,    /* year */
  332.           (n & 1) ? "   " : "\n");
  333.         fputs(line_buf,file);
  334.     } else {
  335.         fputs(cbuf,file);
  336.         fputs("\n",file);
  337.     }
  338. }
  339. /* Provide additional information only on DIR */
  340. static void
  341. print_free_space(file, n)
  342. FILE *file;
  343. int n;
  344. {
  345.     unsigned long free_bytes, total_bytes;
  346.     char s_free[11], s_total[11];
  347.     char cbuf[20];
  348.     struct dfree dtable;
  349.     unsigned long bpcl;
  350.  
  351.     if(n & 1)
  352.         fputs("\n",file);
  353.  
  354.     /* Find disk free space */
  355.     getdfree(0,&dtable);
  356.  
  357.     bpcl = dtable.df_bsec * dtable.df_sclus;
  358.     free_bytes  = dtable.df_avail * bpcl;
  359.     total_bytes = dtable.df_total * bpcl;
  360.  
  361.     sprintf(s_free,"%ld",free_bytes);
  362.     commas(s_free);
  363.     sprintf(s_total,"%ld",total_bytes);
  364.     commas(s_total);
  365.  
  366.     if(n)
  367.         sprintf(cbuf,"%d",n);
  368.     else
  369.         strcpy(cbuf,"No");
  370.  
  371.     fprintf(file,"%s file%s. %s bytes free. Disk size %s bytes.\n",
  372.         cbuf,(n==1? "":"s"),s_free,s_total);
  373. }
  374. static void
  375. free_clist(this)
  376. struct dirsort *this;
  377. {
  378.     struct dirsort *next;
  379.  
  380.     while (this != NULLSORT) {
  381.         next = this->next;
  382.         free(this);
  383.         this = next;
  384.     }
  385. }
  386. #ifdef    notdef
  387. static int
  388. getdir_nosort(path,full,file)
  389. char *path;
  390. int full;
  391. FILE *file;
  392. {
  393.     struct ffblk sbuf;
  394.     int command;
  395.     int n = 0;    /* Number of directory entries */
  396.  
  397.     path = wildcardize(path);
  398.     command = 0;
  399.     while(nextname(command, path, &sbuf)){
  400.         command = 1;    /* Got first one already... */
  401.         if (sbuf.ff_name[0] == '.')    /* drop "." and ".." */
  402.             continue;
  403.         format_fname_full(file, &sbuf, full, ++n);
  404.     }
  405.     if(full)
  406.         print_free_space(file, n);
  407.     return 0;
  408. }
  409. #endif
  410.  
  411. /* Translate those %$#@!! backslashes to proper form */
  412. static void
  413. undosify(s)
  414. char *s;
  415. {
  416.     while(*s != '\0'){
  417.         if(*s == '\\')
  418.             *s = '/';
  419.         s++;
  420.     }
  421. }
  422.