home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / util / att-nameserver / xdaemon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-07-10  |  11.4 KB  |  600 lines

  1. #ifndef NOIDENT
  2. #ident    "@(#)nameserver:xdaemon.c    1.6"
  3. #endif
  4.  
  5. /*
  6.  * Copyright 1988, 1989 AT&T, Inc.
  7.  *
  8.  * Permission to use, copy, modify, and distribute this software and its
  9.  * documentation for any purpose and without fee is hereby granted, provided
  10.  * that the above copyright notice appear in all copies and that both that
  11.  * copyright notice and this permission notice appear in supporting
  12.  * documentation, and that the name of AT&T not be used in advertising
  13.  * or publicity pertaining to distribution of the software without specific,
  14.  * written prior permission.  AT&T makes no representations about the
  15.  * suitability of this software for any purpose.  It is provided "as is"
  16.  * without express or implied warranty.
  17.  *
  18.  * AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  19.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL AT&T
  20.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  21.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  22.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  23.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  *
  25. */
  26.  
  27. #include <X11/Xos.h>
  28. #include <errno.h>
  29. #include <sys/param.h>
  30. #include <signal.h>
  31. #include <sys/stream.h>
  32. #include <sys/stropts.h>
  33. #include <stdio.h>
  34. #include "Xstreams.h"                /* in Xlib sources */
  35. #include <sys/utsname.h>
  36. #include <X11/Xproto.h>
  37.  
  38. #include "osdep.h"
  39.  
  40. #define    NSECONDS    2    
  41.  
  42. extern    char    *calloc(), *realloc();
  43. extern    char    *program;
  44. int    network;
  45. int    nextentry;
  46.  
  47. char    *xalloc();
  48. char    *xrealloc();
  49. char *makePacket();
  50.  
  51. char    *TheEnd;
  52. char    *inbuf;
  53. int    inlen;
  54. int    dispno;
  55. char    display[64];
  56. int    nhosts;
  57. int    nHosts;
  58. int    flags = 0;
  59.  
  60. IOBUFFER InputBuffer[MAXSOCKS];
  61.  
  62. extern int t_errno;
  63.  
  64.  
  65. int ListenFd;
  66. int lastfdesc;            /* maximum file descriptor */
  67.  
  68. long WellKnownConnections;    /* Listener mask */
  69. long AllSockets[mskcnt];    /* select on this */
  70. long AllClients[mskcnt];          /* available clients */
  71. long LastSelectMask[mskcnt];          /* mask returned from last select call */
  72. long MaxClients = MAXSOCKS ;
  73.  
  74. #define SUCCESS        "1"
  75. static char    *ptmx = "/dev/ptmx";
  76.  
  77. /*
  78. int    sig = -1;
  79. catchit()
  80. {
  81. }
  82. */
  83.  
  84.  
  85. WaitForInput()
  86. {
  87.     int    Quit();
  88.     int i;
  89.     struct timeval waittime, *wt;
  90.     long timeout;
  91.     long readyClients[mskcnt];
  92.     long curclient;
  93.     int selecterr;
  94.  
  95.     CLEARBITS(readyClients);
  96.  
  97.     COPYBITS(AllSockets, LastSelectMask);
  98.  
  99.     wt = NULL;
  100.  
  101. /* 
  102.     if (!ANYSET(AllClients))
  103.     {
  104.         wt = &waittime;
  105.     waittime.tv_sec  = 5*60;
  106.     waittime.tv_usec = 0;
  107.     }
  108.     else {
  109.     sleep(1);
  110.         alarm(NSECONDS);
  111.         signal(SIGALRM, catchit);
  112.         while(wait((int *)0) > 0);
  113.         alarm(0);
  114.         wt = NULL;
  115.     }
  116.  
  117. */
  118.     i = select (MAXSOCKS, LastSelectMask, (int *) NULL, (int *) NULL, wt);
  119.  
  120.     selecterr = errno;
  121.     
  122.     if (i <= 0) /* An error or timeout occurred */
  123.     {
  124.     if(i == 0)
  125.         Quit();
  126.     if (i < 0) 
  127.         if (selecterr == EBADF)    /* Some client disconnected */
  128.             CheckConnections ();
  129.         else if (selecterr != EINTR)
  130.             fprintf(stderr, "WaitForInput(): select: errno=%d\n",
  131.                                 selecterr);
  132.     }
  133.     else
  134.     {
  135.     MASKANDSETBITS(readyClients, LastSelectMask, AllClients); 
  136.     if (LastSelectMask[0] & WellKnownConnections) 
  137.            EstablishNewConnections();
  138.     }
  139.     if (ANYSET(readyClients))
  140.     {
  141.     for (i=0; i<mskcnt; i++)
  142.     {
  143.         while (readyClients[i])
  144.         {
  145.         curclient = NextSetBit (readyClients[i]) - 1;
  146.         ServiceClient(curclient);    
  147.         readyClients[i] &= ~(1 << curclient);
  148.         }
  149.     }    
  150.     }
  151. }
  152.  
  153. /* Routines for handling local streams (streams-pipes) */
  154.  
  155. Quit(sig)
  156. int    sig;
  157. {
  158.     fprintf(stderr, "xdeamon: received signal %d\n", sig);
  159.  
  160.     if(unlink(NAME_SERVER_NODE) < 0 && errno != ENOENT){
  161.         fprintf(stderr, "Cannot unlink %s", NAME_SERVER_NODE);
  162.         perror(" ");
  163.         }
  164.     exit(0);
  165. }
  166.  
  167. OpenTheListener()
  168. {
  169.     int     munix, sunix;
  170.     char *    slave;
  171.     char    buf[64];
  172.  
  173. /*
  174.     signal(SIGHUP, Quit);
  175. */
  176.     signal(SIGHUP, SIG_IGN);
  177.     signal(SIGINT, Quit);
  178.     signal(SIGQUIT,Quit);
  179.     signal(SIGTERM, Quit);
  180.  
  181.     sprintf(buf, "%s", NAME_SERVER_NODE);
  182.     if(open(buf, O_RDWR) >= 0){
  183.         fprintf(stderr, "Xdaemon is already running\n");
  184.         return(-1);
  185.         }
  186.     if( (munix = open(ptmx, O_RDWR)) < 0 ){
  187.         fprintf(stderr,"Cannot open %s", ptmx);
  188.         perror(" ");
  189.         return(-1);
  190.     }
  191.     grantpt(munix);
  192.     unlockpt(munix);
  193.  
  194.     if(unlink(buf) < 0 && errno != ENOENT){
  195.         fprintf(stderr, "Cannot unlink %s", buf);
  196.         perror(" ");
  197.         return(-1);
  198.         }
  199.  
  200.     slave = (char *) ptsname(munix);
  201.     if( link(slave, buf) <0 ){
  202.         fprintf(stderr, "Cannot link %s to %s", slave, buf);
  203.         perror(" ");
  204.         return(-1);
  205.         }
  206.     if( chmod(buf, 0666) < 0){
  207.         fprintf(stderr, "Cannot chmod %s", buf);
  208.         perror(" ");
  209.         return(-1);
  210.         }
  211.  
  212.     sunix = open(buf, O_RDWR);
  213.     if(sunix < 0){
  214.         fprintf(stderr, "Cannot open %s", buf);
  215.         perror(" ");
  216.         close(munix);
  217.         return(-1);
  218.         }
  219.     setpgrp();
  220. /*
  221.     if(fcntl(munix, F_SETFL, FNDELAY) < 0)
  222.     {
  223.         fprintf(stderr, "Cannot set nodelay on the nameserver\n");
  224.         exit(1);
  225.  
  226.     }
  227. */
  228.  
  229.     return(munix);
  230. }
  231.  
  232. ConnectNewClients(lfd, MoreConnections)
  233. int    lfd;
  234. char    * MoreConnections;
  235. {
  236.     
  237.     int fd;
  238.     int read_in;
  239.     char length;
  240.     char buf[64];
  241.  
  242.     *MoreConnections = 0;
  243.  
  244.     if( (read_in = read(lfd, &length, 1)) <= 0 ){
  245.         if( !read_in )  /* client closed fd */
  246.             perror("0 bytes read");
  247.         else    perror("Error in reading the local connection msg length");
  248.         return(-1);
  249.         }
  250.  
  251.  
  252.     if( (read_in = read(lfd, buf, length)) <= 0 ){
  253.         if( !read_in )  /* client closed fd */
  254.             perror("0 bytes read");
  255.         else    perror("Error in reading the local connection slave name");
  256.         return(-1);
  257.         }
  258.  
  259.     buf[ length ] = '\0';
  260.  
  261.     if( (fd = open(buf,O_RDWR|O_SYNC)) < 0 ){
  262.         strcat(buf," open fail, clientfd");
  263.         perror(buf);
  264.         return(-1);
  265.         }
  266.  
  267.     write(fd,SUCCESS,1);
  268.     InitClientBuffers(fd);    
  269.  
  270.     return(fd);
  271. }
  272.  
  273. CreateWellKnownSockets()
  274. {
  275.     CLEARBITS(AllSockets);
  276.     CLEARBITS(AllClients);
  277.     CLEARBITS(LastSelectMask);
  278.  
  279.     lastfdesc = ulimit(4, (long)0) - 1;  /* Returns total # of FDs available */
  280.     if (lastfdesc > MAXSOCKS)
  281.     {
  282.     lastfdesc = MAXSOCKS;
  283.     }
  284.  
  285.     WellKnownConnections = 0;
  286.     if ((ListenFd = OpenTheListener()) < 0)
  287.     {
  288.            if(ListenFd == -1)
  289.             return(-1);
  290.     }
  291.     else    WellKnownConnections |= (1<<ListenFd);
  292.  
  293.     if (WellKnownConnections == 0) {
  294.         fprintf(stderr, "No Listeners, nothing to do\n");
  295.         return(-1);
  296.     }
  297.     
  298.     AllSockets[0] = WellKnownConnections;
  299.     return(1);
  300. }
  301.  
  302. EstablishNewConnections()
  303. {
  304.     long readyconnections;     /* mask of listeners that are ready */
  305.     long newconn;                  /* fd of new client */
  306.     char *reason;
  307.     char MoreConnections;
  308.  
  309.     if (readyconnections = (LastSelectMask[0] & WellKnownConnections)) 
  310.     {
  311.       MoreConnections = 0;
  312.       do
  313.       {
  314.     newconn = ConnectNewClients(ListenFd,&MoreConnections);
  315.     if (newconn >= 0)
  316.     {
  317.         fcntl (newconn, F_SETFL, O_NDELAY);
  318.         BITSET(AllClients, newconn);
  319.         BITSET(AllSockets, newconn);
  320.     }
  321.       }
  322.       while(MoreConnections);
  323.     }
  324. }
  325.  
  326. void
  327. CloseDownFileDescriptor(connection)
  328.     long connection;
  329. {
  330.     close(connection);
  331.     BITCLEAR(AllSockets, connection);
  332.     BITCLEAR(AllClients, connection);
  333. }
  334.  
  335.  
  336. CheckConnections()
  337. {
  338.     long        rmask[mskcnt]; 
  339.     long        emask[mskcnt]; 
  340.     register int    curclient;
  341.     int            i;
  342.  
  343.     COPYBITS(AllClients, rmask);
  344.     COPYBITS(AllClients, emask);
  345.     i = select (MAXSOCKS, rmask, (int *) NULL, emask, NULL);
  346.     if (i <= 0)
  347.     return;
  348.  
  349.     for (i=0; i<mskcnt; i++)
  350.     {
  351.         while (emask[i])
  352.         {
  353.         curclient = NextSetBit (emask[i]) - 1 + (i << 5);
  354. #ifdef DEBUG
  355.         printf("CheckConnection closing %d\n", curclient);
  356. #endif
  357.         InitClientBuffers(curclient);
  358.             CloseDownFileDescriptor(curclient);
  359.         BITCLEAR(emask, curclient);
  360.     }
  361.     }    
  362. }
  363.  
  364. /* Find the first set bit
  365.  * i.e. least signifigant 1 bit:
  366.  * 0 => 0
  367.  * 1 => 1
  368.  * 2 => 2
  369.  * 3 => 1
  370.  * 4 => 3
  371.  */
  372. int NextSetBit(mask)
  373. unsigned int    mask;
  374. {
  375.     register i;
  376.  
  377.     if ( ! mask ) return 0;
  378.     i = 1;
  379.     while (! (mask & 1)) {
  380.         i++;
  381.         mask >>= 1;
  382.     }
  383.     return i;
  384. }
  385.  
  386. initBuffers()
  387. {
  388.     int    i;
  389.  
  390.     for(i=0; i< MAXSOCKS; i++)
  391.     {
  392.         InputBuffer[i].flags    = 0;
  393.         InputBuffer[i].buflen    = 0;
  394.         InputBuffer[i].bufptr    = 0;
  395.         InputBuffer[i].inputbuf    = NULL;
  396.     }
  397. }
  398.  
  399. char    path[128];
  400.  
  401. SendNull(fd)
  402. int    fd;
  403. {
  404.  
  405.     char    *ptr, buf[32];
  406.  
  407.     ptr = buf;
  408.     *(int *) ptr = 0;
  409.     ptr += sizeof(int);
  410.     *(int *) ptr = 0;
  411.     write(fd, inbuf, 2*sizeof(int));
  412. }
  413.  
  414. ServiceClient(fd)
  415. int    fd;
  416. {
  417.     register IOBUFFER *iop = &InputBuffer[fd];
  418.     int    n, m;
  419.     char    *ptr, *net;
  420.     int    fds[2];
  421.     int    pid;
  422.  
  423.     if(iop->inputbuf ==  NULL)
  424.     {
  425.         iop->inputbuf = (char *) xalloc(BUFSIZE);
  426.         iop->buflen    = BUFSIZE;
  427.     }
  428.     if(iop->bufptr < HEADERSIZE)
  429.     {
  430.        errno = 0;
  431.        n = read(fd, &iop->inputbuf[iop->bufptr], iop->buflen - iop->bufptr);
  432.        if(n <= 0)
  433.        {
  434.         if(errno == EAGAIN)
  435.             return(0);
  436.         else if(errno == EINTR){
  437.             InitClientBuffers(fd);
  438.             SendNull(fd);
  439.         }
  440.         else {
  441. #ifdef DEBUG
  442.                           fprintf(stderr, "XDEAMON: read error; errno %d\n",
  443.                                                  errno);
  444. #endif
  445.             CloseDownFileDescriptor(fd);
  446.         }
  447.         return(-1);
  448.        }
  449.        iop->bufptr += n;
  450.        if(iop->bufptr < HEADERSIZE)
  451.                return(0);
  452.        iop->msglen = *(int *) iop->inputbuf;
  453.     }
  454.  
  455.     if(iop->buflen < iop->msglen)
  456.     {
  457.        iop->inputbuf = (char *) xrealloc(iop->inputbuf, iop->msglen);
  458.        iop->buflen    = iop->msglen;
  459.     }
  460.  
  461.     if(iop->bufptr < iop->msglen)
  462.     {
  463.            errno = 0;
  464.        n = read(fd, &iop->inputbuf[iop->bufptr], iop->msglen - iop->bufptr);
  465.        if(n <= 0)
  466.        {
  467.                 if(errno == EAGAIN)
  468.                         return(0);
  469.         else if(errno == EINTR){
  470.                         InitClientBuffers(fd);
  471.                         SendNull(fd);
  472.         }
  473.                 else {
  474. #ifdef DEBUG
  475.                           fprintf(stderr, "XDEAMON: read error; errno %d\n",
  476.                                                  errno);
  477. #endif
  478.                         CloseDownFileDescriptor(fd);
  479.         }
  480.         return(-1);
  481.            }
  482.            iop->bufptr += n;
  483.        if(iop->bufptr < iop->msglen)
  484.                         return(0);
  485.     }
  486.  
  487.     ptr = &iop->inputbuf[4*sizeof(int)];
  488.     n = *(int *) ptr;
  489.     ptr += sizeof(int);
  490.     net  = ptr;
  491.     if(ptr[n] != '\0')
  492.     {
  493.         fprintf(stderr, "XDEAMON: net name error\n");
  494.                 SendNull(fd);
  495.     }    
  496.     else if(pipe(fds) < 0){
  497.         fprintf(stderr, "XDEAMON: pipe failed error\n");
  498.                 SendNull(fd);
  499.         }
  500.     else if((pid = fork()) == 0)
  501.     {
  502.         close(0); dup(fds[0]);
  503.         close(1); dup(fd);
  504.         close(fds[0]);
  505.         close(fds[1]);
  506.         sprintf(path, "/usr/X/lib/net/%s/nameserver", net);
  507.         
  508.         execl(path, "nameserver", 0);
  509.         fprintf(stderr, "Cannot exec %s\n", path);
  510.         exit(1);
  511.     }
  512.     else  {
  513.         close(fds[0]);
  514.         if(pid < 0)
  515.         {
  516.             fprintf(stderr, "XDEAMON: fork failed error\n");
  517.                     SendNull(fd);
  518.             close(fds[1]);
  519.         }
  520.         else { 
  521. #ifdef DEBUG
  522.              write(2, iop->inputbuf, iop->msglen);
  523. #endif
  524.              if(write(fds[1], iop->inputbuf, iop->msglen) != iop->msglen){
  525.                 SendNull(fd);
  526.                 fprintf(stderr,"XDEAMON: write failed error\n");
  527.                 }
  528.             close(fds[1]);
  529.         }
  530.     }
  531.     InitClientBuffers(fd);
  532.     return(1);
  533. }
  534.  
  535.  
  536. InitClientBuffers(fd)
  537. int    fd;
  538. {
  539.            InputBuffer[fd].flags    = 0;
  540.     InputBuffer[fd].bufptr    = 0;
  541.     InputBuffer[fd].msglen    = 0;
  542. }
  543.  
  544. char *
  545. xalloc(n)
  546. int    n;
  547. {
  548.     char    *ptr;
  549.  
  550.     if((ptr = (char *) malloc(n)) == NULL)
  551.     {
  552.         fprintf(stderr, "malloc failed\n");
  553.         exit(1);
  554.     }
  555.     return(ptr);
  556. }
  557.  
  558.  
  559. char *
  560. xrealloc(buf, n)
  561. char    *buf;
  562. int    n;
  563. {
  564.      char    *ptr;
  565.  
  566.         if((ptr = (char *) realloc(buf, n)) == NULL)
  567.     {
  568.              fprintf(stderr, "realloc failed\n");
  569.         exit(1);
  570.     }
  571.         return(ptr);
  572. }
  573.  
  574. char    *program;
  575. main(argc, argv)
  576. int    argc;
  577. char    *argv[];
  578. {
  579.     int    i;
  580.     program = argv[0];
  581.     
  582.     i = CreateWellKnownSockets();
  583. /*
  584.     if(argc == 2 && strcmp(argv[1], "-") == 0){
  585.         sig = SIGALRM;
  586.         }
  587.     if(sig > 0)
  588.         kill(getppid(), sig);
  589. */
  590.  
  591.     if(i < 0)
  592.         exit(1);
  593.  
  594.     signal(SIGCLD, SIG_IGN);
  595.  
  596.     for(;;)
  597.         WaitForInput();
  598. }
  599.  
  600.