2 * Copyright (c) 1999 Martin Blapp
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 static const char rcsid[] =
33 #include <sys/param.h>
34 #include <sys/ucred.h>
35 #include <sys/mount.h>
38 #include <nfs/rpcv2.h>
51 static int do_umount (char *, char *);
52 static int do_umntall (char *);
53 static int is_mounted (char *, char *);
54 static void usage (void);
55 int xdr_dir (XDR *, char *);
57 struct mtablist *mtabhead;
60 main(int argc, char **argv) {
61 int ch, keep, success, pathlen;
64 struct mtablist *mtab;
70 success = keep = verbose = 0;
71 while ((ch = getopt(argc, argv, "h:kp:ve:")) != -1)
77 expire = (time_t)optarg;
95 /* Ignore SIGINT and SIGQUIT during shutdown */
96 signal(SIGINT, SIG_IGN);
97 signal(SIGQUIT, SIG_IGN);
99 /* Default expiretime is two days */
103 * Read PATH_MOUNTTAB and check each entry
104 * and do finally the unmounts.
106 if (host == NULL && path == NULL) {
107 if (!read_mtab(mtab)) {
109 warnx("nothing to do, remove %s",
112 for (mtab = mtabhead; mtab != NULL; mtab = mtab->mtab_next) {
113 if (*mtab->mtab_host != '\0' ||
114 mtab->mtab_time <= (time(now) - expire)) {
115 if (keep && is_mounted(mtab->mtab_host,
118 warnx("skipping entry %s:%s",
122 } else if (do_umount(mtab->mtab_host,
124 clean_mtab(mtab->mtab_host,
129 /* Only do a RPC UMNTALL for this specific host */
130 } else if (host != NULL && path == NULL) {
131 if (!do_umntall(host))
135 /* Someone forgot to enter a hostname */
136 } else if (host == NULL && path != NULL)
138 /* Only do a RPC UMOUNT for this specific mount */
140 for (pathlen = strlen(path);
141 pathlen > 1 && path[pathlen - 1] == '/'; pathlen--)
142 path[pathlen - 1] = '\0';
143 if (!do_umount(host, path))
148 /* Write and unlink PATH_MOUNTTAB if necessary */
151 warnx("UMOUNT RPC successfully sent to %s", host);
152 if (read_mtab(mtab)) {
154 clean_mtab(host, path);
166 * Send a RPC_MNT UMNTALL request to hostname.
167 * XXX This works for all mountd implementations,
168 * but produces a RPC IOERR on non FreeBSD systems.
171 do_umntall(char *hostname) {
172 enum clnt_stat clnt_stat;
174 struct sockaddr_in saddr;
175 struct timeval pertry, try;
179 if ((hp = gethostbyname(hostname)) == NULL) {
180 warnx("gethostbyname(%s) failed", hostname);
183 memset(&saddr, 0, sizeof(saddr));
184 saddr.sin_family = AF_INET;
186 memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length,
187 sizeof(saddr.sin_addr)));
191 if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
192 pertry, &so)) == NULL) {
193 clnt_pcreateerror("Cannot send MNT PRC");
196 clp->cl_auth = authunix_create_default();
199 clnt_stat = clnt_call(clp, RPCMNT_UMNTALL, xdr_void, (caddr_t)0,
200 xdr_void, (caddr_t)0, try);
201 if (clnt_stat != RPC_SUCCESS) {
202 clnt_perror(clp, "Bad MNT RPC");
209 * Send a RPC_MNT UMOUNT request for dirp to hostname.
212 do_umount(char *hostname, char *dirp) {
213 enum clnt_stat clnt_stat;
215 struct sockaddr_in saddr;
216 struct timeval pertry, try;
220 if ((hp = gethostbyname(hostname)) == NULL) {
221 warnx("gethostbyname(%s) failed", hostname);
224 memset(&saddr, 0, sizeof(saddr));
225 saddr.sin_family = AF_INET;
227 memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length,
228 sizeof(saddr.sin_addr)));
232 if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
233 pertry, &so)) == NULL) {
234 clnt_pcreateerror("Cannot send MNT PRC");
237 clp->cl_auth = authunix_create_default();
240 clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, dirp,
241 xdr_void, (caddr_t)0, try);
242 if (clnt_stat != RPC_SUCCESS) {
243 clnt_perror(clp, "Bad MNT RPC");
250 * Check if the entry is still/already mounted.
253 is_mounted(char *hostname, char *dirp) {
254 struct statfs *mntbuf;
255 char name[MNAMELEN + 1];
256 size_t bufsize, hostlen, dirlen;
259 hostlen = strlen(hostname);
260 dirlen = strlen(dirp);
261 if ((hostlen + dirlen) >= MNAMELEN)
263 memmove(name, hostname, hostlen);
265 memmove(name + hostlen + 1, dirp, dirlen);
266 name[hostlen + dirlen + 1] = '\0';
267 mntsize = getfsstat(NULL, 0, MNT_NOWAIT);
270 bufsize = (mntsize + 1) * sizeof(struct statfs);
271 if ((mntbuf = malloc(bufsize)) == NULL)
273 mntsize = getfsstat(mntbuf, (long)bufsize, MNT_NOWAIT);
274 for (i = mntsize - 1; i >= 0; i--) {
275 if (strcmp(mntbuf[i].f_mntfromname, name) == 0) {
285 * xdr routines for mount rpc's
288 xdr_dir(XDR *xdrsp, char *dirp) {
290 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
296 (void)fprintf(stderr, "%s\n",
297 "usage: rpc.umntall [-h host] [-k] [-p path] [-t expire] [-v]");