~ubuntu-branches/ubuntu/precise/boinc/precise

« back to all changes in this revision

Viewing changes to client/hostinfo_unix.cpp

Tags: 6.12.8+dfsg-1
* New upstream release.
* Simplified debian/rules

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
#include <cstring>
52
52
#endif
53
53
 
54
 
 
55
 
 
56
 
 
57
54
#include <cstdio>
58
55
#include <cstdlib>
59
56
#include <cstring>
103
100
#include "win/opt_x86.h"
104
101
#endif
105
102
 
106
 
#include "client_types.h"
 
103
#include "error_numbers.h"
107
104
#include "filesys.h"
108
 
#include "error_numbers.h"
109
105
#include "str_util.h"
 
106
#include "str_replace.h"
 
107
#include "util.h"
 
108
 
110
109
#include "client_state.h"
 
110
#include "client_types.h"
 
111
#include "client_msgs.h"
111
112
#include "hostinfo_network.h"
112
 
#include "client_msgs.h"
113
113
 
114
114
using std::string;
115
115
 
125
125
}    // extern "C"
126
126
#endif
127
127
 
128
 
NXEventHandle gEventHandle = NULL;
 
128
mach_port_t gEventHandle = NULL;
129
129
#endif  // __APPLE__
130
130
 
131
131
#ifdef _HPUX_SOURCE
140
140
#include <machine/cpuconf.h>
141
141
#endif
142
142
 
 
143
#ifdef __HAIKU__
 
144
#include <OS.h>
 
145
#endif
 
146
 
 
147
// Some OS define _SC_PAGE_SIZE instead of _SC_PAGESIZE
 
148
#if defined(_SC_PAGE_SIZE) && !defined(_SC_PAGESIZE)
 
149
#define _SC_PAGESIZE _SC_PAGE_SIZE
 
150
#endif
 
151
 
143
152
// The following is intended to be true both on Linux
144
153
// and Debian GNU/kFreeBSD (see trac #521)
145
154
//
146
 
#define LINUX_LIKE_SYSTEM defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)
 
155
#define LINUX_LIKE_SYSTEM (defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(__HAIKU__)
147
156
 
148
157
// functions to get name/addr of local host
149
158
 
292
301
        // if we haven't found a method so far, give up
293
302
        method = NoBattery;
294
303
        // fall through
295
 
    case NoBattery:
296
 
         // we have no way to determine if we're on batteries,
297
 
         // so we say we aren't
298
 
        return false;
299
304
    case ProcAPM:
300
305
        {
301
306
            // use /proc/apm
351
356
            // online is 1 if on AC power, 0 if on battery
352
357
            return (0 == online);
353
358
        }
 
359
    case NoBattery:
 
360
    default:
 
361
         // we have no way to determine if we're on batteries,
 
362
         // so we say we aren't
 
363
        return false;
354
364
    }
355
365
#else
356
366
    return false;
363
373
    double x;
364
374
    FILE* f = fopen("/proc/meminfo", "r");
