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