home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / unix / unixtools / util / c / getwd < prev    next >
Encoding:
Text File  |  1992-07-21  |  5.6 KB  |  331 lines

  1. /* C.Getwd: Get the full pathname of the CWD */
  2.  
  3. #include "kernel.h"
  4. #include "swis.h"
  5.  
  6. #include <string.h>
  7. #include <stdlib.h>
  8.  
  9. #include "utils.h"
  10.  
  11. #define ReadDirName    6
  12. #define ReadDiskName    5
  13. #define SetDir        0
  14. #define GetFSName    33
  15.  
  16. #define BUF_LEN        255
  17.  
  18. /* Some useful chunks of code */
  19.  
  20. #define setdir(d) \
  21. { \
  22.     regs.r[1] = (int)(d); \
  23.     if ( _kernel_swi (OS_FSControl, ®s, ®s) ) \
  24.     { \
  25.         free(cwd); \
  26.         free(pwd); \
  27.         return NULL; \
  28.     } \
  29. }
  30.  
  31. #define GIVE_UP \
  32. { \
  33.     free(pwd); \
  34.     free(cwd); \
  35.     return NULL; \
  36. }
  37.  
  38. static char *append_disk (char *);
  39. static char *append_cwd (char *);
  40. static char *stradd (char *, char *, char);
  41.  
  42. /* Returns CWD pathname. If size != 0, use the area size long at buf,
  43.  * otherwise malloc() an area. Return value is pathname, or 0 on any
  44.  * error.
  45.  */
  46.  
  47. char *getcwd (int preserve_pwd, char **pwd_ptr)
  48. {
  49.         char *pwd;
  50.         char *cwd;
  51.     char buf[BUF_LEN];
  52.     _kernel_osgbpb_block blk;
  53.     _kernel_swi_regs regs;
  54.  
  55.     /* Start with a null string */
  56.     if ((cwd = malloc(1)) == NULL)
  57.         return NULL;
  58.  
  59.     cwd[0] = 0;
  60.  
  61.     /* If we can corrupt the pwd, everything is easy */
  62.     if (!preserve_pwd)
  63.     {
  64.         cwd = append_cwd(cwd);
  65.         if (cwd == NULL)
  66.             return NULL;
  67.  
  68.         /* Reset the cwd */
  69.         setdir(cwd);
  70.         return cwd;
  71.     }
  72.  
  73.     /* We need to save the pwd - start with a null string */
  74.     if ((pwd = malloc(1)) == NULL)
  75.     {
  76.         free(cwd);
  77.         return NULL;
  78.     }
  79.     pwd[0] = 0;
  80.  
  81.     /* Initialise the OS call buffers */
  82.     regs.r[0] = SetDir;
  83.         blk.dataptr = buf;
  84.  
  85.         for (;;)
  86.         {
  87.         /* First get the cwd name */
  88.                 if (_kernel_osgbpb(ReadDirName,0,&blk) == _kernel_ERROR)
  89.             GIVE_UP;
  90.  
  91.         /* Terminate the string */
  92.                 buf [2 + buf[1]] = '\0';
  93.  
  94.         cwd = stradd (cwd, buf+2, '.');
  95.         if (cwd == NULL)
  96.         {
  97.             free(pwd);
  98.             return NULL;
  99.         }
  100.  
  101.         if (buf[1] == 1 && buf[2] == '$')
  102.         {
  103.             /* Reached the end - add fs:disk */
  104.             if ((cwd = append_disk(cwd)) == NULL)
  105.             {
  106.                 free(pwd);
  107.                 return NULL;
  108.             }
  109.  
  110.             /* Now get the remainder of the pwd */
  111.             setdir(*pwd ? "\\.^" : "\\");
  112.             if ((pwd = append_cwd(pwd)) == NULL)
  113.             {
  114.                 free(cwd);
  115.                 return NULL;
  116.             }
  117.  
  118.             /* And exit */
  119.             break;
  120.         }
  121.  
  122.         /* Now get the next part of the pwd. This is "\" if
  123.          * we have none yet (ie *pwd = 0), otherwise "\.^".
  124.          */
  125.  
  126.         setdir(*pwd ? "\\.^" : "\\");
  127.  
  128.                 if (_kernel_osgbpb(ReadDirName,0,&blk) == _kernel_ERROR)
  129.             GIVE_UP;
  130.  
  131.         /* Terminate the string */
  132.                 buf [2 + buf[1]] = '\0';
  133.  
  134.         pwd = stradd (pwd, buf+2, '.');
  135.         if (pwd == NULL)
  136.         {
  137.             free(cwd);
  138.             return NULL;
  139.         }
  140.  
  141.         if (buf[1] == 1 && buf[2] == '$')
  142.         {
  143.             /* Reached the end - add fs:disk */
  144.             if ((pwd = append_disk(pwd)) == NULL)
  145.             {
  146.                 free(cwd);
  147.                 return NULL;
  148.             }
  149.  
  150.             /* Now get the remainder of the cwd */
  151.             setdir("\\.^");
  152.             if ((cwd = append_cwd(cwd)) == NULL)
  153.             {
  154.                 free(cwd);
  155.                 return NULL;
  156.             }
  157.  
  158.             /* And exit */
  159.             break;
  160.         }
  161.  
  162.         /* Now go back to the cwd, and up one level */
  163.         setdir("\\.^");
  164.         }
  165.  
  166.     /* We are OK - restore the CWD and the PWD */
  167.     setdir(pwd);
  168.     setdir(cwd);
  169.  
  170.     if (pwd_ptr)
  171.         *pwd_ptr = pwd;
  172.     else
  173.         free(pwd);
  174.  
  175.     return cwd;
  176. }
  177.  
  178. static char *append_disk (char *s)
  179. {
  180.     char buf[BUF_LEN];
  181.     _kernel_osgbpb_block blk;
  182.         _kernel_swi_regs regs;
  183.  
  184.     blk.dataptr = buf;
  185.  
  186.     if (_kernel_osgbpb(ReadDiskName,0,&blk) == _kernel_ERROR)
  187.     {
  188.         free(s);
  189.         return NULL;
  190.     }
  191.  
  192.         buf [1 + buf[0]] = '\0';    /* Terminate the string */
  193.         buf [0] = ':';            /* Add an initial colon */
  194.  
  195.     s = stradd (s, buf, '.');
  196.  
  197.     if (s == NULL)
  198.         return NULL;
  199.  
  200.     /* Now, get the filing system name */
  201.  
  202.     regs.r[0] = GetFSName;            /* Convert number to name */
  203.     regs.r[1] = _kernel_osargs(0,0,0);    /* Filing system number */
  204.     regs.r[2] = (int)buf;            /* FS name buffer */
  205.     regs.r[3] = BUF_LEN;            /* Length of buffer */
  206.  
  207.     if ( _kernel_swi (OS_FSControl, ®s, ®s) )
  208.     {
  209.         free(s);
  210.         return NULL;
  211.     }
  212.  
  213.     return stradd (s, buf, ':');
  214. }
  215.  
  216. static char *append_cwd (char *s)
  217. {
  218.     char buf[BUF_LEN];
  219.     _kernel_osgbpb_block blk;
  220.         _kernel_swi_regs regs;
  221.  
  222.     /* Set up the registers for the OS_FSControl call to
  223.      * go up one level in the directory tree.
  224.      */
  225.  
  226.     regs.r[0] = SetDir;
  227.     regs.r[1] = (int)"^";
  228.  
  229.     /* Set up the area for the current directory name */
  230.  
  231.     blk.dataptr = buf;
  232.  
  233.     /* Now, go up the tree, adding the current directory name
  234.      * at each level, until we reach the root ($)
  235.      */
  236.  
  237.     do {
  238.         if ( _kernel_osgbpb (ReadDirName, 0, &blk) == _kernel_ERROR )
  239.         {
  240.             free(s);
  241.             return NULL;
  242.         }
  243.  
  244.         buf [2 + buf[1]] = '\0';    /* Terminate the string */
  245.  
  246.         s = stradd (s, buf+2, '.');
  247.  
  248.         if (s == NULL)
  249.             return NULL;
  250.  
  251.         if ( _kernel_swi (OS_FSControl, ®s, ®s) )
  252.         {
  253.             free(s);
  254.             return NULL;
  255.         }
  256.  
  257.     } while (buf[1] != 1 || buf[2] != '$');
  258.  
  259.     /* Add the fs:disk name on, and then return */
  260.  
  261.     return append_disk(s);
  262. }
  263.  
  264. /* Add s2 to string s1. The string s1 must be obtained from malloc().
  265.  * The old s1 will be freed, and a new area of malloc()-ed memory is
  266.  * returned. If s1 is not a null string, ch will be inserted between
  267.  * s1 and s2.
  268.  * If an error occurs, s1 is freed, and NULL is returned.
  269.  */
  270.  
  271. static char *stradd (char *s1, char *s2, char ch)
  272. {
  273.     int newlen = strlen(s1) + strlen(s2) + (ch ? 2 : 1);
  274.     char *new = malloc(newlen);
  275.     char *old = s1;
  276.     char *p = new;
  277.  
  278.     if (new == NULL)
  279.     {
  280.         free(s1);
  281.         return NULL;
  282.     }
  283.  
  284.     while (*s2)
  285.         *p++ = *s2++;
  286.  
  287.     if (*s1)
  288.         *p++ = ch;
  289.  
  290.     while (*old)
  291.         *p++ = *old++;
  292.  
  293.     *p = 0;
  294.     free (s1);
  295.  
  296.     return new;
  297. }
  298.  
  299. /*--------------------------------------------------------------------------*/
  300.  
  301. #ifdef test
  302.  
  303. #include <stdio.h>
  304.  
  305. int main (int argc, char *argv[])
  306. {
  307.     char *p, *q;
  308.  
  309.     if ( argc != 1 )
  310.     {
  311.         printf("%s: No parameters\n", argv[0]);
  312.         return 1;
  313.     }
  314.  
  315.     if ((p = getcwd(1,&q)) == NULL)
  316.     {
  317.         printf("Error\n");
  318.         return 1;
  319.     }
  320.  
  321.     printf("cwd: %s\n", p);
  322.     printf("pwd: %s\n", q);
  323.  
  324.     free(p);
  325.     free(q);
  326.  
  327.     return 0;
  328. }
  329.  
  330. #endif
  331.