home *** CD-ROM | disk | FTP | other *** search
/ Boot Disc 8 / boot-disc-1997-04.iso / PDA_Soft / Psion / comms / p3nfs / nfsd / mp_mount.c < prev    next >
C/C++ Source or Header  |  1996-03-31  |  14KB  |  529 lines

  1. #include <stdio.h>
  2. #include <signal.h>
  3. #include <sys/stat.h>
  4. #include <sys/wait.h>
  5.  
  6. #ifdef __svr4__
  7. #include <stdlib.h>
  8. #include <unistd.h>
  9. extern int inet_addr(char *);
  10. #define PORTMAP        /* I need svcudp_create in rpc/svc_soc.h, sol 2.4 */
  11. #endif
  12.  
  13. #define PSIONHOSTNAME "localhost"
  14. #include "config.h"
  15.  
  16. static char nfshost[128];
  17.  
  18. #define NFSCLIENT
  19. #include <sys/mount.h>
  20.  
  21. #ifdef linux
  22. # include <linux/fs.h>        /* struct nfs_sever for linux/nfs_fs.h */
  23. # include <linux/nfs_fs.h>    /* struct nfs_mount_data */
  24. # include <arpa/inet.h>        /* inet_addr() */
  25. #endif
  26. #ifdef _IBMR2
  27. # include "os-aix3.h"
  28. # include "misc-aix3.h"
  29. # include <sys/vmount.h>
  30. #endif
  31.  
  32. #include <rpc/rpc.h>
  33. #include "nfs_prot.h"
  34.  
  35. #ifndef DONT_UPDATE_MTAB
  36. #if defined(sun) && defined(__svr4__)
  37. #include <sys/mnttab.h>
  38. #else
  39. #include <mntent.h>
  40. #endif
  41. #endif
  42.  
  43. #if defined(sun) && defined(__svr4__) /*gec*/
  44. #include <string.h>        /* strdup */
  45. #include <nfs/mount.h>
  46. #include <sys/fstyp.h>
  47. #include <sys/fsid.h>
  48. #include <sys/types.h>
  49. #include <sys/stat.h>
  50. #define PORTMAP
  51. #endif
  52.  
  53. #if defined(sun) && !defined(__svr4__)
  54. extern int _rpc_dtablesize();
  55. #define umount unmount
  56. #endif
  57.  
  58. #include <sys/socket.h>
  59. #include <netdb.h>
  60. #include <rpc/rpc.h>
  61.  
  62. #include "mp.h"
  63.  
  64. #ifdef __sgi
  65. # define vfork fork
  66. # define NFSMNT_NOCTO 0
  67. #endif
  68.  
  69. #if defined(sun) && defined(__svr4__)
  70. # define setmntent fopen
  71. # define endmntent fclose
  72. # define addmntent putmntent
  73. # define mntent mnttab
  74. #endif
  75.  
  76.  
  77. static char *mntdir;        /* where we mounted the psion */
  78.  
  79.  
  80. static void
  81. doexit()
  82. {
  83.   FILE *fpin, *fpout;
  84. #if defined(sun) && defined(__svr4__)
  85.   struct mntent entr;
  86. #else
  87.   struct mntent *ent;
  88. #endif
  89.   struct stat statb;
  90.  
  91.   exiting--;
  92.  
  93.   if(debug) printf("Doing exit\n");
  94.  
  95. #ifdef _IBMR2
  96.   if (stat(mntdir, &statb))
  97.     {
  98.       perror("stat");
  99.       return;
  100.     }
  101.   if(debug) printf("Next call: uvmount(%d, 0)\n", statb.st_vfs);
  102.   if(uvmount(statb.st_vfs, 0))
  103.     {
  104.       perror("uvmount");
  105.       return;
  106.     }
  107. #else
  108.   if(umount(mntdir))
  109.     {
  110.       perror(mntdir);
  111.       return;
  112.     }
  113. #endif
  114.  
  115. #ifndef DONT_UPDATE_MTAB
  116.   if(debug) printf("unmount succeeded, trying to fix mtab.\n");
  117.  
  118.   if(!(fpout = setmntent(MTAB_TMP, "w")))
  119.     {
  120.       perror(MTAB_TMP);
  121.       return;
  122.     }
  123.   if(!(fpin = setmntent(MTAB_PATH, "r")))
  124.     {
  125.       endmntent(fpout); unlink(MTAB_TMP);
  126.       perror(MTAB_PATH); exit(0);
  127.     }
  128.   if (fstat(fileno(fpin), &statb))
  129.     perror("fstat");
  130.   else
  131.     fchmod(fileno(fpout), statb.st_mode);
  132.  
  133. #if defined(sun) && defined(__svr4__)
  134.   while (!getmntent(fpin,&entr))
  135.     if(strcmp(entr.mnt_special, nfshost) || strcmp(entr.mnt_mountp, mntdir))
  136.       putmntent(fpout, &entr);
  137. #else
  138.   while ((ent = getmntent(fpin)))
  139.     if(strcmp(ent->mnt_fsname, nfshost) || strcmp(ent->mnt_dir, mntdir))
  140.       addmntent(fpout, ent);
  141. #endif
  142.   endmntent(fpin);
  143.   endmntent(fpout);
  144.  
  145.   if(rename(MTAB_TMP, MTAB_PATH))
  146.     {
  147.       perror(MTAB_PATH); 
  148.       unlink(MTAB_TMP);
  149.     }
  150. #else
  151.   if(debug) printf("no mtab fixing needed\n");
  152. #endif
  153.   fprintf(stderr, "p3nfsd: exiting.\n");
  154.   
  155.   exit(0);
  156. }
  157.  
  158. static void
  159. dosystem(str)
  160.   char *str;
  161. {
  162.   extern fattr root_fattr;
  163.  
  164.   if(vfork()) return;
  165.   setgid(root_fattr.gid);
  166.   setuid(root_fattr.uid);
  167.   execl("/bin/sh", "sh", "-c", str, 0);
  168.   perror("/bin/sh");
  169.   _exit(1);
  170. }
  171.  
  172. void
  173. mount_and_run(dir, dev, proc, root_fh)
  174.   char *dir, *dev;
  175.   nfs_fh *root_fh;
  176.   void (*proc)();
  177. {
  178.   int sock, port, pid;
  179.   struct sockaddr_in sain;
  180.   int isalive = 0, ret, dtbsize;
  181.   SVCXPRT *nfsxprt;
  182.   int bufsiz = 0xc000;                        /* room for a few biods */
  183. #ifdef linux
  184.   struct nfs_mount_data nfs_mount_data;
  185.   int mount_flags;
  186.   int ksock, kport;
  187.   struct sockaddr_in kaddr;
  188. #else
  189.   struct nfs_args nfs_args;
  190. #endif
  191.  
  192.   sprintf(nfshost, "localhost:%s", dev);
  193.   bzero((char *)&sain, sizeof(struct sockaddr_in));
  194. #ifdef linux
  195.   bzero(&nfs_mount_data, sizeof(struct nfs_mount_data));
  196. #else
  197.   bzero((char *)&nfs_args, sizeof(struct nfs_args));
  198. #endif
  199.  
  200. /*** First part: set up the rpc service */
  201. /* Create udp socket */
  202.   sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  203.   if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&bufsiz, sizeof(bufsiz)))
  204.     perror("setsockopt");
  205.  
  206. /* Bind it to a reserved port */
  207.   sain.sin_family = AF_INET;
  208.   sain.sin_addr.s_addr = inet_addr("127.0.0.1");
  209.   for(port = IPPORT_RESERVED-1; port > IPPORT_RESERVED/2; port--)
  210.     {
  211.       sain.sin_port = htons(port);
  212.       if(bind(sock, (struct sockaddr *) &sain, sizeof(sain)) >= 0)
  213.         break;
  214.     }
  215.   if(port <= IPPORT_RESERVED/2)
  216.     {
  217.       perror("bind to reserved port"); exit(1);
  218.     }
  219.   if((nfsxprt = svcudp_create(sock)) == 0)
  220.     {
  221.       perror("svcudp_create"); exit(1);
  222.     }
  223.   if(!svc_register(nfsxprt, NFS_PROGRAM, NFS_VERSION, proc, 0))
  224.     {
  225.       perror("svc_register"); exit(1);
  226.     }
  227.  
  228. /*** Second part: mount the directory */
  229. #ifdef linux
  230.   /* 
  231.    * Hold your hat! Another odd internet socket coming up. The linux
  232.    * kernel needs the socket to talk to the nfs daemon.
  233.    */
  234.   ksock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  235.   if (ksock < 0)
  236.     {
  237.       perror("Cannot create kernel socket.");
  238.       exit(1);
  239.     }
  240.   kaddr.sin_family = AF_INET;
  241.   kaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  242.   for (kport = IPPORT_RESERVED - 1; kport > IPPORT_RESERVED/2; kport--)
  243.     {
  244.       kaddr.sin_port = htons(kport);
  245.       if (bind(ksock, (struct sockaddr *)&kaddr, sizeof(kaddr)) >= 0)
  246.         break;
  247.     }
  248.   if (kport <= IPPORT_RESERVED/2)
  249.     {
  250.       perror("bind to reserved port");
  251.       exit(1);
  252.     }
  253.  
  254.   nfs_mount_data.version = NFS_MOUNT_VERSION;
  255.   nfs_mount_data.fd      = ksock;
  256.   nfs_mount_data.root    = *root_fh;    /* structure copy */
  257.   nfs_mount_data.flags   = NFS_MOUNT_INTR | NFS_MOUNT_NOCTO; 
  258.               /* NFS_MOUNT_SECURE | NFS_MOUNT_POSIX | NFS_MOUNT_SOFT | NFS_MOUNT_NOAC */
  259.   nfs_mount_data.rsize    = PBUFSIZE;
  260.   nfs_mount_data.wsize    = PBUFSIZE;
  261.   nfs_mount_data.timeo    = 600;
  262.   nfs_mount_data.retrans  = 10;        /* default 3 */
  263.   nfs_mount_data.acregmin = 3;        /* default 3 seconds */
  264.   nfs_mount_data.acregmax = 60;        /* default 60 seconds */
  265.   nfs_mount_data.acdirmin = 30;        /* default 30 seconds */
  266.   nfs_mount_data.acdirmax = 60;        /* default 60 seconds */
  267.   nfs_mount_data.addr     = sain;    /* structure copy */
  268.   strcpy(nfs_mount_data.hostname, PSIONHOSTNAME);
  269.  
  270.   if (connect(ksock, (struct sockaddr *)&nfs_mount_data.addr, sizeof(nfs_mount_data.addr)) < 0)
  271.     {
  272.       perror("Cannot connect to p3nfsd");
  273.       exit(1);
  274.     }
  275.  
  276.   mount_flags = MS_MGC_VAL; /* | MS_SYNC | MS_RDONLY | MS_NOEXEC | MS_NODEV | MS_NOSUID */
  277.  
  278. #endif
  279.  
  280. #if defined(sun) && defined (__svr4__)
  281.   {                                 /*gec*/
  282.     struct netbuf myaddr;
  283.     struct stat stb;
  284.     struct knetconfig knc;
  285.     struct netconfig *nc=getnetconfigent("udp");
  286.     if (!nc) {
  287.     extern int errno;
  288.     fprintf(stderr, "getnetconfigent \"udp\": (errno %d) ", errno);
  289.     perror("");
  290.     exit(1);
  291.     }
  292.     knc.knc_semantics=nc->nc_semantics;
  293.     knc.knc_protofmly=strdup(nc->nc_protofmly);
  294.     knc.knc_proto=strdup(nc->nc_proto);
  295.  
  296.     if (stat(nc->nc_device,&stb)) {
  297.     extern int errno;
  298.     fprintf(stderr, "stat \"%s\": (errno %d) ",nc->nc_device, errno);
  299.     perror("");
  300.     exit(1);
  301.     }
  302.     knc.knc_rdev=stb.st_rdev;
  303.  
  304.     /*freenetconfigent(nc) has the struct been allocated, or is it static ?!?*/
  305.  
  306.     if (debug)
  307.       printf("%d,%s,%s,%lx (1,inet,udp,0x002c0029)\n", knc.knc_semantics,
  308.                       knc.knc_protofmly,knc.knc_proto,knc.knc_rdev);
  309.  
  310.     myaddr.maxlen=myaddr.len=sizeof(sain);
  311.     myaddr.buf=(char *)&sain;
  312.  
  313.     nfs_args.knconf   = &knc;
  314.     nfs_args.wsize    = PBUFSIZE;
  315.     nfs_args.rsize    = PBUFSIZE;
  316.     nfs_args.addr     = &myaddr;
  317.     nfs_args.fh       = (char *)root_fh;
  318.     nfs_args.retrans  = 10;
  319.     /* 1 minute timeout - see below */
  320.     nfs_args.timeo    = 600;
  321.     nfs_args.hostname = PSIONHOSTNAME;
  322.     nfs_args.flags    = NFSMNT_INT | NFSMNT_HOSTNAME | NFSMNT_NOCTO |
  323.                         NFSMNT_RETRANS | NFSMNT_TIMEO | NFSMNT_WSIZE | 
  324.             NFSMNT_RSIZE | NFSMNT_KNCONF | NFSMNT_NOAC; 
  325.   }
  326. #endif /* solaris */
  327.  
  328. #if (defined(sun) && !defined(__svr4__))  || defined(hpux) || defined(__sgi)
  329.   nfs_args.addr     = &sain;
  330.   nfs_args.fh       = (void *)root_fh;
  331.   nfs_args.wsize    = PBUFSIZE;
  332.   nfs_args.rsize    = PBUFSIZE;
  333.   nfs_args.retrans = 10;
  334.   /* 1 minute timeout - means that we receive double requests in worst case,
  335.    if the file is longer than 100k. So long for the theory. Since SunOS uses
  336.    dynamic retransmission (hardwired), nfs_args.timeo is only a hint. :-( */
  337.   nfs_args.timeo = 600;
  338.   nfs_args.hostname = PSIONHOSTNAME;
  339.   nfs_args.flags    = NFSMNT_INT | NFSMNT_HOSTNAME | NFSMNT_NOCTO |
  340.                    NFSMNT_RETRANS | NFSMNT_TIMEO | NFSMNT_WSIZE | NFSMNT_RSIZE;
  341. #endif
  342.  
  343. #if defined(_IBMR2)
  344.   nfs_args.addr     = sain;
  345.   nfs_args.fh       = *(fhandle_t *)root_fh;
  346.   nfs_args.wsize    = PBUFSIZE;
  347.   nfs_args.rsize    = PBUFSIZE;
  348.   nfs_args.retrans  = 0; /* Shouldn't need bigger retrans since there is
  349.                             only one biod. Somebody prove it ? Nice feature. */
  350.   nfs_args.biods    = 1;
  351.   nfs_args.timeo    = 150;
  352.   nfs_args.hostname = PSIONHOSTNAME;
  353.   nfs_args.flags    = NFSMNT_INT | NFSMNT_HOSTNAME | NFSMNT_BIODS |
  354.                    NFSMNT_RETRANS | NFSMNT_TIMEO | NFSMNT_WSIZE | NFSMNT_RSIZE;
  355. #endif
  356.  
  357.   mntdir = dir;
  358.   switch(pid=fork())
  359.     {
  360.       case 0:
  361.         break;
  362.       case -1:
  363.         perror("fork");
  364.     exit(1);
  365.       default:
  366.     if(debug)
  367.       printf("Going to mount...\n");
  368. #ifdef __sgi
  369.         if(mount("", dir, MS_DATA, "nfs", &nfs_args, sizeof(nfs_args)))
  370. #endif
  371.  
  372. #ifdef sun 
  373. #  ifndef __svr4__
  374.     if(mount("nfs", dir, M_NEWTYPE, (caddr_t)&nfs_args))
  375. #  else /*gec*/
  376.         if(mount("", dir, MS_DATA, "nfs", &nfs_args, sizeof(nfs_args)))
  377.     /* eventually drop knc-strings now (memory-leak) */
  378. #  endif
  379. #endif
  380.  
  381. #ifdef hpux
  382.     if (vfsmount(MOUNT_NFS, dir, 0, &nfs_args))    
  383. #endif
  384. #ifdef linux
  385.     if (mount("nfs", dir, "nfs", mount_flags, &nfs_mount_data))
  386. #endif
  387. #ifdef _IBMR2
  388.     if(aix3_mount("psion:loc", dir, 0, MOUNT_TYPE_NFS, &nfs_args, "p3nfsd"))
  389. #endif
  390.       {
  391.         extern int errno;
  392.  
  393.         fprintf(stderr, "nfs mount %s: (errno %d) ", dir, errno);
  394.         perror("");
  395.         kill(pid, SIGTERM);
  396.         exit(0);
  397.       }
  398.     else
  399.       {
  400. #ifndef DONT_UPDATE_MTAB
  401.         FILE *mfp;
  402.         struct mntent mnt;
  403. # if defined(sun) && defined(__svr4__) /*gec*/
  404.         char tim[32];
  405. # endif
  406.  
  407.         if(debug)
  408.               printf("Mount succeded, making mtab entry.\n");
  409.  
  410. # if defined(sun) && defined(__svr4__) /*gec*/
  411.         mnt.mnt_special = nfshost;
  412.         mnt.mnt_mountp = mntdir;
  413.         mnt.mnt_fstype = "nfs";
  414.         mnt.mnt_mntopts = "hard,intr"; /* dev=??? */
  415.         sprintf(tim,"%ld",time(NULL)); /* umount crashes! without this*/
  416.         mnt.mnt_time = tim;
  417. # else
  418.         mnt.mnt_fsname = nfshost;
  419.         mnt.mnt_dir = mntdir;
  420.         mnt.mnt_type = "nfs";
  421.         mnt.mnt_opts = "hard,intr";
  422.         mnt.mnt_freq = mnt.mnt_passno = 0;
  423. # endif
  424.  
  425.         if ((mfp = setmntent(MTAB_PATH, "a")))
  426.           addmntent(mfp, &mnt);
  427.         else
  428.           perror(MTAB_PATH);
  429.         endmntent(mfp);
  430. #endif /* !DONT_UPDATE_MTAB */
  431.       }
  432.     if(!background)
  433.       while(wait(&ret) != pid)
  434.         ;
  435.     exit(0);
  436.     }
  437.  
  438. /*** Third part: let's go */
  439.   printf("p3nfsd: to stop the server do \"ls %s/exit\". (pid %d)\n",
  440.          mntdir, getpid());
  441.  
  442. #if defined(sun) && !defined(__svr4__)
  443.   dtbsize = _rpc_dtablesize();
  444.   if(psionfd  >= dtbsize) dtbsize = psionfd+1;
  445.   if(masterfd >= dtbsize) dtbsize = masterfd+1;
  446. #else
  447.   dtbsize = FD_SETSIZE;
  448. #endif
  449.  
  450.   for(;;)
  451.     {
  452.       fd_set readfd;
  453.       struct timeval tv;
  454.       struct cache *cp;
  455.       struct dcache *dcp;
  456.  
  457.       readfd = svc_fdset;
  458.       FD_SET(psionfd, &readfd);
  459.       if(masterfd >= 0)
  460.     FD_SET(masterfd, &readfd);
  461.       tv.tv_sec = 2; tv.tv_usec = 0;
  462.  
  463.       ret = select(dtbsize, &readfd, 0, 0, &tv);
  464.       if(ret > 0)
  465.         {
  466.       if(FD_ISSET(psionfd, &readfd)) /* Terminal input from the psion */
  467.         {
  468.           unsigned char c;
  469.  
  470.           read(psionfd, &c, 1);
  471.           shell_feed(c);
  472.           continue;
  473.         }
  474.       if(masterfd >=0 && FD_ISSET(masterfd, &readfd)) /* Terminal output */
  475.         {
  476. #define PLEN 245        /* to make life easier for the psion */
  477.           char buf[PLEN+1];
  478.           int len;
  479.  
  480.           len = read(masterfd, buf, PLEN);
  481.           buf[len] = 0;
  482.           if(len <= 0)
  483.             {
  484.           close(masterfd);
  485.           masterfd = -1;
  486.         }
  487.           /* not 0-byte clean. :-( but its faster and PREFIX is no problem*/
  488.           sendcmd(PFS_OP_TTYDATA, buf, 0, 0);
  489.           continue;
  490.         }
  491.       svc_getreqset(&readfd);
  492.     }
  493.       if(ret != 0)
  494.         continue;
  495.  
  496. /* Do some housekeeping */
  497.       
  498.       if(exiting)
  499.         doexit();
  500.       query_cache = 0;            /* clear the GETDENTS "cache". */
  501.  
  502.       /* print some warnings about not written blocks */
  503.       for(cp = attrcache; cp; cp = cp->next)
  504.     for(dcp = cp->dcache; dcp; dcp = dcp->next)
  505.       if(!dcp->written)
  506.         {
  507.           printf("P3NFSD: WARNING, block at offset %d in %s not written\n",
  508.                dcp->offset, get_num(cp->inode)->name);
  509.           break;
  510.         }
  511.       clean_cache(&attrcache);
  512.  
  513.       ret = fd_is_still_alive(psionfd, 0);
  514.       if(isalive && !ret)
  515.         {
  516.       if(debug) printf("Disconnected...\n");
  517.       if(disconnprog && *disconnprog)
  518.         dosystem(disconnprog);
  519.     }
  520.       else if(!isalive && ret)
  521.         {
  522.       if(debug) printf("Connected...\n");
  523.       if(connprog && *connprog)
  524.         dosystem(connprog);
  525.     }
  526.       isalive = ret;
  527.     }
  528. }
  529.