365
375
    if (!f) {
366
 
        msg_printf(NULL, MSG_USER_ERROR,
367
 
            "Can't open /proc/meminfo - defaulting to 1 GB."
 
376
        msg_printf(NULL, MSG_INFO,
 
377
            "Can't open /proc/meminfo to get memory size - defaulting to 1 GB."
368
378
        );
369
379
        host.m_nbytes = GIGA;
370
380
        host.m_swap = GIGA;
393
403
    char buf[256], features[1024], model_buf[1024];
394
404
    bool vendor_found=false, model_found=false;
395
405
    bool cache_found=false, features_found=false;
396
 
    bool icache_found=false,dcache_found=false;
397
406
    bool model_hack=false, vendor_hack=false;
398
407
    int n;
399
408
    int family=-1, model=-1, stepping=-1;
401
410
 
402
411
    FILE* f = fopen("/proc/cpuinfo", "r");
403
412
    if (!f) {
404
 
        msg_printf(NULL, MSG_USER_ERROR, "Can't open /proc/cpuinfo.");
 
413
        msg_printf(NULL, MSG_INFO,
 
414
            "Can't open /proc/cpuinfo to get CPU info"
 
415
        );
405
416
        strcpy(host.p_model, "unknown");
406
417
        strcpy(host.p_vendor, "unknown");
407
418
        return;
506
517
            stepping = atoi(buf+strlen("stepping\t: "));
507
518
        }
508
519
#ifdef __hppa__
 
520
        bool icache_found=false,dcache_found=false;
509
521
        if (!icache_found && strstr(buf, "I-cache\t\t: ")) {
510
522
            icache_found = true;
511
523
            sscanf(buf, "I-cache\t\t: %d", &n);
646
658
        brand_string, family, model, stepping
647
659
    );
648
660
#else       // PowerPC
649
 
    char capabilities[256], model[256];
 
661
    char model[256];
650
662
    int response = 0;
651
663
    int retval;
652
664
    len = sizeof(response);
653
 
    safe_strcpy(host.p_vendor, "Power Macintosh");
654
665
    retval = sysctlbyname("hw.optional.altivec", &response, &len, NULL, 0);
655
666
    if (response && (!retval)) {
656
 
        safe_strcpy(capabilities, "AltiVec");
 
667
        safe_strcpy(host.p_features, "AltiVec");
657
668
    }
658
669
        
659
670
    len = sizeof(model);
660
671
    sysctlbyname("hw.model", model, &len, NULL, 0);
661
672
 
662
 
    snprintf(host.p_model, p_model_size, "%s [%s Model %s] [%s]", host.p_vendor, host.p_vendor, model, capabilities);
 
673
    safe_strcpy(host.p_vendor, "Power Macintosh");
 
674
    snprintf(host.p_model, p_model_size, "%s [%s Model %s] [%s]", host.p_vendor, host.p_vendor, model, host.p_features);
663
675
 
664
676
#endif
665
677
 
675
687
}
676
688
#endif
677
689
 
 
690
#ifdef __HAIKU__
 
691
static void get_cpu_info_haiku(HOST_INFO& host) {
 
692
    /* This function has been adapted from Haiku's sysinfo.c
 
693
     * which spits out a bunch of formatted CPU info to
 
694
     * the terminal, it was easier to copy some of the logic
 
695
     * here.
 
696
     */
 
697
    system_info sys_info;
 
698
    int32 cpu = 0; // always use first CPU for now
 
699
    cpuid_info cpuInfo;
 
700
    int32 maxStandardFunction;
 
701
    int32 maxExtendedFunction = 0;
 
702
    
 
703
    char brand_string[256];
 
704
 
 
705
    if (get_system_info(&sys_info) != B_OK) {
 
706
        msg_printf(NULL, MSG_INTERNAL_ERROR, "Error getting Haiku system information!\n");
 
707
        return;
 
708
    }
 
709
 
 
710
    if (get_cpuid(&cpuInfo, 0, cpu) != B_OK) {
 
711
        // this CPU doesn't support cpuid
 
712
        return;
 
713
    }
 
714
        
 
715
    snprintf(host.p_vendor, sizeof(host.p_vendor), "%.12s",
 
716
        cpuInfo.eax_0.vendor_id);
 
717
    
 
718
    maxStandardFunction = cpuInfo.eax_0.max_eax;
 
719
    if (maxStandardFunction >= 500)
 
720
        maxStandardFunction = 0; /* old Pentium sample chips has
 
721
                                    cpu signature here */
 
722
 
 
723
    /* Extended cpuid */
 
724
    get_cpuid(&cpuInfo, 0x80000000, cpu);
 
725
 
 
726
    // extended cpuid is only supported if max_eax is greater
 
727
    // than the service id
 
728
    if (cpuInfo.eax_0.max_eax > 0x80000000)
 
729
        maxExtendedFunction = cpuInfo.eax_0.max_eax & 0xff;
 
730
 
 
731
    if (maxExtendedFunction >=4 ) {
 
732
        char buffer[49];
 
733
        char *name = buffer;
 
734
        int32 i;
 
735
 
 
736
        memset(buffer, 0, sizeof(buffer));
 
737
 
 
738
        for (i = 0; i < 3; i++) {
 
739
            cpuid_info nameInfo;
 
740
            get_cpuid(&nameInfo, 0x80000002 + i, cpu);
 
741
 
 
742
            memcpy(name, &nameInfo.regs.eax, 4);
 
743
            memcpy(name + 4, &nameInfo.regs.ebx, 4);
 
744
            memcpy(name + 8, &nameInfo.regs.ecx, 4);
 
745
            memcpy(name + 12, &nameInfo.regs.edx, 4);
 
746
            name += 16;
 
747
        }
 
748
 
 
749
        // cut off leading spaces (names are right aligned)
 
750
        name = buffer;
 
751
        while (name[0] == ' ')
 
752
            name++;
 
753
 
 
754
        // the BIOS may not have set the processor name
 
755
        if (name[0]) {
 
756
            strlcpy(brand_string, name, sizeof(brand_string));
 
757
        } else {
 
758
            // Intel CPUs don't seem to have the genuine vendor field
 
759
            snprintf(brand_string, sizeof(brand_string), "%.12s",
 
760
                cpuInfo.eax_0.vendor_id);
 
761
        }
 
762
    }
 
763
 
 
764
    get_cpuid(&cpuInfo, 1, cpu);
 
765
        
 
766
    int family, stepping, model;
 
767
 
 
768
    family = cpuInfo.eax_1.family + (cpuInfo.eax_1.family == 0xf ?
 
769
        cpuInfo.eax_1.extended_family : 0);
 
770
 
 
771
    // model calculation is different for AMD and INTEL
 
772
    if ((sys_info.cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_AMD_x86) {
 
773
        model = cpuInfo.eax_1.model + (cpuInfo.eax_1.model == 0xf ?
 
774
            cpuInfo.eax_1.extended_model << 4 : 0);
 
775
    } else if ((sys_info.cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86) {
 
776
        model = cpuInfo.eax_1.model + ((cpuInfo.eax_1.family == 0xf ||
 
777
            cpuInfo.eax_1.family == 0x6) ? cpuInfo.eax_1.extended_model << 4 : 0);
 
778
    }
 
779
 
 
780
    stepping = cpuInfo.eax_1.stepping;
 
781
 
 
782
    snprintf(host.p_model, sizeof(host.p_model),
 
783
        "%s [Family %u Model %u Stepping %u]", brand_string, family, model,
 
784
        stepping);
 
785
 
 
786
    static const char *kFeatures[32] = {
 
787
        "fpu", "vme", "de", "pse",
 
788
        "tsc", "msr", "pae", "mce",
 
789
        "cx8", "apic", NULL, "sep",
 
790
        "mtrr", "pge", "mca", "cmov",
 
791
        "pat", "pse36", "psnum", "clflush",
 
792
        NULL, "ds", "acpi", "mmx",
 
793
        "fxsr", "sse", "sse2", "ss",
 
794
        "htt", "tm", "ia64", "pbe",
 
795
    };
 
796
 
 
797
    int32 found = 0;
 
798
    int32 i;
 
799
    char buf[12];
 
800
 
 
801
    for (i = 0; i < 32; i++) {
 
802
        if ((cpuInfo.eax_1.features & (1UL << i)) && kFeatures[i] != NULL) {
 
803
            snprintf(buf, sizeof(buf), "%s%s", found == 0 ? "" : " ", 
 
804
                kFeatures[i]);
 
805
            strlcat(host.p_features, buf, sizeof(host.p_features));
 
806
            found++;
 
807
        }
 
808
    }
 
809
 
 
810
    if (maxStandardFunction >= 1) {
 
811
        /* Extended features */
 
812
        static const char *kFeatures2[32] = {
 
813
            "sse3", NULL, "dtes64", "monitor", "ds-cpl", "vmx", "smx" "est",
 
814
            "tm2", "ssse3", "cnxt-id", NULL, NULL, "cx16", "xtpr", "pdcm",
 
815
            NULL, NULL, "dca", "sse4.1", "sse4.2", "x2apic", "movbe", "popcnt",
 
816
            NULL, NULL, "xsave", "osxsave", NULL, NULL, NULL, NULL
 
817
        };
 
818
 
 
819
        for (i = 0; i < 32; i++) {
 
820
            if ((cpuInfo.eax_1.extended_features & (1UL << i)) &&
 
821
                kFeatures2[i] != NULL) {
 
822
                snprintf(buf, sizeof(buf), "%s%s", found == 0 ? "" : " ",
 
823
                    kFeatures2[i]);
 
824
                strlcat(host.p_features, buf, sizeof(host.p_features));
 
825
                found++;
 
826
            }
 
827
        }
 
828
    }
 
829
 
 
830
    //TODO: there are additional AMD features that probably need to be queried
 
831
}
 
832
#endif
 
833
 
 
834
 
 
835
// Note: this may also work on other UNIX-like systems in addition to Macintosh
 
836
#ifdef __APPLE__
 
837
 
 
838
#include <net/if.h>
 
839
#include <net/if_dl.h>
 
840
#include <net/route.h>
 
841
 
 
842
// detect the network usage totals for the host.
 
843
//
 
844
int get_network_usage_totals(unsigned int& total_received, unsigned int& total_sent) {
 
845
        static size_t  sysctlBufferSize = 0;
 
846
        static uint8_t *sysctlBuffer = NULL;
 
847
 
 
848
        int     mib[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
 
849
    struct if_msghdr *ifmsg;
 
850
        size_t currentSize = 0;
 
851
 
 
852
    total_received = 0;
 
853
    total_sent = 0;
 
854
    
 
855
    if (sysctl(mib, 6, NULL, &currentSize, NULL, 0) != 0) return errno;
 
856
    if (!sysctlBuffer || (currentSize > sysctlBufferSize)) {
 
857
        if (sysctlBuffer) free(sysctlBuffer);
 
858
        sysctlBufferSize = 0;
 
859
        sysctlBuffer = (uint8_t*)malloc(currentSize);
 
860
        if (!sysctlBuffer) return ERR_MALLOC;
 
861
        sysctlBufferSize = currentSize;
 
862
    }
 
863
    
 
864
    // Read in new data
 
865
    if (sysctl(mib, 6, sysctlBuffer, &currentSize, NULL, 0) != 0) return errno;
 
866
    
 
867
    // Walk through the reply 
 
868
    uint8_t *currentData = sysctlBuffer;
 
869
    uint8_t *currentDataEnd = sysctlBuffer + currentSize;
 
870
 
 
871
    while (currentData < currentDataEnd) {
 
872
        // Expecting interface data
 
873
        ifmsg = (struct if_msghdr *)currentData;
 
874
        if (ifmsg->ifm_type != RTM_IFINFO) {
 
875
            currentData += ifmsg->ifm_msglen;
 
876
            continue;
 
877
        }
 
878
        // Must not be loopback
 
879
        if (ifmsg->ifm_flags & IFF_LOOPBACK) {
 
880
            currentData += ifmsg->ifm_msglen;
 
881
            continue;
 
882
        }
 
883
        // Only look at link layer items
 
884
        struct sockaddr_dl *sdl = (struct sockaddr_dl *)(ifmsg + 1);
 
885
        if (sdl->sdl_family != AF_LINK) {
 
886
            currentData += ifmsg->ifm_msglen;
 
887
            continue;
 
888
        }
 
889
        
 
890
#if 0   // Use this code if we want only Ethernet interface 0
 
891
        if (!strcmp(sdl->sdl_data, "en0")) {
 
892
            total_received = ifmsg->ifm_data.ifi_ibytes;
 
893
            total_sent = ifmsg->ifm_data.ifi_obytes;
 
894
            return 0;
 
895
        }
 
896
#else   // Use this code if we want total of all non-loopback interfaces
 
897
        total_received += ifmsg->ifm_data.ifi_ibytes;
 
898
        total_sent += ifmsg->ifm_data.ifi_obytes;
 
899
#endif
 
900
    }
 
901
        
 
902
    return 0;
 
903
}
 
904
 
 
905
 
 
906
#if defined(__i386__) || defined(__x86_64__)
 
907
 
 
908
// Code to get maximum CPU temperature (Apple Intel only)
 
909
// Adapted from Apple System Management Control (SMC) Tool under the GPL
 
910
 
 
911
#define KERNEL_INDEX_SMC      2
 
912
 
 
913
#define SMC_CMD_READ_BYTES    5
 
914
#define SMC_CMD_READ_KEYINFO  9
 
915
 
 
916
typedef struct {
 
917
    char                  major;
 
918
    char                  minor;
 
919
    char                  build;
 
920
    char                  reserved[1]; 
 
921
    UInt16                release;
 
922
} SMCKeyData_vers_t;
 
923
 
 
924
typedef struct {
 
925
    UInt16                version;
 
926
    UInt16                length;
 
927
    UInt32                cpuPLimit;
 
928
    UInt32                gpuPLimit;
 
929
    UInt32                memPLimit;
 
930
} SMCKeyData_pLimitData_t;
 
931
 
 
932
typedef struct {
 
933
    UInt32                dataSize;
 
934
    UInt32                dataType;
 
935
    char                  dataAttributes;
 
936
} SMCKeyData_keyInfo_t;
 
937
 
 
938
typedef char              SMCBytes_t[32]; 
 
939
 
 
940
typedef struct {
 
941
  UInt32                  key; 
 
942
  SMCKeyData_vers_t       vers; 
 
943
  SMCKeyData_pLimitData_t pLimitData;
 
944
  SMCKeyData_keyInfo_t    keyInfo;
 
945
  char                    result;
 
946
  char                    status;
 
947
  char                    data8;
 
948
  UInt32                  data32;
 
949
  SMCBytes_t              bytes;
 
950
} SMCKeyData_t;
 
951
 
 
952
static io_connect_t conn;
 
953
 
 
954
kern_return_t SMCOpen()
 
955
{
 
956
    kern_return_t       result;
 
957
    mach_port_t         masterPort;
 
958
    io_iterator_t       iterator;
 
959
    io_object_t         device;
 
960
 
 
961
    result = IOMasterPort(MACH_PORT_NULL, &masterPort);
 
962
 
 
963
    CFMutableDictionaryRef matchingDictionary = IOServiceMatching("AppleSMC");
 
964
    result = IOServiceGetMatchingServices(masterPort, matchingDictionary, &iterator);
 
965
    if (result != kIOReturnSuccess)
 
966
    {
 
967
        return result;
 
968
    }
 
969
 
 
970
    device = IOIteratorNext(iterator);
 
971
    IOObjectRelease(iterator);
 
972
    if (device == 0)
 
973
    {
 
974
        return result;
 
975
    }
 
976
 
 
977
    result = IOServiceOpen(device, mach_task_self(), 0, &conn);
 
978
    IOObjectRelease(device);
 
979
    if (result != kIOReturnSuccess)
 
980
    {
 
981
        return result;
 
982
    }
 
983
 
 
984
    return kIOReturnSuccess;
 
985
}
 
986
 
 
987
kern_return_t SMCClose()
 
988
{
 
989
    if (conn) {
 
990
        return IOServiceClose(conn);
 
991
    }
 
992
    return kIOReturnSuccess;
 
993
}
 
994
 
 
995
 
 
996
kern_return_t SMCReadKey(UInt32 key, SMCBytes_t val)
 
997
{
 
998
    kern_return_t       result;
 
999
    SMCKeyData_t        inputStructure;
 
1000
    SMCKeyData_t        outputStructure;
 
1001
        size_t              structureInputSize;
 
1002
    size_t              structureOutputSize;
 
1003
 
 
1004
    memset(&inputStructure, 0, sizeof(SMCKeyData_t));
 
1005
    memset(&outputStructure, 0, sizeof(SMCKeyData_t));
 
1006
    memset(val, 0, sizeof(val));
 
1007
 
 
1008
    inputStructure.key = key;
 
1009
    inputStructure.data8 = SMC_CMD_READ_KEYINFO;    
 
1010
 
 
1011
    structureInputSize = sizeof(inputStructure);
 
1012
    structureOutputSize = sizeof(outputStructure);
 
1013
        result = IOConnectMethodStructureIStructureO(
 
1014
                    conn, KERNEL_INDEX_SMC, structureInputSize, &structureOutputSize, 
 
1015
                    &inputStructure, &outputStructure
 
1016
            );
 
1017
    if (result != kIOReturnSuccess)
 
1018
        return result;
 
1019
 
 
1020
    inputStructure.keyInfo.dataSize = outputStructure.keyInfo.dataSize;
 
1021
    inputStructure.data8 = SMC_CMD_READ_BYTES;
 
1022
 
 
1023
        result = IOConnectMethodStructureIStructureO(
 
1024
                    conn, KERNEL_INDEX_SMC, structureInputSize, &structureOutputSize, 
 
1025
                    &inputStructure, &outputStructure
 
1026
            );
 
1027
    if (result != kIOReturnSuccess)
 
1028
        return result;
 
1029
 
 
1030
    memcpy(val, outputStructure.bytes, sizeof(outputStructure.bytes));
 
1031
 
 
1032
    return kIOReturnSuccess;
 
1033
}
 
1034
 
 
1035
 
 
1036
// Check up to 10 die temperatures (TC0D, TC1D, etc.) and 
 
1037
// 10 heatsink temperatures (TCAH, TCBH, etc.)
 
1038
// Returns the highest current CPU temperature as degrees Celsius.
 
1039
// Returns zero if it fails (or on a PowerPC Mac).
 
1040
int get_max_cpu_temperature() {
 
1041
    kern_return_t       result;
 
1042
    int                 maxTemp = 0, thisTemp, i;
 
1043
    union tempKey {
 
1044
        UInt32          word;
 
1045
        char            bytes[4];
 
1046
    };
 
1047
    tempKey             key;
 
1048
    SMCBytes_t          val;
 
1049
    static bool         skip[20];
 
1050
 
 
1051
    // open connection to SMC kext if this is the first time
 
1052
    if (!conn) {
 
1053
        result = SMCOpen();
 
1054
        if (result != kIOReturnSuccess) {
 
1055
            return 0;
 
1056
        }
 
1057
    }
 
1058
 
 
1059
    for (i=0; i<20; ++i) {
 
1060
        if (skip[i]) continue;
 
1061
        if (i < 10) {
 
1062
            key.word = 'TC0D';
 
1063
            key.bytes[1] += i;          // TC0D, TC1D, TC2D, etc.
 
1064
        } else {
 
1065
            key.word = 'TCAH';
 
1066
            key.bytes[1] += (i - 10);   // TCAH, TCBH, TCCH, etc.
 
1067
        }
 
1068
        result = SMCReadKey(key.word, val);
 
1069
        if (result != kIOReturnSuccess) {
 
1070
            skip[i] = true;
 
1071
            continue;
 
1072
        }
 
1073
        
 
1074
        if (val[0] < 1) {
 
1075
            skip[i] = true;
 
1076
            continue;
 
1077
        }
 
1078
        
 
1079
        thisTemp = val[0];
 
1080
        if (val[1] & 0x80) ++thisTemp;
 
1081
        if (thisTemp > maxTemp) {
 
1082
            maxTemp = thisTemp;
 
1083
        }
 
1084
    }
 
1085
    
 
1086
    return maxTemp;
 
1087
}
 
1088
 
 
1089
#else       // PowerPC
 
1090
 
 
1091
int GetMaxCPUTemperature() {
 
1092
    return 0;
 
1093
}
 
1094
 
 
1095
#endif
 
1096
#endif  // __APPLE__
 
1097
 
 
1098
// see if Virtualbox is installed
 
1099
//
 
1100
int HOST_INFO::get_virtualbox_version() {
 
1101
    char path[MAXPATHLEN];
 
1102
    char cmd [MAXPATHLEN+35];
 
1103
    char *newlinePtr;
 
1104
    FILE* fd;
 
1105
 
 
1106
#if LINUX_LIKE_SYSTEM
 
1107
    strcpy(path, "/usr/lib/virtualbox/VBoxManage");
 
1108
#elif defined( __APPLE__)
 
1109
    FSRef theFSRef;
 
1110
    OSStatus status = noErr;
 
1111
 
 
1112
    // First try to locate the VirtualBox application by Bundle ID and Creator Code
 
1113
    status = LSFindApplicationForInfo('VBOX', CFSTR("org.virtualbox.app.VirtualBox"),   
 
1114
                                        NULL, &theFSRef, NULL
 
1115
                                    );
 
1116
    if (status == noErr) {
 
1117
        status = FSRefMakePath(&theFSRef, (unsigned char *)path, sizeof(path));
 
1118
    }
 
1119
    // If that failed, try its default location
 
1120
    if (status != noErr) {
 
1121
        strcpy(path, "/Applications/VirtualBox.app");
 
1122
    }
 
1123
#endif
 
1124
 
 
1125
    if (boinc_file_exists(path)) {
 
1126
#if LINUX_LIKE_SYSTEM
 
1127
        safe_strcpy(cmd, path);
 
1128
        safe_strcat(cmd, " --version");
 
1129
#elif defined( __APPLE__)
 
1130
        safe_strcpy(cmd, "defaults read ");
 
1131
        safe_strcat(cmd, path);
 
1132
        safe_strcat(cmd, "/Contents/Info CFBundleShortVersionString");
 
1133
#endif
 
1134
        fd = popen(cmd, "r");
 
1135
        if (fd) {
 
1136
            fgets(virtualbox_version, sizeof(virtualbox_version), fd);
 
1137
            newlinePtr = strchr(virtualbox_version, '\n');
 
1138
            if (newlinePtr) *newlinePtr = '\0';
 
1139
            newlinePtr = strchr(virtualbox_version, '\r');
 
1140
            if (newlinePtr) *newlinePtr = '\0';
 
1141
            pclose(fd);
 
1142
        }
 
1143
    }
 
1144
 
 
1145
    return 0;
 
1146
}
 
1147
 
678
1148
// Rules:
679
1149
// - Keep code in the right place
680
1150
// - only one level of #if
681
1151
//
682
1152
int HOST_INFO::get_host_info() {
683
1153
    get_filesystem_info(d_total, d_free);
 
1154
    get_virtualbox_version();
684
1155
 
685
1156
///////////// p_vendor, p_model, p_features /////////////////
686
1157
#if LINUX_LIKE_SYSTEM
694
1165
    CPU_INFO_t    cpuInfo;
695
1166
    strlcpy( p_vendor, cpuInfo.vendor.company, sizeof(p_vendor));
696
1167
    strlcpy( p_model, cpuInfo.name.fromID, sizeof(p_model));
 
1168
#elif defined(__HAIKU__)
 
1169
    get_cpu_info_haiku(*this);
697
1170
#elif defined(HAVE_SYS_SYSCTL_H)
698
1171
    int mib[2];
699
1172
    size_t len;
700
1173
 
701
1174
    // Get machine
 
1175
#ifdef IRIX
 
1176
    mib[0] = 0;
 
1177
    mib[1] = 1;
 
1178
#else
702
1179
    mib[0] = CTL_HW;
703
1180
    mib[1] = HW_MACHINE;
 
1181
#endif
704
1182
    len = sizeof(p_vendor);
705
1183
    sysctl(mib, 2, &p_vendor, &len, NULL, 0);
706
1184
 
707
1185
    // Get model
 
1186
#ifdef IRIX
 
1187
    mib[0] = 0;
 
1188
    mib[1] = 1;
 
1189
#else
708
1190
    mib[0] = CTL_HW;
709
1191
    mib[1] = HW_MODEL;
 
1192
#endif
710
1193
    len = sizeof(p_model);
711
1194
    sysctl(mib, 2, &p_model, &len, NULL, 0);
712
1195
#elif defined(__osf__)
872
1355
    statfs(".", &fs_info);
873
1356
    m_swap = (double)fs_info.f_bsize * (double)fs_info.f_bfree;
874
1357
 
 
1358
#elif defined(__HAIKU__)
 
1359
#warning HAIKU: missing swapfile size info
875
1360
#elif defined(HAVE_VMMETER_H) && defined(HAVE_SYS_SYSCTL_H) && defined(CTL_VM) && defined(VM_METER)
876
1361
    // MacOSX, I think...
877
1362
    // <http://www.osxfaq.com/man/3/sysctl.ws>
906
1391
    struct utsname u;
907
1392
    uname(&u);
908
1393
    safe_strcpy(os_name, u.sysname);
909
 
#ifdef __EMX__ // OS2: version is in u.version
 
1394
#if defined(__EMX__) // OS2: version is in u.version
910
1395
    safe_strcpy(os_version, u.version);
 
1396
#elif defined(__HAIKU__)
 
1397
    snprintf(os_version, sizeof(os_version), "%s, %s", u.release, u.version); 
911
1398
#else
912
1399
    safe_strcpy(os_version, u.release);
913
1400
#endif
1073
1560
 
1074
1561
#ifdef __APPLE__
1075
1562
 
 
1563
// NXIdleTime() is an undocumented Apple API to return user idle time, which 
 
1564
// was implemented from before OS 10.0 through OS 10.5.  In OS 10.4, Apple 
 
1565
// added the CGEventSourceSecondsSinceLastEventType() API as a replacement for 
 
1566
// NXIdleTime().  However, BOINC could not use this newer API when configured 
 
1567
// as a pre-login launchd daemon unless that daemon was running as root, 
 
1568
// because it could not connect to the Window Server.  So BOINC continued to 
 
1569
// use NXIdleTime().  
 
1570
//
 
1571
// In OS 10.6, Apple removed the NXIdleTime() API.  BOINC can instead use the 
 
1572
// IOHIDGetParameter() API in OS 10.6.  When BOINC is a pre-login launchd 
 
1573
// daemon running as user boinc_master, this API works properly under OS 10.6 
 
1574
// but fails under OS 10.5 and earlier.
 
1575
//
 
1576
// So we use weak-linking of NxIdleTime() to prevent a run-time crash from the 
 
1577
// dynamic linker, and use the IOHIDGetParameter() API if NXIdleTime does not 
 
1578
// exist.
 
1579
//
1076
1580
bool HOST_INFO::users_idle(
1077
1581
    bool check_all_logins, double idle_time_to_run, double *actual_idle_time
1078
1582
) {
1079
 
    double idleTime = 0;
1080
 
      
1081
 
    if (gEventHandle) {
1082
 
        idleTime = NXIdleTime(gEventHandle);    
1083
 
    } else {
1084
 
        // Initialize Mac OS X idle time measurement / idle detection
1085
 
        // Do this here because NXOpenEventStatus() may not be available 
1086
 
        // immediately on system startup when running as a deaemon.
1087
 
        gEventHandle = NXOpenEventStatus();
1088
 
    }
 
1583
    static bool     error_posted = false;
 
1584
    double          idleTime = 0;
 
1585
    io_service_t    service;
 
1586
    kern_return_t   kernResult = kIOReturnError; 
 
1587
    UInt64          params;
 
1588
    IOByteCount     rcnt = sizeof(UInt64);
 
1589
            
 
1590
    if (error_posted) goto bail;
 
1591
 
 
1592
    if (NXIdleTime) {   // Use NXIdleTime API in OS 10.5 and earlier
 
1593
        if (gEventHandle) {
 
1594
            idleTime = NXIdleTime(gEventHandle);    
 
1595
        } else {
 
1596
            // Initialize Mac OS X idle time measurement / idle detection
 
1597
            // Do this here because NXOpenEventStatus() may not be available 
 
1598
            // immediately on system startup when running as a deaemon.
 
1599
            
 
1600
            gEventHandle = NXOpenEventStatus();
 
1601
            if (!gEventHandle) {
 
1602
                if (TickCount() > (120*60)) {        // If system has been up for more than 2 minutes 
 
1603
                     msg_printf(NULL, MSG_INFO,
 
1604
                        "User idle detection is disabled: initialization failed."
 
1605
                    );
 
1606
                    error_posted = true;
 
1607
                    goto bail;
 
1608
                }
 
1609
            }
 
1610
        }
 
1611
    } else {        // NXIdleTime API does not exist in OS 10.6 and later
 
1612
        if (gEventHandle) {
 
1613
            kernResult = IOHIDGetParameter( gEventHandle, CFSTR(EVSIOIDLE), sizeof(UInt64), &params, &rcnt );
 
1614
            if ( kernResult != kIOReturnSuccess ) {
 
1615
                msg_printf(NULL, MSG_INFO,
 
1616
                    "User idle time measurement failed because IOHIDGetParameter failed."
 
1617
                );
 
1618
                error_posted = true;
 
1619
                goto bail;
 
1620
            }
 
1621
            idleTime = ((double)params) / 1000.0 / 1000.0 / 1000.0;
 
1622
        } else {
 
1623
            service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass));
 
1624
            if (service) {
 
1625
                 kernResult = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &gEventHandle);
 
1626
            }
 
1627
            if ( (!service) || (kernResult != KERN_SUCCESS) ) {
 
1628
                // When the system first starts up, allow time for HIDSystem to be available if needed
 
1629
                if (TickCount() > (120*60)) {        // If system has been up for more than 2 minutes 
 
1630
                     msg_printf(NULL, MSG_INFO,
 
1631
                        "Could not connect to HIDSystem: user idle detection is disabled."
 
1632
                    );
 
1633
                    error_posted = true;
 
1634
                    goto bail;
 
1635
                }
 
1636
            }
 
1637
        }   // End gEventHandle == NULL
 
1638
    }       // End NXIdleTime API does not exist
1089
1639
    
 
1640
 bail:   
1090
1641
    if (actual_idle_time) {
1091
1642
        *actual_idle_time = idleTime;
1092
1643
    }
1164
1715
 
1165
1716
#endif  // ! __APPLE__
1166
1717
 
1167
 
const char *BOINC_RCSID_2cf92d205b = "$Id: hostinfo_unix.cpp 16117 2008-10-02 21:25:40Z boincadm $";