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