struct mntentchn mounttable;
 static int got_mtab = 0;
+struct mntentchn fstab;
+static int got_fstab = 0;
 
 static void read_mounttable(void);
+static void read_fstab(void);
 
 static struct mntentchn *
 mtab_head() {
        return &mounttable;
 }
 
+static struct mntentchn *
+fstab_head()
+{
+       if (!got_fstab)
+               read_fstab();
+       return &fstab;
+}
+
 static void
 my_free(const void *s) {
        if (s)
         read_mntentchn(mfp, fnam, mc);
 }
 
+static void
+read_fstab()
+{
+       mntFILE *mfp = NULL;
+       const char *fnam;
+       struct mntentchn *mc = &fstab;
+
+       got_fstab = 1;
+       mc->nxt = mc->prev = NULL;
+
+       fnam = _PATH_FSTAB;
+       mfp = nfs_setmntent (fnam, "r");
+       if (mfp == NULL || mfp->mntent_fp == NULL) {
+               int errsv = errno;
+               error(_("warning: can't open %s: %s"),
+                       _PATH_FSTAB, strerror (errsv));
+               return;
+       }
+       read_mntentchn(mfp, fnam, mc);
+}
+
 /*
  * Given the directory name NAME, and the place MCPREV we found it last time,
  * try to find more occurrences.
        return NULL;
 }
 
+/* Find the dir FILE in fstab.  */
+struct mntentchn *
+getfsfile (const char *file)
+{
+       struct mntentchn *mc, *mc0;
+
+       mc0 = fstab_head();
+       for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+               if (streq(mc->m.mnt_dir, file))
+                       return mc;
+       return NULL;
+}
+
+/* Find the device SPEC in fstab.  */
+struct mntentchn *
+getfsspec (const char *spec)
+{
+       struct mntentchn *mc, *mc0;
+
+       mc0 = fstab_head();
+       for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+               if (streq(mc->m.mnt_fsname, spec))
+                       return mc;
+       return NULL;
+}
+
 /* Updating mtab ----------------------------------------------*/
 
 /* Flag for already existing lock file. */
 
 #include <sys/mount.h>
 #include <getopt.h>
 #include <mntent.h>
+#include <pwd.h>
 
 #include "fstab.h"
 #include "xcommon.h"
   int  mask;                    /* flag mask value */
 };
 
+/* Custom mount options for our own purposes.  */
+#define MS_DUMMY       0x00000000
+#define MS_USERS       0x40000000
+#define MS_USER                0x80000000
+
 static const struct opt_map opt_map[] = {
   { "defaults", 0, 0, 0         },      /* default options */
   { "ro",       1, 0, MS_RDONLY },      /* read-only */
   { "remount",  0, 0, MS_REMOUNT},      /* Alter flags of mounted FS */
   { "bind",     0, 0, MS_BIND   },      /* Remount part of tree elsewhere */
   { "rbind",    0, 0, MS_BIND|MS_REC }, /* Idem, plus mounted subtrees */
+  { "auto",     0, 0, MS_DUMMY },       /* Can be mounted using -a */
+  { "noauto",   0, 0, MS_DUMMY },       /* Can  only be mounted explicitly */
+  { "users",    1, 0, MS_USERS|MS_NOEXEC|MS_NOSUID|MS_NODEV  },
+                                       /* Allow ordinary user to mount */
+  { "nousers",  0, 1, MS_DUMMY  },      /* Forbid ordinary user to mount */
+  { "user",     1, 0, MS_USER|MS_NOEXEC|MS_NOSUID|MS_NODEV  },
+                                       /* Allow ordinary user to mount */
+  { "nouser",   0, 1, MS_DUMMY   },     /* Forbid ordinary user to mount */
+  { "owner",    0, 0, MS_DUMMY  },      /* Let the owner of the device mount */
+  { "noowner",  0, 0, MS_DUMMY  },      /* Device owner has no special privs */
+  { "group",    0, 0, MS_DUMMY  },      /* Let the group of the device mount */
+  { "nogroup",  0, 0, MS_DUMMY  },      /* Device group has no special privs */
+  { "_netdev",  0, 0, MS_DUMMY},        /* Device requires network */
+  { "comment",  0, 0, MS_DUMMY},        /* fstab comment only (kudzu,_netdev)*/
 
   /* add new options here */
 #ifdef MS_NOSUB
   { "mand",     0, 0, MS_MANDLOCK },    /* Allow mandatory locks on this FS */
   { "nomand",   0, 1, MS_MANDLOCK },    /* Forbid mandatory locks on this FS */
 #endif
+  { "loop",     1, 0, MS_DUMMY   },      /* use a loop device */
 #ifdef MS_NOATIME
   { "atime",    0, 1, MS_NOATIME },     /* Update access time */
   { "noatime",  0, 0, MS_NOATIME },     /* Do not update access time */
        char *new_opts;
 
        new_opts = xstrdup((flags & MS_RDONLY) ? "ro" : "rw");
+       if (flags & MS_USER) {
+               /* record who mounted this so they can unmount */
+               struct passwd *pw = getpwuid(getuid());
+               if(pw)
+                       new_opts = xstrconcat3(new_opts, ",user=", pw->pw_name);
+       }
+       if (flags & MS_USERS)
+               new_opts = xstrconcat3(new_opts, ",users", "");
+       
        for (om = opt_map; om->opt != NULL; om++) {
                if (om->skip)
                        continue;
        int c, flags = 0, nfs_mount_vers = 0, mnt_err = 1, fake = 0;
        char *spec, *mount_point, *extra_opts = NULL;
        char *mount_opts = NULL, *p;
+       uid_t uid = getuid();
 
        progname = argv[0];
        if ((p = strrchr(progname, '/')) != NULL)
                progname = p+1;
 
-       if (getuid() != 0) {
-               printf("%s: only root can do that.\n", progname);
-               exit(1);
-       }
-
        if(!strncmp(progname, "umount", strlen("umount"))) {
                if(argc < 2) {
                        umount_usage();
        }
 
        spec = argv[1];
-       mount_point = canonicalize(argv[2]);
+       mount_point = argv[2];
+
+       if (uid != 0) {
+               /* don't even think about it unless options exactly
+                * make fstab
+                */
+               struct mntentchn *mc;
+
+               if ((mc = getfsfile(mount_point)) == NULL ||
+                   strcmp(mc->m.mnt_fsname, spec) != 0 ||
+                   strcmp(mc->m.mnt_opts, mount_opts) != 0) {
+                       fprintf(stderr, "%s: permission died - no match for fstab\n",
+                               progname);
+                       exit(1);
+               }
+               mounttype = 0;
+       }
+
+       mount_point = canonicalize(mount_point);
        
        parse_opts(mount_opts, &flags, &extra_opts);
 
+       if (uid != 0) {
+           if (! (flags & (MS_USERS | MS_USER))) {
+                   fprintf(stderr, "%s: permission denied\n", progname);
+                   exit(1);
+           }
+       }
+
        if (!strcmp(progname, "mount.nfs4") || nfs_mount_vers == 4) {
                nfs_mount_vers = 4;
                mnt_err = nfs4mount(spec, mount_point, &flags, &extra_opts, &mount_opts, 0);