1/* 2 3Copyright 1988, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25*/ 26 27/* 28 * This file contains routines to handle common selection targets. 29 * 30 * Public entry points: 31 * 32 * XmuConvertStandardSelection() return a known selection 33 */ 34 35#ifdef HAVE_CONFIG_H 36#include <config.h> 37#endif 38 39#include <X11/IntrinsicP.h> 40#include <X11/Xatom.h> 41#include <X11/ShellP.h> 42#ifdef XTHREADS 43#include <X11/Xthreads.h> 44#endif 45#include <stdio.h> 46 47#ifdef WIN32 48#include <X11/Xwinsock.h> 49#else 50#ifndef Lynx 51#include <sys/socket.h> 52#else 53#include <sys/types.h> 54#include <socket.h> 55#endif 56#define XOS_USE_XT_LOCKING 57#endif 58#include <X11/Xos_r.h> 59 60#include <X11/Xos.h> 61#include <stdlib.h> 62#include "Atoms.h" 63#include "StdSel.h" 64#include "SysUtil.h" 65#include <X11/Xfuncs.h> 66 67#ifndef OS_NAME 68# ifndef X_OS_FILE 69# ifdef HAVE_UNAME 70# define USE_UNAME 71# endif 72# endif /*X_OS_FILE*/ 73# ifdef USE_UNAME 74# include <sys/utsname.h> 75# endif 76#endif 77 78/* 79 * Prototypes 80 */ 81static char *get_os_name(void); 82static Bool isApplicationShell(Widget); 83 84/* 85 * Implementation 86 */ 87static char * 88get_os_name(void) 89{ 90#ifdef OS_NAME 91 return XtNewString(OS_NAME); 92#else 93#if defined(X_OS_FILE) || defined(MOTD_FILE) 94 FILE *f = NULL; 95#endif 96 97#ifdef USE_UNAME 98 struct utsname utss; 99 100 if (uname (&utss) >= 0) { 101 char *os_name; 102 int len = strlen(utss.sysname) + 1; 103#ifndef hpux /* because of hostname length crock */ 104 len += 2 + strlen(utss.release); 105#endif 106 os_name = XtMalloc (len); 107 strcpy (os_name, utss.sysname); 108#ifndef hpux 109 strcat (os_name, " "); 110 strcat (os_name, utss.release); 111#endif 112 return os_name; 113 } 114#endif 115 116#ifdef X_OS_FILE 117 f = fopen(X_OS_FILE, "r"); 118 if (!f) 119#endif 120#ifdef MOTD_FILE 121 f = fopen(MOTD_FILE, "r"); 122#endif 123#if defined(X_OS_FILE) || defined(MOTD_FILE) 124 if (f) { 125 char motd[512]; 126 motd[0] = '\0'; 127 (void) fgets(motd, 511, f); 128 fclose(f); 129 motd[511] = '\0'; 130 if (motd[0] != '\0') { 131 int len = strlen(motd); 132 if (motd[len - 1] == '\n') 133 motd[len - 1] = '\0'; 134 return XtNewString(motd); 135 } 136 } 137#endif 138 139#if !defined(SYSV) && (defined(CSRG_BASED) || defined(unix)) 140 return XtNewString("BSD"); 141#else 142 return NULL; 143#endif 144 145#endif /*OS_NAME*/ 146} 147 148/* This is a trick/kludge. To make shared libraries happier (linking 149 * against Xmu but not linking against Xt, and apparently even work 150 * as we desire on SVR4, we need to avoid an explicit data reference 151 * to applicationShellWidgetClass. XtIsTopLevelShell is known 152 * (implementation dependent assumption!) to use a bit flag. So we 153 * go that far. Then, we test whether it is an applicationShellWidget 154 * class by looking for an explicit class name. Seems pretty safe. 155 */ 156static Bool 157isApplicationShell(Widget w) 158{ 159 register WidgetClass c; 160 161 if (!XtIsTopLevelShell(w)) 162 return False; 163 for (c = XtClass(w); c; c = c->core_class.superclass) { 164 if (!strcmp(c->core_class.class_name, "ApplicationShell")) 165 return True; 166 } 167 return False; 168} 169 170Boolean 171XmuConvertStandardSelection(Widget w, Time time, Atom *selection, Atom *target, 172 Atom *type, XPointer *value, 173 unsigned long *length, int *format) 174{ 175 Display *d = XtDisplay(w); 176 if (*target == XA_TIMESTAMP(d)) { 177 *value = XtMalloc(4); 178 if (sizeof(long) == 4) 179 *(long*)*value = time; 180 else { 181 long temp = time; 182 memcpy((char*)*value, ((char*)&temp)+sizeof(long)-4, 4); 183 } 184 *type = XA_INTEGER; 185 *length = 1; 186 *format = 32; 187 return True; 188 } 189 if (*target == XA_HOSTNAME(d)) { 190 char hostname[1024]; 191 hostname[0] = '\0'; 192 *length = XmuGetHostname (hostname, sizeof hostname); 193 *value = XtNewString(hostname); 194 *type = XA_STRING; 195 *format = 8; 196 return True; 197 } 198 if (*target == XA_USER(d)) { 199 char *name = (char*)getenv("USER"); 200 if (name == NULL) return False; 201 *value = XtNewString(name); 202 *type = XA_STRING; 203 *length = strlen(name); 204 *format = 8; 205 return True; 206 } 207 if (*target == XA_CLASS(d)) { 208 Widget parent = XtParent(w); 209 String class; 210 int len; 211 while (parent != NULL && !isApplicationShell(w)) { 212 w = parent; 213 parent = XtParent(w); 214 } 215 if (isApplicationShell(w)) 216 class = ((ApplicationShellWidget) w)->application.class; 217 else 218 class = XtClass(w)->core_class.class_name; 219 *length = (len=strlen(w->core.name)) + strlen(class) + 2; 220 *value = XtMalloc(*length); 221 strcpy( (char*)*value, w->core.name ); 222 strcpy( (char*)*value+len+1, class ); 223 *type = XA_STRING; 224 *format = 8; 225 return True; 226 } 227 if (*target == XA_NAME(d)) { 228 Widget parent = XtParent(w); 229 230 while (parent != NULL && !XtIsWMShell(w)) { 231 w = parent; 232 parent = XtParent(w); 233 } 234 if (!XtIsWMShell(w)) return False; 235 *value = XtNewString( ((WMShellWidget) w)->wm.title ); 236 *length = strlen(*value); 237 *type = XA_STRING; 238 *format = 8; 239 return True; 240 } 241 if (*target == XA_CLIENT_WINDOW(d)) { 242 Widget parent = XtParent(w); 243 while (parent != NULL) { 244 w = parent; 245 parent = XtParent(w); 246 } 247 *value = XtMalloc(sizeof(Window)); 248 *(Window*)*value = w->core.window; 249 *type = XA_WINDOW; 250 *length = 1; 251 *format = 32; 252 return True; 253 } 254 if (*target == XA_OWNER_OS(d)) { 255 *value = get_os_name(); 256 if (*value == NULL) return False; 257 *type = XA_STRING; 258 *length = strlen(*value); 259 *format = 8; 260 return True; 261 } 262 if (*target == XA_TARGETS(d)) { 263#if defined(unix) 264# define NUM_TARGETS 7 265#else 266# define NUM_TARGETS 6 267#endif 268 Atom* std_targets = (Atom*)XtMalloc(NUM_TARGETS*sizeof(Atom)); 269 int i = 0; 270 std_targets[i++] = XA_TIMESTAMP(d); 271 std_targets[i++] = XA_HOSTNAME(d); 272 std_targets[i++] = XA_USER(d); 273 std_targets[i++] = XA_CLASS(d); 274 std_targets[i++] = XA_NAME(d); 275 std_targets[i++] = XA_CLIENT_WINDOW(d); 276#ifdef unix 277 std_targets[i++] = XA_OWNER_OS(d); 278#endif 279 *value = (XPointer)std_targets; 280 *type = XA_ATOM; 281 *length = NUM_TARGETS; 282 *format = 32; 283 return True; 284 } 285 /* else */ 286 return False; 287} 288