xref: /original-bsd/sbin/umount/umount.c (revision c3e32dec)
1 /*-
2  * Copyright (c) 1980, 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1980, 1989, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)umount.c	8.1 (Berkeley) 06/05/93";
16 #endif /* not lint */
17 
18 #include <sys/param.h>
19 #include <sys/stat.h>
20 #include <sys/mount.h>
21 
22 #ifdef NFS
23 #include <sys/time.h>
24 #include <sys/socket.h>
25 #include <sys/socketvar.h>
26 #include <netdb.h>
27 #include <rpc/rpc.h>
28 #include <rpc/pmap_clnt.h>
29 #include <rpc/pmap_prot.h>
30 #include <nfs/rpcv2.h>
31 #endif
32 
33 #include <fstab.h>
34 #include <stdio.h>
35 #include <string.h>
36 
37 #ifdef NFS
38 int xdr_dir();
39 char *nfshost;
40 #endif
41 
42 int	vflag, all, errs, fake;
43 int	fflag = 0;
44 char	*getmntname();
45 
46 #define	MNTON	1
47 #define	MNTFROM	2
48 #define	MNTTYPE 3
49 
50 int *typelist, *maketypelist();
51 
52 char *namelist[] = INITMOUNTNAMES;
53 
54 main(argc, argv)
55 	int argc;
56 	char **argv;
57 {
58 	extern char *optarg;
59 	extern int optind;
60 	int ch;
61 
62 	sync();
63 	while ((ch = getopt(argc, argv, "afFh:t:v")) != EOF)
64 		switch((char)ch) {
65 		case 'v':
66 			vflag++;
67 			break;
68 		case 'f':
69 			fflag = MNT_FORCE;
70 			break;
71 		case 'F':
72 			fake++;
73 			break;
74 		case 'a':
75 			all++;
76 			break;
77 		case 't':
78 			typelist = maketypelist(optarg);
79 			break;
80 #ifdef	NFS
81 		case 'h':
82 			/* -h flag implies -a, and "-t nfs" if no -t flag */
83 			nfshost = optarg;
84 			all++;
85 			if (typelist == NULL)
86 				typelist = maketypelist("nfs");
87 			break;
88 #endif /* NFS */
89 		case '?':
90 		default:
91 			usage();
92 			/* NOTREACHED */
93 		}
94 	argc -= optind;
95 	argv += optind;
96 
97 	if (argc == 0 && !all)
98 		usage();
99 	if (all) {
100 		if (argc > 0)
101 			usage();
102 		if (setfsent() == 0)
103 			perror(FSTAB), exit(1);
104 		umountall(typelist);
105 		exit(0);
106 	} else
107 		setfsent();
108 	while (argc > 0) {
109 		if (umountfs(*argv++, 0) == 0)
110 			errs++;
111 		argc--;
112 	}
113 	exit(errs);
114 }
115 
116 usage()
117 {
118 	fprintf(stderr,
119 		"%s\n%s\n",
120 		"Usage: umount [-fv] special | node",
121 #ifndef	NFS
122 		"    or umount -a[fv] [-t fstypelist]"
123 #else
124 		"    or umount -a[fv] [-h host] [-t fstypelist]"
125 #endif
126 	      );
127 	exit(1);
128 }
129 
130 umountall(typelist)
131 	char **typelist;
132 {
133 	register struct fstab *fs;
134 	char *cp;
135 
136 	while (fs = getfsent()) {
137 		if (badtype(fsnametotype(fs->fs_vfstype), typelist))
138 			continue;
139 		if (strcmp(fs->fs_file, "/") == 0)
140 			continue;
141 		if (strcmp(fs->fs_type, FSTAB_RW) &&
142 		    strcmp(fs->fs_type, FSTAB_RO) &&
143 		    strcmp(fs->fs_type, FSTAB_RQ))
144 			continue;
145 		cp = (char *)malloc((unsigned)strlen(fs->fs_file) + 1);
146 		if (cp == NULL) {
147 			fprintf(stderr, "Out of memory.\n");
148 			exit(2);
149 		}
150 		strcpy(cp, fs->fs_file);
151 		umountall(typelist);
152 		break;
153 	}
154 	if (fs) {
155 		(void) umountfs(cp, typelist);
156 		free(cp);
157 	}
158 }
159 
160 umountfs(name, typelist)
161 	char *name;
162 	int *typelist;
163 {
164 	char *mntpt;
165 	struct stat stbuf;
166 	int type;
167 #ifdef NFS
168 	register CLIENT *clp;
169 	struct hostent *hp = 0;
170 	struct sockaddr_in saddr;
171 	struct timeval pertry, try;
172 	enum clnt_stat clnt_stat;
173 	int so = RPC_ANYSOCK;
174 	char *hostp, *delimp;
175 #endif /* NFS */
176 
177 	if (stat(name, &stbuf) < 0) {
178 		if (getmntname(name, MNTFROM, &type) != 0)
179 			mntpt = name;
180 		else if ((mntpt = getmntname(name, MNTON, &type)) == 0) {
181 			fprintf(stderr, "%s: not currently mounted\n", name);
182 			return (0);
183 		}
184 	} else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) {
185 		if ((mntpt = getmntname(name, MNTON, &type)) == 0) {
186 			fprintf(stderr, "%s: not currently mounted\n", name);
187 			return (0);
188 		}
189 	} else if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
190 		mntpt = name;
191 		if (getmntname(mntpt, MNTFROM, &type) == 0) {
192 			fprintf(stderr, "%s: not currently mounted\n", name);
193 			return (0);
194 		}
195 	} else {
196 		fprintf(stderr, "%s: not a directory or special device\n",
197 			name);
198 		return (0);
199 	}
200 
201 	if (badtype(type, typelist))
202 		return(1);
203 #ifdef NFS
204 	if ((delimp = index(name, '@')) != NULL) {
205 		hostp = delimp + 1;
206 		*delimp = '\0';
207 		hp = gethostbyname(hostp);
208 		*delimp = '@';
209 	} else if ((delimp = index(name, ':')) != NULL) {
210 		*delimp = '\0';
211 		hostp = name;
212 		hp = gethostbyname(hostp);
213 		name = delimp+1;
214 		*delimp = ':';
215 	}
216 
217 	if (!namematch(hp, nfshost))
218 		return(1);
219 #endif	/* NFS */
220 	if (!fake && unmount(mntpt, fflag) < 0) {
221 		perror(mntpt);
222 		return (0);
223 	}
224 	if (vflag)
225 		fprintf(stderr, "%s: Unmounted from %s\n", name, mntpt);
226 
227 #ifdef	NFS
228 	if (!fake && hp != NULL && (fflag & MNT_FORCE) == 0) {
229 		*delimp = '\0';
230 		bcopy(hp->h_addr,(caddr_t)&saddr.sin_addr,hp->h_length);
231 		saddr.sin_family = AF_INET;
232 		saddr.sin_port = 0;
233 		pertry.tv_sec = 3;
234 		pertry.tv_usec = 0;
235 		if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
236 		    pertry, &so)) == NULL) {
237 			clnt_pcreateerror("Cannot MNT PRC");
238 			return (1);
239 		}
240 		clp->cl_auth = authunix_create_default();
241 		try.tv_sec = 20;
242 		try.tv_usec = 0;
243 		clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, name,
244 			xdr_void, (caddr_t)0, try);
245 		if (clnt_stat != RPC_SUCCESS) {
246 			clnt_perror(clp, "Bad MNT RPC");
247 			return (1);
248 		}
249 		auth_destroy(clp->cl_auth);
250 		clnt_destroy(clp);
251 	}
252 #endif /* NFS */
253 	return (1);
254 }
255 
256 char *
257 getmntname(name, what, type)
258 	char *name;
259 	int what;
260 	int *type;
261 {
262 	int mntsize, i;
263 	struct statfs *mntbuf;
264 
265 	if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) {
266 		perror("umount");
267 		return (0);
268 	}
269 	for (i = 0; i < mntsize; i++) {
270 		if (what == MNTON && !strcmp(mntbuf[i].f_mntfromname, name)) {
271 			if (type)
272 				*type = mntbuf[i].f_type;
273 			return (mntbuf[i].f_mntonname);
274 		}
275 		if (what == MNTFROM && !strcmp(mntbuf[i].f_mntonname, name)) {
276 			if (type)
277 				*type = mntbuf[i].f_type;
278 			return (mntbuf[i].f_mntfromname);
279 		}
280 	}
281 	return (0);
282 }
283 
284 static int skipvfs;
285 
286 badtype(type, typelist)
287 	int type;
288 	int *typelist;
289 {
290 	if (typelist == 0)
291 		return(0);
292 	while (*typelist) {
293 		if (type == *typelist)
294 			return(skipvfs);
295 		typelist++;
296 	}
297 	return(!skipvfs);
298 }
299 
300 int *
301 maketypelist(fslist)
302 	char *fslist;
303 {
304 	register char *nextcp;
305 	register int *av, i;
306 
307 	if (fslist == NULL)
308 		return(NULL);
309 	if (fslist[0] == 'n' && fslist[1] == 'o') {
310 		fslist += 2;
311 		skipvfs = 1;
312 	} else
313 		skipvfs = 0;
314 	for (i = 0, nextcp = fslist; *nextcp; nextcp++)
315 		if (*nextcp == ',')
316 			i++;
317 	av = (int *)malloc((i+2) * sizeof(int));
318 	if (av == NULL)
319 		return(NULL);
320 	for (i = 0; fslist; fslist = nextcp) {
321 		if (nextcp = index(fslist, ','))
322 			*nextcp++ = '\0';
323 		av[i++] = fsnametotype(fslist);
324 	}
325 	av[i++] = 0;
326 	return(av);
327 }
328 
329 fsnametotype(name)
330 	char *name;
331 {
332 	char **cp;
333 
334 	for (cp = namelist; *cp; cp++)
335 		if (strcmp(name, *cp) == 0)
336 			return (cp - namelist);
337 	return (MOUNT_NONE);
338 }
339 
340 #ifdef	NFS
341 namematch(hp, nfshost)
342 	struct hostent *hp;
343 	char *nfshost;
344 {
345 	register char *cp;
346 	register char **np;
347 
348 	if (hp == NULL || nfshost == NULL)
349 		return(1);
350 	if (strcasecmp(nfshost, hp->h_name) == 0)
351 		return(1);
352 	if (cp = index(hp->h_name, '.')) {
353 		*cp = '\0';
354 		if (strcasecmp(nfshost, hp->h_name) == 0)
355 			return(1);
356 	}
357 	for (np = hp->h_aliases; *np; np++) {
358 		if (strcasecmp(nfshost, *np) == 0)
359 			return(1);
360 		if (cp = index(*np, '.')) {
361 			*cp = '\0';
362 			if (strcasecmp(nfshost, *np) == 0)
363 				return(1);
364 		}
365 	}
366 	return(0);
367 }
368 
369 /*
370  * xdr routines for mount rpc's
371  */
372 xdr_dir(xdrsp, dirp)
373 	XDR *xdrsp;
374 	char *dirp;
375 {
376 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
377 }
378 #endif /* NFS */
379