- Added implementation of setenv() for systems without it.

- Fixed bug in x_opengl.C.  On systems where putenv() adds the string to
      the environment rather than copies it, the environment would end up
      containing a random peice of the stack where the DISPLAY variable had
      been temporarily stored.



svn path=/trunk/boinc/; revision=15134
This commit is contained in:
Eric J. Korpela 2008-05-06 17:10:44 +00:00
parent 98041a4866
commit 8b72dc9370
5 changed files with 96 additions and 5 deletions

View File

@ -30,6 +30,7 @@
#include "app_ipc.h"
#include "util.h"
#include "filesys.h"
#include "unix_util.h"
#include "boinc_gl.h"
#include "boinc_glut.h"
@ -488,8 +489,7 @@ static void timer_handler(int) {
case MODE_FULLSCREEN:
case MODE_BLANKSCREEN:
if (strlen(m.display)) {
sprintf(buf, "DISPLAY=%s", m.display);
putenv(buf);
setenv("DISPLAY",m.display,1);
}
set_mode(m.mode);
break;

View File

@ -3607,3 +3607,18 @@ David May 5 2008
sched_send.C
html/user/
profile_rate.php
Eric K May 6 2008
- Added implementation of setenv() for systems without it.
- Fixed bug in x_opengl.C. On systems where putenv() adds the string to the
environment rather than copies it, the environment would end up containing
a random peice of the stack where the DISPLAY variable had been
temporarily stored.
configure.ac
lib/
unix_util.[Ch]
api/
x_opengl.C

View File

@ -445,7 +445,7 @@ AC_LANG_POP
dnl Checks for library functions.
AC_PROG_GCC_TRADITIONAL
AC_FUNC_VPRINTF
AC_CHECK_FUNCS(alloca _alloca setpriority strlcpy strlcat strcasestr sigaction getutent setutent getisax strdup strdupa daemon stat64)
AC_CHECK_FUNCS(alloca _alloca setpriority strlcpy strlcat strcasestr sigaction getutent setutent getisax strdup strdupa daemon stat64 putenv setenv)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST

View File

@ -19,10 +19,79 @@
#include "unix_util.h"
#ifndef HAVE_SETENV
#include <vector>
#include <cstring>
#include <cerrno>
#include <cstdlib>
static std::vector<char *> envstrings;
// In theory setenv() is posix, but some implementations of unix
// don't have it. The implementation isn't trivial because of
// differences in how putenv() behaves on different systems.
int setenv(const char *name, const char *value, int overwrite) {
char *buf;
int rv;
// Name can't contant an equal sign.
if (strchr(name,'=')) {
errno=EINVAL;
return -1;
}
// get any existing environment string.
buf=getenv(name);
if (!buf) {
// no existing string, allocate a new one.
buf=(char *)malloc(strlen(name)+strlen(value)+2);
if (buf) envstrings.push_back(buf);
} else {
// we do have an existing string.
// Are we allowed to overwrite it? If not return success.
if (!overwrite) return 0;
// is it long enough to hold our current string?
if (strlen(buf)<(strlen(name)+strlen(value)+1)) {
// no. See if we originally allocated this string.
std::vector<char *>::iterator i=envstrings.begin();
for (;i!=envstrings.end();i++) {
if (*i == buf) break;
}
if (i!=envstrings.end()) {
// we allocated this string. Reallocate it.
buf=(char *)realloc(buf,strlen(name)+strlen(value)+2);
*i=buf;
} else {
// someone else allocated the string. Allocate new memory.
buf=(char *)malloc(strlen(name)+strlen(value)+2);
if (buf) envstrings.push_back(buf);
}
}
}
if (!buf) {
errno=ENOMEM;
return -1;
}
sprintf(buf,"%s=%s",name,value);
rv=putenv(buf);
// Yes, there is a potential memory leak here. Some versions of operating
// systems copy the string into the environment, others make the
// existing string part of the environment. If we were to
// implement unsetenv(), it might be possible to recover some of
// this memory. But unsetenv() is even less trivial than setenv.
return rv;
}
#endif /* !HAVE_SETENV */
#ifndef HAVE_DAEMON
#include <cstdio>
#include <cstdlib>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
using std::FILE;
using std::freopen;
static FILE *stderr_null, *stdout_null;
@ -57,4 +126,4 @@ int daemon(int nochdir, int noclose) {
return 0;
}
#endif /* HAVE_DAEMON */
#endif /* !HAVE_DAEMON */

View File

@ -25,9 +25,16 @@
#include "config.h"
#ifndef HAVE_SETENV
extern "C" int setenv(const char *name, const char *value, int overwrite);
#endif
#ifndef HAVE_DAEMON
extern int daemon(int nochdir, int noclose);
extern "C" int daemon(int nochdir, int noclose);
#endif /* HAVE_DAEMON */