- Build fixes for non-Win32, non-Linux, non-MacOS systems.

- configure script:
        - Added checks for functions strdup(), strdupa(),
            daemon(), stat64(), strcasestr()
        - Fixed problems with kc_mysql.m4 and wxWidgets.m4 returning
            invalid CFLAGS and LIBS flags.
        - Fixed incorrect order of pthread flag checking on solaris.
    - New files: lib/unix_util.[Ch].  Currently contains implementation of
        daemon() for systems that lack it.
    - Access to binary files in /proc was failing on some systems when compiled
        with 64 bit file access.  Rearranged headers and defines to force 32bit
        file access in hostinfo_unix.C
    - all_tty_idle() didn't work as advertised on any system as far as I can
        tell.  I rewrote it to check ttys that are not named /dev/tty[1-9].
        The old implementation was modifying a statically allocated read-only
        string, (and crashing on some systems) anyway.
    - added implementation of non-standard function strcasestr() to str_util.C
    - added #define of MAP_FILE to shmem.C, because it is missing from most
        unix systems, (and is unnecessary on linux anyway).
    - other minor bug fixes.


svn path=/trunk/boinc/; revision=14996
This commit is contained in:
Eric J. Korpela 2008-04-01 21:44:12 +00:00
parent 64d7e70ddd
commit 51e24737bd
15 changed files with 492 additions and 57 deletions

View File

@ -24,6 +24,8 @@
#include "boinc_win.h"
#elif (!defined(__EMX__))
#include <sys/stat.h>
#else
#include "config.h"
#endif
#include <cstring>

View File

@ -2937,3 +2937,46 @@ David April 1 2008
lib/
filesys.C
Eric K April 1 2008
- Build fixes for non-Win32, non-Linux, non-MacOS systems.
- configure script:
- Added checks for functions strdup(), strdupa(),
daemon(), stat64(), strcasestr()
- Fixed problems with kc_mysql.m4 and wxWidgets.m4 returning
invalid CFLAGS and LIBS flags.
- Fixed incorrect order of pthread flag checking on solaris.
- New files: lib/unix_util.[Ch]. Currently contains implementation of
daemon() for systems that lack it.
- Access to binary files in /proc was failing on some systems when compiled
with 64 bit file access. Rearranged headers and defines to force 32bit
file access in hostinfo_unix.C
- all_tty_idle() didn't work as advertised on any system as far as I can
tell. I rewrote it to check ttys that are not named /dev/tty[1-9].
The old implementation was modifying a statically allocated read-only
string, anyway.
- added implementation of non-standard function strcasestr() to str_util.C
- added #define of MAP_FILE to shmem.C, because it is missing from most
unix systems, (and is unnecessary on linux anyway).
- other minor bug fixes.
configure.ac
client/
main.C
hostinfo_unix.C
m4/
kc_mysql.m4
acx_pthread.m4
wxWidgets.m4
lib/
str_util.[Ch]
shmem.C
unix_util.[Ch]
parse.h
Makefile.am
api/
graphics2_util.C

View File

