xref: /titanic_50/usr/src/cmd/rexd/where.c (revision a237e38e9161f0acd6451439d4a7dd597e66291d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * where.c - get full pathname including host:
29  */
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 #include <netdb.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <errno.h>
40 #include <string.h>
41 
42 #include <sys/mntent.h>
43 
44 #include <sys/mnttab.h>
45 #include <sys/param.h>
46 #include <sys/stat.h>
47 
48 #include <sharefs/share.h>
49 #include "sharetab.h"
50 
51 extern	FILE	*setmntent();
52 
53 FILE *setsharetab();
54 void endsharetab();
55 
56 
57 
58 extern	int	Debug;
59 
60 /*
61  * where(pn, host, fsname, within)
62  *
63  * pn is the pathname we are looking for,
64  * host gets the name of the host owning the file system,
65  * fsname gets the file system name on the host,
66  * within gets whatever is left from the pathname
67  *
68  * Returns: 0 if ERROR, 1 if OK
69  */
70 int
where(pn,host,fsname,within)71 where(pn, host, fsname, within)
72 char *pn;
73 char *host;
74 char *fsname;
75 char *within;
76 {
77 	struct stat sb;
78 	char curdir[MAXPATHLEN];
79 	char qualpn[MAXPATHLEN];
80 	char *p;
81 
82 	if (Debug)
83 	    printf("where: pn %s\n", pn);
84 
85 	if (stat(pn, &sb) < 0) {
86 		char *errstr;
87 
88 		if ((errstr = strerror(errno)) == NULL)
89 			errstr = "unknown error";
90 
91 		if (Debug)
92 		    printf("where: stat failed");
93 		strcpy(within, errstr);
94 		return (0);
95 	}
96 	/*
97 	 * first get the working directory,
98 	 */
99 	if (getcwd(curdir, MAXPATHLEN) == NULL) {
100 		sprintf(within, "Unable to get working directory (%s)",
101 			curdir);
102 		return (0);
103 	}
104 	if (chdir(pn) == 0) {
105 		getcwd(qualpn, MAXPATHLEN);
106 		chdir(curdir);
107 	} else {
108 		if (p = strrchr(pn, '/')) {
109 			*p = 0;
110 			chdir(pn);
111 			(void) getcwd(qualpn, MAXPATHLEN);
112 			chdir(curdir);
113 			strcat(qualpn, "/");
114 			strcat(qualpn, p+1);
115 		} else {
116 			strcpy(qualpn, curdir);
117 			strcat(qualpn, "/");
118 			strcat(qualpn, pn);
119 		}
120 	}
121 	return (findmount(qualpn, host, fsname, within));
122 }
123 
124 /*
125  * findmount(qualpn, host, fsname, within)
126  *
127  * Searches the mount table to find the appropriate file system
128  * for a given absolute path name.
129  * host gets the name of the host owning the file system,
130  * fsname gets the file system name on the host,
131  * within gets whatever is left from the pathname
132  *
133  * Returns: 0 on failure, 1 on success.
134  */
135 int
findmount(qualpn,host,fsname,within)136 findmount(qualpn, host, fsname, within)
137 char *qualpn;
138 char *host;
139 char *fsname;
140 char *within;
141 {
142 	FILE	*mfp;
143 	char	bestname[MAXPATHLEN];
144 	int	bestlen = 0,
145 	bestnfs = 0;
146 	struct	share *exp;
147 	struct	mnttab		mp,
148 	*mnt;
149 	char	*endhost;	/* points past the colon in name */
150 	int	i,
151 	len;
152 
153 	if (Debug)
154 		printf("findmount: qualpn %s\n", qualpn);
155 
156 	for (i = 0; i < 10; i++) {
157 		mfp = setmntent("/etc/mnttab", "r");
158 		if (mfp != NULL)
159 			break;
160 		sleep(1);
161 	}
162 
163 	if (mfp == NULL) {
164 		sprintf(within, "mount table problem");
165 		return (0);
166 	}
167 
168 	bestname[0] = '\0';
169 	while ((getmntent(mfp, &mp)) == 0) {
170 		if (strcmp(mp.mnt_fstype, "nfs") != 0)
171 			/*
172 			 * If it is not nfs filesystem type, skip the
173 			 * entry
174 			 */
175 			continue;
176 
177 		len = preflen(qualpn, mp.mnt_mountp);
178 
179 		if (Debug)
180 			printf("preflen: %d %s %s", len, qualpn, mp.mnt_mountp);
181 
182 		if (qualpn[len] != '/' && qualpn[len] != '\0' && len > 1)
183 			/*
184 			 * If the last matching character is neither / nor
185 			 * the end of the pathname, not a real match
186 			 * (except for matching root, len==1)
187 			 */
188 			continue;
189 
190 		if (len > bestlen) {
191 			bestlen = len;
192 			strncpy(bestname, mp.mnt_special, sizeof (bestname));
193 		}
194 		if (Debug)
195 			printf(" %s\n", bestname);
196 	}
197 
198 	endmntent(mfp);
199 
200 	endhost = strchr(bestname, ':');
201 
202 	/*
203 	 * If the file system was of type NFS, then there should already
204 	 * be a host name, otherwise, use ours.
205 	 */
206 	if (endhost) {
207 		*endhost++ = 0;
208 		strncpy(host, bestname, MAXHOSTNAMELEN);
209 		strncpy(fsname, endhost, MAXPATHLEN);
210 
211 		/*
212 		 * special case to keep the "/" when we match root
213 		 */
214 		if (bestlen == 1)
215 			bestlen = 0;
216 	} else {
217 		gethostname(host, MAXHOSTNAMELEN);
218 
219 		/*
220 		 *	If this is our file system, try for an even longer
221 		 *	match from /etc/xtab.
222 		 */
223 		if (mfp = setsharetab()) {
224 			while (getshare(mfp, &exp) > 0)
225 				if (len = preflen(qualpn, exp->sh_path))
226 					if (len > bestlen) {
227 						bestlen = len;
228 						strncpy(bestname, exp->sh_path,
229 							sizeof (bestname));
230 					}
231 			endsharetab(mfp);
232 		}
233 		strncpy(fsname, qualpn, bestlen);
234 		fsname[bestlen] = 0;
235 	}
236 	strncpy(within, qualpn + bestlen, MAXPATHLEN);
237 
238 	if (Debug)
239 		printf("findmount: qualpn %s\nhost %s\nfsname %s\nwithin %s\n",
240 			qualpn, host, fsname, within);
241 	return (1);
242 }
243 
244 /*
245  * Returns: length of second argument if it is a prefix of the
246  * first argument, otherwise zero.
247  */
248 int
preflen(str,pref)249 preflen(str, pref)
250 char	*str, *pref;
251 {
252 	int len;
253 
254 	len = strlen(pref);
255 	if (strncmp(str, pref, len) == 0)
256 		return (len);
257 	return (0);
258 }
259 
260 FILE
setsharetab()261 *setsharetab()
262 {
263 	FILE	*f;
264 
265 	f = fopen(SHARETAB, "r");
266 	if (f == NULL) {
267 		return (NULL);
268 	}
269 
270 	return (f);
271 }
272 
273 
274 void
endsharetab(f)275 endsharetab(f)
276 FILE	*f;
277 {
278 	(void) fclose(f);
279 }
280