home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / PATHNAME.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  6KB  |  210 lines

  1. /* Convert relative to absolute pathnames
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include "global.h"
  5. #include "dirutil.h"
  6. #include "config.h"
  7. #include "index.h"
  8. #ifdef CALLSERVER
  9. #include <string.h>
  10. extern char *CDROM; /* buckbook.c: defines CDROM drive letter e.g. "s:"  */
  11. #endif
  12.   
  13. void crunch __ARGS((char *buf,char *path));
  14. static char* getroot __ARGS((char *buf,char *path));
  15.   
  16. /* Given a working directory and an arbitrary pathname, resolve them into
  17.  * an absolute pathname. Memory is allocated for the result, which
  18.  * the caller must free
  19.  */
  20. char *
  21. pathname(cd,path)
  22. char *cd;       /* Current working directory */
  23. char *path;     /* Pathname argument */
  24. {
  25.     char *buf;
  26. #ifdef  MSDOS
  27.     char *cp,c;
  28.     int tflag = 0;
  29. #endif
  30. #ifdef CALLSERVER
  31.     int drive = 0;  /* is there a drive spec to preserve? */
  32. #endif
  33.   
  34.     if(cd == NULLCHAR || path == NULLCHAR)
  35.         return NULLCHAR;
  36.   
  37. #ifdef  MSDOS
  38.     /* If path has any backslashes, make a local copy with them
  39.      * translated into forward slashes
  40.      */
  41.     if(strchr(path,'\\') != NULLCHAR){
  42.         tflag = 1;
  43.         cp = path = strdup(path);
  44.         while(*cp) {
  45.             if(*cp == '\\')
  46.                 *cp = '/';
  47.             cp++;
  48.         }
  49.         cp = path;
  50.     }
  51. #endif
  52.   
  53.     /* Strip any leading white space on args */
  54.     cd = skipwhite(cd);
  55.     path = skipwhite(path);
  56.   
  57.     if(*path == '\0')
  58.         return strdup(cd);
  59.   
  60. #ifdef CALLSERVER
  61.     if (CDROM != NULLCHAR) {
  62.         if(!strncmp(path, CDROM, 2))  {
  63.             buf = strdup(path);
  64.             return buf;
  65.         }
  66.         if(!strncmp(cd, CDROM, 2))
  67.             drive = 1;  /* make a note  */
  68.     }
  69. #endif
  70.   
  71.     /* Allocate and initialize output buffer; user must free */
  72.     buf = mallocw((unsigned)strlen(cd) + strlen(path) + 10);        /* fudge factor */
  73.     buf[0] = '\0';
  74.   
  75.     /* Interpret path relative to cd only if it doesn't begin with "/"
  76.      * or doesn't have a drive letter indicator */
  77.     if((path[0] != '/') || (strlen(path) > 1 && path[1] != ':'))
  78.         crunch(buf,cd);
  79.   
  80. #ifdef CALLSERVER
  81.     else
  82.         drive = 0;
  83. #endif
  84.   
  85.     crunch(buf,path);
  86.     /* Special case: null final path means the root directory */
  87.     if(buf[0] == '\0'){
  88.         buf[0] = '/';
  89.         buf[1] = '\0';
  90.     }
  91. #ifdef  MSDOS
  92.     else if(buf[1] == ':' && buf[2] == '\0'){
  93.         buf[2] = '/';
  94.         buf[3] = '\0';
  95.     }
  96.     if(tflag)
  97.         free(path);
  98. #endif
  99. #ifdef CALLSERVER
  100.     if (drive)  {
  101.         cp = buf;
  102.         while(*cp != '\0')
  103.             *cp = *(cp++ + 1);
  104.     }
  105. #endif
  106.     return buf;
  107. }
  108.   
  109. /* Process a path name string, starting with and adding to
  110.  * the existing buffer
  111.  */
  112. void
  113. crunch(buf,path)
  114. char *buf;
  115. char *path;
  116. {
  117.     char *cp;
  118. #ifdef MSDOS
  119.     path=getroot(buf,path); /* for a case drive is specified */
  120.     if(buf[0] != '\0' && buf[1] == ':')
  121.         buf+=2; /* don't allow drive to be removed by '..' */
  122. #endif
  123.   
  124.     cp = buf + strlen(buf); /* Start write at end of current buffer */
  125.   
  126.     /* Now start crunching the pathname argument */
  127.     for(;;){
  128.         /* Strip leading /'s; one will be written later */
  129.         while(*path == '/')
  130.             path++;
  131.         if(*path == '\0')
  132.             break;          /* no more, all done */
  133.         /* Look for parent directory references, either at the end
  134.          * of the path or imbedded in it
  135.          */
  136.         if(strcmp(path,"..") == 0 || strncmp(path,"../",3) == 0){
  137.             /* Hop up a level */
  138.             if((cp = strrchr(buf,'/')) == NULLCHAR)
  139.                 cp = buf;       /* Don't back up beyond root */
  140.             *cp = '\0';             /* In case there's another .. */
  141.             path += 2;              /* Skip ".." */
  142.             while(*path == '/')     /* Skip one or more slashes */
  143.                 path++;
  144.         /* Look for current directory references, either at the end
  145.          * of the path or imbedded in it
  146.          */
  147.         } else if(strcmp(path,".") == 0 || strncmp(path,"./",2) == 0){
  148.             /* "no op" */
  149.             path++;                 /* Skip "." */
  150.             while(*path == '/')     /* Skip one or more slashes */
  151.                 path++;
  152.         } else {
  153.             /* Ordinary name, copy up to next '/' or end of path */
  154.             *cp++ = '/';
  155.             while(*path != '/' && *path != '\0')
  156.                 *cp++ = *path++;
  157.         }
  158.     }
  159.     *cp++ = '\0';
  160. }
  161.   
  162. /* Get the first path out of the path from ftpusers, and
  163.  * allocate a new string for it. Caller should free this!
  164.  */
  165. char *firstpath(char *path) {
  166.     char *cp;
  167.     int len;
  168.   
  169.     len = strcspn(path,"; \t");     /* Find length */
  170.     cp = mallocw(len+1);            /* and copy it into new buffer */
  171.     memcpy(cp,path,len);
  172.     *(cp+len) = '\0';
  173.     return cp;
  174. }
  175.   
  176. #ifdef  MSDOS
  177. /* If path specifies drive (e.g. A:), set buf to root on the drive
  178.  * and return path without drive specification, otherwise return path
  179.  * in any case remove leading / from path and set root if any found -jt
  180.  */
  181. static char*
  182. getroot(buf,path)
  183. char *buf,*path;
  184. {
  185.     int root=0;
  186.   
  187.     if(path[0] != '\0' && path[1] == ':') {
  188.         *buf++=*path++;
  189.         *buf++=*path++;
  190.         root=1;
  191.         /* Question here: what to do if drive specified
  192.          * is same as default ? Go to root directory or remain in
  193.          * current ? Currently goes to the root.
  194.          */
  195.     }
  196.     /* Skip all leading '/' */
  197.     while(*path == '/') {
  198.         path++;
  199.         root=1;
  200.     }
  201.     if(root) {
  202.         if(buf[0] != '\0' && buf[1] == ':')
  203.             buf+=2; /* leave drive if set earlier */
  204.         buf[0]='\0';
  205.     }
  206.     return path;
  207. }
  208. #endif /* MSDOS */
  209.   
  210.