This is mount.c in view mode; [Download] [Up]
/*
* Name: mount.c
* Description: Functions that do the NFS socket setup and NFS mount/unmount.
* Parts of it are based on the mount module of p3nfs (Psion NFS).
* Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
* Date: 1996-11-14
* Copyright: GNU-GPL
* Tabsize: 4
*/
#define NFSCLIENT
#include <rpc/rpc.h>
#include "syshdr.h"
#include "nfs_prot.h"
#include <netdb.h>
#include <arpa/inet.h>
#include <mntent.h>
#include "my_defines.h"
#define DPRINTF(arg) if(debug_mode & DEBUG_NFS) dprintf arg
#define DDPRINTF(arg) if(debug_mode & DEBUG_DISPATCH) dprintf arg
static char *mntdir;
static int do_exit = 0;
static int do_nfsumount = 0;
#define MTAB_TMP (MOUNTED ".tmp")
/* ------------------------------------------------------------------------- */
static void my_perror(char *s)
{
eprintf("%s: [%d] %s\n", s, errno, strerror(errno));
}
/* ------------------------------------------------------------------------- */
static void nfs_unmount(void)
{
FILE *fpout, *fpin;
struct mntent *ent;
dprintf("Going to unmount NFS...\n");
while(unmount(mntdir)){
if(errno != ENOENT)
my_perror(mntdir);
if(errno != EBUSY){
break;
}
sleep(1);
}
/* update mtab */
if((fpout = setmntent(MTAB_TMP, "w")) == NULL){
my_perror(MTAB_TMP);
}else if((fpin = setmntent(MOUNTED, "r")) == NULL){
endmntent(fpout);
unlink(MTAB_TMP);
my_perror(MOUNTED);
}else{
while ((ent = getmntent(fpin)) != NULL){
if(strcmp(ent->mnt_dir, mntdir) != 0)
addmntent(fpout, ent);
}
endmntent(fpin);
endmntent(fpout);
if(rename(MTAB_TMP, MOUNTED) != 0){
my_perror(MOUNTED);
unlink(MTAB_TMP);
}
}
dprintf("NFS unmounted.\n");
}
/* ------------------------------------------------------------------------- */
void terminate(int exitcode)
{
nfs_unmount();
fo_unmount();
exit(exitcode);
}
/* ------------------------------------------------------------------------- */
void do_unmount(int signr)
{
do_exit = 1;
do_nfsumount = 1;
switch(signr){
case SIGHUP: case SIGINT: case SIGQUIT:
case SIGUSR1: case SIGUSR2:
dprintf("** caught signal %d, preparing for unmount\n", signr);
break; /* if the signal was user-induced: unmount nfs from mainloop */
default:
dprintf("** caught signal %d, unmounting\n", signr);
terminate(1);
}
}
/* ------------------------------------------------------------------------- */
static void dispatch_loop(void)
{
fd_set readfd;
struct timeval tv;
for(;;){
readfd = svc_fdset;
tv.tv_sec = 2; tv.tv_usec = 0;
DDPRINTF(("- going into select\n"));
if(select(FD_SETSIZE, &readfd, NULL, NULL, &tv) > 0){
DDPRINTF(("- executing request\n"));
svc_getreqset(&readfd);
}
if(do_exit){
DDPRINTF(("- doing exit\n"));
if(do_nfsumount)
nfs_unmount();
fo_unmount();
dprintf("Exiting.\n");
exit(0);
}
DDPRINTF(("- checking for regular jobs()\n"));
fo_regular();
}
}
/* ------------------------------------------------------------------------- */
void mount_and_dispatch(char *dir, void (*proc)(), void *root_fh, int bg)
{
int sock, port, child_pid, parent_pid, other_pid;
struct sockaddr_in sain;
SVCXPRT *nfsxprt;
int bufsiz = 0xc000; /* room for a few biods */
signal(SIGHUP, do_unmount);
signal(SIGINT, do_unmount);
signal(SIGQUIT, do_unmount);
signal(SIGILL, do_unmount);
signal(SIGIOT, do_unmount);
signal(SIGTRAP, do_unmount);
#ifdef SIGEMT
signal(SIGEMT, do_unmount);
#endif
signal(SIGFPE, do_unmount);
signal(SIGBUS, do_unmount);
signal(SIGSEGV, do_unmount);
#ifdef SIGSYS
signal(SIGSYS, do_unmount);
#endif
signal(SIGPIPE, SIG_IGN); /* ignore pipe signals */
signal(SIGTERM, do_unmount);
signal(SIGUSR1, do_unmount);
signal(SIGUSR2, do_unmount);
bzero(&sain, sizeof(struct sockaddr_in));
/*** First part: set up the rpc service */
/* Create udp socket */
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&bufsiz,sizeof(bufsiz)))
my_perror("setsockopt");
/* Bind it to a reserved port */
sain.sin_family = AF_INET;
sain.sin_addr.s_addr = inet_addr("127.0.0.1");
for(port = IPPORT_RESERVED-1; port > IPPORT_RESERVED/2; port--){
DPRINTF(("trying to use port %d\n", port));
sain.sin_port = htons(port);
if(bind(sock, (struct sockaddr *) &sain, sizeof(sain)) >= 0)
break;
}
dprintf("Using port %d for NFS.\n", port);
if(port <= IPPORT_RESERVED/2){
my_perror("bind to reserved port"); exit(1);
}
if((nfsxprt = svcudp_create(sock)) == 0){
my_perror("svcudp_create"); exit(1);
}
if(!svc_register(nfsxprt, NFS_PROGRAM, NFS_VERSION, proc, 0)){
my_perror("svc_register"); exit(1);
}
/*** Second part: mount the directory */
mntdir = dir;
parent_pid = getpid();
use_syslog = 1; /* we will reset this in the parent */
if((child_pid = fork()) == -1){
use_syslog = 0;
my_perror("fork");
exit(1);
}
if(child_pid != 0 || !bg){ /* we are the parent || not background */
use_syslog = 0;
}
if((child_pid == 0 && bg) || (child_pid != 0 && !bg)){
dispatch_loop();
}else{
DPRINTF(("Going to mount...\n"));
other_pid = child_pid == 0 ? parent_pid : child_pid;
if(syscall_mount(dir, root_fh, sock, &sain) < 0){
eprintf("nfs mount %s: [%d] %s\n", dir, errno, strerror(errno));
kill(other_pid, SIGKILL);
}else{
FILE *fp;
struct mntent mnt;
char fsname[256];
sprintf(fsname, "rumba-%d", other_pid);
mnt.mnt_fsname = fsname;
mnt.mnt_dir = mntdir;
mnt.mnt_type = "nfs";
mnt.mnt_opts ="soft";
mnt.mnt_freq = mnt.mnt_passno = 0;
if ((fp = setmntent(MOUNTED, "a")))
addmntent(fp, &mnt);
else
my_perror(MOUNTED);
endmntent(fp);
}
exit(0);
}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.