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 libraries 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 */
129 * Get the number of currently possible file descriptors.
132 _tt_getdtablesize(void)
134 #if !defined(OPT_GETDTABLESIZE)
136 if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
137 return (int)rl.rlim_cur;
142 return getdtablesize();
143 #endif /* OPT_GETDTABLESIZE */
147 static struct rlimit original_dtablesize = { 0, 0 };
149 * Maximize the number of possible file descriptors.
153 * -1 Error (errno is set)
156 _tt_zoomdtablesize(void)
162 if (getrlimit(RLIMIT_NOFILE, &rl) != 0) {
165 if (original_dtablesize.rlim_cur == 0) {
166 original_dtablesize = rl;
168 if (rl.rlim_cur < rl.rlim_max) {
169 rl.rlim_cur = rl.rlim_max;
170 return setrlimit(RLIMIT_NOFILE, &rl);
177 _tt_restoredtablesize(void)
182 if (original_dtablesize.rlim_cur == 0) {
185 return setrlimit(RLIMIT_NOFILE, &original_dtablesize);
195 #if defined(OPT_SYSINFO)
199 if (sysinfo(SI_HW_SERIAL, serial_num, 40) > 0) {
200 sscanf(serial_num, "%12lx", &_hostid);
203 #elif defined(hpux) || defined(_AIX)
204 struct utsname uts_name;
208 _hostid = atol(uts_name.machine);
210 _hostid = atol(uts_name.idnumber);
213 _hostid = gethostid();
219 * _tt_sigset sets up a signal handler in such a way that the handler
220 * is *not* unregistered when the signal handler is entered. If
221 * returns 0 if an error occurs, else 1, and leaves errno set according
222 * to the underlying system call (sigaction, signal, sigset.)
229 #if defined(OPT_POSIX_SIGNAL)
231 * There seems to be some controversy over the type of sa_handler in
232 * C++ programs. Everybody\'s man page seems to say it is of type
233 * "void (*)()", and that\'s what Solaris does, and I think that\'s what
234 * POSIX says, but both HP and IBM define it as the arguably much more
235 * useful "void (*)(int)", a/k/a SIG_PF.
237 * [4 Apr 95] Solaris 2.5 has switched to use void (*)(int), which
238 * is nice for the long run but causes us some short-run problems
239 * as we want this level of the source to compile both on
240 * Solaris 2.4 and Solaris 2.5 for a while. To solve this, we use
241 * the "sa_sigaction" element of the sigaction structure, which is the
242 * three-argument flavor of the function pointer. This is, strictly,
243 * a lie, but it's safe since our signal handlers never look at the
244 * arguments anyway. sa_sigaction is, fortunately, the same on all
246 * Once the requirement to compile on Solaris 2.4 goes away, we can
247 * simply remove the OPT_BUG_SUNOS_5 ifdefs here.
249 struct sigaction act;
250 #if defined(OPT_BUG_SUNOS_5)
251 act.sa_sigaction = (void (*)(int, siginfo_t *, void *)) handler;
253 act.sa_handler = handler;
255 sigemptyset(&act.sa_mask);
257 return 0==sigaction(sig, &act, NULL);
258 #elif defined(OPT_BSD_SIGNAL)
259 return SIG_ERR!=signal(sig, handler);
261 return SIG_ERR!=sigset(sig, handler);
266 * _tt_putenv - putenv()s a buffer containing "variable=value"
267 * On success, returns the malloc()ed buffer that was passed to putenv().
268 * On failure, returns 0.
270 * Note: the returned buffer becomes a storage leak after this or any
271 * other form of putenv() replaces variable in the environment.
275 const char *variable,
285 char *buf = (char *)malloc( strlen(variable) + strlen(value) + 2 );
289 sprintf( buf, "%s=%s", variable, value );
290 if (putenv( buf ) != 0) {
297 // prefix passed to _tt_openlog()
298 static _Tt_string *_tt_syslog_prefix = 0;
300 // prefix if _tt_openlog() has never been called
301 static _Tt_string *_tt_syslog_default_prefix = 0;
310 if (_tt_syslog_prefix == 0) {
311 _tt_syslog_prefix = new _Tt_string;
314 // Save the prefix, for when we write the prefix ourselves
315 // instead of letting syslog() do it
317 *_tt_syslog_prefix = prefix;
318 if (logopt & LOG_PID) {
320 _tt_syslog_prefix->cat("[").cat( getpid() ).cat("]");
322 *_tt_syslog_prefix = _tt_syslog_prefix->cat(": ");
323 openlog( prefix, logopt, facility );
334 // XXX also log to ~/.dt/errorlog
335 if (_tt_global && _tt_global->silent) {
338 _Tt_string _format( format );
339 if ( (_tt_syslog_default_prefix == 0)
340 && (_tt_syslog_prefix == 0))
343 // Only initialize default prefix if openlog() is uncalled
345 _tt_syslog_default_prefix = new _Tt_string( "libtt[" );
346 *_tt_syslog_default_prefix =
347 _tt_syslog_default_prefix->cat( getpid() ).cat( "]: " );
349 if ((_tt_syslog_prefix == 0) && (_tt_syslog_default_prefix != 0)) {
351 // libtt cannot presume to call openlog(),
352 // so we add our own prefix when openlog() is uncalled
354 _format = _tt_syslog_default_prefix->cat( _format );
357 if (_tt_syslog_prefix != 0) {
358 _tt_syslog_prefix->print( sink );
360 // XXX We do not handle %%m.
361 _format = _format.replace( "%m", strerror( errno ) );
362 vfprintf( sink, _format, args );
368 #if defined(OPT_BUG_AIX) || defined(OPT_BUG_HPUX)
370 vsprintf( buf, _format, args );
371 syslog( priority, buf );
373 vsyslog( priority, _format, args );
387 va_start( args, format );
388 _tt_vsyslog( sink, priority, format, args );
394 // _tt_get_first_set_env_var - getenvs i_num_names char*s in the environment, and returns
395 // the value of the first one found with a non-null value, or NULL if all have no value.
396 // The check is done from left to right across the supplied names.
397 // e.g. _tt_get_first_set_env_var (2, "FOO", "BAR") is functionally equivalent to
398 // getenv("FOO") ? getenv("FOO") : getenv("BAR");
401 char* _tt_get_first_set_env_var (int i_num_names, ...) {
403 // set up for variable number of arguments
405 va_start(p_var, i_num_names);
407 char* pc_name_to_check; // name of the environment var we're currently looking for
408 char* pc_value = NULL; // value of environment var we're currently looking for
409 int i_index; // indexes through each of the names supplied
411 // check each of the names in turn
412 for (i_index = 0; i_index < i_num_names; i_index++) {
414 // get the next name to check
415 pc_name_to_check = va_arg(p_var, char*);
417 if (!pc_name_to_check) // ignore any null names
420 // get the environment value (if any)
421 pc_value = getenv(pc_name_to_check);
423 if (pc_value) // we found one with a value
435 // _tt_put_all_env_var - sets i_num_names char*s in the environment, to pc_val, using _tt_putenv.
436 // NOTE: xxx see the _tt_putenv comments about memory leakage.
437 // _tt_putenv are processed from left to right across the supplied names. If any
438 // _tt_putenv fails, putenv'ing stops. The number of successful putenv's is returned
439 // e.g. _tt_put_all_env_var (2, "HELLO", "FOO", "BAR") is functionally equivalent to
440 // _tt_putenv("FOO", "HELLO") ? 0 : (_tt_putenv("BAR", "HELLO") ? 1 : 2);
442 int _tt_put_all_env_var (int i_num_names, const char* pc_val, ...) {
444 // set up for variable number of arguments
446 va_start(p_var, pc_val);
448 char* pc_name_to_set; // name of the environment var we're currently looking for
449 char* pc_buff; // value of _tt_putenv call
450 int i_index; // indexes through each of the names supplied
452 // check each of the names in turn
453 for (i_index = 0; i_index < i_num_names; i_index++) {
455 // get the next name to check
456 pc_name_to_set = va_arg(p_var, char*);
458 if (!pc_name_to_set) // ignore any null names
461 // set the environment value (if any)
462 pc_buff = _tt_putenv(pc_name_to_set, pc_val);
464 if (!pc_buff) // we had a problem