+ xlog_open(progname);
+
+ nfsd_enable_protos(&proto4, &proto6);
+
+ if (!NFSCTL_TCPISSET(protobits)) {
+ NFSCTL_TCPUNSET(proto4);
+ NFSCTL_TCPUNSET(proto6);
+ }
+
+ if (!NFSCTL_UDPISSET(protobits)) {
+ NFSCTL_UDPUNSET(proto4);
+ NFSCTL_UDPUNSET(proto6);
+ }
+
+ /* make sure that at least one version is enabled */
+ found_one = 0;
+ for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) {
+ if (NFSCTL_VERISSET(versbits, c))
+ found_one = 1;
+ }
+ if (!found_one) {
+ xlog(L_ERROR, "no version specified");
+ exit(1);
+ }
+
+ if (NFSCTL_VERISSET(versbits, 4) &&
+ !NFSCTL_TCPISSET(proto4) &&
+ !NFSCTL_TCPISSET(proto6)) {
+ xlog(L_ERROR, "version 4 requires the TCP protocol");
+ exit(1);
+ }
+
+ if (chdir(NFS_STATEDIR)) {
+ xlog(L_ERROR, "chdir(%s) failed: %m", NFS_STATEDIR);
+ exit(1);
+ }
+
+ /* make sure nfsdfs is mounted if it's available */
+ nfssvc_mount_nfsdfs(progname);
+
+ /* can only change number of threads if nfsd is already up */
+ if (nfssvc_inuse()) {
+ socket_up = 1;
+ goto set_threads;
+ }
+
+ /*
+ * must set versions before the fd's so that the right versions get
+ * registered with rpcbind. Note that on older kernels w/o the right
+ * interfaces, these are a no-op.
+ */
+ nfssvc_setvers(versbits, minorvers41);
+
+ error = nfssvc_set_sockets(AF_INET, proto4, haddr, port);
+ if (!error)
+ socket_up = 1;
+
+#ifdef IPV6_SUPPORTED
+ error = nfssvc_set_sockets(AF_INET6, proto6, haddr, port);
+ if (!error)
+ socket_up = 1;
+#endif /* IPV6_SUPPORTED */
+
+set_threads:
+ /* don't start any threads if unable to hand off any sockets */
+ if (!socket_up) {
+ xlog(L_ERROR, "unable to set any sockets for nfsd");
+ goto out;
+ }
+ error = 0;
+
+ /*
+ * KLUDGE ALERT:
+ * Some kernels let nfsd kernel threads inherit open files
+ * from the program that spawns them (i.e. us). So close
+ * everything before spawning kernel threads. --Chip
+ */