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