home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Utilities / vmount-0.6a-I / src / nfs / mount.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-06  |  6.9 KB  |  272 lines

  1. /*
  2.  * Name: mount.c
  3.  * Description: Functions that do the NFS socket setup and NFS mount/unmount.
  4.  *     Parts of it are based on the mount module of p3nfs (Psion NFS).
  5.  * Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
  6.  * Date: 1996-11-14
  7.  * Copyright: GNU-GPL
  8.  * Tabsize: 4
  9.  */
  10. #include <libc.h>
  11.  
  12. #define NFSCLIENT
  13. #include <rpc/rpc.h>
  14. #include "nfs_prot.h"
  15. #include <errno.h>
  16. #include <signal.h>
  17. #include <sys/types.h>
  18. #include <sys/mount.h>
  19. #include <sys/socket.h>
  20. #include <netdb.h>
  21. #include <arpa/inet.h>
  22. #include <nfs/nfs_mount.h>
  23. #include <mntent.h>
  24. #include "my_defines.h"
  25.  
  26. #define    DPRINTF(arg)    if(debug_mode & DEBUG_NFS)    dprintf arg
  27. #define    DDPRINTF(arg)    if(debug_mode & DEBUG_DISPATCH)    dprintf arg
  28.  
  29. static char    *mntdir = NULL;
  30. static int    do_exit = 0;
  31. static int    do_nfsumount = 0;
  32. extern int    errno;
  33.  
  34. #define    MTAB_TMP    (MOUNTED ".tmp")
  35.  
  36. /* ------------------------------------------------------------------------- */
  37.  
  38. static void    my_perror(char *s)
  39. {
  40.     eprintf("%s: [%d] %s\n", s, errno, strerror(errno));
  41. }
  42.  
  43. /* ------------------------------------------------------------------------- */
  44.  
  45. static int    nfs_unmount(int forced)
  46. {
  47. FILE            *fpout, *fpin;
  48. struct mntent    *ent;
  49. char            tempfile[2048];
  50.  
  51.     if(mntdir == NULL)    /* not mounted until now! */
  52.         return 1;
  53.     dprintf("Trying to unmount NFS...\n");
  54.     if(forced)
  55.         while(unmount(mntdir)){
  56.             if(errno != ENOENT)
  57.                 my_perror(mntdir);
  58.             if(errno != EBUSY){
  59.                 break;
  60.             }
  61.             sleep(1);
  62.         }
  63.     else if(unmount(mntdir) != 0 && errno == EBUSY)
  64.         return 0;
  65.     /* update mtab */
  66.     sprintf(tempfile, "%s-%d", MTAB_TMP, getpid());
  67.     lock_mtab();
  68.     if((fpout = setmntent(tempfile, "w")) == NULL){
  69.         my_perror(tempfile);
  70.     }else if((fpin = setmntent(MOUNTED, "r")) == NULL){
  71.         endmntent(fpout);
  72.         unlink(tempfile);
  73.         my_perror(MOUNTED);
  74.     }else{
  75.         while ((ent = getmntent(fpin)) != NULL){
  76.             if(strcmp(ent->mnt_dir, mntdir) != 0)
  77.                 addmntent(fpout, ent);
  78.         }
  79.         endmntent(fpin);
  80.         endmntent(fpout);
  81.         if(rename(tempfile, MOUNTED) != 0){
  82.             my_perror(MOUNTED);
  83.             unlink(tempfile);
  84.         }
  85.     }
  86.     unlock_mtab();
  87.     dprintf("NFS unmounted.\n");
  88.     return 1;
  89. }
  90.  
  91. /* ------------------------------------------------------------------------- */
  92.  
  93. void    terminate(int exitcode)
  94. {
  95.     nfs_unmount(1);
  96.     exit(exitcode);
  97. }
  98.  
  99. /* ------------------------------------------------------------------------- */
  100.  
  101. void    do_unmount(int signr)
  102. {
  103. static volatile int    in_handler = 0;
  104.  
  105.     if(in_handler){
  106.         eprintf("** caught signal %d, during handler!!\n", signr);
  107.         eprintf("** aborting immediately!!\n");
  108.         exit(2);
  109.     }
  110.     in_handler = 1;
  111.     do_exit = 1;
  112.     do_nfsumount = 1;
  113.     switch(signr){
  114.     case SIGHUP:    case SIGINT:    case SIGQUIT:
  115.     case SIGUSR1:    case SIGUSR2:
  116.         dprintf("** caught signal %d, preparing for unmount\n", signr);
  117.         break;    /* if the signal was user-induced: unmount nfs from mainloop */
  118.     default:
  119.         eprintf("** caught signal %d, unmounting\n", signr);
  120.         do_nfsumount = 0;
  121.         nfs_unmount(1);
  122.     }
  123.     in_handler = 0;
  124. }
  125.  
  126. /* ------------------------------------------------------------------------- */
  127.  
  128. static void    dispatch_loop(void)
  129. {
  130. fd_set            readfd;
  131. struct timeval    tv;
  132.  
  133.     for(;;){
  134.         readfd = svc_fdset;
  135.         tv.tv_sec = 1; tv.tv_usec = 0;
  136.     
  137.         DDPRINTF(("- going into select\n"));
  138.         if(select(FD_SETSIZE, &readfd, NULL, NULL, &tv) > 0){
  139.             DDPRINTF(("- executing request\n"));
  140.             svc_getreqset(&readfd);
  141.         }
  142.         if(do_exit){
  143.             DDPRINTF(("- doing exit\n"));
  144.             if(!do_nfsumount || nfs_unmount(0)){
  145.                 if(wr_enable){
  146.                     dprintf("Going to unmount disk...\n");
  147.                     my_unmount();
  148.                     dprintf("Disk unmounted.\n");
  149.                 }
  150.                 close(my_fd);
  151.                 eprintf("Exiting.\n");
  152.                 exit(0);
  153.             }
  154.         }
  155.         DDPRINTF(("- checking for regular jobs()\n"));
  156.         dummies_regular();    /* calls all other regulars */
  157.     }
  158. }
  159.  
  160. /* ------------------------------------------------------------------------- */
  161.  
  162. void    mount_and_dispatch(char *dir, void (*proc)(), void *proot_fh, int bg, char *options)
  163. {
  164. int                    sock, port, child_pid, parent_pid, other_pid;
  165. struct sockaddr_in    sain;
  166. SVCXPRT                *nfsxprt;
  167. int                    bufsiz = 0xc000;    /* room for a few biods */
  168. struct nfs_args        nfs_args;
  169. nfs_fh                *root_fh = proot_fh;
  170.  
  171.     signal(SIGHUP, do_unmount);
  172.     signal(SIGINT, do_unmount);
  173.     signal(SIGQUIT, do_unmount);
  174.     signal(SIGILL, do_unmount);
  175.     signal(SIGIOT, do_unmount);
  176.     signal(SIGTRAP, do_unmount);
  177.     signal(SIGEMT, do_unmount);
  178.     signal(SIGFPE, do_unmount);
  179.     signal(SIGBUS, do_unmount);
  180.     signal(SIGSEGV, do_unmount);
  181.     signal(SIGSYS, do_unmount);
  182.     signal(SIGPIPE, do_unmount);
  183.     signal(SIGTERM, do_unmount);
  184.     signal(SIGUSR1, do_unmount);
  185.     signal(SIGUSR2, do_unmount);
  186.     bzero(&sain, sizeof(struct sockaddr_in));
  187.     bzero(&nfs_args, sizeof(struct nfs_args));
  188.  
  189. /*** First part: set up the rpc service */
  190. /* Create udp socket */
  191.     sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  192.     if(setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&bufsiz,sizeof(bufsiz)))
  193.         my_perror("setsockopt");
  194.  
  195. /* Bind it to a reserved port */
  196.     sain.sin_family = AF_INET;
  197.     sain.sin_addr.s_addr = inet_addr("127.0.0.1");
  198. /*sain.sin_addr.s_addr = htonl(INADDR_ANY);gec*/
  199.     for(port = IPPORT_RESERVED-1; port > IPPORT_RESERVED/2; port--){
  200.     DPRINTF(("trying to use port %d\n", port));
  201.         sain.sin_port = htons(port);
  202.         if(bind(sock, (struct sockaddr *) &sain, sizeof(sain)) >= 0)
  203.             break;
  204.     }
  205.     dprintf("Using port %d for NFS.\n", port);
  206.     if(port <= IPPORT_RESERVED/2){
  207.         my_perror("bind to reserved port"); exit(1);
  208.     }
  209.     if((nfsxprt = svcudp_create(sock)) == 0){
  210.         my_perror("svcudp_create"); exit(1);
  211.     }
  212.     if(!svc_register(nfsxprt, NFS_PROGRAM, NFS_VERSION, proc, 0)){
  213.         my_perror("svc_register"); exit(1);
  214.     }
  215.  
  216. /*** Second part: mount the directory */
  217.  
  218.     nfs_args.wsize    = 32768;
  219.     nfs_args.rsize    = 32768;
  220.     nfs_args.addr     = &sain;
  221.     nfs_args.fh       = (char *)root_fh;
  222.     nfs_args.retrans = 0;
  223.     nfs_args.timeo = 200;    /* 20s timeout */
  224.     nfs_args.hostname = "vmount";
  225.     nfs_args.netname = "net";
  226.     nfs_args.flags    = NFSMNT_SOFT | NFSMNT_HOSTNAME |
  227.                         NFSMNT_RETRANS | NFSMNT_TIMEO |
  228.                         NFSMNT_WSIZE | NFSMNT_RSIZE;
  229.  
  230.     mntdir = dir;
  231.     parent_pid = getpid();
  232.     use_syslog = 1;                    /* we will reset this in the parent */
  233.     if((child_pid = fork()) == -1){
  234.         use_syslog = 0;
  235.         my_perror("fork");
  236.         exit(1);
  237.     }
  238.     if(child_pid != 0 || !bg){        /* we are the parent || not background */
  239.         use_syslog = 0;
  240.     }
  241.     if((child_pid == 0 && bg) || (child_pid != 0 && !bg)){
  242.         dispatch_loop();
  243.     }else{
  244.         DPRINTF(("Going to mount...\n"));
  245.         other_pid = child_pid == 0 ? parent_pid : child_pid;
  246.         
  247.         if(mount(MOUNT_NFS, dir, wr_enable ? 0:M_RDONLY,(caddr_t)&nfs_args)<0){
  248.             eprintf("nfs mount %s: [%d] %s\n", dir, errno, strerror(errno));
  249.             kill(other_pid, SIGKILL);
  250.         }else{
  251.             FILE            *fp;
  252.             struct mntent    mnt;
  253.             char            typename[256];
  254.  
  255.             sprintf(typename, "vmount-%d", other_pid);
  256.             mnt.mnt_fsname = device_name;
  257.             mnt.mnt_dir = mntdir;
  258.             mnt.mnt_type = typename;
  259.             mnt.mnt_opts = options!=NULL && *options!=0 ? options : "default";
  260.             mnt.mnt_freq = mnt.mnt_passno = 0;
  261.             lock_mtab();
  262.             if ((fp = setmntent(MOUNTED, "a")))
  263.                 addmntent(fp, &mnt);
  264.             else
  265.                 my_perror(MOUNTED);
  266.             endmntent(fp);
  267.             unlock_mtab();
  268.         }
  269.         exit(0);
  270.     }
  271. }
  272.