1 /*
2  * SCCSID(@(#)curdir.c	4.5);
3  */
4 #include	<sys/param.h>
5 #include	<sys/stat.h>
6 #include	<sys/dir.h>
7 
8 #define	dot	"."
9 #define	dotdot	".."
10 
11 static	char	*name;
12 
13 static	int	off;
14 static	struct	stat	d, dd;
15 static	struct	direct	*dir;
16 static	DIR	*dirp;
17 static	int	cat(), prexit();
18 
19 char *
20 curdir(np)
21 char *np;
22 {
23 	int rdev, rino;
24 
25 	off = -1;
26 	*np++ = '/';
27 	name = np;
28 	stat("/", &d);
29 	rdev = d.st_dev;
30 	rino = d.st_ino;
31 	for (;;) {
32 		stat(dot, &d);
33 		if (d.st_ino==rino && d.st_dev==rdev)
34 			goto done;
35 		if ((dirp = opendir(dotdot)) == 0)
36 			prexit("curdir: cannot open ..\n");
37 		fstat(dirp->dd_fd, &dd);
38 		chdir(dotdot);
39 		if(d.st_dev == dd.st_dev) {
40 			if(d.st_ino == dd.st_ino)
41 				goto done;
42 			do
43 				if ((dir = readdir(dirp)) == 0)
44 					prexit("curdir: read error in ..\n");
45 			while (dir->d_ino != d.st_ino);
46 		} else
47 			do {
48 				if ((dir = readdir(dirp)) == 0)
49 					prexit("curdir: read error in ..\n");
50 				stat(dir->d_name, &dd);
51 			} while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
52 		closedir(dirp);
53 		cat();
54 	}
55 done:
56 	name--;
57 	if (chdir(name) < 0) {
58 		write(2, name, strlen(name));
59 		prexit(": can't change back\n");
60 	}
61 	return (0);
62 }
63 
64 static
65 cat()
66 {
67 	register i, j;
68 
69 	i = dir->d_namlen;
70 	if ((off+i+2) > 1024-1)
71 		return;
72 	for(j=off+1; j>=0; --j)
73 		name[j+i+1] = name[j];
74 	if (off >= 0)
75 		name[i] = '/';
76 	off += i+1;
77 	name[off] = 0;
78 	for(--i; i>=0; --i)
79 		name[i] = dir->d_name[i];
80 }
81 
82 static
83 prexit(cp)
84 char *cp;
85 {
86 	write(2, cp, strlen(cp));
87 	exit(1);
88 }
89