/* Copyright (c) 1986, Greg McGary */
static char sccsid[] = "@(#)paths.c	1.1 86/10/09";

#include	<bool.h>
#include	<stdio.h>
#include	<string.h>

bool canCrunch();
char *getDirToName();
char *rootName();
char *skipJunk();
char *spanPath();
char *suffName();

char *
spanPath(dir, arg)
	char		*dir;
	char		*arg;
{
	static char	pathBuf[BUFSIZ];
	char		*path;
	char		*argTail;
	char		*dirTail;
	int		argLength;
	int		dirLength;

	for (dirTail = &dir[strlen(dir)-1]; *dirTail == '/'; dirTail--)
		*dirTail = '\0';
	for (;;) {
		dir = skipJunk(dir);
		if ((dirTail = strchr(dir, '/')) == NULL)
			dirTail = &dir[strlen(dir)];
		dirLength = dirTail - dir;

		arg = skipJunk(arg);
		if ((argTail = strchr(arg, '/')) == NULL)
			break;
		argLength = argTail - arg;

		if (argLength != dirLength)
			break;
		if (!strnequ(arg, dir, argLength))
			break;
		arg = argTail;
		dir = dirTail;
	}

	(path = pathBuf)[0] = '\0';
	for (; dir && *dir; dir = skipJunk(strchr(dir, '/'))) {
		strcpy(path, "../");
		path += 3;
	}
	strcat(path, arg);
	return pathBuf;
}

char *
skipJunk(path)
	char		*path;
{
	if (path == NULL)
		return NULL;
	while (*path == '/')
		path++;
	while (path[0] == '.' && path[1] == '/') {
		path += 2;
		while (*path == '/')
			path++;
	}
	if (strequ(path, "."))
		path++;
	
	return path;
}

char *
rootName(path)
	char		*path;
{
	static char	pathBuf[BUFSIZ];
	char		*root;
	char		*dot;

	if ((root = strrchr(path, '/')) == NULL)
		root = path;
	else
		root++;
	
	if ((dot = strrchr(root, '.')) == NULL)
		strcpy(pathBuf, root);
	else {
		strncpy(pathBuf, root, dot - root);
		pathBuf[dot - root] = '\0';
	}
	return pathBuf;
}

char *
suffName(path)
	char		*path;
{
	char		*dot;

	if ((dot = strrchr(path, '.')) == NULL)
		return "";
	return dot;
}

bool
canCrunch(path1, path2)
	char		*path1;
	char		*path2;
{
	char		*slash1;
	char		*slash2;

	slash1 = strrchr(path1, '/');
	slash2 = strrchr(path2, '/');

	if (slash1 == NULL && slash2 == NULL)
		return strequ(suffName(path1), suffName(path2));
	if ((slash1 - path1) != (slash2 - path2))
		return FALSE;
	if (!strnequ(path1, path2, slash1 - path1))
		return FALSE;
	return strequ(suffName(slash1), suffName(slash2));
}
#include	<sys/types.h>
#include	<sys/stat.h>
#ifdef NDIR
#include	<ndir.h>
#else
#include	<sys/dir.h>
#endif

static char	dot[]	 = ".";
static char	dotdot[] = "..";

/*
	Return our directory name relative to the first parent dir
	that contains a file with a name that matches `topName'.
	Fail if we hit the root, or if any dir in our way is unreadable.
*/
char *
getDirToName(topName)
	char		*topName;
{
	register struct direct	*dirp;
	register DIR	*dirdp;
	static char	nameBuf[BUFSIZ];
	char		*name;
	struct	stat	dStat;
	struct	stat	ddStat;

	name = &nameBuf[sizeof(nameBuf)-1];
	*name = '\0';
	for (;;) {
		if (stat(topName, &dStat) == 0) {
			if (!*name)
				name = dot;
			else
				chdir(name);
			return name;
		} if (stat(dot, &dStat) < 0)
			return NULL;
		if ((dirdp = opendir(dotdot)) == NULL)
			return NULL;
		if (fstat(dirdp->dd_fd, &ddStat) < 0)
			return NULL;
		if (chdir(dotdot) < 0)
			return NULL;
		if (dStat.st_dev == ddStat.st_dev) {
			if (dStat.st_ino == ddStat.st_ino)
				return NULL;
			do {
				if ((dirp = readdir(dirdp)) == NULL)
					return NULL;
			} while (dirp->d_ino != dStat.st_ino);
		} else {
			do {
				if ((dirp = readdir(dirdp)) == NULL)
					return NULL;
				stat(dirp->d_name, &ddStat);
			} while (ddStat.st_ino != dStat.st_ino || ddStat.st_dev != dStat.st_dev);
		}
		closedir(dirdp);
	
		if (*name != '\0')
			*--name = '/';
		name -= dirp->d_namlen;
		strncpy(name, dirp->d_name, dirp->d_namlen);
	}
}
