home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 13 / MA_Cover_13.bin / source / c / nfsd / src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-30  |  7.1 KB  |  262 lines

  1. /*  nfsd - an Amiga NFS daemon
  2.  
  3.     ©1998, 1999 Joseph Walton
  4.  
  5.     This software is distributed under the terms of the GNU General Public
  6.     License; either version 2 of the License, or (at your option) any
  7.     later version.
  8. */
  9.  
  10. /*
  11.     This is the main routine - it opens libraries, calls allocation routines,
  12.     checks versions, and installs RPC dispatchers.
  13. */
  14.  
  15. /*
  16.     28-Sep-1999 - Uses ReadArgs. Allows the user to set the GMT offset.
  17.     30-Nov-1999 - Major changes to support new RPC code.
  18. */
  19.  
  20. #include "nfsd.h"
  21. #include "nfs.h"
  22. #include "mount.h"
  23. #include "pcnfsd.h"
  24.  
  25. #include "service_nfsd.h" // service()
  26.  
  27. #include "rpc_register.h"
  28. #include "handle_list.h"
  29. #include "memory.h"
  30. #include "config.h"
  31. #include "timerdev.h"
  32. #include "nfs_utils.h"
  33.  
  34. #include <stdio.h>
  35. #include <signal.h>
  36. #include <string.h>         /* strcmp */
  37. #include <sys/socket.h>
  38. #include <netinet/in.h>
  39.  
  40. #include <dos/dosextens.h>  /* struct Process */
  41.  
  42. #include <proto/socket.h>
  43. #include <proto/exec.h>
  44. #include <proto/dos.h>
  45.  
  46. /* Seems some SDKs don't follow Amiga conventions... */
  47. #ifndef SOCKETNAME
  48. #define SOCKETNAME "bsdsocket.library"
  49. #endif
  50.  
  51. /* Are we verbose? If so, print copious output */
  52. BOOL verbose = FALSE;
  53.  
  54. /* This changes how authentication behaves */
  55. extern BOOL allow_root; /* in auth.c */
  56.  
  57. /* The offset of local time from GMT */
  58. extern LONG amigaGMTOffset; /* in nfs_util.c */
  59.  
  60. /* I'm relying on DiceC to have opened these */
  61. extern struct Library *SysBase;
  62. extern struct DosLibrary *DOSBase;
  63.  
  64. struct Library *SocketBase = NULL;
  65.  
  66. /* This is a rather busy main, but what the hey... */
  67. int main(int argc, char *argv[])
  68. {
  69.     /* Declarations first */
  70.  
  71.     /* Keep track of whether or not we need to deregister these */
  72.     BOOL registered_nfsd = FALSE,
  73.         registered_mount = FALSE,
  74.         registered_pcnfsd = FALSE;
  75.  
  76.     /* Our future point of presence in IP space */
  77.     int sock = -1;
  78.  
  79.     /* We need these to inhibit graphical requesters */
  80.     struct Process *process;
  81.     APTR vptr;
  82.  
  83.     /* Just a little beta-blaring... */
  84.     puts("nfsd beta, ©1998, 1999 Joseph Walton <ver@etla.org>\n"
  85.          "This version compiled " __DATE__ ".\n"
  86.          "nfsd is free software, distributed under the terms of the GNU General Public License.\n"
  87.          "It comes with ABSOLUTELY NO WARRANTY.");
  88.     /* Moved from pre-pre- to just plain pre-...
  89.         And now we're a plain beta... */
  90.  
  91.     /* We'll handle CTRL-C's ourselves */
  92.     signal(SIGINT, SIG_IGN);
  93.  
  94.     /* We need some v39 exec.library functions - sorry */
  95.     if (SysBase->lib_Version < 39) {
  96.         puts("nfsd requires v39 exec.library");
  97.         goto finish;
  98.     }
  99.  
  100.     /* We do need some v39 dos.library functions - sorry */
  101.     if (DOSBase->dl_lib.lib_Version < 39) {
  102.         puts("nfsd requires v39 dos.library");
  103.         goto finish;
  104.     }
  105.  
  106.     /* We manually open timer.device, as SAS/C won't do it for us */
  107.     if (!td_opentimer()) {
  108.         puts("Unable to open " TIMERNAME);
  109.         goto finish;
  110.     }
  111.  
  112.     /* Oh, I might need some socket handling routines... */
  113.     SocketBase = OpenLibrary(SOCKETNAME, 4);
  114.  
  115.     if (!SocketBase) {
  116.         puts("Unable to open " SOCKETNAME " v4");
  117.         goto finish;
  118.     }
  119.  
  120.     /* Need to get memory to work with */
  121.     if (!init_memory()) {
  122.         puts("Unable to allocate handle list");
  123.         goto finish;
  124.     }
  125.  
  126.     /* Check the command line */
  127.     {
  128.         STRPTR template = "GMTOFFSET/K/N,ALLOWROOT/S,VERBOSE/S";
  129.         LONG opts[3] = {0, 0, 0};
  130.         struct RDArgs *argsptr;
  131.  
  132.         if (NULL == (argsptr = ReadArgs(template, opts, NULL))) {
  133.             PrintFault(IoErr(), NULL);
  134.             goto finish;
  135.         }
  136.  
  137.         /* Now act on those arguments */
  138.         if (opts[0]) {
  139.             amigaGMTOffset = *(LONG *)opts[0];
  140.         }
  141.  
  142.         if (opts[1]) {
  143.             allow_root = TRUE;
  144.             puts("Allowing remote accesses by root");
  145.         }
  146.  
  147.         if (opts[2]) {
  148.             verbose = TRUE;
  149.             puts("Verbose mode enabled");
  150.         }
  151.  
  152.         FreeArgs(argsptr);
  153.     }
  154.  
  155.     /* And parse our configuration */
  156.     if (!process_cfg("nfsd.config")) {
  157.         puts("Unable to get configuration");
  158.         goto finish;
  159.     }
  160.  
  161.     /* Now fetch the inode base */
  162.     persistent_inode_fetch();
  163.     /* Any failure is dealt with internally, by starting afresh at 1 */
  164.  
  165.     /* We need a socket to communicate with */
  166.     sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  167.     if (sock < 0) {
  168.         printSocketError("Could not create a socket");
  169.         goto finish;
  170.     }
  171.  
  172.     /* nfsd needs to bind to a well-known port */
  173.     {
  174.         struct sockaddr_in addr = {
  175.             sizeof(struct sockaddr_in),
  176.             AF_INET,
  177.             htons(NFS_PORT),
  178.             {htonl(INADDR_ANY)}
  179.         };
  180.  
  181.         /* Can I do this without a macro? */
  182.         #define A(x) #x
  183.  
  184.         if (-1 == bind(sock, &addr, sizeof(addr))) {
  185.             printSocketError("Unable to bind to port " A(NFS_PORT));
  186.             goto finish;
  187.         }
  188.  
  189.         #undef A
  190.     }
  191.  
  192.     /*
  193.         We don't try to get rid of any old mapping at the moment.
  194.         It might well fail confusingly, and gazumping services like
  195.         that is hardly polite.
  196.     */
  197.  
  198.     /* Establish mappings. We bind everything to the same port. */
  199.     if (pmap_set(sock, NFS_PROGRAM, NFS_VERSION, NFS_PORT)) {
  200.         registered_nfsd = TRUE;
  201.     } else {
  202.         puts("Unable to register (NFS_PROGRAM, NFS_VERSION, NFS_PORT).");
  203.         goto finish;
  204.     }
  205.  
  206.     if (pmap_set(sock, MOUNT_PROGRAM, MOUNT_VERSION, NFS_PORT)) {
  207.         registered_mount = TRUE;
  208.     } else {
  209.         puts("Unable to register (MOUNT_PROGRAM, MOUNT_VERSION, NFS_PORT).");
  210.         goto finish;
  211.     }
  212.  
  213.     if (pmap_set(sock, PCNFSD_PROGRAM, PCNFSD_VERSION, NFS_PORT)) {
  214.         registered_pcnfsd = TRUE;
  215.     } else {
  216.         puts("Unable to register (PCNFSD_PROGRAM, PCNFSD_VERSION, NFS_PORT).");
  217.         goto finish;
  218.     }
  219.  
  220.     /* We don't want any requesters popped up */
  221.     process = (struct Process *)FindTask(NULL);
  222.     vptr = process->pr_WindowPtr;
  223.     process->pr_WindowPtr = (APTR)-1L;
  224.  
  225.     puts("Serving.");
  226.     service(sock); /* This where we jump to the Real Work */
  227.  
  228.     puts("Finished.");
  229.  
  230.     /* Now return things to normal */
  231.     process->pr_WindowPtr = vptr;
  232.  
  233.     if (!persistent_inode_store())
  234.         puts("Failed to store current inode");
  235.  
  236.     /* Now, free any resources and exit */
  237.     finish:
  238.     td_closetimer();
  239.  
  240.     if (SocketBase) {
  241.         if (sock >= 0) {
  242.             /* If any of these time out we should probably skip the
  243.                 rest, but we currently don't export that information
  244.                 from the registration process */
  245.             if (registered_pcnfsd)
  246.                 if (!pmap_unset(sock, PCNFSD_PROGRAM, PCNFSD_VERSION))
  247.                     puts("Unable to deregister the PCNFSD service.");
  248.             if (registered_nfsd)
  249.                 if (!pmap_unset(sock, NFS_PROGRAM, NFS_VERSION))
  250.                     puts("Unable to deregister the NFS service.");
  251.             if (registered_mount)
  252.                 if (!pmap_unset(sock, MOUNT_PROGRAM, MOUNT_VERSION))
  253.                     puts("Unable to deregister the mount service.");
  254.             CloseSocket(sock);
  255.         }
  256.         CloseLibrary(SocketBase);
  257.     }
  258.     free_memory();
  259.     return RETURN_OK;
  260. }
  261.  
  262.