home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / network / src_1218.zip / PATHNAME.C < prev    next >
C/C++ Source or Header  |  1991-03-08  |  3KB  |  123 lines

  1. /* Convert relative to absolute pathnames
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "dirutil.h"
  7.  
  8. static void crunch __ARGS((char *buf,char *path));
  9.  
  10. /* Given a working directory and an arbitrary pathname, resolve them into
  11.  * an absolute pathname. Memory is allocated for the result, which
  12.  * the caller must free
  13.  */
  14. char *
  15. pathname(cd,path)
  16. char *cd;    /* Current working directory */
  17. char *path;    /* Pathname argument */
  18. {
  19.     register char *buf;
  20. #ifdef    MSDOS
  21.     char *cp,c;
  22.     char *tbuf;
  23.     int tflag = 0;
  24. #endif
  25.  
  26.     if(cd == NULLCHAR || path == NULLCHAR)
  27.         return NULLCHAR;
  28.  
  29. #ifdef    MSDOS
  30.     /* If path has any backslashes, make a local copy with them
  31.      * translated into forward slashes
  32.      */
  33.     if(strchr(path,'\\') != NULLCHAR){
  34.         tflag = 1;
  35.         cp = tbuf = mallocw(strlen(path));
  36.         while((c = *path++) != '\0'){
  37.             if(c == '\\')
  38.                 *cp++ = '/';
  39.             else
  40.                 *cp++ = c;
  41.         }
  42.         *cp = '\0';
  43.         path = tbuf;
  44.     }
  45. #endif
  46.  
  47.     /* Strip any leading white space on args */
  48.     while(*cd == ' ' || *cd == '\t')
  49.         cd++;
  50.     while(*path == ' ' || *path == '\t')
  51.         path++;
  52.  
  53.     /* Allocate and initialize output buffer; user must free */
  54.     buf = mallocw((unsigned)strlen(cd) + strlen(path) + 10);    /* fudge factor */
  55.     buf[0] = '\0';
  56.  
  57.     /* Interpret path relative to cd only if it doesn't begin with "/" */
  58.     if(path[0] != '/')
  59.         crunch(buf,cd);
  60.  
  61.     crunch(buf,path);
  62.  
  63.     /* Special case: null final path means the root directory */
  64.     if(buf[0] == '\0'){
  65.         buf[0] = '/';
  66.         buf[1] = '\0';
  67.     }
  68. #ifdef    MSDOS
  69.     if(tflag)
  70.         free(tbuf);
  71. #endif
  72.     return buf;
  73. }
  74.  
  75. /* Process a path name string, starting with and adding to
  76.  * the existing buffer
  77.  */
  78. static void
  79. crunch(buf,path)
  80. char *buf;
  81. register char *path;
  82. {
  83.     register char *cp;
  84.     
  85.  
  86.     cp = buf + strlen(buf);    /* Start write at end of current buffer */
  87.     
  88.     /* Now start crunching the pathname argument */
  89.     for(;;){
  90.         /* Strip leading /'s; one will be written later */
  91.         while(*path == '/')
  92.             path++;
  93.         if(*path == '\0')
  94.             break;        /* no more, all done */
  95.         /* Look for parent directory references, either at the end
  96.          * of the path or imbedded in it
  97.          */
  98.         if(strcmp(path,"..") == 0 || strncmp(path,"../",3) == 0){
  99.             /* Hop up a level */
  100.             if((cp = strrchr(buf,'/')) == NULLCHAR)
  101.                 cp = buf;    /* Don't back up beyond root */
  102.             *cp = '\0';        /* In case there's another .. */
  103.             path += 2;        /* Skip ".." */
  104.             while(*path == '/')    /* Skip one or more slashes */
  105.                 path++;
  106.         /* Look for current directory references, either at the end
  107.          * of the path or imbedded in it
  108.          */
  109.         } else if(strcmp(path,".") == 0 || strncmp(path,"./",2) == 0){
  110.             /* "no op" */
  111.             path++;            /* Skip "." */
  112.             while(*path == '/')    /* Skip one or more slashes */
  113.                 path++;
  114.         } else {
  115.             /* Ordinary name, copy up to next '/' or end of path */
  116.             *cp++ = '/';
  117.             while(*path != '/' && *path != '\0')
  118.                 *cp++ = *path++;
  119.         }
  120.     }
  121.     *cp++ = '\0';
  122. }
  123.