]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/nfsd/nfsd.c
nfs-utils: convert rpc.nfsd to use xlog()
[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 <netdb.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25
26 #include "nfslib.h"
27 #include "nfssvc.h"
28 #include "xlog.h"
29
30 static void     usage(const char *);
31
32 static struct option longopts[] =
33 {
34         { "host", 1, 0, 'H' },
35         { "help", 0, 0, 'h' },
36         { "no-nfs-version", 1, 0, 'N' },
37         { "no-tcp", 0, 0, 'T' },
38         { "no-udp", 0, 0, 'U' },
39         { "port", 1, 0, 'P' },
40         { "port", 1, 0, 'p' },
41         { "debug", 0, 0, 'd' },
42         { "syslog", 0, 0, 's' },
43         { NULL, 0, 0, 0 }
44 };
45 unsigned int protobits = NFSCTL_ALLBITS;
46 unsigned int versbits = NFSCTL_ALLBITS;
47 int minorvers4 = NFSD_MAXMINORVERS4;            /* nfsv4 minor version */
48 char *haddr = NULL;
49
50 int
51 main(int argc, char **argv)
52 {
53         int     count = 1, c, error, port, fd, found_one;
54         struct servent *ent;
55         struct hostent *hp;
56         char *p, *progname;
57
58         ent = getservbyname ("nfs", "udp");
59         if (ent != NULL)
60                 port = ntohs (ent->s_port);
61         else
62                 port = 2049;
63
64         progname = strdup(basename(argv[0]));
65         if (!progname) {
66                 fprintf(stderr, "%s: unable to allocate memory.\n", argv[0]);
67                 exit(1);
68         }
69
70         xlog_syslog(0);
71         xlog_stderr(1);
72
73         while ((c = getopt_long(argc, argv, "dH:hN:p:P:sTU", longopts, NULL)) != EOF) {
74                 switch(c) {
75                 case 'd':
76                         xlog_config(D_ALL, 1);
77                         break;
78                 case 'H':
79                         if (inet_addr(optarg) != INADDR_NONE) {
80                                 haddr = strdup(optarg);
81                         } else if ((hp = gethostbyname(optarg)) != NULL) {
82                                 haddr = inet_ntoa((*(struct in_addr*)(hp->h_addr_list[0])));
83                         } else {
84                                 fprintf(stderr, "%s: Unknown hostname: %s\n",
85                                         progname, optarg);
86                                 usage(progname);
87                         }
88                         break;
89                 case 'P':       /* XXX for nfs-server compatibility */
90                 case 'p':
91                         port = atoi(optarg);
92                         if (port <= 0 || port > 65535) {
93                                 fprintf(stderr, "%s: bad port number: %s\n",
94                                         progname, optarg);
95                                 usage(progname);
96                         }
97                         break;
98                 case 'N':
99                         switch((c = strtol(optarg, &p, 0))) {
100                         case 4:
101                                 if (*p == '.') {
102                                         minorvers4 = -atoi(p + 1);
103                                         break;
104                                 }
105                         case 3:
106                         case 2:
107                                 NFSCTL_VERUNSET(versbits, c);
108                                 break;
109                         default:
110                                 fprintf(stderr, "%s: Unsupported version\n", optarg);
111                                 exit(1);
112                         }
113                         break;
114                 case 's':
115                         xlog_syslog(1);
116                         xlog_stderr(0);
117                         break;
118                 case 'T':
119                         NFSCTL_TCPUNSET(protobits);
120                         break;
121                 case 'U':
122                         NFSCTL_UDPUNSET(protobits);
123                         break;
124                 default:
125                         fprintf(stderr, "Invalid argument: '%c'\n", c);
126                 case 'h':
127                         usage(progname);
128                 }
129         }
130
131         xlog_open(progname);
132
133         /*
134          * Do some sanity checking, if the ctlbits are set
135          */
136         if (!NFSCTL_UDPISSET(protobits) && !NFSCTL_TCPISSET(protobits)) {
137                 xlog(L_ERROR, "invalid protocol specified");
138                 exit(1);
139         }
140         found_one = 0;
141         for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) {
142                 if (NFSCTL_VERISSET(versbits, c))
143                         found_one = 1;
144         }
145         if (!found_one) {
146                 xlog(L_ERROR, "no version specified");
147                 exit(1);
148         }                       
149
150         if (NFSCTL_VERISSET(versbits, 4) && !NFSCTL_TCPISSET(protobits)) {
151                 xlog(L_ERROR, "version 4 requires the TCP protocol");
152                 exit(1);
153         }
154         if (haddr == NULL) {
155                 struct in_addr in = {INADDR_ANY}; 
156                 haddr = strdup(inet_ntoa(in));
157         }
158
159         if (chdir(NFS_STATEDIR)) {
160                 xlog(L_ERROR, "chdir(%s) failed: %m", NFS_STATEDIR);
161                 exit(1);
162         }
163
164         if (optind < argc) {
165                 if ((count = atoi(argv[optind])) < 0) {
166                         /* insane # of servers */
167                         xlog(L_ERROR, "invalid server count (%d), using 1",
168                                       count);
169                         count = 1;
170                 }
171         }
172         /* KLUDGE ALERT:
173            Some kernels let nfsd kernel threads inherit open files
174            from the program that spawns them (i.e. us).  So close
175            everything before spawning kernel threads.  --Chip */
176         fd = open("/dev/null", O_RDWR);
177         if (fd == -1)
178                 xlog(L_ERROR, "Unable to open /dev/null: %m");
179         else {
180                 /* switch xlog output to syslog since stderr is being closed */
181                 xlog_syslog(1);
182                 xlog_stderr(0);
183                 (void) dup2(fd, 0);
184                 (void) dup2(fd, 1);
185                 (void) dup2(fd, 2);
186         }
187         closeall(3);
188
189         if ((error = nfssvc(port, count, versbits, minorvers4, protobits, haddr)) < 0)
190                 xlog(L_ERROR, "nfssvc: errno %d (%m)", errno);
191
192         free(progname);
193         return (error != 0);
194 }
195
196 static void
197 usage(const char *prog)
198 {
199         fprintf(stderr, "Usage:\n"
200                 "%s [-d|--debug] [-H hostname] [-p|-P|--port port] [-N|--no-nfs-version version ] [-s|--syslog] [-T|--no-tcp] [-U|--no-udp] nrservs\n", 
201                 prog);
202         exit(2);
203 }