#include <stand.h>
#include <string.h>
#include "bootstrap.h"
char *DirBase;
COMMAND_SET(cd, "cd", "Change directory", command_chdir);
static int
command_chdir(int ac, char **av)
{
int result;
if (ac == 1) {
result = chdir(getenv("base"));
} else if (ac == 2) {
result = chdir(av[1]);
} else {
sprintf(command_errbuf, "usage: cd [<directory>]");
result = CMD_ERROR;
}
return result;
}
COMMAND_SET(optcd, "optcd",
"Change directory; ignore exit status", command_optchdir);
static int
command_optchdir(int ac, char **av)
{
if (ac == 1) {
chdir(getenv("base"));
} else if (ac == 2) {
chdir(av[1]);
} else {
sprintf(command_errbuf, "usage: optcd [<directory>]");
}
return(CMD_OK);
}
int
chdir(const char *path)
{
struct stat st;
char *base;
char *p;
char *b;
char *s;
char *w;
int len;
int dlen;
int res;
if (DirBase == NULL)
DirBase = strdup("/");
len = strlen(path);
if (path[0] == '/') {
base = malloc(len + 2);
bcopy(path, base, len + 1);
} else {
while (len && path[len-1] == '/')
--len;
dlen = strlen(DirBase);
base = malloc(dlen + len + 2);
bcopy(DirBase, base, dlen);
bcopy(path, base + dlen, len);
base[dlen + len] = 0;
}
if (stat(base, &st) == 0 && S_ISDIR(st.st_mode)) {
p = b = w = s = base;
while (*s) {
if (*s == '/') {
if (s - b == 2 && b[0] == '.' && b[1] == '.') {
w = p;
} else {
p = b;
b = s + 1;
}
while (s[1] == '/')
++s;
}
*w = *s;
++w;
++s;
}
if (s - b == 2 && b[0] == '.' && b[1] == '.')
w = p;
while (w > base && w[-1] == '/')
--w;
*w++ = '/';
*w = 0;
if (DirBase)
free(DirBase);
DirBase = base;
res = CMD_OK;
} else {
free(base);
sprintf(command_errbuf, "Unable to find directory");
res = CMD_ERROR;
}
return (res);
}
COMMAND_SET(pwd, "pwd", "Get current directory", command_pwd);
static int
command_pwd(int ac, char **av)
{
printf("%s\n", DirBase ? DirBase : "/");
return(0);
}
int
rel_open(const char *path, char **abspathp, int flags)
{
int fd;
char *ptr;
if (DirBase == NULL)
DirBase = strdup("/");
if (path[0] != '/') {
ptr = malloc(strlen(DirBase) + strlen(path) + 1);
sprintf(ptr, "%s%s", DirBase, path);
fd = open(ptr, flags);
if (abspathp && fd >= 0) {
*abspathp = ptr;
} else if (abspathp) {
*abspathp = NULL;
free(ptr);
} else {
free(ptr);
}
} else {
fd = open(path, flags);
if (abspathp && fd >= 0) {
*abspathp = strdup(path);
} else if (abspathp) {
*abspathp = NULL;
}
}
return(fd);
}
int
rel_stat(const char *path, struct stat *st)
{
char *ptr;
int res;
if (DirBase == NULL)
DirBase = strdup("/");
if (path[0] != '/') {
ptr = malloc(strlen(DirBase) + strlen(path) + 1);
sprintf(ptr, "%s%s", DirBase, path);
res = stat(ptr, st);
free(ptr);
} else {
res = stat(path, st);
}
return(res);
}
char *
rel_rootpath(const char *path)
{
char *rootpath;
char *abspath;
if (DirBase == NULL)
DirBase = strdup("/");
if (path[0] == '/') {
abspath = strdup(path);
} else {
abspath = malloc(strlen(DirBase) + strlen(path) + 1);
sprintf(abspath, "%s%s", DirBase, path);
}
if (strncmp(abspath, "/boot/", sizeof("/boot/")-1) == 0) {
rootpath = abspath;
} else {
rootpath = malloc(strlen(abspath) + sizeof("/boot"));
sprintf(rootpath, "/boot%s", abspath);
free(abspath);
}
return (rootpath);
}