home *** CD-ROM | disk | FTP | other *** search
- static char sccs_id[] = "@(#) getcwd.c 3.0 " __DATE__ " HJR";
-
- /*
- * Completely re-written by Alun Jones, auj@aber.ac.uk, 23/2/94,
- * The original version corrupted the P.S.D. when run.
- *
- * OS_Args 7 and Prefix$Dir hacke by Simon.Callan@gpt.co.uk
- */
-
- /* getcwd.c (c) Copyright 1990 H.Rogers */
-
- /* thanks to Andy (torq@gnu.ai.mit.edu) for the OS calls */
-
- #include <errno.h>
- #include <string.h>
- #include <stdlib.h>
-
- #include "sys/unix.h"
- #include "sys/os.h"
- #include "sys/param.h"
- #include "sys/syslib.h"
-
- char *
- getcwd (char *v, int l)
- {
- char ro_path[MAXPATHLEN];
- char *rp = ro_path + MAXPATHLEN - 1;
- char b[MAXPATHLEN];
- register char *s, *t;
- int r[10];
- os_error *e;
- int handle;
-
- /* Try OS_Args 7 (get cannonicalised name) */
-
- /* Open CSD for read only */
- if (!os_fopen (0x40, "@", &handle))
- {
- r[0] = 7;
- r[1] = handle;
- r[2] = (int) ro_path;
- r[5] = MAXPATHLEN;
- e = os_swi (9, r);
- os_fclose (handle);
- if (!e)
- { /* OS_ARGS 7 worked, parse the path name */
- s = ro_path;
- t = v;
- *t++ = '/';
- l--;
- while (*s && *s != '$' && l-- > 0)
- *t++ = *s++;
-
- while (*s && l-- > 0)
- {
- if (*s != '.')
- *t++ = *s;
- else
- *t++ = '/';
- s++;
- }
- if (l == 0)
- {
- errno = ENOMEM;
- return 0;
- }
- else
- {
- *t = '\0';
- return v;
- }
- }
- }
-
- r[0] = (int) "Prefix$Dir";
- r[1] = (int) ro_path;
- r[2] = MAXPATHLEN - 1;
- r[3] = 0;
- r[4] = 0;
- os_swi (0x23, r);
- if (r[2] > 0)
- {
- ro_path[r[2]] = '\0';
- s = ro_path;
- t = v;
- *t++ = '/';
- l--;
- while (*s && *s != '$' && l-- > 0)
- *t++ = *s++;
-
- while (*s && l-- > 0)
- {
- if (*s != '.')
- *t++ = *s;
- else
- *t++ = '/';
- s++;
- }
- if (l == 0)
- {
- errno = ENOMEM;
- return 0;
- }
- else
- {
- *t = '\0';
- return v;
- }
- }
- /* Search backwards up the tree.
- */
- *rp = 0;
- while (1)
- {
- /* Read current directory name
- */
- r[0] = 6;
- r[2] = (int) b;
- if (e = os_swi (0x0c, r))
- {
- /* Failed to read dirname
- * So swap CSD & PSD then chdir back to original
- * directory.
- */
- __seterr (e);
- if (*rp)
- {
- r[0] = 0;
- r[1] = (int) "\\";
- if (!os_swi (0x29, r))
- {
- /* cd \ successful, so now need to cd \.{rp}
- */
- *--rp = '.';
- *--rp = '\\';
- }
- r[0] = 0;
- r[1] = (int) rp;
- os_swi (0x29, r);
- }
- return 0;
- }
-
- /* If at root directory then break
- */
- if ((b[2] == '$') && (b[1] == 1))
- {
- break;
- }
-
- /* Copy the directory name into the RISC OS name
- * buffer.
- */
- rp -= b[1];
- memcpy (rp, b + 2, b[1]);
- *--rp = '.';
-
- /* Now select PSD.
- */
- r[0] = 0;
- r[1] = (int) "\\";
- if (os_swi (0x29, r))
- {
- /* If cd \ failed then just cd ^
- */
- r[0] = 0;
- r[1] = (int) "^";
- os_swi (0x29, r);
- }
- else
- {
- /* Select new PSD.^
- * This ensures that the PSD doesn't get corrupted by
- * calling getcwd()
- */
- r[0] = 0;
- r[1] = (int) "\\.^";
- os_swi (0x29, r);
- }
- }
-
- /* OK, reached the root directory.
- */
- *--rp = '$';
-
- /* Again, PSD then original directory
- */
- r[0] = 0;
- r[1] = (int) "\\";
- if (e = os_swi (0x29, r))
- {
- __seterr (e);
- return 0;
- }
-
- r[0] = 0;
- r[1] = (int) rp;
- if (e = os_swi (0x29, r))
- {
- __seterr (e);
- return 0;
- }
-
- /* OK, rp now contains the current directory, and
- * the PSD is unchanged.
- *
- * Next find the FS name.
- */
-
- /* FS number
- */
- if (e = os_args (0, 0, 0, r))
- {
- __seterr (e);
- return 0;
- }
-
- /* Convert number to name
- */
- r[1] = r[0];
- r[2] = (int) b + 1;
- r[3] = MAXPATHLEN;
- r[0] = 33;
- if (e = os_swi (0x29, r))
- {
- __seterr (e);
- return (0);
- }
-
- /* Now have "/ADFS::", for example in b.
- */
- b[0] = '/';
- strcat (b, "::");
-
- /* Copy the disk name across to v
- */
- if (strlen (b) < l)
- {
- strcpy (v, b);
- }
- else
- {
- errno = ENOMEM;
- return 0;
- }
-
- /* Next find the disk name
- */
- r[0] = 5;
- r[2] = (int) b;
- if (e = os_swi (0x0c, r))
- {
- __seterr (e);
- return 0;
- }
- *(b + b[0] + 1) = '\0';
- strcat (b, ".$");
- if (strlen (v) + strlen (b + 1) < l)
- {
- strcat (v, b + 1);
- }
- else
- {
- errno = ENOMEM;
- return (0);
- }
-
- /* v now contains "/ADFS::fred.$", for example.
-
- * Finally convert the RISC OS name from rp, appending it to v.
- */
- s = v + strlen (v);
- for (t = rp + 1; *t; t++)
- {
- if (s - v == l)
- {
- errno = ENOMEM;
- return 0;
- }
- *s++ = (*t == '.') ? '/' : *t;
- }
- *s = '\0';
- return (v);
- }
-