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