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