Add support for suppressing different NFS versions.
[nfs-utils.git] / utils / nfsd / nfsd.c
1 /*
2  * nfsd
3  *
4  * This is the user level part of nfsd. This is very primitive, because
5  * all the work is now done in the kernel module.
6  *
7  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
8  */
9
10 #ifdef HAVE_CONFIG_H
11 #include <config.h>
12 #endif
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <getopt.h>
21 #include <syslog.h>
22 #include <netdb.h>
23 #include "nfslib.h"
24
25 static void     usage(const char *);
26
27 static struct option longopts[] =
28 {
29         { "help", 0, 0, 'h' },
30         { "no-nfs-version", 1, 0, 'N' },
31         { NULL, 0, 0, 0 }
32 };
33 unsigned int versbits = NFSCTL_ALLBITS;
34
35 int
36 main(int argc, char **argv)
37 {
38         int     count = 1, c, error, port, fd, found_one;
39         struct servent *ent;
40
41         ent = getservbyname ("nfs", "udp");
42         if (ent != NULL)
43                 port = ntohs (ent->s_port);
44         else
45                 port = 2049;
46
47         while ((c = getopt_long(argc, argv, "hN:p:P:", longopts, NULL)) != EOF) {
48                 switch(c) {
49                 case 'P':       /* XXX for nfs-server compatibility */
50                 case 'p':
51                         port = atoi(optarg);
52                         if (port <= 0 || port > 65535) {
53                                 fprintf(stderr, "%s: bad port number: %s\n",
54                                         argv[0], optarg);
55                                 usage(argv [0]);
56                         }
57                         break;
58                 case 'N':
59                         switch((c = atoi(optarg))) {
60                         case 2:
61                         case 3:
62                         case 4:
63                                 NFSCTL_VERUNSET(versbits, c);
64                                 break;
65                         default:
66                                 fprintf(stderr, "%c: Unsupported version\n", c);
67                                 exit(1);
68                         }
69                         break;
70                 default:
71                         fprintf(stderr, "Invalid argument: '%c'\n", c);
72                 case 'h':
73                         usage(argv[0]);
74                 }
75         }
76         /*
77          * Do some sanity checking, if the ctlbits are set
78          */
79         found_one = 0;
80         for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) {
81                 if (NFSCTL_VERISSET(versbits, c))
82                         found_one = 1;
83         }
84         if (!found_one) {
85                 fprintf(stderr, "no version specified\n");
86                 exit(1);
87         }                       
88
89         if (chdir(NFS_STATEDIR)) {
90                 fprintf(stderr, "%s: chdir(%s) failed: %s\n",
91                         argv [0], NFS_STATEDIR, strerror(errno));
92                 exit(1);
93         }
94
95         if (optind < argc) {
96                 if ((count = atoi(argv[optind])) < 0) {
97                         /* insane # of servers */
98                         fprintf(stderr,
99                                 "%s: invalid server count (%d), using 1\n",
100                                 argv[0], count);
101                         count = 1;
102                 }
103         }
104         /* KLUDGE ALERT:
105            Some kernels let nfsd kernel threads inherit open files
106            from the program that spawns them (i.e. us).  So close
107            everything before spawning kernel threads.  --Chip */
108         fd = open("/dev/null", O_RDWR);
109         if (fd == -1)
110                 perror("/dev/null");
111         else {
112                 (void) dup2(fd, 0);
113                 (void) dup2(fd, 1);
114                 (void) dup2(fd, 2);
115         }
116         closeall(3);
117
118         openlog("nfsd", LOG_PID, LOG_DAEMON);
119         if ((error = nfssvc(port, count, versbits)) < 0) {
120                 int e = errno;
121                 syslog(LOG_ERR, "nfssvc: %s", strerror(e));
122                 closelog();
123         }
124
125         return (error != 0);
126 }
127
128 static void
129 usage(const char *prog)
130 {
131         fprintf(stderr, "Usage:\n"
132                 "%s [-p|-P|--port port] [-N|--no-nfs-version version ] nrservs\n", 
133                 prog);
134         exit(2);
135 }