@ -17,10 +17,44 @@
// or write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "cpp.h"
// There is a reason that having a file called "cpp.h" that includes config.h
// and some of the C++ header files. That reason is because there are #defines
// that alter the behiour of the standard C and C++ headers. In this case
// we need to use the "small files" environment on some unix systems. That
// can't be done if we include "cpp.h"
// #include "cpp.h"
// copied directly from cpp.h
#if defined(_WIN32) && !defined(__CYGWIN32__)
#if defined(_WIN64) && defined(_M_X64)
#define HOSTTYPE "windows_x86_64"
#define HOSTTYPEALT "windows_intelx86"
#else
#define HOSTTYPE "windows_intelx86"
#endif
#include "version.h" // version numbers from autoconf
#endif
#if !defined(_WIN32) || defined(__CYGWIN32__)
#include "config.h"
// Access to binary files in /proc filesystem doesn't work in the 64bit
// files environment on some systems. None of the functions here need
// 64bit file functions, so we'll undefine _FILE_OFFSET_BITS and _LARGE_FILES.
#undef _FILE_OFFSET_BITS
#undef _LARGE_FILES
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#endif
#include "config.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
@ -579,8 +613,8 @@ int HOST_INFO::get_host_info() {
get_cpu_info_maxosx(*this);
#elif defined(__EMX__)
CPU_INFO_t cpuInfo;
strcpy( p_vendor, cpuInfo.vendor.company);
strcpy( p_model, cpuInfo.name.fromID);
strlcpy( p_vendor, cpuInfo.vendor.company, sizeof(p_vendor));
strlcpy( p_model, cpuInfo.name.fromID, sizeof(p_model));
#elif defined(HAVE_SYS_SYSCTL_H)
int mib[2];
size_t len;
@ -608,6 +642,7 @@ int HOST_INFO::get_host_info() {
CPU_TYPE_TO_TEXT( (cpu_type& 0xffffffff), cpu_type_name);
strncpy( p_model, "Alpha ", sizeof( p_model));
strncat( p_model, cpu_type_name, (sizeof( p_model)- strlen( p_model)- 1));
p_model[sizeof(p_model)-1]=0;
#elif defined(HAVE_SYS_SYSTEMINFO_H)
sysinfo(SI_PLATFORM, p_vendor, sizeof(p_vendor));
sysinfo(SI_ISALIST, p_model, sizeof(p_model));
@ -832,7 +867,71 @@ inline bool device_idle(time_t t, const char *device) {
return stat(device, &sbuf) || (sbuf.st_atime < t);
}
inline bool all_tty_idle(time_t t, char *device, char first_char, int num_tty) {
static const struct dir_dev {
char *dir;
char *dev;
} tty_patterns[] = {
#ifdef unix
{ "/dev","tty" },
{ "/dev","pty" },
{ "/dev/pts","" },
#endif
// add other ifdefs here as necessary.
{ NULL, NULL },
};
std::vector<std::string> get_tty_list() {
// Create a list of all terminal devices on the system.
char devname[1024];
char fullname[1024];
int done,i=0;
std::vector<std::string> tty_list;
do {
DIRREF dev=dir_open(tty_patterns[i].dir);
if (dev) {
do {
// get next file
done=dir_scan(devname,dev,1024);
// does it match our tty pattern? If so, add it to the tty list.
if (!done && (strstr(devname,tty_patterns[i].dev) == devname)) {
// don't add anything starting with .
if (devname[0] != '.') {
sprintf(fullname,"%s/%s",tty_patterns[i].dir,devname);
tty_list.push_back(fullname);
}
}
} while (!done);
}
i++;
} while (tty_patterns[i].dir != NULL);
return tty_list;
}
inline bool all_tty_idle(time_t t) {
// The initial implementation of this function was very broken.
// It assumed that incrementing a character is enough to cover all
// possible terminals. It was also being passed a pointer to a string
// allocated in unwritable memory on some systems, and would therefore
// segfault when called. This implementation is better.
static std::vector<std::string> tty_list;
struct stat sbuf;
int i;
if (tty_list.size()==0) tty_list=get_tty_list();
for (i=0; i<tty_list.size(); i++) {
// ignore errors
if (!stat(tty_list[i].c_str(), &sbuf)) {
// printf("%s %d %d\n",tty_list[i].c_str(),sbuf.st_atime,t);
if (sbuf.st_atime >= t) {
return false;
}
}
}
return true;
#if 0
// this is the old implementation
struct stat sbuf;
char *tty_index = device + strlen(device) - 1;
*tty_index = first_char;
@ -845,6 +944,7 @@ inline bool all_tty_idle(time_t t, char *device, char first_char, int num_tty) {
}
}
return true;
#endif
}
#ifdef HAVE_UTMP_H
@ -860,69 +960,69 @@ inline bool user_idle(time_t t, struct utmp* u) {
tty[i+5] = '\0';
}
}
return device_idle(t, tty);
}
return device_idle(t, tty);
}
#if !defined(HAVE_SETUTENT) || !defined(HAVE_GETUTENT)
static FILE *ufp = NULL;
static struct utmp ut;
static FILE *ufp = NULL;
static struct utmp ut;
// get next user login record
// (this is defined on everything except BSD)
//
struct utmp *getutent() {
if (ufp == NULL) {
// get next user login record
// (this is defined on everything except BSD)
//
struct utmp *getutent() {
if (ufp == NULL) {
#if defined(UTMP_LOCATION)
if ((ufp = fopen(UTMP_LOCATION, "r")) == NULL) {
if ((ufp = fopen(UTMP_LOCATION, "r")) == NULL) {
#elif defined(UTMP_FILE)
if ((ufp = fopen(UTMP_FILE, "r")) == NULL) {
if ((ufp = fopen(UTMP_FILE, "r")) == NULL) {
#elif defined(_PATH_UTMP)
if ((ufp = fopen(_PATH_UTMP, "r")) == NULL) {
if ((ufp = fopen(_PATH_UTMP, "r")) == NULL) {
#else
if ((ufp = fopen("/etc/utmp", "r")) == NULL) {
if ((ufp = fopen("/etc/utmp", "r")) == NULL) {
#endif
return((struct utmp *)NULL);
}
}
do {
if (fread((char *)&ut, sizeof(ut), 1, ufp) != 1) {
return((struct utmp *)NULL);
}
} while (ut.ut_name[0] == 0);
return(&ut);
}
return((struct utmp *)NULL);
}
}
do {
if (fread((char *)&ut, sizeof(ut), 1, ufp) != 1) {
return((struct utmp *)NULL);
}
} while (ut.ut_name[0] == 0);
return(&ut);
}
void setutent() {
if (ufp != NULL) rewind(ufp);
}
void setutent() {
if (ufp != NULL) rewind(ufp);
}
#endif
// scan list of logged-in users, and see if they're all idle
//
inline bool all_logins_idle(time_t t) {
struct utmp* u;
setutent();
// scan list of logged-in users, and see if they're all idle
//
inline bool all_logins_idle(time_t t) {
struct utmp* u;
setutent();
while ((u = getutent()) != NULL) {
if (!user_idle(t, u)) {
return false;
}
}
return true;
}
while ((u = getutent()) != NULL) {
if (!user_idle(t, u)) {
return false;
}
}
return true;
}
#endif // HAVE_UTMP_H
#ifdef __APPLE__
bool HOST_INFO::users_idle(
bool check_all_logins, double idle_time_to_run, double *actual_idle_time
) {
double idleTime = 0;
if (gEventHandle) {
idleTime = NXIdleTime(gEventHandle);
} else {
// Initialize Mac OS X idle time measurement / idle detection
bool HOST_INFO::users_idle(
bool check_all_logins, double idle_time_to_run, double *actual_idle_time
) {
double idleTime = 0;
if (gEventHandle) {
idleTime = NXIdleTime(gEventHandle);
} else {
// Initialize Mac OS X idle time measurement / idle detection
// Do this here because NXOpenEventStatus() may not be available
// immediately on system startup when running as a deaemon.
gEventHandle = NXOpenEventStatus();
@ -945,7 +1045,7 @@ bool HOST_INFO::users_idle(bool check_all_logins, double idle_time_to_run) {
}
#endif
if (!all_tty_idle(idle_time, "/dev/tty1", '1', 7)) return false;
if (!all_tty_idle(idle_time)) return false;
// According to Frank Thomas (#463) the following may be pointless
//

View File

@ -65,6 +65,7 @@ typedef void (CALLBACK* ClientLibraryShutdown)();
#include "error_numbers.h"
#include "str_util.h"
#include "util.h"
#include "unix_util.h"
#include "prefs.h"
#include "filesys.h"
#include "network.h"

View File

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

View File

@ -56,7 +56,7 @@ endif
libboinc_a_SOURCES = \
app_ipc.C \
base64.C \
coproc.C \
coproc.C \
crypt.C \
diagnostics.C \
filesys.C \
@ -78,6 +78,7 @@ libboinc_a_SOURCES = \
shmem.C \
str_util.C \
util.C \
unix_util.C \
$(mac_sources)
include_HEADERS = \

View File

@ -23,13 +23,17 @@
#ifdef _WIN32
#include "boinc_win.h"
#else
#include "config.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <math.h>
#ifdef solaris
#include <cmath>
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
extern "C" {
int finite(double);
}
#endif
#endif

View File

@ -53,6 +53,12 @@ extern "C" int debug_printf(const char *fmt, ...);
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
// MAP_FILE isn't defined on most operating systems, and even then, it
// is often defined just for the sake of compatibility. On those that
// don't define it, we will....
#ifndef MAP_FILE
#define MAP_FILE 0
#endif
#endif
#include "error_numbers.h"
@ -316,6 +322,7 @@ int destroy_shmem_mmap(key_t key){
return 0;
}
int attach_shmem_mmap(char *path, void** pp) {
int fd, retval;
struct stat sbuf;

View File

@ -30,6 +30,10 @@
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <cctype>
#ifdef HAVE_ALLOCA_H
#include "alloca.h"
#endif
#endif
@ -77,6 +81,59 @@ size_t strlcat(char *dst, const char *src, size_t size) {
}
#endif // !HAVE_STRLCAT
#if !defined(HAVE_STRCASESTR)
extern char *strcasestr(const char *s1, const char *s2) {
char *needle, *haystack, *p=NULL;
// Is alloca() really less likely to fail with out of memory error
// than strdup?
#if defined(HAVE_STRDUPA)
haystack=strdupa(s1);
needle=strdupa(s2);
#elif defined(HAVE_ALLOCA_H) || defined(HAVE_ALLOCA)
haystack=(char *)alloca(strlen(s1)+1);
needle=(char *)alloca(strlen(s2)+1);
if (needle && haystack) {
strlcpy(haystack,s1,strlen(s1)+1);
strlcpy(needle,s2,strlen(s2)+1);
}
#elif defined(HAVE_STRDUP)
haystack=strdup(s1);
needle=strdup(s1)
#else
haystack=(char *)malloc(strlen(s1)+1);
needle=(char *)malloc(strlen(s2)+1);
if (needle && haystack) {
strlcpy(haystack,s1,strlen(s1)+1);
strlcpy(needle,s2,strlen(s2)+1);
}
#endif
if (needle && haystack) {
// convert both strings to lower case
do {
*haystack=tolower(*haystack);
} while (*(++haystack));
do {
*needle=tolower(*needle);
} while (*(++needle));
// find the substring
p=strstr(haystack,needle);
// correct the pointer to point to the substring within s1
if (p) {
// C++ type checking requires const_cast here, although this
// is dangerous if s1 points to read only storage. But the C
// function definitely takes a const char * as the first parameter
// and returns a char *. So that's what we'll do.
p=const_cast<char *>(s1)+(p-haystack);
}
}
#if !defined(HAVE_STRDUPA) && !defined(HAVE_ALLOCA) && !defined(HAVE_ALLOC_H)
// If we didn't allocate on the stack free our strings
if (needle) free(needle);
if (haystack) free(haystack);
#endif
return p;
}
#endif
// Converts a double precision time (where the value of 1 represents
// a day) into a string. smallest_timescale determines the smallest
// unit of time division used

View File

@ -39,6 +39,10 @@ extern size_t strlcpy(char*, const char*, size_t);
extern size_t strlcat(char *dst, const char *src, size_t size);
#endif
#if !defined(HAVE_STRCASESTR)
extern char *strcasestr(const char *s1, const char *s2);
#endif
extern int ndays_to_string(double x, int smallest_timescale, char *buf);
extern void nbytes_to_string(double nbytes, double total_bytes, char* str, int len);
extern int parse_command_line(char*, char**);

59
lib/unix_util.C Normal file
View File

@ -0,0 +1,59 @@
// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
// Copyright (C) 2005 University of California
//
// This is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// To view the GNU Lesser General Public License visit
// http://www.gnu.org/copyleft/lesser.html
// or write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "unix_util.h"
#ifndef HAVE_DAEMON
FILE *stderr_null, *stdout_null;
int daemon(int nochdir, int noclose) {
pid_t childpid,sessionid;
if (!nochdir) {
chdir("/");
}
if (!noclose) {
stderr_null=freopen("/dev/null","w",stderr);
stdout_null=freopen("/dev/null","w",stdout);
}
childpid=fork();
if (childpid>0) {
// Fork successful. We are the parent process.
_exit(0);
}
if (childpid<0) {
// Fork unsuccessful. Return -1
return -1;
}
// Fork successful, We are the child. Make us the lead process of a new
// session.
sessionid=setsid();
if (sessionid <= 0) {
// setsid() failed
return -1;
}
// success
return 0;
}
#endif /* HAVE_DAEMON */

52
lib/unix_util.h Normal file
View File

@ -0,0 +1,52 @@
// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
// Copyright (C) 2005 University of California
//
// This is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// To view the GNU Lesser General Public License visit
// http://www.gnu.org/copyleft/lesser.html
// or write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef UNIX_UTIL_H
#define UNIX_UTIL_H
#include "config.h"
#ifdef __cplusplus
#include <cstdio>
#include <cstdlib>
#else
#include <stdio.h>
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef HAVE_DAEMON
#ifdef __cplusplus
extern "C" {
#endif
int daemon(int nochdir, int noclose);
#ifdef __cplusplus
}
#endif
#endif /* HAVE_DAEMON */
#endif /* UNIX_UTIL_H */

View File

@ -72,7 +72,7 @@ case "${host_cpu}-${host_os}" in
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
acx_pthread_flags="-pthreads -pthread pthread -mt $acx_pthread_flags"
;;
esac

View File

@ -33,6 +33,43 @@ else
MYSQL_CFLAGS=`echo $MYSQL_CFLAGS | sed -e 's|-arch i386||g'`
;;
esac
# on solaris the mysql CFLAGS and LIBS can be messed up because of the
# compiler used in the default installs. So we need to fix them.
case "${host}" in
sparc-sun-solaris*)
old_mysql_cflags="${MYSQL_CFLAGS}"
MYSQL_CFLAGS=
for flag in $old_mysql_cflags ; do
case "${flag}" in
-x*)
echo > /dev/null
;;
-mt)
MYSQL_CFLAGS="${MYSQL_CFLAGS} ${PTHREAD_CFLAGS}"
;;
*)
MYSQL_CFLAGS="${MYSQL_CFLAGS} ${flag}"
;;
esac
done
old_mysql_libs="${MYSQL_LIBS}"
MYSQL_LIBS=
for flag in $old_mysql_libs ; do
case "${flag}" in
-x*)
echo > /dev/null
;;
-mt)
MYSQL_LIBS="${MYSQL_LIBS} ${PTHREAD_LIBS}"
;;
*)
MYSQL_LIBS="${MYSQL_LIBS} ${flag}"
;;
esac
done
;;
esac
AC_MSG_RESULT($MYSQL_CFLAGS)
no_mysql=no
fi

View File

@ -249,6 +249,74 @@ AC_DEFUN([AM_PATH_WXCONFIG],
fi
# on solaris the wx CFLAGS and LIBS can be messed up because of the compiler
# used in the default installs. So we need to fix them.
case "${host}" in
sparc-sun-solaris*)
old_wx_cflags="${WX_CFLAGS}"
WX_CFLAGS=
for flag in $old_wx_cflags ; do
case "${flag}" in
-x*)
echo > /dev/null
;;
-mt)
WX_CFLAGS="${WX_CFLAGS} ${PTHREAD_CFLAGS}"
;;
*)
WX_CFLAGS="${WX_CFLAGS} ${flag}"
;;
esac
done
old_wx_cppflags="${WX_CPPFLAGS}"
WX_CPPFLAGS=
for flag in $old_wx_cppflags ; do
case "${flag}" in
-x*)
echo > /dev/null
;;
-mt)
WX_CPPFLAGS="${WX_CPPFLAGS} ${PTHREAD_CFLAGS}"
;;
*)
WX_CPPFLAGS="${WX_CPPFLAGS} ${flag}"
;;
esac
done
old_wx_cxxflags="${WX_CXXFLAGS}"
WX_CXXFLAGS=
for flag in $old_wx_cxxflags ; do
case "${flag}" in
-x*)
echo > /dev/null
;;
-mt)
WX_CXXFLAGS="${WX_CXXFLAGS} ${PTHREAD_CFLAGS}"
;;
*)
WX_CXXFLAGS="${WX_CXXFLAGS} ${flag}"
;;
esac
done
old_wx_libs="${WX_LIBS}"
WX_LIBS=
for flag in $old_wx_libs ; do
case "${flag}" in
-x*)
echo > /dev/null
;;
-mt)
WX_LIBS="${WX_LIBS} ${PTHREAD_LIBS}"
;;
*)
WX_LIBS="${WX_LIBS} ${flag}"
;;
esac
done
;;
esac
AC_SUBST(WX_CPPFLAGS)
AC_SUBST(WX_CFLAGS)
AC_SUBST(WX_CXXFLAGS)