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