1 /*
2  * tclUnixSock.c --
3  *
4  *	This file contains Unix-specific socket related code.
5  *
6  * Copyright (c) 1995 Sun Microsystems, Inc.
7  *
8  * See the file "license.terms" for information on usage and redistribution of
9  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
10  */
11 
12 #include "tclInt.h"
13 
14 /*
15  * The following variable holds the network name of this host.
16  */
17 
18 static TclInitProcessGlobalValueProc InitializeHostName;
19 static ProcessGlobalValue hostName =
20 	{0, 0, NULL, NULL, InitializeHostName, NULL, NULL};
21 
22 
23 /*
24  *----------------------------------------------------------------------
25  *
26  * InitializeHostName --
27  *
28  * 	This routine sets the process global value of the name of the local
29  * 	host on which the process is running.
30  *
31  * Results:
32  *	None.
33  *
34  *----------------------------------------------------------------------
35  */
36 
37 static void
InitializeHostName(char ** valuePtr,int * lengthPtr,Tcl_Encoding * encodingPtr)38 InitializeHostName(
39     char **valuePtr,
40     int *lengthPtr,
41     Tcl_Encoding *encodingPtr)
42 {
43     CONST char *native = NULL;
44 
45 #ifndef NO_UNAME
46     struct utsname u;
47     struct hostent *hp;
48 
49     memset(&u, (int) 0, sizeof(struct utsname));
50     if (uname(&u) > -1) {				/* INTL: Native. */
51         hp = TclpGetHostByName(u.nodename);		/* INTL: Native. */
52 	if (hp == NULL) {
53 	    /*
54 	     * Sometimes the nodename is fully qualified, but gets truncated
55 	     * as it exceeds SYS_NMLN. See if we can just get the immediate
56 	     * nodename and get a proper answer that way.
57 	     */
58 
59 	    char *dot = strchr(u.nodename, '.');
60 
61 	    if (dot != NULL) {
62 		char *node = ckalloc((unsigned) (dot - u.nodename + 1));
63 
64 		memcpy(node, u.nodename, (size_t) (dot - u.nodename));
65 		node[dot - u.nodename] = '\0';
66 		hp = TclpGetHostByName(node);
67 		ckfree(node);
68 	    }
69 	}
70         if (hp != NULL) {
71 	    native = hp->h_name;
72         } else {
73 	    native = u.nodename;
74         }
75     }
76     if (native == NULL) {
77 	native = tclEmptyStringRep;
78     }
79 #else
80     /*
81      * Uname doesn't exist; try gethostname instead.
82      *
83      * There is no portable macro for the maximum length of host names
84      * returned by gethostbyname(). We should only trust SYS_NMLN if it is at
85      * least 255 + 1 bytes to comply with DNS host name limits.
86      *
87      * Note: SYS_NMLN is a restriction on "uname" not on gethostbyname!
88      *
89      * For example HP-UX 10.20 has SYS_NMLN == 9, while gethostbyname() can
90      * return a fully qualified name from DNS of up to 255 bytes.
91      *
92      * Fix suggested by Viktor Dukhovni (viktor@esm.com)
93      */
94 
95 #    if defined(SYS_NMLN) && SYS_NMLEN >= 256
96     char buffer[SYS_NMLEN];
97 #    else
98     char buffer[256];
99 #    endif
100 
101     if (gethostname(buffer, sizeof(buffer)) > -1) {	/* INTL: Native. */
102 	native = buffer;
103     }
104 #endif
105 
106     *encodingPtr = Tcl_GetEncoding(NULL, NULL);
107     *lengthPtr = strlen(native);
108     *valuePtr = ckalloc((unsigned int) (*lengthPtr)+1);
109     memcpy(*valuePtr, (void *) native, (size_t)(*lengthPtr)+1);
110 }
111 
112 /*
113  *----------------------------------------------------------------------
114  *
115  * Tcl_GetHostName --
116  *
117  *	Returns the name of the local host.
118  *
119  * Results:
120  *	A string containing the network name for this machine, or an empty
121  *	string if we can't figure out the name. The caller must not modify or
122  *	free this string.
123  *
124  * Side effects:
125  *	Caches the name to return for future calls.
126  *
127  *----------------------------------------------------------------------
128  */
129 
130 CONST char *
Tcl_GetHostName(void)131 Tcl_GetHostName(void)
132 {
133     return Tcl_GetString(TclGetProcessGlobalValue(&hostName));
134 }
135 
136 /*
137  *----------------------------------------------------------------------
138  *
139  * TclpHasSockets --
140  *
141  *	Detect if sockets are available on this platform.
142  *
143  * Results:
144  *	Returns TCL_OK.
145  *
146  * Side effects:
147  *	None.
148  *
149  *----------------------------------------------------------------------
150  */
151 
152 int
TclpHasSockets(Tcl_Interp * interp)153 TclpHasSockets(
154     Tcl_Interp *interp)		/* Not used. */
155 {
156     return TCL_OK;
157 }
158 
159 /*
160  *----------------------------------------------------------------------
161  *
162  * TclpFinalizeSockets --
163  *
164  *	Performs per-thread socket subsystem finalization.
165  *
166  * Results:
167  *	None.
168  *
169  * Side effects:
170  *	None.
171  *
172  *----------------------------------------------------------------------
173  */
174 
175 void
TclpFinalizeSockets(void)176 TclpFinalizeSockets(void)
177 {
178     return;
179 }
180 
181 /*
182  * Local Variables:
183  * mode: c
184  * c-basic-offset: 4
185  * fill-column: 78
186  * End:
187  */
188