parsedpy.c revision 273c00b8
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#include <X11/Xauth.h> /* for FamilyLocal */ 40#include <X11/Xmu/SysUtil.h> 41 42#include <sys/stat.h> 43#include <limits.h> 44 45#if defined(UNIXCONN) || defined(LOCALCONN) 46#define UNIX_CONNECTION "unix" 47#define UNIX_CONNECTION_LENGTH 4 48#endif 49 50#include <stdlib.h> 51#include "xauth.h" 52 53/* 54 * private utility routines 55 */ 56 57char * 58copystring (const char *src, int len) 59{ 60 char *cp; 61 62 if (!src && len != 0) return NULL; 63 cp = malloc (len + 1); 64 if (cp) { 65 if (src) memcpy (cp, src, len); 66 cp[len] = '\0'; 67 } 68 return cp; 69} 70 71 72char * 73get_local_hostname (char *buf, int maxlen) 74{ 75 buf[0] = '\0'; 76 (void) XmuGetHostname (buf, maxlen); 77 return (buf[0] ? buf : NULL); 78} 79 80#ifndef UNIXCONN 81static char * 82copyhostname (void) 83{ 84 char buf[256]; 85 86 return (get_local_hostname (buf, sizeof buf) ? 87 copystring (buf, strlen (buf)) : NULL); 88} 89#endif 90 91/* 92 * parse_displayname - display a display string up into its component parts 93 */ 94Bool 95parse_displayname (const char *displayname, 96 int *familyp, /* return */ 97 char **hostp, /* return */ 98 int *dpynump, /* return */ 99 int *scrnump, /* return */ 100 char **restp) /* return */ 101{ 102 char *ptr; /* work variables */ 103 int len; /* work variable */ 104 int family = -1; /* value to be returned */ 105 char *host = NULL; /* must free if set and error return */ 106 int dpynum = -1; /* value to be returned */ 107 int scrnum = 0; /* value to be returned */ 108 char *rest = NULL; /* must free if set and error return */ 109 Bool dnet = False; /* if true then using DECnet */ 110 111 /* check the name */ 112 if (!displayname || !displayname[0]) return False; 113 114 /* must have at least :number */ 115 ptr = strrchr(displayname, ':'); 116 if (!ptr || !ptr[1]) return False; 117 if ((ptr != displayname) && (*(ptr - 1) == ':')) { 118 ptr--; 119 dnet = True; 120 } 121 122 123 /* 124 * get the host string; if none is given, use the most effiecient path 125 */ 126 127 len = (ptr - displayname); /* length of host name */ 128 if (len == 0) { /* choose most efficient path */ 129#if defined(UNIXCONN) || defined(LOCALCONN) 130 host = copystring (UNIX_CONNECTION, UNIX_CONNECTION_LENGTH); 131 family = FamilyLocal; 132#else 133 if (dnet) { 134 host = copystring ("0", 1); 135 family = FamilyDECnet; 136 } else { 137 host = copyhostname (); 138 family = FamilyInternet; 139 } 140#endif 141 } else if (!dnet && (*displayname == '[') && (*(ptr - 1) == ']')) { 142 /* Allow RFC2732-like [<IPv6NumericAddress>]:display syntax */ 143 family = FamilyInternet6; 144 host = copystring (displayname + 1, len - 2); 145 } else { 146 host = copystring (displayname, len); 147 if (dnet) { 148 family = dnet; 149 } else { 150#if defined(UNIXCONN) || defined(LOCALCONN) 151 if (host && strcmp (host, UNIX_CONNECTION) == 0) 152 family = FamilyLocal; 153 else 154#endif 155 family = FamilyInternet; 156 } 157 } 158 159 if (!host) return False; 160 161 { 162 /* 163 * If using launchd socket, remove the screen number from the end 164 * of $DISPLAY and check if it is a path to a socket. 165 */ 166 char path[PATH_MAX]; 167 struct stat sbuf; 168 169#ifdef HAVE_STRLCPY 170 strlcpy(path, displayname, sizeof(path)); 171#else 172 strncpy(path, displayname, sizeof(path) - 1); 173 path[sizeof(path) - 1] = '\0'; 174#endif 175 if (0 == stat(path, &sbuf) && S_ISSOCK(sbuf.st_mode)) { 176 family = FamilyLocal; 177 } else { 178 char *dot = strrchr(path, '.'); 179 if (dot) { 180 *dot = '\0'; 181 /* screen = atoi(dot + 1); */ 182 if (0 == stat(path, &sbuf) && S_ISSOCK(sbuf.st_mode)) { 183 family = FamilyLocal; 184 } 185 } 186 } 187 } 188 189 /* 190 * get the display number; we know that there is something after the 191 * colon (or colons) from above. note that host is now set and must 192 * be freed if there is an error. 193 */ 194 195 if (dnet) ptr++; /* skip the extra DECnet colon */ 196 ptr++; /* move to start of display num */ 197 { 198 register char *cp; 199 200 for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ; 201 len = (cp - ptr); 202 /* check present and valid follow */ 203 if (len == 0 || (*cp && *cp != '.')) { 204 free (host); 205 return False; 206 } 207 208 dpynum = atoi (ptr); /* it will handle num. as well */ 209 ptr = cp; 210 } 211 212 /* 213 * now get screen number if given; ptr may point to nul at this point 214 */ 215 if (ptr[0] == '.') { 216 register char *cp; 217 218 ptr++; 219 for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ; 220 len = (cp - ptr); 221 if (len == 0 || (*cp && *cp != '.')) { /* all prop name */ 222 free (host); 223 return False; 224 } 225 226 scrnum = atoi (ptr); /* it will handle num. as well */ 227 ptr = cp; 228 } 229 230 /* 231 * and finally, get any additional stuff that might be following the 232 * the screen number; ptr must point to a period if there is anything 233 */ 234 235 if (ptr[0] == '.') { 236 ptr++; 237 len = strlen (ptr); 238 if (len > 0) { 239 rest = copystring (ptr, len); 240 if (!rest) { 241 free (host); 242 return False; 243 } 244 } 245 } 246 247 /* 248 * and we are done! 249 */ 250 251 *familyp = family; 252 *hostp = host; 253 *dpynump = dpynum; 254 *scrnump = scrnum; 255 *restp = rest; 256 return True; 257} 258 259 260