home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 1 / RISC_DISC_1.iso / pd_share / code / unixlib / !UnixLib / src / unix / c / getcwd < prev    next >
Encoding:
Text File  |  1994-09-30  |  4.6 KB  |  285 lines

  1. static char sccs_id[] = "@(#) getcwd.c 3.0 " __DATE__ " HJR";
  2.  
  3. /*
  4.  * Completely re-written by Alun Jones, auj@aber.ac.uk, 23/2/94,
  5.  * The original version corrupted the P.S.D. when run.
  6.  *
  7.  * OS_Args 7 and Prefix$Dir hacke by Simon.Callan@gpt.co.uk
  8.  */
  9.  
  10. /* getcwd.c (c) Copyright 1990 H.Rogers */
  11.  
  12. /* thanks to Andy (torq@gnu.ai.mit.edu) for the OS calls */
  13.  
  14. #include <errno.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17.  
  18. #include "sys/unix.h"
  19. #include "sys/os.h"
  20. #include "sys/param.h"
  21. #include "sys/syslib.h"
  22.  
  23. char *
  24. getcwd (char *v, int l)
  25. {
  26.   char ro_path[MAXPATHLEN];
  27.   char *rp = ro_path + MAXPATHLEN - 1;
  28.   char b[MAXPATHLEN];
  29.   register char *s, *t;
  30.   int r[10];
  31.   os_error *e;
  32.   int handle;
  33.  
  34.   /* Try OS_Args 7 (get cannonicalised name) */
  35.  
  36.   /* Open CSD for read only */
  37.   if (!os_fopen (0x40, "@", &handle))
  38.     {
  39.       r[0] = 7;
  40.       r[1] = handle;
  41.       r[2] = (int) ro_path;
  42.       r[5] = MAXPATHLEN;
  43.       e = os_swi (9, r);
  44.       os_fclose (handle);
  45.       if (!e)
  46.     {            /* OS_ARGS 7 worked, parse the path name */
  47.       s = ro_path;
  48.       t = v;
  49.       *t++ = '/';
  50.       l--;
  51.       while (*s && *s != '$' && l-- > 0)
  52.         *t++ = *s++;
  53.  
  54.       while (*s && l-- > 0)
  55.         {
  56.           if (*s != '.')
  57.         *t++ = *s;
  58.           else
  59.         *t++ = '/';
  60.           s++;
  61.         }
  62.       if (l == 0)
  63.         {
  64.           errno = ENOMEM;
  65.           return 0;
  66.         }
  67.       else
  68.         {
  69.           *t = '\0';
  70.           return v;
  71.         }
  72.     }
  73.     }
  74.  
  75.   r[0] = (int) "Prefix$Dir";
  76.   r[1] = (int) ro_path;
  77.   r[2] = MAXPATHLEN - 1;
  78.   r[3] = 0;
  79.   r[4] = 0;
  80.   os_swi (0x23, r);
  81.   if (r[2] > 0)
  82.     {
  83.       ro_path[r[2]] = '\0';
  84.       s = ro_path;
  85.       t = v;
  86.       *t++ = '/';
  87.       l--;
  88.       while (*s && *s != '$' && l-- > 0)
  89.     *t++ = *s++;
  90.  
  91.       while (*s && l-- > 0)
  92.     {
  93.       if (*s != '.')
  94.         *t++ = *s;
  95.       else
  96.         *t++ = '/';
  97.       s++;
  98.     }
  99.       if (l == 0)
  100.     {
  101.       errno = ENOMEM;
  102.       return 0;
  103.     }
  104.       else
  105.     {
  106.       *t = '\0';
  107.       return v;
  108.     }
  109.     }
  110.   /* Search backwards up the tree.
  111.    */
  112.   *rp = 0;
  113.   while (1)
  114.     {
  115.       /* Read current directory name
  116.        */
  117.       r[0] = 6;
  118.       r[2] = (int) b;
  119.       if (e = os_swi (0x0c, r))
  120.     {
  121.       /* Failed to read dirname
  122.        * So swap CSD & PSD then chdir back to original
  123.        * directory.
  124.        */
  125.       __seterr (e);
  126.       if (*rp)
  127.         {
  128.           r[0] = 0;
  129.           r[1] = (int) "\\";
  130.           if (!os_swi (0x29, r))
  131.         {
  132.           /* cd \ successful, so now need to cd \.{rp}
  133.            */
  134.           *--rp = '.';
  135.           *--rp = '\\';
  136.         }
  137.           r[0] = 0;
  138.           r[1] = (int) rp;
  139.           os_swi (0x29, r);
  140.         }
  141.       return 0;
  142.     }
  143.  
  144.       /* If at root directory then break
  145.        */
  146.       if ((b[2] == '$') && (b[1] == 1))
  147.     {
  148.       break;
  149.     }
  150.  
  151.       /* Copy the directory name into the RISC OS name
  152.        * buffer.
  153.        */
  154.       rp -= b[1];
  155.       memcpy (rp, b + 2, b[1]);
  156.       *--rp = '.';
  157.  
  158.       /* Now select PSD.
  159.        */
  160.       r[0] = 0;
  161.       r[1] = (int) "\\";
  162.       if (os_swi (0x29, r))
  163.     {
  164.       /* If cd \ failed then just cd ^
  165.        */
  166.       r[0] = 0;
  167.       r[1] = (int) "^";
  168.       os_swi (0x29, r);
  169.     }
  170.       else
  171.     {
  172.       /* Select new PSD.^
  173.        * This ensures that the PSD doesn't get corrupted by
  174.        * calling getcwd()
  175.        */
  176.       r[0] = 0;
  177.       r[1] = (int) "\\.^";
  178.       os_swi (0x29, r);
  179.     }
  180.     }
  181.  
  182.   /* OK, reached the root directory.
  183.    */
  184.   *--rp = '$';
  185.  
  186.   /* Again, PSD then original directory
  187.    */
  188.   r[0] = 0;
  189.   r[1] = (int) "\\";
  190.   if (e = os_swi (0x29, r))
  191.     {
  192.       __seterr (e);
  193.       return 0;
  194.     }
  195.  
  196.   r[0] = 0;
  197.   r[1] = (int) rp;
  198.   if (e = os_swi (0x29, r))
  199.     {
  200.       __seterr (e);
  201.       return 0;
  202.     }
  203.  
  204.   /* OK, rp now contains the current directory, and
  205.    * the PSD is unchanged.
  206.    *
  207.    * Next find the FS name.
  208.    */
  209.  
  210.   /* FS number
  211.    */
  212.   if (e = os_args (0, 0, 0, r))
  213.     {
  214.       __seterr (e);
  215.       return 0;
  216.     }
  217.  
  218.   /* Convert number to name
  219.    */
  220.   r[1] = r[0];
  221.   r[2] = (int) b + 1;
  222.   r[3] = MAXPATHLEN;
  223.   r[0] = 33;
  224.   if (e = os_swi (0x29, r))
  225.     {
  226.       __seterr (e);
  227.       return (0);
  228.     }
  229.  
  230.   /* Now have "/ADFS::", for example in b.
  231.    */
  232.   b[0] = '/';
  233.   strcat (b, "::");
  234.  
  235.   /* Copy the disk name across to v
  236.    */
  237.   if (strlen (b) < l)
  238.     {
  239.       strcpy (v, b);
  240.     }
  241.   else
  242.     {
  243.       errno = ENOMEM;
  244.       return 0;
  245.     }
  246.  
  247.   /* Next find the disk name
  248.    */
  249.   r[0] = 5;
  250.   r[2] = (int) b;
  251.   if (e = os_swi (0x0c, r))
  252.     {
  253.       __seterr (e);
  254.       return 0;
  255.     }
  256.   *(b + b[0] + 1) = '\0';
  257.   strcat (b, ".$");
  258.   if (strlen (v) + strlen (b + 1) < l)
  259.     {
  260.       strcat (v, b + 1);
  261.     }
  262.   else
  263.     {
  264.       errno = ENOMEM;
  265.       return (0);
  266.     }
  267.  
  268.   /* v now contains "/ADFS::fred.$", for example.
  269.  
  270.    * Finally convert the RISC OS name from rp, appending it to v.
  271.    */
  272.   s = v + strlen (v);
  273.   for (t = rp + 1; *t; t++)
  274.     {
  275.       if (s - v == l)
  276.     {
  277.       errno = ENOMEM;
  278.       return 0;
  279.     }
  280.       *s++ = (*t == '.') ? '/' : *t;
  281.     }
  282.   *s = '\0';
  283.   return (v);
  284. }
  285.