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.