parsedpy.c revision 0d22642b
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) strncpy (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)) { 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)) { 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