]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unix/ux_x11.c
Remove the TODO comment at the top of uxputty.c; I'm now not aware
[PuTTY.git] / unix / ux_x11.c
1 /*
2  * ux_x11.c: fetch local auth data for X forwarding.
3  */
4
5 #include <ctype.h>
6 #include <unistd.h>
7 #include "putty.h"
8
9 void platform_get_x11_auth(char *display, int *protocol,
10                            unsigned char *data, int *datalen)
11 {
12     FILE *fp;
13     char *command;
14     int maxsize = *datalen;
15     char *localbuf;
16     int proto = -1;
17
18     /*
19      * Normally we should run `xauth list DISPLAYNAME'. However,
20      * there's an oddity when the display is local: the display
21      * `localhost:0' (or `:0') should become just `:0'.
22      */
23     if (!strncmp(display, "localhost:", 10))
24         command = dupprintf("xauth list %s 2>/dev/null", display+9);
25     else
26         command = dupprintf("xauth list %s 2>/dev/null", display);
27     fp = popen(command, "r");
28     sfree(command);
29
30     if (!fp)
31         return;                        /* assume no auth */
32
33     localbuf = snewn(maxsize, char);
34
35     while (1) {
36         /*
37          * Read a line from stdin, and attempt to parse it into a
38          * display name (ignored), auth protocol, and auth string.
39          */
40         int c, i, hexdigit;
41         char protoname[64];
42
43         /* Skip the display name. */
44         while (c = getc(fp), c != EOF && c != '\n' && !isspace(c));
45         if (c == EOF) break;
46         if (c == '\n') continue;
47
48         /* Skip white space. */
49         while (c != EOF && c != '\n' && isspace(c))
50             c = getc(fp);
51         if (c == EOF) break;
52         if (c == '\n') continue;
53
54         /* Read the auth protocol name, and see if it matches any we
55          * know about. */
56         i = 0;
57         while (c != EOF && c != '\n' && !isspace(c)) {
58             if (i < lenof(protoname)-1) protoname[i++] = c;
59             c = getc(fp);
60         }
61         protoname[i] = '\0';
62
63         for (i = X11_NO_AUTH; ++i < X11_NAUTHS ;) {
64             if (!strcmp(protoname, x11_authnames[i]))
65                 break;
66         }
67         if (i >= X11_NAUTHS || i <= proto) {
68             /* Unrecognised protocol name, or a worse one than we already have.
69              * Skip this line. */
70             while (c != EOF && c != '\n')
71                 c = getc(fp);
72             if (c == EOF) break;
73         }
74         proto = i;
75
76         /* Skip white space. */
77         while (c != EOF && c != '\n' && isspace(c))
78             c = getc(fp);
79         if (c == EOF) break;
80         if (c == '\n') continue;
81
82         /*
83          * Now grab pairs of hex digits and shove them into `data'.
84          */
85         i = 0;
86         hexdigit = -1;
87         while (c != EOF && c != '\n') {
88             int hexval = -1;
89             if (c >= 'A' && c <= 'F')
90                 hexval = c + 10 - 'A';
91             if (c >= 'a' && c <= 'f')
92                 hexval = c + 10 - 'a';
93             if (c >= '0' && c <= '9')
94                 hexval = c - '0';
95             if (hexval >= 0) {
96                 if (hexdigit >= 0) {
97                     hexdigit = (hexdigit << 4) + hexval;
98                     if (i < maxsize)
99                         localbuf[i++] = hexdigit;
100                     hexdigit = -1;
101                 } else
102                     hexdigit = hexval;
103             }
104             c = getc(fp);
105         }
106
107         *datalen = i;
108         *protocol = proto;
109         memcpy(data, localbuf, i);
110
111         /* Nonetheless, continue looping round; we might find a better one. */
112     }
113     pclose(fp);
114     sfree(localbuf);
115 }