]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/nfsmount.c
Currently nfs4mount() sets the retry value to 10000 on both fg and bg
[nfs-utils.git] / utils / mount / nfsmount.c
index 4b862f05a3f7f8aee7dfa2b4f5534450b874260d..a9dd91764fbb7276521245885133c928640966f7 100644 (file)
@@ -23,7 +23,7 @@
  *
  * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
  * - added Native Language Support
- * 
+ *
  * Modified by Olaf Kirch and Trond Myklebust for new NFS code,
  * plus NFSv3 stuff.
  *
  * nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
  */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <ctype.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <paths.h>
 #include <syslog.h>
 
-#include "conn.h"
 #include "xcommon.h"
 #include "mount.h"
-#include "nfsumount.h"
 #include "nfs_mount.h"
 #include "mount_constants.h"
 #include "nls.h"
 #include "error.h"
+#include "network.h"
 
 #ifndef NFS_PORT
 #define NFS_PORT 2049
@@ -88,273 +91,11 @@ typedef union {
 } mntres_t;
 
 extern int nfs_mount_data_version;
+extern char *progname;
 extern int verbose;
 extern int sloppy;
 
-extern int linux_version_code();
-
-static const unsigned int probe_udp_only[] = {
-       IPPROTO_UDP,
-       0,
-};
-
-static const unsigned int probe_udp_first[] = {
-       IPPROTO_UDP,
-       IPPROTO_TCP,
-       0,
-};
-
-static const unsigned int probe_tcp_first[] = {
-       IPPROTO_TCP,
-       IPPROTO_UDP,
-       0,
-};
-
-static const unsigned long probe_nfs2_only[] = {
-       2,
-       0,
-};
-
-static const unsigned long probe_nfs3_first[] = {
-       3,
-       2,
-       0,
-};
-
-static const unsigned long probe_mnt1_first[] = {
-       1,
-       2,
-       0,
-};
-
-static const unsigned long probe_mnt3_first[] = {
-       3,
-       1,
-       2,
-       0,
-};
-
-int nfs_gethostbyname(const char *, struct sockaddr_in *);
-int nfs_gethostbyname(const char *hostname, struct sockaddr_in *saddr)
-{
-       struct hostent *hp;
-
-       saddr->sin_family = AF_INET;
-       if (!inet_aton(hostname, &saddr->sin_addr)) {
-               if ((hp = gethostbyname(hostname)) == NULL) {
-                       fprintf(stderr, _("mount: can't get address for %s\n"),
-                               hostname);
-                       return 0;
-               } else {
-                       if (hp->h_length > sizeof(*saddr)) {
-                               fprintf(stderr,
-                                       _("mount: got bad hp->h_length\n"));
-                               hp->h_length = sizeof(*saddr);
-                       }
-                       memcpy(&saddr->sin_addr, hp->h_addr, hp->h_length);
-               }
-       }
-       return 1;
-}
-
-/*
- * getport() is very similar to pmap_getport() with
- * the exception this version uses a non-reserve ports 
- * instead of reserve ports since reserve ports
- * are not needed for pmap requests.
- */
-u_short
-getport(
-       struct sockaddr_in *saddr, 
-       u_long prog, 
-       u_long vers, 
-       u_int prot)
-{
-       u_short port = 0;
-       int    socket;
-       CLIENT *clnt = NULL;
-       struct pmap parms;
-       enum clnt_stat stat;
-
-       saddr->sin_port = htons (PMAPPORT);
-       socket = get_socket(saddr, prot, FALSE, FALSE);
-
-       switch (prot) {
-       case IPPROTO_UDP:
-               clnt = clntudp_bufcreate(saddr,
-                                        PMAPPROG, PMAPVERS, TIMEOUT, &socket,
-                                        UDPMSGSIZE, UDPMSGSIZE);
-               break;
-       case IPPROTO_TCP:
-               clnt = clnttcp_create(saddr,
-                       PMAPPROG, PMAPVERS, &socket, 50, 500);
-               break;
-       }
-       if (clnt != NULL) {
-               parms.pm_prog = prog;
-               parms.pm_vers = vers;
-               parms.pm_prot = prot;
-               parms.pm_port = 0;    /* not needed or used */
-
-               stat = clnt_call(clnt, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap,
-                       (caddr_t)&parms, (xdrproc_t)xdr_u_short, (caddr_t)&port, TIMEOUT);
-               if (stat) {
-                       clnt_geterr(clnt, &rpc_createerr.cf_error);
-                       rpc_createerr.cf_stat = stat;
-               }
-               clnt_destroy(clnt);
-               if (stat != RPC_SUCCESS)
-                       port = 0;
-               else if (port == 0)
-                       rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
-       }
-       if (socket != 1)
-               close(socket);
-
-       return port;
-}
-
-/*
- * Use the portmapper to discover whether or not the service we want is
- * available. The lists 'versions' and 'protos' define ordered sequences
- * of service versions and udp/tcp protocols to probe for.
- */
-static int
-probe_port(clnt_addr_t *server, 
-          const u_long *versions,
-          const u_int *protos)
-{
-       struct sockaddr_in *saddr = &server->saddr;
-       struct pmap *pmap = &server->pmap;
-       const u_long prog = pmap->pm_prog, *p_vers;
-       const u_int prot = (u_int)pmap->pm_prot,
-               *p_prot;
-       const u_short port = (u_short) pmap->pm_port;
-       u_long vers = pmap->pm_vers;
-       u_short p_port;
-       p_prot = prot ? &prot : protos;
-       p_vers = vers ? &vers : versions;
-       rpc_createerr.cf_stat = 0;
-       for (;;) {
-               saddr->sin_port = htons(PMAPPORT);
-               p_port = getport(saddr, prog, *p_vers, *p_prot);
-               if (p_port) {
-                       if (!port || port == p_port) {
-                               saddr->sin_port = htons(p_port);
-                               if (verbose) {
-                                       fprintf(stderr, 
-                                               "mount: trying %s prog %ld vers %ld prot %s port %d\n", 
-                                               inet_ntoa(saddr->sin_addr), prog, *p_vers,
-                                               *p_prot == IPPROTO_UDP ? "udp" : "tcp", p_port);
-                               }
-                               if (clnt_ping(saddr, prog, *p_vers, *p_prot, NULL))
-                                       goto out_ok;
-                               if (rpc_createerr.cf_stat == RPC_TIMEDOUT)
-                                       goto out_bad;
-                       }
-               }
-               if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED) 
-                       goto out_bad;
-
-               if (!prot) {
-                       if (*++p_prot)
-                               continue;
-                       p_prot = protos;
-               }
-               if (vers == pmap->pm_vers) {
-                       p_vers = versions;
-                       vers = 0;
-               }
-               if (vers || !*++p_vers)
-                       break;
-       }
-out_bad:
-       return 0;
-
- out_ok:
-       if (!vers)
-               pmap->pm_vers = *p_vers;
-       if (!prot)
-               pmap->pm_prot = *p_prot;
-       if (!port)
-               pmap->pm_port = p_port;
-       rpc_createerr.cf_stat = 0;
-       return 1;
-}
-
-static int probe_nfsport(clnt_addr_t *nfs_server)
-{
-       struct pmap *pmap = &nfs_server->pmap;
-
-       if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
-               return 1;
-
-       if (nfs_mount_data_version >= 4)
-               return probe_port(nfs_server, probe_nfs3_first, probe_tcp_first);
-       else
-               return probe_port(nfs_server, probe_nfs2_only, probe_udp_only);
-}
-
-int probe_mntport(clnt_addr_t *mnt_server)
-{
-       struct pmap *pmap = &mnt_server->pmap;
-
-       if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
-               return 1;
-
-       if (nfs_mount_data_version >= 4)
-               return probe_port(mnt_server, probe_mnt3_first, probe_udp_first);
-       else
-               return probe_port(mnt_server, probe_mnt1_first, probe_udp_only);
-}
-
-static int
-probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
-{
-       struct pmap *nfs_pmap = &nfs_server->pmap;
-       struct pmap *mnt_pmap = &mnt_server->pmap;
-       struct pmap save_nfs, save_mnt;
-       int res;
-       const unsigned long *probe_vers;
-
-       if (mnt_pmap->pm_vers && !nfs_pmap->pm_vers)
-               nfs_pmap->pm_vers = mntvers_to_nfs(mnt_pmap->pm_vers);
-       else if (nfs_pmap->pm_vers && !mnt_pmap->pm_vers)
-               mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
-       if (nfs_pmap->pm_vers)
-               goto version_fixed;
-
-       memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
-       memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
-       probe_vers = (nfs_mount_data_version >= 4) ?
-                       probe_mnt3_first : probe_mnt1_first;
-
-       for (; *probe_vers; probe_vers++) {
-               nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
-               if ((res = probe_nfsport(nfs_server) != 0)) {
-                       mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
-                       if ((res = probe_mntport(mnt_server)) != 0)
-                               return 1;
-                       memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
-               }
-               switch (rpc_createerr.cf_stat) {
-               case RPC_PROGVERSMISMATCH:
-               case RPC_PROGNOTREGISTERED:
-                       break;
-               default:
-                       goto out_bad;
-               }
-               memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
-       }
-
-out_bad:
-       return 0;
-
-version_fixed:
-       if (!probe_nfsport(nfs_server))
-               goto out_bad;
-       return probe_mntport(mnt_server);
-}
+extern int linux_version_code(void);
 
 static inline enum clnt_stat
 nfs3_mount(CLIENT *clnt, mnt3arg_t *mnt3arg, mnt3res_t *mnt3res)
