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