/* * nfsd * * This is the user level part of nfsd. This is very primitive, because * all the work is now done in the kernel module. * * Copyright (C) 1995, 1996 Olaf Kirch */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "nfslib.h" static void usage(const char *); static struct option longopts[] = { { "host", 1, 0, 'H' }, { "help", 0, 0, 'h' }, { "no-nfs-version", 1, 0, 'N' }, { "no-tcp", 0, 0, 'T' }, { "no-udp", 0, 0, 'U' }, { "port", 1, 0, 'P' }, { "port", 1, 0, 'p' }, { NULL, 0, 0, 0 } }; unsigned int protobits = NFSCTL_ALLBITS; unsigned int versbits = NFSCTL_ALLBITS; int minorvers4; /* nfsv4 minor version */ char *haddr = NULL; int main(int argc, char **argv) { int count = 1, c, error, port, fd, found_one; struct servent *ent; struct hostent *hp; ent = getservbyname ("nfs", "udp"); if (ent != NULL) port = ntohs (ent->s_port); else port = 2049; while ((c = getopt_long(argc, argv, "H:hN:p:P:TU", longopts, NULL)) != EOF) { switch(c) { case 'H': if (inet_addr(optarg) != INADDR_NONE) { haddr = strdup(optarg); } else if ((hp = gethostbyname(optarg)) != NULL) { haddr = inet_ntoa((*(struct in_addr*)(hp->h_addr_list[0]))); } else { fprintf(stderr, "%s: Unknown hostname: %s\n", argv[0], optarg); usage(argv [0]); } break; case 'P': /* XXX for nfs-server compatibility */ case 'p': port = atoi(optarg); if (port <= 0 || port > 65535) { fprintf(stderr, "%s: bad port number: %s\n", argv[0], optarg); usage(argv [0]); } break; case 'N': switch((c = atoi(optarg))) { case 2: case 3: case 4: NFSCTL_VERUNSET(versbits, c); break; default: fprintf(stderr, "%s: Unsupported version\n", optarg); exit(1); } break; case 'T': NFSCTL_TCPUNSET(protobits); break; case 'U': NFSCTL_UDPUNSET(protobits); break; default: fprintf(stderr, "Invalid argument: '%c'\n", c); case 'h': usage(argv[0]); } } /* * Do some sanity checking, if the ctlbits are set */ if (!NFSCTL_UDPISSET(protobits) && !NFSCTL_TCPISSET(protobits)) { fprintf(stderr, "invalid protocol specified\n"); exit(1); } found_one = 0; for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) { if (NFSCTL_VERISSET(versbits, c)) found_one = 1; } if (!found_one) { fprintf(stderr, "no version specified\n"); exit(1); } if (NFSCTL_VERISSET(versbits, 4) && !NFSCTL_TCPISSET(protobits)) { fprintf(stderr, "version 4 requires the TCP protocol\n"); exit(1); } if (haddr == NULL) { struct in_addr in = {INADDR_ANY}; haddr = strdup(inet_ntoa(in)); } if (chdir(NFS_STATEDIR)) { fprintf(stderr, "%s: chdir(%s) failed: %s\n", argv [0], NFS_STATEDIR, strerror(errno)); exit(1); } if (optind < argc) { if ((count = atoi(argv[optind])) < 0) { /* insane # of servers */ fprintf(stderr, "%s: invalid server count (%d), using 1\n", argv[0], count); count = 1; } } /* 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 */ fd = open("/dev/null", O_RDWR); if (fd == -1) perror("/dev/null"); else { (void) dup2(fd, 0); (void) dup2(fd, 1); (void) dup2(fd, 2); } closeall(3); openlog("nfsd", LOG_PID, LOG_DAEMON); if ((error = nfssvc(port, count, versbits, minorvers4, protobits, haddr)) < 0) { int e = errno; syslog(LOG_ERR, "nfssvc: %s", strerror(e)); closelog(); } return (error != 0); } static void usage(const char *prog) { fprintf(stderr, "Usage:\n" "%s [-H hostname] [-p|-P|--port port] [-N|--no-nfs-version version ] [-T|--no-tcp] [-U|--no-udp] nrservs\n", prog); exit(2); }