1 /*- 2 * Copyright (c) 1980, 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1980, 1989 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)umount.c 5.18 (Berkeley) 01/22/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