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.15 (Berkeley) 04/16/91"; 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 = MNT_NOFORCE; 44 char *getmntname(); 45 46 #define MNTON 1 47 #define MNTFROM 2 48 #define MNTTYPE 3 49 50 int *typelist, *maketypelist(); 51 52 main(argc, argv) 53 int argc; 54 char **argv; 55 { 56 extern char *optarg; 57 extern int optind; 58 int ch; 59 60 sync(); 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(); 97 if (all) { 98 if (argc > 0) 99 usage(); 100 if (setfsent() == 0) 101 perror(FSTAB), exit(1); 102 umountall(typelist); 103 exit(0); 104 } else 105 setfsent(); 106 while (argc > 0) { 107 if (umountfs(*argv++, 0) == 0) 108 errs++; 109 argc--; 110 } 111 exit(errs); 112 } 113 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; 130 { 131 register struct fstab *fs; 132 struct fstab *allocfsent(); 133 134 if ((fs = getfsent()) == (struct fstab *)0) 135 return; 136 fs = allocfsent(fs); 137 umountall(typelist); 138 if (strcmp(fs->fs_file, "/") == 0) { 139 freefsent(fs); 140 return; 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); 146 return; 147 } 148 (void) umountfs(fs->fs_file, typelist); 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; 158 159 new = (struct fstab *)malloc((unsigned)sizeof (*fs)); 160 cp = (char *)malloc((unsigned)strlen(fs->fs_file) + 1); 161 strcpy(cp, fs->fs_file); 162 new->fs_file = cp; 163 cp = (char *)malloc((unsigned)strlen(fs->fs_type) + 1); 164 strcpy(cp, fs->fs_type); 165 new->fs_type = cp; 166 cp = (char *)malloc((unsigned)strlen(fs->fs_spec) + 1); 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); 185 } 186 187 umountfs(name, typelist) 188 char *name; 189 int *typelist; 190 { 191 char *mntpt; 192 struct stat stbuf; 193 int type; 194 #ifdef NFS 195 register CLIENT *clp; 196 struct hostent *hp = 0; 197 struct sockaddr_in saddr; 198 struct timeval pertry, try; 199 enum clnt_stat clnt_stat; 200 int so = RPC_ANYSOCK; 201 char *hostp, *delimp; 202 #endif /* NFS */ 203 204 if (stat(name, &stbuf) < 0) { 205 if ((mntpt = getmntname(name, MNTON, &type)) == 0) 206 return (0); 207 } else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) { 208 if ((mntpt = getmntname(name, MNTON, &type)) == 0) 209 return (0); 210 } else if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 211 mntpt = name; 212 if ((name = getmntname(mntpt, MNTFROM, &type)) == 0) 213 return (0); 214 } else { 215 fprintf(stderr, "%s: not a directory or special device\n", 216 name); 217 return (0); 218 } 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) { 240 perror(mntpt); 241 return (0); 242 } 243 if (vflag) 244 fprintf(stderr, "%s: Unmounted from %s\n", name, mntpt); 245 246 #ifdef NFS 247 if (!fake && hp != NULL && (fflag & MNT_FORCE) == 0) { 248 *delimp = '\0'; 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); 258 } 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); 267 } 268 auth_destroy(clp->cl_auth); 269 clnt_destroy(clp); 270 } 271 #endif /* NFS */ 272 return (1); 273 } 274 275 char * 276 getmntname(name, what, type) 277 char *name; 278 int what; 279 int *type; 280 { 281 int mntsize, i; 282 struct statfs *mntbuf; 283 284 if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { 285 perror("umount"); 286 return (0); 287 } 288 for (i = 0; i < mntsize; i++) { 289 if (what == MNTON && !strcmp(mntbuf[i].f_mntfromname, name)) { 290 if (type) 291 *type = mntbuf[i].f_type; 292 return (mntbuf[i].f_mntonname); 293 } 294 if (what == MNTFROM && !strcmp(mntbuf[i].f_mntonname, name)) { 295 if (type) 296 *type = mntbuf[i].f_type; 297 return (mntbuf[i].f_mntfromname); 298 } 299 } 300 fprintf(stderr, "%s: not currently mounted\n", name); 301 return (0); 302 } 303 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; 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 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 } 394 #endif /* NFS */ 395