xref: /onnv-gate/usr/src/cmd/rexd/where.c (revision 3957:86c9dda5df37)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*3957Sth199096  * Common Development and Distribution License (the "License").
6*3957Sth199096  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
20*3957Sth199096  */
21*3957Sth199096 
22*3957Sth199096 /*
23*3957Sth199096  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate  * where.c - get full pathname including host:
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <netdb.h>
340Sstevel@tonic-gate #include <stdio.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <unistd.h>
380Sstevel@tonic-gate #include <fcntl.h>
390Sstevel@tonic-gate #include <errno.h>
400Sstevel@tonic-gate #include <string.h>
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #include <sys/mntent.h>
430Sstevel@tonic-gate 
440Sstevel@tonic-gate #include <sys/mnttab.h>
450Sstevel@tonic-gate #include <sys/param.h>
460Sstevel@tonic-gate #include <sys/stat.h>
470Sstevel@tonic-gate 
48*3957Sth199096 #include <sharefs/share.h>
490Sstevel@tonic-gate #include "sharetab.h"
500Sstevel@tonic-gate 
510Sstevel@tonic-gate extern	FILE	*setmntent();
520Sstevel@tonic-gate 
530Sstevel@tonic-gate FILE *setsharetab();
540Sstevel@tonic-gate void endsharetab();
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 
570Sstevel@tonic-gate 
580Sstevel@tonic-gate extern	int	Debug;
590Sstevel@tonic-gate 
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate  * where(pn, host, fsname, within)
620Sstevel@tonic-gate  *
630Sstevel@tonic-gate  * pn is the pathname we are looking for,
640Sstevel@tonic-gate  * host gets the name of the host owning the file system,
650Sstevel@tonic-gate  * fsname gets the file system name on the host,
660Sstevel@tonic-gate  * within gets whatever is left from the pathname
670Sstevel@tonic-gate  *
680Sstevel@tonic-gate  * Returns: 0 if ERROR, 1 if OK
690Sstevel@tonic-gate  */
700Sstevel@tonic-gate int
where(pn,host,fsname,within)710Sstevel@tonic-gate where(pn, host, fsname, within)
720Sstevel@tonic-gate char *pn;
730Sstevel@tonic-gate char *host;
740Sstevel@tonic-gate char *fsname;
750Sstevel@tonic-gate char *within;
760Sstevel@tonic-gate {
770Sstevel@tonic-gate 	struct stat sb;
780Sstevel@tonic-gate 	char curdir[MAXPATHLEN];
790Sstevel@tonic-gate 	char qualpn[MAXPATHLEN];
800Sstevel@tonic-gate 	char *p;
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	if (Debug)
830Sstevel@tonic-gate 	    printf("where: pn %s\n", pn);
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 	if (stat(pn, &sb) < 0) {
860Sstevel@tonic-gate 		char *errstr;
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 		if ((errstr = strerror(errno)) == NULL)
890Sstevel@tonic-gate 			errstr = "unknown error";
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 		if (Debug)
920Sstevel@tonic-gate 		    printf("where: stat failed");
930Sstevel@tonic-gate 		strcpy(within, errstr);
940Sstevel@tonic-gate 		return (0);
950Sstevel@tonic-gate 	}
960Sstevel@tonic-gate 	/*
970Sstevel@tonic-gate 	 * first get the working directory,
980Sstevel@tonic-gate 	 */
990Sstevel@tonic-gate 	if (getcwd(curdir, MAXPATHLEN) == NULL) {
1000Sstevel@tonic-gate 		sprintf(within, "Unable to get working directory (%s)",
1010Sstevel@tonic-gate 			curdir);
1020Sstevel@tonic-gate 		return (0);
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 	if (chdir(pn) == 0) {
1050Sstevel@tonic-gate 		getcwd(qualpn, MAXPATHLEN);
1060Sstevel@tonic-gate 		chdir(curdir);
1070Sstevel@tonic-gate 	} else {
1080Sstevel@tonic-gate 		if (p = strrchr(pn, '/')) {
1090Sstevel@tonic-gate 			*p = 0;
1100Sstevel@tonic-gate 			chdir(pn);
1110Sstevel@tonic-gate 			(void) getcwd(qualpn, MAXPATHLEN);
1120Sstevel@tonic-gate 			chdir(curdir);
1130Sstevel@tonic-gate 			strcat(qualpn, "/");
1140Sstevel@tonic-gate 			strcat(qualpn, p+1);
1150Sstevel@tonic-gate 		} else {
1160Sstevel@tonic-gate 			strcpy(qualpn, curdir);
1170Sstevel@tonic-gate 			strcat(qualpn, "/");
1180Sstevel@tonic-gate 			strcat(qualpn, pn);
1190Sstevel@tonic-gate 		}
1200Sstevel@tonic-gate 	}
1210Sstevel@tonic-gate 	return (findmount(qualpn, host, fsname, within));
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate /*
1250Sstevel@tonic-gate  * findmount(qualpn, host, fsname, within)
1260Sstevel@tonic-gate  *
1270Sstevel@tonic-gate  * Searches the mount table to find the appropriate file system
1280Sstevel@tonic-gate  * for a given absolute path name.
1290Sstevel@tonic-gate  * host gets the name of the host owning the file system,
1300Sstevel@tonic-gate  * fsname gets the file system name on the host,
1310Sstevel@tonic-gate  * within gets whatever is left from the pathname
1320Sstevel@tonic-gate  *
1330Sstevel@tonic-gate  * Returns: 0 on failure, 1 on success.
1340Sstevel@tonic-gate  */
1350Sstevel@tonic-gate int
findmount(qualpn,host,fsname,within)1360Sstevel@tonic-gate findmount(qualpn, host, fsname, within)
1370Sstevel@tonic-gate char *qualpn;
1380Sstevel@tonic-gate char *host;
1390Sstevel@tonic-gate char *fsname;
1400Sstevel@tonic-gate char *within;
1410Sstevel@tonic-gate {
1420Sstevel@tonic-gate 	FILE	*mfp;
1430Sstevel@tonic-gate 	char	bestname[MAXPATHLEN];
1440Sstevel@tonic-gate 	int	bestlen = 0,
1450Sstevel@tonic-gate 	bestnfs = 0;
1460Sstevel@tonic-gate 	struct	share *exp;
1470Sstevel@tonic-gate 	struct	mnttab		mp,
1480Sstevel@tonic-gate 	*mnt;
1490Sstevel@tonic-gate 	char	*endhost;	/* points past the colon in name */
1500Sstevel@tonic-gate 	int	i,
1510Sstevel@tonic-gate 	len;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	if (Debug)
1540Sstevel@tonic-gate 		printf("findmount: qualpn %s\n", qualpn);
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	for (i = 0; i < 10; i++) {
1570Sstevel@tonic-gate 		mfp = setmntent("/etc/mnttab", "r");
1580Sstevel@tonic-gate 		if (mfp != NULL)
1590Sstevel@tonic-gate 			break;
1600Sstevel@tonic-gate 		sleep(1);
1610Sstevel@tonic-gate 	}
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	if (mfp == NULL) {
1640Sstevel@tonic-gate 		sprintf(within, "mount table problem");
1650Sstevel@tonic-gate 		return (0);
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	bestname[0] = '\0';
1690Sstevel@tonic-gate 	while ((getmntent(mfp, &mp)) == 0) {
1700Sstevel@tonic-gate 		if (strcmp(mp.mnt_fstype, "nfs") != 0)
1710Sstevel@tonic-gate 			/*
1720Sstevel@tonic-gate 			 * If it is not nfs filesystem type, skip the
1730Sstevel@tonic-gate 			 * entry
1740Sstevel@tonic-gate 			 */
1750Sstevel@tonic-gate 			continue;
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 		len = preflen(qualpn, mp.mnt_mountp);
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 		if (Debug)
1800Sstevel@tonic-gate 			printf("preflen: %d %s %s", len, qualpn, mp.mnt_mountp);
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 		if (qualpn[len] != '/' && qualpn[len] != '\0' && len > 1)
1830Sstevel@tonic-gate 			/*
1840Sstevel@tonic-gate 			 * If the last matching character is neither / nor
1850Sstevel@tonic-gate 			 * the end of the pathname, not a real match
1860Sstevel@tonic-gate 			 * (except for matching root, len==1)
1870Sstevel@tonic-gate 			 */
1880Sstevel@tonic-gate 			continue;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 		if (len > bestlen) {
1910Sstevel@tonic-gate 			bestlen = len;
1920Sstevel@tonic-gate 			strncpy(bestname, mp.mnt_special, sizeof (bestname));
1930Sstevel@tonic-gate 		}
1940Sstevel@tonic-gate 		if (Debug)
1950Sstevel@tonic-gate 			printf(" %s\n", bestname);
1960Sstevel@tonic-gate 	}
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	endmntent(mfp);
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	endhost = strchr(bestname, ':');
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	/*
2030Sstevel@tonic-gate 	 * If the file system was of type NFS, then there should already
2040Sstevel@tonic-gate 	 * be a host name, otherwise, use ours.
2050Sstevel@tonic-gate 	 */
2060Sstevel@tonic-gate 	if (endhost) {
2070Sstevel@tonic-gate 		*endhost++ = 0;
2080Sstevel@tonic-gate 		strncpy(host, bestname, MAXHOSTNAMELEN);
2090Sstevel@tonic-gate 		strncpy(fsname, endhost, MAXPATHLEN);
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 		/*
2120Sstevel@tonic-gate 		 * special case to keep the "/" when we match root
2130Sstevel@tonic-gate 		 */
2140Sstevel@tonic-gate 		if (bestlen == 1)
2150Sstevel@tonic-gate 			bestlen = 0;
2160Sstevel@tonic-gate 	} else {
2170Sstevel@tonic-gate 		gethostname(host, MAXHOSTNAMELEN);
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 		/*
2200Sstevel@tonic-gate 		 *	If this is our file system, try for an even longer
2210Sstevel@tonic-gate 		 *	match from /etc/xtab.
2220Sstevel@tonic-gate 		 */
2230Sstevel@tonic-gate 		if (mfp = setsharetab()) {
2240Sstevel@tonic-gate 			while (getshare(mfp, &exp) > 0)
2250Sstevel@tonic-gate 				if (len = preflen(qualpn, exp->sh_path))
2260Sstevel@tonic-gate 					if (len > bestlen) {
2270Sstevel@tonic-gate 						bestlen = len;
2280Sstevel@tonic-gate 						strncpy(bestname, exp->sh_path,
2290Sstevel@tonic-gate 							sizeof (bestname));
2300Sstevel@tonic-gate 					}
2310Sstevel@tonic-gate 			endsharetab(mfp);
2320Sstevel@tonic-gate 		}
2330Sstevel@tonic-gate 		strncpy(fsname, qualpn, bestlen);
2340Sstevel@tonic-gate 		fsname[bestlen] = 0;
2350Sstevel@tonic-gate 	}
2360Sstevel@tonic-gate 	strncpy(within, qualpn + bestlen, MAXPATHLEN);
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	if (Debug)
2390Sstevel@tonic-gate 		printf("findmount: qualpn %s\nhost %s\nfsname %s\nwithin %s\n",
2400Sstevel@tonic-gate 			qualpn, host, fsname, within);
2410Sstevel@tonic-gate 	return (1);
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate /*
2450Sstevel@tonic-gate  * Returns: length of second argument if it is a prefix of the
2460Sstevel@tonic-gate  * first argument, otherwise zero.
2470Sstevel@tonic-gate  */
2480Sstevel@tonic-gate int
preflen(str,pref)2490Sstevel@tonic-gate preflen(str, pref)
2500Sstevel@tonic-gate char	*str, *pref;
2510Sstevel@tonic-gate {
2520Sstevel@tonic-gate 	int len;
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	len = strlen(pref);
2550Sstevel@tonic-gate 	if (strncmp(str, pref, len) == 0)
2560Sstevel@tonic-gate 		return (len);
2570Sstevel@tonic-gate 	return (0);
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate FILE
setsharetab()2610Sstevel@tonic-gate *setsharetab()
2620Sstevel@tonic-gate {
2630Sstevel@tonic-gate 	FILE	*f;
2640Sstevel@tonic-gate 
265*3957Sth199096 	f = fopen(SHARETAB, "r");
2660Sstevel@tonic-gate 	if (f == NULL) {
2670Sstevel@tonic-gate 		return (NULL);
2680Sstevel@tonic-gate 	}
269*3957Sth199096 
2700Sstevel@tonic-gate 	return (f);
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate void
endsharetab(f)2750Sstevel@tonic-gate endsharetab(f)
2760Sstevel@tonic-gate FILE	*f;
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate 	(void) fclose(f);
2790Sstevel@tonic-gate }
280