home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sbin / umount / umount.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-03  |  9.3 KB  |  428 lines

  1. /*-
  2.  * Copyright (c) 1980, 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  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.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1980, 1989 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)umount.c    5.16 (Berkeley) 6/3/91";
  42. #endif /* not lint */
  43.  
  44. #include <sys/param.h>
  45. #include <sys/stat.h>
  46. #include <sys/mount.h>
  47.  
  48. #ifdef NFS
  49. #include <sys/time.h>
  50. #include <sys/socket.h>
  51. #include <sys/socketvar.h>
  52. #include <netdb.h>
  53. #include <rpc/rpc.h>
  54. #include <rpc/pmap_clnt.h>
  55. #include <rpc/pmap_prot.h>
  56. #include <nfs/rpcv2.h>
  57. #endif
  58.  
  59. #include <fstab.h>
  60. #include <stdio.h>
  61. #include <string.h>
  62.  
  63. #ifdef NFS
  64. int xdr_dir();
  65. char *nfshost;
  66. #endif
  67.  
  68. int    vflag, all, errs, fake;
  69. int    fflag = MNT_NOFORCE;
  70. char    *getmntname();
  71.  
  72. #define    MNTON    1
  73. #define    MNTFROM    2
  74. #define    MNTTYPE 3
  75.  
  76. int *typelist, *maketypelist();
  77.  
  78. main(argc, argv)
  79.     int argc;
  80.     char **argv;
  81. {
  82.     extern char *optarg;
  83.     extern int optind;
  84.     int ch;
  85.  
  86.     sync();
  87.     while ((ch = getopt(argc, argv, "afFh:t:v")) != EOF)
  88.         switch((char)ch) {
  89.         case 'v':
  90.             vflag++;
  91.             break;
  92.         case 'f':
  93.             fflag = MNT_FORCE;
  94.             break;
  95.         case 'F':
  96.             fake++;
  97.             break;
  98.         case 'a':
  99.             all++;
  100.             break;
  101.         case 't':
  102.             typelist = maketypelist(optarg);
  103.             break;
  104. #ifdef    NFS
  105.         case 'h':
  106.             /* -h flag implies -a, and "-t nfs" if no -t flag */
  107.             nfshost = optarg;
  108.             all++;
  109.             if (typelist == NULL)
  110.                 typelist = maketypelist("nfs");
  111.             break;
  112. #endif /* NFS */
  113.         case '?':
  114.         default:
  115.             usage();
  116.             /* NOTREACHED */
  117.         }
  118.     argc -= optind;
  119.     argv += optind;
  120.  
  121.     if (argc == 0 && !all)
  122.         usage();
  123.     if (all) {
  124.         if (argc > 0)
  125.             usage();
  126.         if (setfsent() == 0)
  127.             perror(FSTAB), exit(1);
  128.         umountall(typelist);
  129.         exit(0);
  130.     } else
  131.         setfsent();
  132.     while (argc > 0) {
  133.         if (umountfs(*argv++, 0) == 0)
  134.             errs++;
  135.         argc--;
  136.     }
  137.     exit(errs);
  138. }
  139.  
  140. usage()
  141. {
  142.     fprintf(stderr,
  143.         "%s\n%s\n",
  144.         "Usage: umount [-fv] special | node",
  145. #ifndef    NFS
  146.         "    or umount -a[fv] [-t fstypelist]"
  147. #else
  148.         "    or umount -a[fv] [-h host] [-t fstypelist]"
  149. #endif
  150.           );
  151.     exit(1);
  152. }
  153.  
  154. umountall(typelist)
  155.     char **typelist;
  156. {
  157.     register struct fstab *fs;
  158.     struct fstab *allocfsent();
  159.  
  160.     if ((fs = getfsent()) == (struct fstab *)0)
  161.         return;
  162.     fs = allocfsent(fs);
  163.     umountall(typelist);
  164.     if (strcmp(fs->fs_file, "/") == 0) {
  165.         freefsent(fs);
  166.         return;
  167.     }
  168.     if (strcmp(fs->fs_type, FSTAB_RW) &&
  169.         strcmp(fs->fs_type, FSTAB_RO) &&
  170.         strcmp(fs->fs_type, FSTAB_RQ)) {
  171.         freefsent(fs);
  172.         return;
  173.     }
  174.     (void) umountfs(fs->fs_file, typelist);
  175.     freefsent(fs);
  176. }
  177.  
  178. struct fstab *
  179. allocfsent(fs)
  180.     register struct fstab *fs;
  181. {
  182.     register struct fstab *new;
  183.     register char *cp;
  184.  
  185.     new = (struct fstab *)malloc((unsigned)sizeof (*fs));
  186.     cp = (char *)malloc((unsigned)strlen(fs->fs_file) + 1);
  187.     strcpy(cp, fs->fs_file);
  188.     new->fs_file = cp;
  189.     cp = (char *)malloc((unsigned)strlen(fs->fs_type) + 1);
  190.     strcpy(cp, fs->fs_type);
  191.     new->fs_type = cp;
  192.     cp = (char *)malloc((unsigned)strlen(fs->fs_spec) + 1);
  193.     strcpy(cp, fs->fs_spec);
  194.     new->fs_spec = cp;
  195.     new->fs_passno = fs->fs_passno;
  196.     new->fs_freq = fs->fs_freq;
  197.     return (new);
  198. }
  199.  
  200. freefsent(fs)
  201.     register struct fstab *fs;
  202. {
  203.  
  204.     if (fs->fs_file)
  205.         free(fs->fs_file);
  206.     if (fs->fs_spec)
  207.         free(fs->fs_spec);
  208.     if (fs->fs_type)
  209.         free(fs->fs_type);
  210.     free((char *)fs);
  211. }
  212.  
  213. umountfs(name, typelist)
  214.     char *name;
  215.     int *typelist;
  216. {
  217.     char *mntpt;
  218.     struct stat stbuf;
  219.     int type;
  220. #ifdef NFS
  221.     register CLIENT *clp;
  222.     struct hostent *hp = 0;
  223.     struct sockaddr_in saddr;
  224.     struct timeval pertry, try;
  225.     enum clnt_stat clnt_stat;
  226.     int so = RPC_ANYSOCK;
  227.     char *hostp, *delimp;
  228. #endif /* NFS */
  229.  
  230.     if (stat(name, &stbuf) < 0) {
  231.         if (getmntname(name, MNTFROM, &type) != 0)
  232.             mntpt = name;
  233.         else if ((mntpt = getmntname(name, MNTON, &type)) == 0) {
  234.             fprintf(stderr, "%s: not currently mounted\n", name);
  235.             return (0);
  236.         }
  237.     } else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) {
  238.         if ((mntpt = getmntname(name, MNTON, &type)) == 0) {
  239.             fprintf(stderr, "%s: not currently mounted\n", name);
  240.             return (0);
  241.         }
  242.     } else if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
  243.         mntpt = name;
  244.         if (getmntname(mntpt, MNTFROM, &type) == 0) {
  245.             fprintf(stderr, "%s: not currently mounted\n", name);
  246.             return (0);
  247.         }
  248.     } else {
  249.         fprintf(stderr, "%s: not a directory or special device\n",
  250.             name);
  251.         return (0);
  252.     }
  253.  
  254.     if (badtype(type, typelist))
  255.         return(1);
  256. #ifdef NFS
  257.     if ((delimp = index(name, '@')) != NULL) {
  258.         hostp = delimp + 1;
  259.         *delimp = '\0';
  260.         hp = gethostbyname(hostp);
  261.         *delimp = '@';
  262.     } else if ((delimp = index(name, ':')) != NULL) {
  263.         *delimp = '\0';
  264.         hostp = name;
  265.         hp = gethostbyname(hostp);
  266.         name = delimp+1;
  267.         *delimp = ':';
  268.     }
  269.  
  270.     if (!namematch(hp, nfshost))
  271.         return(1);
  272. #endif    /* NFS */
  273.     if (!fake && unmount(mntpt, fflag) < 0) {
  274.         perror(mntpt);
  275.         return (0);
  276.     }
  277.     if (vflag)
  278.         fprintf(stderr, "%s: Unmounted from %s\n", name, mntpt);
  279.  
  280. #ifdef    NFS
  281.     if (!fake && hp != NULL && (fflag & MNT_FORCE) == 0) {
  282.         *delimp = '\0';
  283.         bcopy(hp->h_addr,(caddr_t)&saddr.sin_addr,hp->h_length);
  284.         saddr.sin_family = AF_INET;
  285.         saddr.sin_port = 0;
  286.         pertry.tv_sec = 3;
  287.         pertry.tv_usec = 0;
  288.         if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
  289.             pertry, &so)) == NULL) {
  290.             clnt_pcreateerror("Cannot MNT PRC");
  291.             return (1);
  292.         }
  293.         clp->cl_auth = authunix_create_default();
  294.         try.tv_sec = 20;
  295.         try.tv_usec = 0;
  296.         clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, name,
  297.             xdr_void, (caddr_t)0, try);
  298.         if (clnt_stat != RPC_SUCCESS) {
  299.             clnt_perror(clp, "Bad MNT RPC");
  300.             return (1);
  301.         }
  302.         auth_destroy(clp->cl_auth);
  303.         clnt_destroy(clp);
  304.     }
  305. #endif /* NFS */
  306.     return (1);
  307. }
  308.  
  309. char *
  310. getmntname(name, what, type)
  311.     char *name;
  312.     int what;
  313.     int *type;
  314. {
  315.     int mntsize, i;
  316.     struct statfs *mntbuf;
  317.  
  318.     if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) {
  319.         perror("umount");
  320.         return (0);
  321.     }
  322.     for (i = 0; i < mntsize; i++) {
  323.         if (what == MNTON && !strcmp(mntbuf[i].f_mntfromname, name)) {
  324.             if (type)
  325.                 *type = mntbuf[i].f_type;
  326.             return (mntbuf[i].f_mntonname);
  327.         }
  328.         if (what == MNTFROM && !strcmp(mntbuf[i].f_mntonname, name)) {
  329.             if (type)
  330.                 *type = mntbuf[i].f_type;
  331.             return (mntbuf[i].f_mntfromname);
  332.         }
  333.     }
  334.     return (0);
  335. }
  336.  
  337. static int skipvfs;
  338.  
  339. badtype(type, typelist)
  340.     int type;
  341.     int *typelist;
  342. {
  343.     if (typelist == 0)
  344.         return(0);
  345.     while (*typelist) {
  346.         if (type == *typelist)
  347.             return(skipvfs);
  348.         typelist++;
  349.     }
  350.     return(!skipvfs);
  351. }
  352.  
  353. int *
  354. maketypelist(fslist)
  355.     char *fslist;
  356. {
  357.     register char *nextcp;
  358.     register int *av, i;
  359.  
  360.     if (fslist == NULL)
  361.         return(NULL);
  362.     if (fslist[0] == 'n' && fslist[1] == 'o') {
  363.         fslist += 2;
  364.         skipvfs = 1;
  365.     } else
  366.         skipvfs = 0;
  367.     for (i = 0, nextcp = fslist; *nextcp; nextcp++)
  368.         if (*nextcp == ',')
  369.             i++;
  370.     av = (int *)malloc((i+2) * sizeof(int));
  371.     if (av == NULL)
  372.         return(NULL);
  373.     for (i = 0; fslist; fslist = nextcp) {
  374.         if (nextcp = index(fslist, ','))
  375.             *nextcp++ = '\0';
  376.         if (strcmp(fslist, "ufs") == 0)
  377.             av[i++] = MOUNT_UFS;
  378.         else if (strcmp(fslist, "nfs") == 0)
  379.             av[i++] = MOUNT_NFS;
  380.         else if (strcmp(fslist, "mfs") == 0)
  381.             av[i++] = MOUNT_MFS;
  382.         else if (strcmp(fslist, "pc") == 0)
  383.             av[i++] = MOUNT_PC;
  384.     }
  385.     av[i++] = 0;
  386.     return(av);
  387. }
  388.  
  389. #ifdef    NFS
  390. namematch(hp, nfshost)
  391.     struct hostent *hp;
  392.     char *nfshost;
  393. {
  394.     register char *cp;
  395.     register char **np;
  396.  
  397.     if (hp == NULL || nfshost == NULL)
  398.         return(1);
  399.     if (strcasecmp(nfshost, hp->h_name) == 0)
  400.         return(1);
  401.     if (cp = index(hp->h_name, '.')) {
  402.         *cp = '\0';
  403.         if (strcasecmp(nfshost, hp->h_name) == 0)
  404.             return(1);
  405.     }
  406.     for (np = hp->h_aliases; *np; np++) {
  407.         if (strcasecmp(nfshost, *np) == 0)
  408.             return(1);
  409.         if (cp = index(*np, '.')) {
  410.             *cp = '\0';
  411.             if (strcasecmp(nfshost, *np) == 0)
  412.                 return(1);
  413.         }
  414.     }
  415.     return(0);
  416. }
  417.  
  418. /*
  419.  * xdr routines for mount rpc's
  420.  */
  421. xdr_dir(xdrsp, dirp)
  422.     XDR *xdrsp;
  423.     char *dirp;
  424. {
  425.     return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
  426. }
  427. #endif /* NFS */
  428.