@@ -453,7 +194,6 @@ parse_options(char *old_opts, struct nfs_mount_data *data,
                if ((opteq = strchr(opt, '=')) && isdigit(opteq[1])) {
                        int val = atoi(opteq + 1);      
                        *opteq = '\0';
-/* printf("opt=%s\n", opt); */
                        if (!strcmp(opt, "rsize"))
                                data->rsize = val;
                        else if (!strcmp(opt, "wsize"))
@@ -534,7 +274,8 @@ parse_options(char *old_opts, struct nfs_mount_data *data,
                                char *secflavor = opteq+1;
                                /* see RFC 2623 */
                                if (nfs_mount_data_version < 5) {
-                                       printf(_("Warning: ignoring sec=%s option\n"), secflavor);
+                                       printf(_("Warning: ignoring sec=%s option\n"),
+                                                       secflavor);
                                        continue;
                                } else if (!strcmp(secflavor, "none"))
                                        data->pseudoflavor = AUTH_NONE;
@@ -575,8 +316,9 @@ parse_options(char *old_opts, struct nfs_mount_data *data,
                                int ctxlen = strlen(context);
 
                                if (ctxlen > NFS_MAX_CONTEXT_LEN) {
-                                       printf(_("context parameter exceeds limit of %d\n"),
-                                                NFS_MAX_CONTEXT_LEN);
+                                       nfs_error(_("context parameter exceeds"
+                                                       " limit of %d"),
+                                                       NFS_MAX_CONTEXT_LEN);
                                        goto bad_parameter;
                                }
                                /* The context string is in the format of
@@ -600,9 +342,9 @@ parse_options(char *old_opts, struct nfs_mount_data *data,
                                val = 0;
                                opt += 2;
                        }
-                       if (!strcmp(opt, "bg")) 
+                       if (!strcmp(opt, "bg"))
                                *bg = val;
-                       else if (!strcmp(opt, "fg")) 
+                       else if (!strcmp(opt, "fg"))
                                *bg = !val;
                        else if (!strcmp(opt, "soft")) {
                                data->flags &= ~NFS_MOUNT_SOFT;
@@ -688,15 +430,17 @@ parse_options(char *old_opts, struct nfs_mount_data *data,
                        bad_option:
                                if (sloppy)
                                        continue;
-                               printf(_("Unsupported nfs mount option: "
-                                        "%s%s\n"), val ? "" : "no", opt);
+                               nfs_error(_("%s: Unsupported nfs mount option:"
+                                               " %s%s"), progname,
+                                               val ? "" : "no", opt);
                                goto out_bad;
                        }
-                       sprintf(cbuf, val ? "%s,":"no%s,", opt);
+                       sprintf(cbuf, val ? "%s," : "no%s,", opt);
                }
                len += strlen(cbuf);
                if (len >= opt_size) {
-                       printf(_("mount: excessively long option argument\n"));
+                       nfs_error(_("%s: excessively long option argument"),
+                                       progname);
                        goto out_bad;
                }
                strcat(new_opts, cbuf);
@@ -709,7 +453,7 @@ parse_options(char *old_opts, struct nfs_mount_data *data,
        }
        return 1;
  bad_parameter:
-       printf(_("Bad nfs mount parameter: %s\n"), opt);
+       nfs_error(_("%s: Bad nfs mount parameter: %s\n"), progname, opt);
  out_bad:
        return 0;
 }
@@ -721,22 +465,22 @@ static int nfsmnt_check_compat(const struct pmap *nfs_pmap,
        unsigned int max_mnt_vers = (nfs_mount_data_version >= 4) ? 3 : 2;
 
        if (nfs_pmap->pm_vers == 4) {
-               fprintf(stderr, _("Please use '-t nfs4' "
-                                       "instead of '-o vers=4'.\n"));
+               nfs_error(_("%s: Please use '-t nfs4' "
+                               "instead of '-o vers=4'"), progname);
                goto out_bad;
        }
 
        if (nfs_pmap->pm_vers) {
                if (nfs_pmap->pm_vers > max_nfs_vers || nfs_pmap->pm_vers < 2) {
-                       fprintf(stderr, _("NFS version %ld is not supported.\n"), 
-                                       nfs_pmap->pm_vers);
+                       nfs_error(_("%s: NFS version %ld is not supported"),
+                                       progname, nfs_pmap->pm_vers);
                        goto out_bad;
                }
        }
 
        if (mnt_pmap->pm_vers > max_mnt_vers) {
-               fprintf(stderr, _("NFS mount version %ld s not supported.\n"), 
-                       mnt_pmap->pm_vers);
+               nfs_error(_("%s: NFS mount version %ld is not supported"),
+                               progname, mnt_pmap->pm_vers);
                goto out_bad;
        }
 
@@ -747,9 +491,8 @@ out_bad:
 }
 
 int
-nfsmount(const char *spec, const char *node, int *flags,
-        char **extra_opts, char **mount_opts,
-        int running_bg, int *need_statd)
+nfsmount(const char *spec, const char *node, int flags,
+        char **extra_opts, int fake, int running_bg)
 {
        static char *prev_bg_host;
        char hostdir[1024];
@@ -762,7 +505,7 @@ nfsmount(const char *spec, const char *node, int *flags,
        clnt_addr_t mnt_server = { &mounthost, };
        clnt_addr_t nfs_server = { &hostname, };
        struct sockaddr_in *nfs_saddr = &nfs_server.saddr;
-       struct pmap  *mnt_pmap = &mnt_server.pmap, 
+       struct pmap  *mnt_pmap = &mnt_server.pmap,
                     *nfs_pmap = &nfs_server.pmap;
        struct pmap  save_mnt, save_nfs;
 
@@ -779,8 +522,8 @@ nfsmount(const char *spec, const char *node, int *flags,
        time_t timeout;
 
        if (strlen(spec) >= sizeof(hostdir)) {
-               fprintf(stderr, _("mount: "
-                                 "excessively long host:dir argument\n"));
+               nfs_error(_("%s: excessively long host:dir argument"),
+                               progname);
                goto fail;
        }
        strcpy(hostdir, spec);
@@ -792,14 +535,13 @@ nfsmount(const char *spec, const char *node, int *flags,
                   until they can be fully supported. (mack@sgi.com) */
                if ((s = strchr(hostdir, ','))) {
                        *s = '\0';
-                       fprintf(stderr,
-                               _("mount: warning: "
-                                 "multiple hostnames not supported\n"));
+                       nfs_error(_("%s: warning: "
+                                 "multiple hostnames not supported"),
+                                       progname);
                }
        } else {
-               fprintf(stderr,
-                       _("mount: "
-                         "directory to mount not in host:dir format\n"));
+               nfs_error(_("%s: directory to mount not in host:dir format"),
+                               progname);
                goto fail;
        }
 
@@ -829,7 +571,7 @@ nfsmount(const char *spec, const char *node, int *flags,
 #endif
 
        bg = 0;
-       retry = 10000;          /* 10000 minutes ~ 1 week */
+       retry = -1;
 
        memset(mnt_pmap, 0, sizeof(*mnt_pmap));
        mnt_pmap->pm_prog = MOUNTPROG;
@@ -843,45 +585,47 @@ nfsmount(const char *spec, const char *node, int *flags,
                goto fail;
        if (!nfsmnt_check_compat(nfs_pmap, mnt_pmap))
                goto fail;
-       
-       if (retry == 10000 && !bg)
-               retry = 2; /* reset for fg mounts */
-       
+
+       if (retry == -1) {
+               if (bg)
+                       retry = 10000;  /* 10000 mins == ~1 week*/
+               else
+                       retry = 2;      /* 2 min default on fg mounts */
+       }
 
 #ifdef NFS_MOUNT_DEBUG
-       printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
+       printf(_("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n"),
               data.rsize, data.wsize, data.timeo, data.retrans);
-       printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
+       printf(_("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n"),
               data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
-       printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
+       printf(_("port = %lu, bg = %d, retry = %d, flags = %.8x\n"),
               nfs_pmap->pm_port, bg, retry, data.flags);
-       printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
+       printf(_("mountprog = %lu, mountvers = %lu, nfsprog = %lu, nfsvers = %lu\n"),
               mnt_pmap->pm_prog, mnt_pmap->pm_vers,
               nfs_pmap->pm_prog, nfs_pmap->pm_vers);
-       printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d ",
+       printf(_("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d"),
               (data.flags & NFS_MOUNT_SOFT) != 0,
               (data.flags & NFS_MOUNT_INTR) != 0,
               (data.flags & NFS_MOUNT_POSIX) != 0,
               (data.flags & NFS_MOUNT_NOCTO) != 0,
               (data.flags & NFS_MOUNT_NOAC) != 0);
 #if NFS_MOUNT_VERSION >= 2
-       printf("tcp = %d ",
+       printf(_(", tcp = %d"),
               (data.flags & NFS_MOUNT_TCP) != 0);
 #endif
 #if NFS_MOUNT_VERSION >= 4
-       printf("noacl = %d ", (data.flags & NFS_MOUNT_NOACL) != 0);
+       printf(_(", noacl = %d"), (data.flags & NFS_MOUNT_NOACL) != 0);
 #endif
 #if NFS_MOUNT_VERSION >= 5
-       printf("sec = %u ", data.pseudoflavor);
-       printf("readdirplus = %d ", (data.flags & NFS_MOUNT_NORDIRPLUS) != 0);
+       printf(_(", sec = %u"), data.pseudoflavor);
+       printf(_(", readdirplus = %d"), (data.flags & NFS_MOUNT_NORDIRPLUS) != 0);
 #endif
        printf("\n");
 #endif
 
        data.version = nfs_mount_data_version;
-       *mount_opts = (char *) &data;
 
-       if (*flags & MS_REMOUNT)
+       if (flags & MS_REMOUNT)
                goto out_ok;
 
        /*
@@ -952,15 +696,15 @@ nfsmount(const char *spec, const char *node, int *flags,
                                if (errno == ETIMEDOUT)
                                        break;
                        default:
-                               mount_errors(*nfs_server.hostname, 0, bg);
+                               rpc_mount_errors(*nfs_server.hostname, 0, bg);
                        goto fail;
                        }
                        t = time(NULL);
                        if (t >= timeout) {
-                               mount_errors(*nfs_server.hostname, 0, bg);
+                               rpc_mount_errors(*nfs_server.hostname, 0, bg);
                                goto fail;
                        }
-                       mount_errors(*nfs_server.hostname, 1, bg);
+                       rpc_mount_errors(*nfs_server.hostname, 1, bg);
                        continue;
                }
                if (!running_bg) {
@@ -971,19 +715,18 @@ nfsmount(const char *spec, const char *node, int *flags,
                }
                t = time(NULL);
                if (t >= timeout) {
-                       mount_errors(*nfs_server.hostname, 0, bg);
+                       rpc_mount_errors(*nfs_server.hostname, 0, bg);
                        goto fail;
                }
                if (doonce++ < 1)
-                       mount_errors(*nfs_server.hostname, 1, bg);
+                       rpc_mount_errors(*nfs_server.hostname, 1, bg);
        }
 
-       if (nfs_pmap->pm_vers == 2) {
+       if (mnt_pmap->pm_vers <= 2) {
                if (mntres.nfsv2.fhs_status != 0) {
-                       fprintf(stderr,
-                               _("mount: %s:%s failed, reason given by server: %s\n"),
-                               hostname, dirname,
-                               nfs_strerror(mntres.nfsv2.fhs_status));
+                       nfs_error(_("%s: %s:%s failed, reason given by server: %s"),
+                                       progname, hostname, dirname,
+                                       nfs_strerror(mntres.nfsv2.fhs_status));
                        goto fail;
                }
                memcpy(data.root.data,
@@ -999,23 +742,25 @@ nfsmount(const char *spec, const char *node, int *flags,
 #if NFS_MOUNT_VERSION >= 4
                mountres3_ok *mountres;
                fhandle3 *fhandle;
-               int i, *flavor, yum = 0;
+               int i,  n_flavors, *flavor, yum = 0;
                if (mntres.nfsv3.fhs_status != 0) {
-                       fprintf(stderr,
-                               _("mount: %s:%s failed, reason given by server: %s\n"),
-                               hostname, dirname,
-                               nfs_strerror(mntres.nfsv3.fhs_status));
+                       nfs_error(_("%s: %s:%s failed, reason given by server: %s"),
+                                       progname, hostname, dirname,
+                                       nfs_strerror(mntres.nfsv3.fhs_status));
                        goto fail;
                }
 #if NFS_MOUNT_VERSION >= 5
                mountres = &mntres.nfsv3.mountres3_u.mountinfo;
-               i = mountres->auth_flavors.auth_flavors_len;
-               if (i <= 0) 
+               n_flavors = mountres->auth_flavors.auth_flavors_len;
+               if (n_flavors <= 0)
                        goto noauth_flavors;
 
                flavor = mountres->auth_flavors.auth_flavors_val;
-               while (--i >= 0) {
-                       /* If no flavour requested, use first simple
+               for (i = 0; i < n_flavors; ++i) {
+                       /*
+                        * Per RFC2623, section 2.7, we should prefer the
+                        * flavour listed first.
+                        * If no flavour requested, use the first simple
                         * flavour that is offered.
                         */
                        if (! (data.flags & NFS_MOUNT_SECFLAVOUR) &&
@@ -1027,15 +772,13 @@ nfsmount(const char *spec, const char *node, int *flags,
                        if (flavor[i] == data.pseudoflavor)
                                yum = 1;
 #ifdef NFS_MOUNT_DEBUG
-                       printf("auth flavor %d: %d\n",
-                               i, flavor[i]);
+                       printf(_("auth flavor %d: %d\n"), i, flavor[i]);
 #endif
                }
                if (!yum) {
-                       fprintf(stderr,
-                               "mount: %s:%s failed, "
-                               "security flavor not supported\n",
-                               hostname, dirname);
+                       nfs_error(_("%s: %s:%s failed, security flavor "
+                                       "not supported"),
+                                       progname, hostname, dirname);
                        /* server has registered us in rmtab, send umount */
                        nfs_call_umount(&mnt_server, &dirname);
                        goto fail;
@@ -1071,7 +814,7 @@ noauth_flavors:
        }
 
 #ifdef NFS_MOUNT_DEBUG
-       printf(_("using port %d for nfs deamon\n"), nfs_pmap->pm_port);
+       printf(_("using port %lu for nfs deamon\n"), nfs_pmap->pm_port);
 #endif
        nfs_saddr->sin_port = htons(nfs_pmap->pm_port);
        /*
@@ -1102,8 +845,8 @@ noauth_flavors:
  out_ok:
        /* Ensure we have enough padding for the following strcat()s */
        if (strlen(new_opts) + strlen(s) + 30 >= sizeof(new_opts)) {
-               fprintf(stderr, _("mount: "
-                                 "excessively long option argument\n"));
+               nfs_error(_("%s: excessively long option argument"),
+                               progname);
                goto fail;
        }
 
@@ -1111,8 +854,27 @@ noauth_flavors:
        strcat(new_opts, cbuf);
 
        *extra_opts = xstrdup(new_opts);
-       *need_statd = ! (data.flags & NFS_MOUNT_NONLM);
-       return 0;
+
+       if (!fake && !(data.flags & NFS_MOUNT_NONLM)) {
+               if (!start_statd()) {
+                       nfs_error(_("%s: rpc.statd is not running but is "
+                               "required for remote locking.\n"
+                               "   Either use '-o nolock' to keep "
+                               "locks local, or start statd."),
+                                       progname);
+                       goto fail;
+               }
+       }
+
+       if (!fake) {
+               if (mount(spec, node, "nfs",
+                               flags & ~(MS_USER|MS_USERS), &data)) {
+                       mount_error(spec, node, errno);
+                       goto fail;
+               }
+       }
+
+       return EX_SUCCESS;
 
        /* abort */
  fail: