home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xdm / choose.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-26  |  9.6 KB  |  411 lines

  1. /*
  2.  * $XConsortium: choose.c,v 1.9 91/08/25 10:48:43 keith Exp $
  3.  *
  4.  * Copyright 1990 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Keith Packard, MIT X Consortium
  24.  */
  25.  
  26. /*
  27.  * choose.c
  28.  *
  29.  * xdm interface to chooser program
  30.  */
  31.  
  32. # include   "dm.h"
  33.  
  34. #ifdef XDMCP
  35.  
  36. # include    <X11/X.h>
  37. # include    <sys/types.h>
  38. # include    <sys/socket.h>
  39. # include    <netinet/in.h>
  40. # include    <sys/un.h>
  41. # include    <ctype.h>
  42.  
  43. static
  44. FormatBytes (data, length, buf, buflen)
  45.     unsigned char *data;
  46.     int        length;
  47.     char    *buf;
  48.     int        buflen;
  49. {
  50.     int        i;
  51.     static char        HexChars[] = "0123456789abcdef";
  52.  
  53.     if (buflen < length * 2 + 1)
  54.     return 0;
  55.     for (i = 0; i < length; i++)
  56.     {
  57.     *buf++ = HexChars[(data[i] >> 4) & 0xf];
  58.     *buf++ = HexChars[(data[i]) & 0xf];
  59.     }
  60.     *buf++ = '\0';
  61.     return 1;
  62. }
  63.  
  64. static
  65. FormatARRAY8 (a, buf, buflen)
  66.     ARRAY8Ptr    a;
  67.     char    *buf;
  68.     int        buflen;
  69. {
  70.     return FormatBytes (a->data, a->length, buf, buflen);
  71. }
  72.  
  73. typedef struct _IndirectUsers {
  74.     struct _IndirectUsers   *next;
  75.     ARRAY8    client;
  76.     CARD16    connectionType;
  77. } IndirectUsersRec, *IndirectUsersPtr;
  78.  
  79. static IndirectUsersPtr    indirectUsers;
  80.  
  81. RememberIndirectClient (clientAddress, connectionType)
  82.     ARRAY8Ptr    clientAddress;
  83.     CARD16    connectionType;
  84. {
  85.     IndirectUsersPtr    i;
  86.  
  87.     for (i = indirectUsers; i; i = i->next)
  88.     if (XdmcpARRAY8Equal (clientAddress, &i->client) &&
  89.         connectionType == i->connectionType)
  90.         return 1;
  91.     i = (IndirectUsersPtr) malloc (sizeof (IndirectUsersRec));
  92.     if (!XdmcpCopyARRAY8 (clientAddress, &i->client))
  93.     {
  94.     free ((char *) i);
  95.     return 0;
  96.     }
  97.     i->connectionType = connectionType;
  98.     i->next = indirectUsers;
  99.     indirectUsers = i;
  100.     return 1;
  101. }
  102.  
  103. ForgetIndirectClient (clientAddress, connectionType)
  104.     ARRAY8Ptr    clientAddress;
  105.     CARD16    connectionType;
  106. {
  107.     IndirectUsersPtr    i, prev;
  108.  
  109.     prev = 0;
  110.     for (i = indirectUsers; i; i = i->next)
  111.     {
  112.     if (XdmcpARRAY8Equal (clientAddress, &i->client) &&
  113.         connectionType == i->connectionType)
  114.     {
  115.         if (prev)
  116.         prev->next = i->next;
  117.         else
  118.         indirectUsers = i->next;
  119.         XdmcpDisposeARRAY8 (&i->client);
  120.         free ((char *) i);
  121.         break;
  122.     }
  123.     prev = i;
  124.     }
  125. }
  126.  
  127. IsIndirectClient (clientAddress, connectionType)
  128.     ARRAY8Ptr    clientAddress;
  129.     CARD16    connectionType;
  130. {
  131.     IndirectUsersPtr    i;
  132.  
  133.     for (i = indirectUsers; i; i = i->next)
  134.     if (XdmcpARRAY8Equal (clientAddress, &i->client) &&
  135.         connectionType == i->connectionType)
  136.         return 1;
  137.     return 0;
  138. }
  139.  
  140. extern char *NetaddrPort();
  141.  
  142. static
  143. FormatChooserArgument (buf, len)
  144.     char    *buf;
  145.     int        len;
  146. {
  147.     unsigned char   addr_buf[1024];
  148.     int            addr_len = sizeof (addr_buf);
  149.     unsigned char   result_buf[1024];
  150.     int            result_len = 0;
  151.     int            netfamily;
  152.  
  153.     if (GetChooserAddr (addr_buf, &addr_len) == -1)
  154.     {
  155.     LogError ("Cannot get return address for chooser socket\n");
  156.     Debug ("Cannot get chooser socket address\n");
  157.     return 0;
  158.     }
  159.     netfamily = NetaddrFamily((XdmcpNetaddr)addr_buf);
  160.     switch (netfamily) {
  161.     case AF_INET:
  162.     {
  163.         char *port;
  164.         int portlen;
  165.         ARRAY8Ptr localAddress, getLocalAddress ();
  166.  
  167.         port = NetaddrPort((XdmcpNetaddr)addr_buf, &portlen);
  168.         result_buf[0] = netfamily >> 8;
  169.         result_buf[1] = netfamily & 0xFF;
  170.         result_buf[2] = port[0];
  171.         result_buf[3] = port[1];
  172.         localAddress = getLocalAddress ();
  173.         bcopy ((char *)localAddress->data, (char *)result_buf+4, 4);
  174.         result_len = 8;
  175.     }
  176.     break;
  177. #ifdef AF_DECnet
  178.     case AF_DECnet:
  179.     break;
  180. #endif
  181.     default:
  182.     Debug ("Chooser family %d isn't known\n", netfamily);
  183.     return 0;
  184.     }
  185.  
  186.     return FormatBytes (result_buf, result_len, buf, len);
  187. }
  188.  
  189. typedef struct _Choices {
  190.     struct _Choices *next;
  191.     ARRAY8        client;
  192.     CARD16        connectionType;
  193.     ARRAY8        choice;
  194.     long        time;
  195. } ChoiceRec, *ChoicePtr;
  196.  
  197. static ChoicePtr   choices;
  198.  
  199. ARRAY8Ptr
  200. IndirectChoice (clientAddress, connectionType)
  201.     ARRAY8Ptr    clientAddress;
  202.     CARD16    connectionType;
  203. {
  204.     ChoicePtr    c, next, prev;
  205.     long    now;
  206.  
  207.     now = time (0);
  208.     prev = 0;
  209.     for (c = choices; c; c = next)
  210.     {
  211.     next = c->next;
  212.     if (now - c->time > 15)
  213.     {
  214.         Debug ("Timeout choice\n");
  215.         if (prev)
  216.         prev->next = next;
  217.         else
  218.         choices = next;
  219.         XdmcpDisposeARRAY8 (&c->client);
  220.         XdmcpDisposeARRAY8 (&c->choice);
  221.         free ((char *) c);
  222.     }
  223.     else
  224.     {
  225.         if (XdmcpARRAY8Equal (clientAddress, &c->client) &&
  226.             connectionType == c->connectionType)
  227.             return &c->choice;
  228.         prev = c;
  229.     }
  230.     }
  231.     return 0;
  232. }
  233.  
  234. static int
  235. RegisterIndirectChoice (clientAddress, connectionType, choice)
  236.     ARRAY8Ptr    clientAddress, choice;
  237.     CARD16 connectionType;
  238. {
  239.     ChoicePtr    c;
  240.     int        insert;
  241.  
  242.     Debug ("Got indirect choice back\n");
  243.     for (c = choices; c; c = c->next)
  244.     if (XdmcpARRAY8Equal (clientAddress, &c->client) &&
  245.         connectionType == c->connectionType)
  246.         break;
  247.     insert = 0;
  248.     if (!c)
  249.     {
  250.     c = (ChoicePtr) malloc (sizeof (ChoiceRec));
  251.     insert = 1;
  252.     if (!c)
  253.         return 0;
  254.     c->connectionType = connectionType;
  255.         if (!XdmcpCopyARRAY8 (clientAddress, &c->client))
  256.         {
  257.         free ((char *) c);
  258.         return 0;
  259.         }
  260.     }
  261.     else
  262.     {
  263.     XdmcpDisposeARRAY8 (&c->choice);
  264.     }
  265.     if (!XdmcpCopyARRAY8 (choice, &c->choice))
  266.     {
  267.     XdmcpDisposeARRAY8 (&c->client);
  268.     free ((char *) c);
  269.     return 0;
  270.     }
  271.     if (insert)
  272.     {
  273.     c->next = choices;
  274.     choices = c;
  275.     }
  276.     c->time = time (0);
  277.     return 1;
  278. }
  279.  
  280. #ifdef notdef
  281. static
  282. RemoveIndirectChoice (clientAddress, connectionType)
  283.     ARRAY8Ptr    clientAddress;
  284.     CARD16    connectionType;
  285. {
  286.     ChoicePtr    c, prev;
  287.  
  288.     prev = 0;
  289.     for (c = choices; c; c = c->next)
  290.     {
  291.     if (XdmcpARRAY8Equal (clientAddress, &c->client) &&
  292.         connectionType == c->connectionType)
  293.     {
  294.         if (prev)
  295.         prev->next = c->next;
  296.         else
  297.         choices = c->next;
  298.         XdmcpDisposeARRAY8 (&c->client);
  299.         XdmcpDisposeARRAY8 (&c->choice);
  300.         free ((char *) c);
  301.         return;
  302.     }
  303.     prev = c;
  304.     }
  305. }
  306. #endif
  307.  
  308. /*ARGSUSED*/
  309. static
  310. AddChooserHost (connectionType, addr, closure)
  311.     CARD16    connectionType;
  312.     ARRAY8Ptr    addr;
  313.     char    *closure;
  314. {
  315.     char    ***argp, **parseArgs();
  316.     char    hostbuf[1024];
  317.  
  318.     argp = (char ***) closure;
  319.     if (addr->length == strlen ("BROADCAST") &&
  320.     !strncmp ((char *)addr->data, "BROADCAST", addr->length))
  321.     {
  322.     *argp = parseArgs (*argp, "BROADCAST");
  323.     }
  324.     else if (FormatARRAY8 (addr, hostbuf, sizeof (hostbuf)))
  325.     {
  326.     *argp = parseArgs (*argp, hostbuf);
  327.     }
  328. }
  329.  
  330. ProcessChooserSocket (fd)
  331.     int fd;
  332. {
  333.     int client_fd;
  334.     char    buf[1024];
  335.     int        len;
  336.     XdmcpBuffer    buffer;
  337.     ARRAY8    clientAddress;
  338.     CARD16    connectionType;
  339.     ARRAY8    choice;
  340.  
  341.     Debug ("Process chooser socket\n");
  342.     len = sizeof (buf);
  343.     client_fd = accept (fd, buf, &len);
  344.     if (client_fd == -1)
  345.     {
  346.     LogError ("Cannot accept chooser connection\n");
  347.     return;
  348.     }
  349.     Debug ("Accepted %d\n", client_fd);
  350.     
  351.     len = read (client_fd, buf, sizeof (buf));
  352.     Debug ("Read returns %d\n", len);
  353.     if (len > 0)
  354.     {
  355.         buffer.data = (BYTE *) buf;
  356.         buffer.size = sizeof (buf);
  357.         buffer.count = len;
  358.         buffer.pointer = 0;
  359.     clientAddress.data = 0;
  360.     clientAddress.length = 0;
  361.     choice.data = 0;
  362.     choice.length = 0;
  363.     if (XdmcpReadARRAY8 (&buffer, &clientAddress) &&
  364.         XdmcpReadCARD16 (&buffer, &connectionType) &&
  365.         XdmcpReadARRAY8 (&buffer, &choice))
  366.     {
  367.         Debug ("Read from chooser succesfully\n");
  368.         RegisterIndirectChoice (&clientAddress, connectionType, &choice);
  369.     }
  370.     XdmcpDisposeARRAY8 (&clientAddress);
  371.     XdmcpDisposeARRAY8 (&choice);
  372.     }
  373.     else
  374.     {
  375.     LogError ("Invalid choice response length %d\n", len);
  376.     }
  377.  
  378.     close (client_fd);
  379. }
  380.  
  381. RunChooser (d)
  382.     struct display  *d;
  383. {
  384.     char    **args, **parseArgs(), **systemEnv();
  385.     char    buf[1024];
  386.     char    **env;
  387.  
  388.     Debug ("RunChooser %s\n", d->name);
  389.     SetTitle (d->name, "chooser", (char *) 0);
  390.     LoadXloginResources (d);
  391.     args = parseArgs ((char **) 0, d->chooser);
  392.     strcpy (buf, "-xdmaddress ");
  393.     if (FormatChooserArgument (buf + strlen (buf), sizeof (buf) - strlen (buf)))
  394.     args = parseArgs (args, buf);
  395.     strcpy (buf, "-clientaddress ");
  396.     if (FormatARRAY8 (&d->clientAddr, buf + strlen (buf), sizeof (buf) - strlen (buf)))
  397.     args = parseArgs (args, buf);
  398.     sprintf (buf, "-connectionType %d", d->connectionType);
  399.     args = parseArgs (args, buf);
  400.     ForEachChooserHost (&d->clientAddr, d->connectionType, AddChooserHost,
  401.             (char *) &args);
  402.     env = systemEnv (d, (char *) 0, (char *) 0);
  403.     Debug ("Running %s\n", args[0]);
  404.     execute (args, env);
  405.     Debug ("Couldn't run %s\n", args[0]);
  406.     LogError ("Cannot execute %s\n", args[0]);
  407.     exit (REMANAGE_DISPLAY);
  408. }
  409.  
  410. #endif /* XDMCP */
  411.