ftp.nice.ch/pub/next/unix/disk/vmount.0.6a.s.tar.gz#/vmount.0.6a.s/nfs/mount.c

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
 */
#include <libc.h>

#define NFSCLIENT
#include <rpc/rpc.h>
#include "nfs_prot.h"
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <nfs/nfs_mount.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 = NULL;
static int	do_exit = 0;
static int	do_nfsumount = 0;
extern int	errno;

#define	MTAB_TMP	(MOUNTED ".tmp")

/* ------------------------------------------------------------------------- */

static void	my_perror(char *s)
{
	eprintf("%s: [%d] %s\n", s, errno, strerror(errno));
}

/* ------------------------------------------------------------------------- */

static int	nfs_unmount(int forced)
{
FILE			*fpout, *fpin;
struct mntent	*ent;
char			tempfile[2048];

	if(mntdir == NULL)	/* not mounted until now! */
		return 1;
	dprintf("Trying to unmount NFS...\n");
	if(forced)
		while(unmount(mntdir)){
			if(errno != ENOENT)
				my_perror(mntdir);
			if(errno != EBUSY){
				break;
			}
			sleep(1);
		}
	else if(unmount(mntdir) != 0 && errno == EBUSY)
		return 0;
	/* update mtab */
	sprintf(tempfile, "%s-%d", MTAB_TMP, getpid());
	lock_mtab();
	if((fpout = setmntent(tempfile, "w")) == NULL){
		my_perror(tempfile);
	}else if((fpin = setmntent(MOUNTED, "r")) == NULL){
		endmntent(fpout);
		unlink(tempfile);
		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(tempfile, MOUNTED) != 0){
			my_perror(MOUNTED);
			unlink(tempfile);
		}
	}
	unlock_mtab();
	dprintf("NFS unmounted.\n");
	return 1;
}

/* ------------------------------------------------------------------------- */

void	terminate(int exitcode)
{
	nfs_unmount(1);
	exit(exitcode);
}

/* ------------------------------------------------------------------------- */

void	do_unmount(int signr)
{
static volatile int	in_handler = 0;

	if(in_handler){
		eprintf("** caught signal %d, during handler!!\n", signr);
		eprintf("** aborting immediately!!\n");
		exit(2);
	}
	in_handler = 1;
	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:
		eprintf("** caught signal %d, unmounting\n", signr);
		do_nfsumount = 0;
		nfs_unmount(1);
	}
	in_handler = 0;
}

/* ------------------------------------------------------------------------- */

static void	dispatch_loop(void)
{
fd_set			readfd;
struct timeval	tv;

	for(;;){
		readfd = svc_fdset;
		tv.tv_sec = 1; 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(0)){
				if(wr_enable){
					dprintf("Going to unmount disk...\n");
					my_unmount();
					dprintf("Disk unmounted.\n");
				}
				close(my_fd);
				eprintf("Exiting.\n");
				exit(0);
			}
		}
		DDPRINTF(("- checking for regular jobs()\n"));
		dummies_regular();	/* calls all other regulars */
	}
}

/* ------------------------------------------------------------------------- */

void	mount_and_dispatch(char *dir, void (*proc)(), void *proot_fh, int bg, char *options)
{
int					sock, port, child_pid, parent_pid, other_pid;
struct sockaddr_in	sain;
SVCXPRT				*nfsxprt;
int					bufsiz = 0xc000;	/* room for a few biods */
struct nfs_args		nfs_args;
nfs_fh				*root_fh = proot_fh;

	signal(SIGHUP, do_unmount);
	signal(SIGINT, do_unmount);
	signal(SIGQUIT, do_unmount);
	signal(SIGILL, do_unmount);
	signal(SIGIOT, do_unmount);
	signal(SIGTRAP, do_unmount);
	signal(SIGEMT, do_unmount);
	signal(SIGFPE, do_unmount);
	signal(SIGBUS, do_unmount);
	signal(SIGSEGV, do_unmount);
	signal(SIGSYS, do_unmount);
	signal(SIGPIPE, do_unmount);
	signal(SIGTERM, do_unmount);
	signal(SIGUSR1, do_unmount);
	signal(SIGUSR2, do_unmount);
	bzero(&sain, sizeof(struct sockaddr_in));
	bzero(&nfs_args, sizeof(struct nfs_args));

/*** 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");
/*sain.sin_addr.s_addr = htonl(INADDR_ANY);gec*/
	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 */

	nfs_args.wsize    = 32768;
	nfs_args.rsize    = 32768;
	nfs_args.addr     = &sain;
	nfs_args.fh       = (char *)root_fh;
	nfs_args.retrans = 0;
	nfs_args.timeo = 200;	/* 20s timeout */
	nfs_args.hostname = "vmount";
	nfs_args.netname = "net";
	nfs_args.flags    = NFSMNT_SOFT | NFSMNT_HOSTNAME |
						NFSMNT_RETRANS | NFSMNT_TIMEO |
						NFSMNT_WSIZE | NFSMNT_RSIZE;

	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(mount(MOUNT_NFS, dir, wr_enable ? 0:M_RDONLY,(caddr_t)&nfs_args)<0){
			eprintf("nfs mount %s: [%d] %s\n", dir, errno, strerror(errno));
			kill(other_pid, SIGKILL);
		}else{
			FILE			*fp;
			struct mntent	mnt;
			char			typename[256];

			sprintf(typename, "vmount-%d", other_pid);
			mnt.mnt_fsname = device_name;
			mnt.mnt_dir = mntdir;
			mnt.mnt_type = typename;
			mnt.mnt_opts = options!=NULL && *options!=0 ? options : "default";
			mnt.mnt_freq = mnt.mnt_passno = 0;
			lock_mtab();
			if ((fp = setmntent(MOUNTED, "a")))
				addmntent(fp, &mnt);
			else
				my_perror(MOUNTED);
			endmntent(fp);
			unlock_mtab();
		}
		exit(0);
	}
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.