home *** CD-ROM | disk | FTP | other *** search
- /* C.Getwd: Get the full pathname of the CWD */
-
- #include "kernel.h"
- #include "swis.h"
-
- #include <string.h>
- #include <stdlib.h>
-
- #include "utils.h"
-
- #define ReadDirName 6
- #define ReadDiskName 5
- #define SetDir 0
- #define GetFSName 33
-
- #define BUF_LEN 255
-
- /* Some useful chunks of code */
-
- #define setdir(d) \
- { \
- regs.r[1] = (int)(d); \
- if ( _kernel_swi (OS_FSControl, ®s, ®s) ) \
- { \
- free(cwd); \
- free(pwd); \
- return NULL; \
- } \
- }
-
- #define GIVE_UP \
- { \
- free(pwd); \
- free(cwd); \
- return NULL; \
- }
-
- static char *append_disk (char *);
- static char *append_cwd (char *);
- static char *stradd (char *, char *, char);
-
- /* Returns CWD pathname. If size != 0, use the area size long at buf,
- * otherwise malloc() an area. Return value is pathname, or 0 on any
- * error.
- */
-
- char *getcwd (int preserve_pwd, char **pwd_ptr)
- {
- char *pwd;
- char *cwd;
- char buf[BUF_LEN];
- _kernel_osgbpb_block blk;
- _kernel_swi_regs regs;
-
- /* Start with a null string */
- if ((cwd = malloc(1)) == NULL)
- return NULL;
-
- cwd[0] = 0;
-
- /* If we can corrupt the pwd, everything is easy */
- if (!preserve_pwd)
- {
- cwd = append_cwd(cwd);
- if (cwd == NULL)
- return NULL;
-
- /* Reset the cwd */
- setdir(cwd);
- return cwd;
- }
-
- /* We need to save the pwd - start with a null string */
- if ((pwd = malloc(1)) == NULL)
- {
- free(cwd);
- return NULL;
- }
- pwd[0] = 0;
-
- /* Initialise the OS call buffers */
- regs.r[0] = SetDir;
- blk.dataptr = buf;
-
- for (;;)
- {
- /* First get the cwd name */
- if (_kernel_osgbpb(ReadDirName,0,&blk) == _kernel_ERROR)
- GIVE_UP;
-
- /* Terminate the string */
- buf [2 + buf[1]] = '\0';
-
- cwd = stradd (cwd, buf+2, '.');
- if (cwd == NULL)
- {
- free(pwd);
- return NULL;
- }
-
- if (buf[1] == 1 && buf[2] == '$')
- {
- /* Reached the end - add fs:disk */
- if ((cwd = append_disk(cwd)) == NULL)
- {
- free(pwd);
- return NULL;
- }
-
- /* Now get the remainder of the pwd */
- setdir(*pwd ? "\\.^" : "\\");
- if ((pwd = append_cwd(pwd)) == NULL)
- {
- free(cwd);
- return NULL;
- }
-
- /* And exit */
- break;
- }
-
- /* Now get the next part of the pwd. This is "\" if
- * we have none yet (ie *pwd = 0), otherwise "\.^".
- */
-
- setdir(*pwd ? "\\.^" : "\\");
-
- if (_kernel_osgbpb(ReadDirName,0,&blk) == _kernel_ERROR)
- GIVE_UP;
-
- /* Terminate the string */
- buf [2 + buf[1]] = '\0';
-
- pwd = stradd (pwd, buf+2, '.');
- if (pwd == NULL)
- {
- free(cwd);
- return NULL;
- }
-
- if (buf[1] == 1 && buf[2] == '$')
- {
- /* Reached the end - add fs:disk */
- if ((pwd = append_disk(pwd)) == NULL)
- {
- free(cwd);
- return NULL;
- }
-
- /* Now get the remainder of the cwd */
- setdir("\\.^");
- if ((cwd = append_cwd(cwd)) == NULL)
- {
- free(cwd);
- return NULL;
- }
-
- /* And exit */
- break;
- }
-
- /* Now go back to the cwd, and up one level */
- setdir("\\.^");
- }
-
- /* We are OK - restore the CWD and the PWD */
- setdir(pwd);
- setdir(cwd);
-
- if (pwd_ptr)
- *pwd_ptr = pwd;
- else
- free(pwd);
-
- return cwd;
- }
-
- static char *append_disk (char *s)
- {
- char buf[BUF_LEN];
- _kernel_osgbpb_block blk;
- _kernel_swi_regs regs;
-
- blk.dataptr = buf;
-
- if (_kernel_osgbpb(ReadDiskName,0,&blk) == _kernel_ERROR)
- {
- free(s);
- return NULL;
- }
-
- buf [1 + buf[0]] = '\0'; /* Terminate the string */
- buf [0] = ':'; /* Add an initial colon */
-
- s = stradd (s, buf, '.');
-
- if (s == NULL)
- return NULL;
-
- /* Now, get the filing system name */
-
- regs.r[0] = GetFSName; /* Convert number to name */
- regs.r[1] = _kernel_osargs(0,0,0); /* Filing system number */
- regs.r[2] = (int)buf; /* FS name buffer */
- regs.r[3] = BUF_LEN; /* Length of buffer */
-
- if ( _kernel_swi (OS_FSControl, ®s, ®s) )
- {
- free(s);
- return NULL;
- }
-
- return stradd (s, buf, ':');
- }
-
- static char *append_cwd (char *s)
- {
- char buf[BUF_LEN];
- _kernel_osgbpb_block blk;
- _kernel_swi_regs regs;
-
- /* Set up the registers for the OS_FSControl call to
- * go up one level in the directory tree.
- */
-
- regs.r[0] = SetDir;
- regs.r[1] = (int)"^";
-
- /* Set up the area for the current directory name */
-
- blk.dataptr = buf;
-
- /* Now, go up the tree, adding the current directory name
- * at each level, until we reach the root ($)
- */
-
- do {
- if ( _kernel_osgbpb (ReadDirName, 0, &blk) == _kernel_ERROR )
- {
- free(s);
- return NULL;
- }
-
- buf [2 + buf[1]] = '\0'; /* Terminate the string */
-
- s = stradd (s, buf+2, '.');
-
- if (s == NULL)
- return NULL;
-
- if ( _kernel_swi (OS_FSControl, ®s, ®s) )
- {
- free(s);
- return NULL;
- }
-
- } while (buf[1] != 1 || buf[2] != '$');
-
- /* Add the fs:disk name on, and then return */
-
- return append_disk(s);
- }
-
- /* Add s2 to string s1. The string s1 must be obtained from malloc().
- * The old s1 will be freed, and a new area of malloc()-ed memory is
- * returned. If s1 is not a null string, ch will be inserted between
- * s1 and s2.
- * If an error occurs, s1 is freed, and NULL is returned.
- */
-
- static char *stradd (char *s1, char *s2, char ch)
- {
- int newlen = strlen(s1) + strlen(s2) + (ch ? 2 : 1);
- char *new = malloc(newlen);
- char *old = s1;
- char *p = new;
-
- if (new == NULL)
- {
- free(s1);
- return NULL;
- }
-
- while (*s2)
- *p++ = *s2++;
-
- if (*s1)
- *p++ = ch;
-
- while (*old)
- *p++ = *old++;
-
- *p = 0;
- free (s1);
-
- return new;
- }
-
- /*--------------------------------------------------------------------------*/
-
- #ifdef test
-
- #include <stdio.h>
-
- int main (int argc, char *argv[])
- {
- char *p, *q;
-
- if ( argc != 1 )
- {
- printf("%s: No parameters\n", argv[0]);
- return 1;
- }
-
- if ((p = getcwd(1,&q)) == NULL)
- {
- printf("Error\n");
- return 1;
- }
-
- printf("cwd: %s\n", p);
- printf("pwd: %s\n", q);
-
- free(p);
- free(q);
-
- return 0;
- }
-
- #endif
-