2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
24 //%% (c) Copyright 1993, 1994 International Business Machines Corp.
25 //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
26 //%% (c) Copyright 1993, 1994 Novell, Inc.
27 //%% $TOG: tt_port.C /main/5 1999/10/14 19:02:43 mgreess $
28 /* @(#)tt_port.C 1.20 93/09/07
32 * Routines for centralizing non-portable constructs.
34 * Copyright (c) 1992 by Sun Microsystems, Inc.
37 #include "tt_options.h"
40 #include <sys/param.h>
43 #include <sys/resource.h>
48 #if defined(OPT_BUG_HPUX) && !defined(hpV4)
50 int syslog(int priority, const char *message, ...);
51 int openlog(const char *ident, int logopt, int facility);
55 #include <sys/utsname.h>
59 #include "tt_global_env.h"
60 #include "tt_string.h"
62 #if defined(OPT_BUG_SUNOS_4)
63 # if defined(__GNUG__)
64 # define uname NotAnAnsiCPrototypeForUname
65 # include <sys/utsname.h>
67 extern "C" { int uname( struct utsname * ); }
70 # include <sys/utsname.h>
73 # include <sys/utsname.h>
76 #if defined(OPT_SYSINFO)
77 # include <sys/systeminfo.h>
79 # include <stdlib.h> // atol()
82 #if defined(OPT_BUG_SGI) || defined(OPT_BUG_AIX)
83 extern "C" {extern int getdtablesize(void);}
88 * Get the name of the host.
94 * If for some reason we can't get a host name, use "localhost".
95 * This at least has a chance of doing the right thing, say on
96 * a non-networked machine, and so is more useful than just returning
97 * null or an error and having our callers bail out.
100 const char *default_hostname = "localhost";
103 #if !defined(OPT_GETHOSTNAME)
104 struct utsname uts_name;
107 if (uname(&uts_name) >= 0) {
108 result = uts_name.nodename;
110 result = default_hostname;
113 // It's not completely clear to me whether or not MAXHOSTNAMELEN is
114 // supposed to have room for the null byte at the end. Leave an
115 // extra byte just to be sure.
117 char curhostname[MAXHOSTNAMELEN+1];
118 if (0==gethostname(curhostname, sizeof curhostname)) {
119 result = curhostname;
121 result = default_hostname;
123 #endif /* OPT_GETHOSTNAME */
126 // An environment variable will be created by /usr/dt/bin/Xsession if
127 // we have started the system without a network configured. This will
128 // be true during an initial system installation.
130 if (getenv("DTNONETWORK"))
131 result = default_hostname;
138 * Get the number of currently possible file descriptors.
141 _tt_getdtablesize(void)
143 #if !defined(OPT_GETDTABLESIZE)
145 if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
146 return (int)rl.rlim_cur;
151 return getdtablesize();
152 #endif /* OPT_GETDTABLESIZE */
156 static struct rlimit original_dtablesize = { 0, 0 };
158 * Maximize the number of possible file descriptors.
162 * -1 Error (errno is set)
165 _tt_zoomdtablesize(void)
171 if (getrlimit(RLIMIT_NOFILE, &rl) != 0) {
174 if (original_dtablesize.rlim_cur == 0) {
175 original_dtablesize = rl;
177 if (rl.rlim_cur < rl.rlim_max) {
178 rl.rlim_cur = rl.rlim_max;
179 return setrlimit(RLIMIT_NOFILE, &rl);
186 _tt_restoredtablesize(void)
191 if (original_dtablesize.rlim_cur == 0) {
194 return setrlimit(RLIMIT_NOFILE, &original_dtablesize);
204 #if defined(OPT_SYSINFO)
208 if (sysinfo(SI_HW_SERIAL, serial_num, 40) > 0) {
209 sscanf(serial_num, "%12lx", &_hostid);
212 #elif defined(hpux) || defined(_AIX) || defined(__osf__)
213 struct utsname uts_name;
216 # if defined(_AIX) || defined(__osf__)
217 _hostid = atol(uts_name.machine);
219 _hostid = atol(uts_name.idnumber);
222 _hostid = gethostid();
228 * _tt_sigset sets up a signal handler in such a way that the handler
229 * is *not* unregistered when the signal handler is entered. If
230 * returns 0 if an error occurs, else 1, and leaves errno set according
231 * to the underlying system call (sigaction, signal, sigset.)
238 #if defined(OPT_POSIX_SIGNAL)
240 * There seems to be some controversy over the type of sa_handler in
241 * C++ programs. Everybody\'s man page seems to say it is of type
242 * "void (*)()", and that\'s what Solaris does, and I think that\'s what
243 * POSIX says, but both HP and IBM define it as the arguably much more
244 * useful "void (*)(int)", a/k/a SIG_PF.
246 * [4 Apr 95] Solaris 2.5 has switched to use void (*)(int), which
247 * is nice for the long run but causes us some short-run problems
248 * as we want this level of the source to compile both on
249 * Solaris 2.4 and Solaris 2.5 for a while. To solve this, we use
250 * the "sa_sigaction" element of the sigaction structure, which is the
251 * three-argument flavor of the function pointer. This is, strictly,
252 * a lie, but it's safe since our signal handlers never look at the
253 * arguments anyway. sa_sigaction is, fortunately, the same on all
255 * Once the requirement to compile on Solaris 2.4 goes away, we can
256 * simply remove the OPT_BUG_SUNOS_5 ifdefs here, leaving only the
259 struct sigaction act;
260 #if defined(OPT_BUG_SUNOS_5)
261 act.sa_sigaction = (void (*)(int, siginfo_t *, void *)) handler;
262 #elif defined(OPT_BUG_USL) || defined(OPT_BUG_UXP)
263 act.sa_handler = (void (*)()) handler;
265 act.sa_handler = handler;
267 sigemptyset(&act.sa_mask);
269 return 0==sigaction(sig, &act, NULL);
270 #elif defined(OPT_BSD_SIGNAL)
271 return SIG_ERR!=signal(sig, handler);
273 return SIG_ERR!=sigset(sig, handler);
278 * _tt_putenv - putenv()s a buffer containing "variable=value"
279 * On success, returns the malloc()ed buffer that was passed to putenv().
280 * On failure, returns 0.
282 * Note: the returned buffer becomes a storage leak after this or any
283 * other form of putenv() replaces variable in the environment.
287 const char *variable,
297 char *buf = (char *)malloc( strlen(variable) + strlen(value) + 2 );
301 sprintf( buf, "%s=%s", variable, value );
302 if (putenv( buf ) != 0) {
309 // prefix passed to _tt_openlog()
310 static _Tt_string *_tt_syslog_prefix = 0;
312 // prefix if _tt_openlog() has never been called
313 static _Tt_string *_tt_syslog_default_prefix = 0;
322 if (_tt_syslog_prefix == 0) {
323 _tt_syslog_prefix = new _Tt_string;
326 // Save the prefix, for when we write the prefix ourselves
327 // instead of letting syslog() do it
329 *_tt_syslog_prefix = prefix;
330 if (logopt & LOG_PID) {
332 _tt_syslog_prefix->cat("[").cat( getpid() ).cat("]");
334 *_tt_syslog_prefix = _tt_syslog_prefix->cat(": ");
335 openlog( prefix, logopt, facility );
346 // XXX also log to ~/.dt/errorlog
347 if (_tt_global && _tt_global->silent) {
350 _Tt_string _format( format );
351 if ( (_tt_syslog_default_prefix == 0)
352 && (_tt_syslog_prefix == 0))
355 // Only initialize default prefix if openlog() is uncalled
357 _tt_syslog_default_prefix = new _Tt_string( "libtt[" );
358 *_tt_syslog_default_prefix =
359 _tt_syslog_default_prefix->cat( getpid() ).cat( "]: " );
361 if ((_tt_syslog_prefix == 0) && (_tt_syslog_default_prefix != 0)) {
363 // libtt cannot presume to call openlog(),
364 // so we add our own prefix when openlog() is uncalled
366 _format = _tt_syslog_default_prefix->cat( _format );
369 if (_tt_syslog_prefix != 0) {
370 _tt_syslog_prefix->print( sink );
372 // XXX We do not handle %%m.
373 _format = _format.replace( "%m", strerror( errno ) );
374 vfprintf( sink, _format, args );
380 #if defined(OPT_BUG_AIX) || defined(OPT_BUG_HPUX) || defined(OPT_BUG_USL) || defined(OPT_BUG_UXP) || defined(__osf__)
382 vsprintf( buf, _format, args );
383 syslog( priority, buf );
385 vsyslog( priority, _format, args );
399 va_start( args, format );
400 _tt_vsyslog( sink, priority, format, args );
406 // _tt_get_first_set_env_var - getenvs i_num_names char*s in the environment, and returns
407 // the value of the first one found with a non-null value, or NULL if all have no value.
408 // The check is done from left to right across the supplied names.
409 // e.g. _tt_get_first_set_env_var (2, "FOO", "BAR") is functionally equivalent to
410 // getenv("FOO") ? getenv("FOO") : getenv("BAR");
413 char* _tt_get_first_set_env_var (int i_num_names, ...) {
415 // set up for variable number of arguments
417 va_start(p_var, i_num_names);
419 char* pc_name_to_check; // name of the environment var we're currently looking for
420 char* pc_value = NULL; // value of environment var we're currently looking for
421 int i_index; // indexes through each of the names supplied
423 // check each of the names in turn
424 for (i_index = 0; i_index < i_num_names; i_index++) {
426 // get the next name to check
427 pc_name_to_check = va_arg(p_var, char*);
429 if (!pc_name_to_check) // ignore any null names
432 // get the environment value (if any)
433 pc_value = getenv(pc_name_to_check);
435 if (pc_value) // we found one with a value
447 // _tt_put_all_env_var - sets i_num_names char*s in the environment, to pc_val, using _tt_putenv.
448 // NOTE: xxx see the _tt_putenv comments about memory leakage.
449 // _tt_putenv are processed from left to right across the supplied names. If any
450 // _tt_putenv fails, putenv'ing stops. The number of successful putenv's is returned
451 // e.g. _tt_put_all_env_var (2, "HELLO", "FOO", "BAR") is functionally equivalent to
452 // _tt_putenv("FOO", "HELLO") ? 0 : (_tt_putenv("BAR", "HELLO") ? 1 : 2);
454 int _tt_put_all_env_var (int i_num_names, const char* pc_val, ...) {
456 // set up for variable number of arguments
458 va_start(p_var, pc_val);
460 char* pc_name_to_set; // name of the environment var we're currently looking for
461 char* pc_buff; // value of _tt_putenv call
462 int i_index; // indexes through each of the names supplied
464 // check each of the names in turn
465 for (i_index = 0; i_index < i_num_names; i_index++) {
467 // get the next name to check
468 pc_name_to_set = va_arg(p_var, char*);
470 if (!pc_name_to_set) // ignore any null names
473 // set the environment value (if any)
474 pc_buff = _tt_putenv(pc_name_to_set, pc_val);
476 if (!pc_buff) // we had a problem