Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / lib / DtSvc / DtEncap / connect.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  * File:         connect.c $TOG: connect.c /main/8 1998/04/09 17:44:33 mgreess $
25  * Language:     C
26  *
27  * (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
28  *
29  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
30  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
31  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
32  * (c) Copyright 1993, 1994 Novell, Inc.                                *
33  */
34
35 #include <Dt/UserMsg.h>
36
37 #include <bms/sbport.h>                 /* NOTE: sbport.h must be the first include. */
38
39 #include <sys/socket.h>         /**** needed by gethostbyname et al *****/
40 #define X_INCLUDE_NETDB_H
41 #define XOS_USE_XT_LOCKING
42 #include <X11/Xos_r.h>
43
44 #include <bms/bms.h>              
45 #include <bms/connect.h>          
46 #include <bms/MemoryMgr.h>       /* Xe_make_struct, make_str ...       */
47 #include <bms/XeUserMsg.h>
48 #include <bms/pathwexp.h>        /* Xe_shellexp                    */
49 #include "DtSvcLock.h"
50
51 #include <codelibs/pathutils.h>
52
53 /*
54  * local variables
55  */
56 static XeString context_host = NULL;
57
58 static XeString FindDomainHost (XeString host_spec);
59 static void UnParseFileString (XeString host, XeString path);
60 static int GetDomainName (XeString buffer, unsigned int bufsize);
61
62 #define strequal(xxx_str1, xxx_str2) (!strcmp(xxx_str1, xxx_str2))
63
64 /*------------------------------------------------------------------------+*/
65 XeString 
66 XeCreateContextString(XeString host,
67                       XeString directory,
68                       XeString file)
69 /*------------------------------------------------------------------------+*/
70 {
71    XeString context_string;
72
73    host = XeFindShortHost(host);
74
75    if ((strequal(directory, (XeString)"")) || (directory == NULL)){
76       if ((strequal(file, (XeString)"")) || (file == NULL)){
77          Xe_release_str(host);
78          return((XeString) NULL);
79       } else {
80          context_string = XeMalloc (strlen(host) + strlen(file) + 2);
81          sprintf (context_string, "%s:%s", host, file);
82       }
83    } else {
84       if ((strequal(file, (XeString)"")) || (file == NULL)){
85          context_string = XeMalloc(strlen(host) + strlen(directory) + 2);
86          sprintf (context_string, "%s:%s", host, directory);
87       }
88       else {
89          context_string = XeMalloc(strlen(host) + strlen(directory) + 
90                           strlen(file) + 3);
91          sprintf (context_string, "%s:%s/%s", host, directory, file);
92       }
93    }
94    Xe_release_str(host);
95    return(context_string);
96 }
97
98 /*------------------------------------------------------------------------+*/
99 XeString 
100 XeFindShortHost(XeString host_spec)
101 /*------------------------------------------------------------------------+*/
102 {
103    XeString host, ptr, ptr2;
104    XeChar localhost[MAXHOSTNAMELEN];
105    
106    if (!host_spec || !host_spec[0] || strequal(host_spec, (XeString)"-")) {
107       _DtSvcProcessLock();
108       if (!context_host){
109          context_host = (XeString) XeMalloc (MAXHOSTNAMELEN);
110          Xegetcwd(context_host, MAXHOSTNAMELEN);
111       }
112       _DtSvcProcessUnlock();
113       host_spec = context_host;
114    }
115    host_spec = Xe_shellexp(host_spec);
116    ptr = strstr(host_spec, (XeString)".");
117    if (!ptr) /* short name already */
118       host = strdup(host_spec);
119    else {
120       GetDomainName(localhost, MAXHOSTNAMELEN);
121       ptr2 = strstr(localhost, (XeString)".");
122       if (ptr2 && strequal(ptr, ptr2)) { /* domains same, can eliminate */
123          host = Xe_make_ntype(ptr-host_spec+1, XeChar);
124          strncpy(host, host_spec, ptr-host_spec); /* copy only up to "." */
125          host[ptr-host_spec] = '\0'; /* NULL terminate copy */
126       }
127       else
128          host = strdup(host_spec);
129    }
130    return host;
131 }
132
133 /* temporary without domain comparisons */
134 /*------------------------------------------------------------------------+*/
135 XeString 
136 XeFindHost(XeString host_spec)
137 /*------------------------------------------------------------------------+*/
138 {
139    if (!host_spec || !host_spec[0] || strequal(host_spec, (XeString)"-")) {
140       _DtSvcProcessLock();
141       if (!context_host){
142          context_host = (XeString) XeMalloc (MAXHOSTNAMELEN);
143          Xegetcwd(context_host, MAXHOSTNAMELEN);
144       }
145       _DtSvcProcessUnlock();
146       host_spec = context_host;
147    }
148    host_spec = Xe_shellexp(host_spec);
149    return strdup(host_spec);
150 }
151
152
153 /* this should be XeFindHost but is called other name for 1.0 operation
154    using only simple names if in short domain.  See defect HZNlp05737 */
155
156 /*------------------------------------------------------------------------+*/
157 static XeString 
158 FindDomainHost(XeString host_spec)
159 /*------------------------------------------------------------------------+*/
160 {
161    XeString host;
162    XeString ptr;
163    XeChar localhost[MAXHOSTNAMELEN];
164    
165    if (!host_spec || !host_spec[0] || strequal(host_spec, (XeString)"-")) {
166       _DtSvcProcessLock();
167       if (!context_host){
168          context_host = (XeString) XeMalloc (MAXHOSTNAMELEN);
169          Xegetcwd(context_host, MAXHOSTNAMELEN);
170       }
171       _DtSvcProcessUnlock();
172       host_spec = context_host;
173    }
174    else if (strequal(host_spec, (XeString)"*")) {
175       host_spec = strdup((XeString)"*");
176       return host_spec;
177    }
178    host_spec = Xe_shellexp(host_spec);
179    ptr = strstr(host_spec, (XeString)".");
180    if (ptr)
181       host = strdup(host_spec);
182    else {
183       GetDomainName(localhost, MAXHOSTNAMELEN);
184       ptr = strstr(localhost, (XeString)"."); /* points to domain name if one exists */
185       if (ptr) {
186          host = Xe_make_ntype(strlen(host_spec)+strlen(ptr)+1, XeChar);
187          strcpy(host, host_spec);
188          strcat(host, ptr);
189       }
190       else
191          host = strdup(host_spec);
192    }
193    return(host);
194 }
195
196 /******  XeParseFileString and UnParseFileString work together to munge and
197          unmunge a path into a host path pair.  UnParseFileString DOES NOT WORK
198          FOR ARBITRARY STRINGS.  It is not a general functions (it is a hack).
199          Do not use It as a general function.
200 ******/
201
202 /*------------------------------------------------------------------------+*/
203 static void
204 UnParseFileString(XeString host, XeString path)
205 /*------------------------------------------------------------------------+*/
206 {
207    if (host) { /* there was a host in the original string */
208       *--path = (XeChar) ':';
209    }
210 }
211
212
213 /*------------------------------------------------------------------------+*/
214 int
215 XeParseFileString(XeString line,
216                   XeString *host_addr,
217                   XeString *path_addr)
218 /*------------------------------------------------------------------------+*/
219 {
220    XeString current_position = line;
221
222    if ((XeChar)'/' == *line) {  
223       *host_addr = XeString_NULL;
224       *path_addr = line;
225       return(0);
226    }
227      
228    while (*current_position && ((XeChar) ':' != *current_position)) {
229      int len;
230      if ((len = mblen(current_position, MB_CUR_MAX)) > 1)
231          current_position += len;
232      else
233          current_position++;
234    }
235    if (*current_position) {                 /* host was specified */
236       *current_position++ = XeChar_NULL;  /* ":" goes to NULL */
237       *host_addr = line;
238       *path_addr = current_position;
239    } else {
240       *host_addr = XeString_NULL;
241       *path_addr = line;
242    }
243    return(0);
244 }
245
246 /***** Xegethostname is a replacement for gethostname which always returns the
247        canonical (domain) hostname
248 ******/
249
250 static XeString domainname = XeString_NULL;
251
252 /* this should be Xegethostname but is called other name for 1.0 operation
253    using only simple names if in short domain.  See defect HZNlp05737 */
254
255 /*------------------------------------------------------------------------+*/
256 static int
257 GetDomainName(XeString buffer, unsigned int bufsize)
258 /*------------------------------------------------------------------------+*/
259 {
260    XeString tmpbuf = Xe_make_buffer(bufsize);
261    XeString ptr;
262    struct hostent       *host_ret;
263    _Xgethostbynameparams host_buf; 
264    static Boolean firstPass = TRUE;
265    int status;
266    
267    /* try to get domain name from hostname */
268    if ((status = gethostname(tmpbuf, bufsize))) {
269       XeFree(tmpbuf);
270       return status; /* failed gethostname */
271    }
272    ptr = strstr(tmpbuf, (XeString)".");
273    _DtSvcProcessLock();
274    if (domainname && ptr && strcmp(domainname, ptr)) /* domains are different */
275       _DtSimpleError(XeProgName, XeWarning, NULL, (XeString) "><Domain configured in hostname and domain server are different: '%s', '%s'", domainname, ptr);
276    if (!domainname && ptr)
277       domainname = strdup(ptr);
278    if (ptr) { /* "." in hostname */
279       strncpy(buffer, tmpbuf, bufsize);
280       XeFree(tmpbuf);
281       _DtSvcProcessUnlock();
282       return 0;
283    }
284
285    /* look up domain name in domain server */
286    if (!domainname && (firstPass)) {
287       firstPass = FALSE;
288       host_ret = _XGethostbyname(tmpbuf, host_buf);
289       if (host_ret == NULL) {
290          _DtSimpleError(XeProgName, XeWarning, NULL, (XeString) "><%s not found in hosts database", tmpbuf);
291          _DtSvcProcessUnlock();
292          return -1;
293       }
294       if ((ptr = strstr(host_ret->h_name, (XeString)"."))) /* if dot in canonical name */
295          domainname = strdup(ptr);
296    }
297
298    /* construct full domain name for return */
299    strncpy(buffer, tmpbuf, bufsize);
300    if (domainname)
301       strncat(buffer, domainname, bufsize - strlen(tmpbuf));
302    XeFree(tmpbuf);
303    _DtSvcProcessUnlock();
304    return 0;
305 }
306
307 /*------------------------------------------------------------------------+*/
308 int
309 Xegetshorthostname(XeString buffer, unsigned int bufsize)
310 /*------------------------------------------------------------------------+*/
311 {
312    XeString ptr;
313    int status;
314    
315    if ((status = gethostname(buffer, bufsize)))
316       return status; /* failed gethostname */
317    if ((ptr = strstr(buffer, (XeString)".")))
318       *ptr = '\0';  /* delete domain name if there is one */
319    return 0;
320 }
321
322 /*------------------------------------------------------------------------+*/
323 int
324 Xegethostname(XeString buffer, unsigned int bufsize)
325 /*------------------------------------------------------------------------+*/
326 {
327    return Xegetshorthostname(buffer, bufsize);
328 }
329
330
331 /*------------------------------------------------------------------------+*/
332 Boolean
333 XeIsLocalHostP(XeString hostname)
334 /*------------------------------------------------------------------------+*/
335 {
336    XeChar localhost[MAXHOSTNAMELEN];
337    XeString found_host = FindDomainHost(hostname);
338    int status;
339    
340    GetDomainName(localhost, MAXHOSTNAMELEN);
341    status = strcmp(localhost, found_host)==0;
342    XeFree(found_host);
343    return status;
344 }
345
346 /*------------------------------------------------------------------------+*/
347 Boolean
348 XeIsSameHostP(XeString host1, XeString host2)
349 /*------------------------------------------------------------------------+*/
350 {
351    XeString long_host1 = FindDomainHost(host1);
352    XeString long_host2 = FindDomainHost(host2);
353    int status = strcmp(long_host1, long_host2) == 0;
354    if (!host1 || !host1[0] || !strcmp(host1,(XeString)"-")
355        || !host2 || !host2[0] || !strcmp(host2,(XeString)"-"))
356         status = strcmp(host1, host2) == 0;
357
358    XeFree(long_host1);
359    XeFree(long_host2);
360    return status;
361 }
362
363
364 /* note the following functions use char not Xechar because they are
365    plug replacements for the Unix functions */
366
367 static char *last_env_string = NULL; /* save env so it can be freed later */
368
369 /* Note: only use this function for $PWD as it assumes it can free the
370    env variable when a new one is assigned -- this will only be true if
371    the same variable is used for all calls to copying_putenv */
372 static void
373 copying_putenv(char *env)
374 {
375    char *env_copy = XeCopyStringM(env);
376    putenv(env_copy);
377    _DtSvcProcessLock();
378    if (last_env_string)
379       XeFree(last_env_string);
380    last_env_string = env_copy;
381    _DtSvcProcessUnlock();
382 }
383
384 /*------------------------------------------------------------------------+*/
385 char *
386 Xegetcwd(char *buf, int size)
387 /*------------------------------------------------------------------------+*/
388 {
389    Boolean pwd_ok = FALSE;
390    char *env, *current_dir;
391
392    if ((current_dir = getenv("PWD"))) { /* use PWD instead of slow call */
393       int s1, s2;
394       struct stat sb1, sb2;
395
396       /* The code used to copy size-1 bytes.  This is a waste most of */
397       /* the time.  All we need to copy is strlen($PWD) bytes unless  */
398       /* there are more bytes that fit into the array passed in.      */
399
400       int len=strlen(current_dir);
401       if (len > size-1)
402           len = size-1;
403       
404       strncpy(buf, current_dir, len);
405       buf[len] = '\0';
406
407       /* Make sure $PWD is the same as "." before we trust it. */
408       /* All this is still much faster the getcwd() esp. on UX discless. */
409       s1 = stat(buf, &sb1);
410       s2 = stat(".", &sb2);
411
412       /* If device and inode are the same, we have a match */
413       pwd_ok = ((s1 == 0 && s2 == 0) &&
414                 (sb1.st_dev == sb2.st_dev && sb1.st_ino == sb2.st_ino) );
415    }     
416
417    if (!pwd_ok) {
418       current_dir = getcwd(buf, size);
419       env = XeMalloc(MAXPATHLEN+10);
420       sprintf(env, "PWD=%s", buf);
421       copying_putenv(env);      /* set PWD if necessary for later cache use */
422       XeFree(env);
423    }
424    return current_dir;
425 }
426
427 /*------------------------------------------------------------------------+*/
428 int
429 Xechdir (const char *path)
430 /*------------------------------------------------------------------------+*/
431 {
432    int status;
433    char *simple_path = NULL;
434    char *env;
435    char buf[MAXPATHLEN+10];
436    if ((status = chdir(path))==0) {
437       env = XeMalloc(MAXPATHLEN+10);
438
439       if (path[0] != '/') { /* relative path */
440          path = getcwd(buf, sizeof buf);
441          sprintf(env, "PWD=%s", path);
442       }
443       else {
444          char *canon_path = pathcollapse(path, NULL, FALSE);
445          /* absolute path */
446          sprintf(env, "PWD=%s", canon_path);
447          /* note XeFree() not appropriate if Xemalloc not used */
448          free(canon_path); 
449       }
450       
451       copying_putenv(env); /* update PWD if directory changed */
452       XeFree(env);
453    }
454    return status;
455 }