parsedpy.c revision 765b7306
1/*
2 *
3 * parse_displayname - utility routine for splitting up display name strings
4 *
5 *
6Copyright 1989, 1998  The Open Group
7
8Permission to use, copy, modify, distribute, and sell this software and its
9documentation for any purpose is hereby granted without fee, provided that
10the above copyright notice appear in all copies and that both that
11copyright notice and this permission notice appear in supporting
12documentation.
13
14The above copyright notice and this permission notice shall be included in
15all copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of The Open Group shall not be
25used in advertising or otherwise to promote the sale, use or other dealings
26in this Software without prior written authorization from The Open Group.
27 * *
28 * Author:  Jim Fulton, MIT X Consortium
29 */
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include <stdio.h>			/* for NULL */
36#include <ctype.h>			/* for isascii() and isdigit() */
37#include <X11/Xos.h>			/* for strchr() and string routines */
38#include <X11/Xlib.h>			/* for Family constants */
39#ifdef hpux
40#include <sys/utsname.h>		/* for struct utsname */
41#endif
42#include <X11/Xauth.h>			/* for FamilyLocal */
43#include <X11/Xmu/SysUtil.h>
44
45#include <sys/stat.h>
46#include <limits.h>
47
48#if defined(UNIXCONN) || defined(LOCALCONN)
49#define UNIX_CONNECTION "unix"
50#define UNIX_CONNECTION_LENGTH 4
51#endif
52
53#include <stdlib.h>
54#include "xauth.h"
55
56/*
57 * private utility routines
58 */
59
60char *
61copystring (const char *src, int len)
62{
63    char *cp;
64
65    if (!src && len != 0) return NULL;
66    cp = malloc (len + 1);
67    if (cp) {
68	if (src) memcpy (cp, src, len);
69	cp[len] = '\0';
70    }
71    return cp;
72}
73
74
75char *
76get_local_hostname (char *buf, int maxlen)
77{
78    buf[0] = '\0';
79    (void) XmuGetHostname (buf, maxlen);
80    return (buf[0] ? buf : NULL);
81}
82
83#ifndef UNIXCONN
84static char *
85copyhostname (void)
86{
87    char buf[256];
88
89    return (get_local_hostname (buf, sizeof buf) ?
90	    copystring (buf, strlen (buf)) : NULL);
91}
92#endif
93
94/*
95 * parse_displayname - display a display string up into its component parts
96 */
97Bool
98parse_displayname (const char *displayname,
99		   int *familyp,	/* return */
100		   char **hostp,	/* return */
101		   int *dpynump,	/* return */
102		   int *scrnump,	/* return */
103		   char **restp)	/* return */
104{
105    char *ptr;				/* work variables */
106    int len;				/* work variable */
107    int family = -1;			/* value to be returned */
108    char *host = NULL;			/* must free if set and error return */
109    int dpynum = -1;			/* value to be returned */
110    int scrnum = 0;			/* value to be returned */
111    char *rest = NULL;			/* must free if set and error return */
112    Bool dnet = False;			/* if true then using DECnet */
113
114					/* check the name */
115    if (!displayname || !displayname[0]) return False;
116
117					/* must have at least :number */
118    ptr = strrchr(displayname, ':');
119    if (!ptr || !ptr[1]) return False;
120    if ((ptr != displayname) && (*(ptr - 1) == ':')) {
121	ptr--;
122	dnet = True;
123    }
124
125
126    /*
127     * get the host string; if none is given, use the most effiecient path
128     */
129
130    len = (ptr - displayname);	/* length of host name */
131    if (len == 0) {			/* choose most efficient path */
132#if defined(UNIXCONN) || defined(LOCALCONN)
133	host = copystring (UNIX_CONNECTION, UNIX_CONNECTION_LENGTH);
134	family = FamilyLocal;
135#else
136	if (dnet) {
137	    host = copystring ("0", 1);
138	    family = FamilyDECnet;
139	} else {
140	    host = copyhostname ();
141	    family = FamilyInternet;
142	}
143#endif
144    } else if (!dnet && (*displayname == '[') && (*(ptr - 1) == ']')) {
145	/* Allow RFC2732-like [<IPv6NumericAddress>]:display syntax */
146	family = FamilyInternet6;
147	host = copystring (displayname + 1, len - 2);
148    } else {
149	host = copystring (displayname, len);
150	if (dnet) {
151	    family = dnet;
152	} else {
153#if defined(UNIXCONN) || defined(LOCALCONN)
154	    if (host && strcmp (host, UNIX_CONNECTION) == 0)
155	      family = FamilyLocal;
156	    else
157#endif
158	      family = FamilyInternet;
159	}
160    }
161
162    if (!host) return False;
163
164    {
165        /*
166         * If using launchd socket, remove the screen number from the end
167         * of $DISPLAY and check if it is a path to a socket.
168         */
169        char path[PATH_MAX];
170        struct stat sbuf;
171
172#ifdef HAVE_STRLCPY
173        strlcpy(path, displayname, sizeof(path));
174#else
175        strncpy(path, displayname, sizeof(path) - 1);
176        path[sizeof(path) - 1] = '\0';
177#endif
178        if (0 == stat(path, &sbuf) && S_ISSOCK(sbuf.st_mode)) {
179            family = FamilyLocal;
180        } else {
181            char *dot = strrchr(path, '.');
182            if (dot) {
183                *dot = '\0';
184                /* screen = atoi(dot + 1); */
185                if (0 == stat(path, &sbuf) && S_ISSOCK(sbuf.st_mode)) {
186                    family = FamilyLocal;
187                }
188            }
189        }
190    }
191
192    /*
193     * get the display number; we know that there is something after the
194     * colon (or colons) from above.  note that host is now set and must
195     * be freed if there is an error.
196     */
197
198    if (dnet) ptr++;			/* skip the extra DECnet colon */
199    ptr++;				/* move to start of display num */
200    {
201	register char *cp;
202
203	for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
204	len = (cp - ptr);
205					/* check present and valid follow */
206	if (len == 0 || (*cp && *cp != '.')) {
207	    free (host);
208	    return False;
209	}
210
211	dpynum = atoi (ptr);		/* it will handle num. as well */
212	ptr = cp;
213    }
214
215    /*
216     * now get screen number if given; ptr may point to nul at this point
217     */
218    if (ptr[0] == '.') {
219	register char *cp;
220
221	ptr++;
222	for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
223	len = (cp - ptr);
224	if (len == 0 || (*cp && *cp != '.')) {	/* all prop name */
225	    free (host);
226	    return False;
227	}
228
229	scrnum = atoi (ptr);		/* it will handle num. as well */
230	ptr = cp;
231    }
232
233    /*
234     * and finally, get any additional stuff that might be following the
235     * the screen number; ptr must point to a period if there is anything
236     */
237
238    if (ptr[0] == '.') {
239	ptr++;
240	len = strlen (ptr);
241	if (len > 0) {
242	    rest = copystring (ptr, len);
243	    if (!rest) {
244		free (host);
245		return False;
246	    }
247	}
248    }
249
250    /*
251     * and we are done!
252     */
253
254    *familyp = family;
255    *hostp = host;
256    *dpynump = dpynum;
257    *scrnump = scrnum;
258    *restp = rest;
259    return True;
260}
261
262
263