Example #1
0
// M$-Windows implementation of Screen('Computer'): This is very rudimentary for now.
// We only report the operating sytem type (="Windows") and MAC-Address, but don't report any more useful
// information. MAC query does not work yet - We do not have the neccessary libraries to compile the code :(
PsychError SCREENComputer(void)
{
    // Info struct for queries to OS:
    OSVERSIONINFO osvi;
    char versionString[256];

    // const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "kern", "hw", "processUserLongName", 
    //      "processUserShortName", "consoleUserName", "machineName", "localHostName", "location", "MACAddress", "system" };
    const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "system", "IsVistaClass", "gstreamer", "supported"};

    const char *kernStructFieldNames[]={"ostype", "osrelease", "osrevision", "version","hostname"};
    const char *hwStructFieldNames[]={"machine", "model", "ncpu", "physmem", "usermem", "busfreq", "cpufreq"};
    int numMajorStructDimensions=1, numKernStructDimensions=1, numHwStructDimensions=1;
    int numMajorStructFieldNames=8, numKernStructFieldNames=5, numHwStructFieldNames=7;

    PsychGenericScriptType *majorStruct;
    //all subfunctions should have these two lines
    PsychPushHelp(useString, synopsisString, seeAlsoString);
    if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};

    PsychErrorExit(PsychCapNumOutputArgs(1));
    PsychErrorExit(PsychCapNumInputArgs(0));

    //fill the major struct 
    PsychAllocOutStructArray(1, FALSE, numMajorStructDimensions, numMajorStructFieldNames, majorStructFieldNames, &majorStruct);
    PsychSetStructArrayDoubleElement("macintosh", 0, 0, majorStruct);
    PsychSetStructArrayDoubleElement("windows", 0, 1, majorStruct);
    PsychSetStructArrayDoubleElement("linux", 0, 0, majorStruct);
    PsychSetStructArrayDoubleElement("osx", 0, 0, majorStruct);

    // Official support status:
    PsychSetStructArrayStringElement("supported", 0, (char*) PsychSupportStatus(), majorStruct);

    // GStreamer availability and rough version:
    #if defined(PTB_USE_GSTREAMER)
        #if GST_CHECK_VERSION(1,0,0)
        PsychSetStructArrayDoubleElement("gstreamer", 0, 1 * 10000 + 0 * 100 + 0, majorStruct);
        #else
        PsychSetStructArrayDoubleElement("gstreamer", 0, 0 * 10000 + 10 * 100 + 0, majorStruct);
        #endif
    #else
        PsychSetStructArrayDoubleElement("gstreamer", 0, 0, majorStruct);
    #endif

    // Query info about Windows version:
    versionString[0]=0;
    memset(&osvi, 0, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx(&osvi);

    // Convert into string with major.minor.buildnumber - Name of service packs (max 128 chars) etc.:
    // Versions to products: 6.1 = Windows-7, 6.0  = Vista, 5.2 = Windows Server 2003, 5.1 = WindowsXP, 5.0 = Windows 2000, 4.x = NT
    sprintf(versionString, "NT-%i.%i.%i - %s", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber, (char*) osvi.szCSDVersion);
    PsychSetStructArrayStringElement("system", 0, versionString, majorStruct);

    PsychSetStructArrayDoubleElement("IsVistaClass", 0, (PsychIsMSVista() ? 1 : 0), majorStruct);

    return(PsychError_none);
}
PsychError SCREENComputer(void) 
{
    const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "kern", "hw", "processUserLongName", 
                                         "processUserShortName", "consoleUserName", "machineName", "localHostName", "location", "MACAddress", "system", "gstreamer", "supported" };
    const char *kernStructFieldNames[]={"ostype", "osrelease", "osrevision", "version","hostname"};
    const char *hwStructFieldNames[]={"machine", "model", "ncpu", "physmem", "usermem", "busfreq", "cpufreq"};
    int numMajorStructDimensions=-1, numKernStructDimensions=-1, numHwStructDimensions=-1;
    int numMajorStructFieldNames=16, numKernStructFieldNames=5, numHwStructFieldNames=7;
    PsychGenericScriptType	*kernStruct, *hwStruct, *majorStruct;
    //char tempStr[CTL_MAXNAME];   //this seems like a bug in Darwin, CTL_MAXNAME is shorter than the longest name.  
    char            tempStr[256], *ethernetMACStr;
    size_t          tempIntSize,  tempStrSize, tempULongIntSize;
    int             mib[2];
    int             tempInt;
    psych_uint64    tempULongInt;
    char            *tempStrPtr;
    CFStringRef     tempCFStringRef;
    psych_bool      stringSuccess;
    int             stringLengthChars, ethernetMACStrSizeBytes;
    long            gestaltResult;
    OSErr           gestaltError;
    int             i,strIndex, bcdDigit, lengthSystemVersionString;
    int             osMajor, osMinor, osBugfix;
    char            systemVersionStr[256];

    //all subfunctions should have these two lines
    PsychPushHelp(useString, synopsisString, seeAlsoString);
    if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};

    PsychErrorExit(PsychCapNumOutputArgs(1));
    PsychErrorExit(PsychCapNumInputArgs(0));

    //fill the major struct 
    PsychAllocOutStructArray(1, FALSE, numMajorStructDimensions, numMajorStructFieldNames, majorStructFieldNames, &majorStruct);
    PsychSetStructArrayDoubleElement("macintosh", 0, 0, majorStruct);
    PsychSetStructArrayDoubleElement("windows", 0, 0, majorStruct);
    PsychSetStructArrayDoubleElement("linux", 0, 0, majorStruct);
    PsychSetStructArrayDoubleElement("osx", 0, 1, majorStruct);

    // Official support status:
    PsychSetStructArrayStringElement("supported", 0, (char*) PsychSupportStatus(), majorStruct);

    // GStreamer availability and rough version:
    #if defined(PTB_USE_GSTREAMER)
        #if GST_CHECK_VERSION(1,0,0)
        PsychSetStructArrayDoubleElement("gstreamer", 0, 1 * 10000 + 0 * 100 + 0, majorStruct);
        #else
        PsychSetStructArrayDoubleElement("gstreamer", 0, 0 * 10000 + 10 * 100 + 0, majorStruct);
        #endif
    #else
        PsychSetStructArrayDoubleElement("gstreamer", 0, 0, majorStruct);
    #endif

    //fill the kern struct and implant it within the major struct
    PsychAllocOutStructArray(-1, FALSE, numKernStructDimensions, numKernStructFieldNames, kernStructFieldNames, &kernStruct);
    mib[0]=CTL_KERN;

    mib[1]=KERN_OSTYPE;
    tempStrSize=sizeof(tempStr);
    ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0));
    PsychSetStructArrayStringElement("ostype", 0, tempStr, kernStruct);

    mib[1]=KERN_OSRELEASE;
    tempStrSize=sizeof(tempStr);
    ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0));
    PsychSetStructArrayStringElement("osrelease", 0, tempStr, kernStruct);

    mib[1]=KERN_OSREV;
    tempIntSize=sizeof(tempInt);
    ReportSysctlError(sysctl(mib, 2, &tempInt, &tempIntSize, NULL, 0));
    PsychSetStructArrayDoubleElement("osrevision", 0, (double)tempInt, kernStruct);

    mib[1]=KERN_VERSION;
    tempStrSize=sizeof(tempStr);
    ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0));
    PsychSetStructArrayStringElement("version", 0, tempStr, kernStruct);

    mib[1]=KERN_HOSTNAME;
    tempStrSize=sizeof(tempStr);
    ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0));
    PsychSetStructArrayStringElement("hostname", 0, tempStr, kernStruct);
    PsychSetStructArrayStructElement("kern",0, kernStruct, majorStruct);

    //fill the hw struct and implant it within the major struct
    PsychAllocOutStructArray(-1, FALSE, numHwStructDimensions, numHwStructFieldNames, hwStructFieldNames, &hwStruct);
    mib[0]=CTL_HW;

    mib[1]=HW_MACHINE;
    tempStrSize=sizeof(tempStr);
    ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0));
    PsychSetStructArrayStringElement("machine", 0, tempStr, hwStruct);

    mib[1]=HW_MODEL;
    tempStrSize=sizeof(tempStr);
    ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0));
    PsychSetStructArrayStringElement("model", 0, tempStr, hwStruct);

    mib[1]=HW_NCPU;
    tempIntSize=sizeof(tempInt);
    ReportSysctlError(sysctl(mib, 2, &tempInt, &tempIntSize, NULL, 0));
    PsychSetStructArrayDoubleElement("ncpu", 0, (double)tempInt, hwStruct);

    mib[1]=HW_MEMSIZE;
    tempULongIntSize=sizeof(tempULongInt);
    tempULongInt = 0;
    ReportSysctlError(sysctl(mib, 2, &tempULongInt, &tempULongIntSize, NULL, 0));
    PsychSetStructArrayDoubleElement("physmem", 0, (double)tempULongInt, hwStruct);

    mib[1]=HW_USERMEM;
    tempULongIntSize=sizeof(tempULongInt);
    tempULongInt = 0;
    ReportSysctlError(sysctlbyname("hw.usermem", &tempULongInt, &tempULongIntSize, NULL, 0));
    PsychSetStructArrayDoubleElement("usermem", 0, (double)tempULongInt, hwStruct);

    mib[1]=HW_BUS_FREQ;
    tempULongIntSize=sizeof(tempULongInt);
    tempULongInt = 0;
    ReportSysctlError(sysctlbyname("hw.busfrequency", &tempULongInt, &tempULongIntSize, NULL, 0));
    PsychSetStructArrayDoubleElement("busfreq", 0, (double)tempULongInt, hwStruct);

    mib[1]=HW_CPU_FREQ;
    tempULongIntSize=sizeof(tempULongInt);
    tempULongInt = 0;
    ReportSysctlError(sysctlbyname("hw.cpufrequency", &tempULongInt, &tempULongIntSize, NULL, 0));
    PsychSetStructArrayDoubleElement("cpufreq", 0, (double)tempULongInt, hwStruct);
    PsychSetStructArrayStructElement("hw",0, hwStruct, majorStruct);

    //fill in the process user, console user and machine name in the root struct.
    tempCFStringRef = SCDynamicStoreCopyComputerName(NULL, NULL);
    if (tempCFStringRef) {
        stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingASCII);
        tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1));
        stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingASCII);

        if(stringSuccess) {
            PsychSetStructArrayStringElement("machineName", 0, tempStrPtr, majorStruct);
        }
        else {
            PsychSetStructArrayStringElement("machineName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct);
        }

        free(tempStrPtr);
        CFRelease(tempCFStringRef);
    }
    else {
        PsychSetStructArrayStringElement("machineName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct);
    }

    struct passwd* thisUser = getpwuid(getuid());
    if (thisUser) {
        PsychSetStructArrayStringElement("processUserShortName", 0, thisUser->pw_name, majorStruct);
    }
    else {
        PsychSetStructArrayStringElement("processUserShortName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct);
    }

    PsychSetStructArrayStringElement("processUserLongName", 0, PsychCocoaGetFullUsername(), majorStruct);

    tempCFStringRef= SCDynamicStoreCopyConsoleUser(NULL, NULL, NULL);
    if (tempCFStringRef) {
        stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingASCII);
        tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1));
        stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingASCII);

        if(stringSuccess) {
            PsychSetStructArrayStringElement("consoleUserName", 0, tempStrPtr, majorStruct);
        }
        else {
            PsychSetStructArrayStringElement("consoleUserName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct);
        }

        free(tempStrPtr);
        CFRelease(tempCFStringRef);
    }
    else {
        PsychSetStructArrayStringElement("consoleUserName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct);
    }

    tempCFStringRef= SCDynamicStoreCopyLocalHostName(NULL);
    if (tempCFStringRef) {
        stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingASCII);
        tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1));
        stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingASCII);
        if(stringSuccess) {
            PsychSetStructArrayStringElement("localHostName", 0, tempStrPtr, majorStruct);
        }
        else {
            PsychSetStructArrayStringElement("localHostName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct);
        }

        free(tempStrPtr);
        CFRelease(tempCFStringRef);
    }
    else {
        PsychSetStructArrayStringElement("localHostName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct);
    }

    tempCFStringRef= SCDynamicStoreCopyLocation(NULL);
    if (tempCFStringRef) {
        stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingASCII);
        tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1));
        stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingASCII);
        if(stringSuccess) {
            PsychSetStructArrayStringElement("location", 0, tempStrPtr, majorStruct);
        }
        else {
            PsychSetStructArrayStringElement("location", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct);
        }

        free(tempStrPtr);
        CFRelease(tempCFStringRef);
    }
    else {
        PsychSetStructArrayStringElement("location", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct);
    }

    //Add the ethernet MAC address of the primary ethernet interface to the stuct.  This can serve as a unique identifier for the computer.
    ethernetMACStrSizeBytes=GetPrimaryEthernetAddressStringLengthBytes(TRUE)+1;
    ethernetMACStr=(char*) malloc(sizeof(char) * ethernetMACStrSizeBytes);
    GetPrimaryEthernetAddressString(ethernetMACStr, TRUE, TRUE);
    PsychSetStructArrayStringElement("MACAddress", 0, ethernetMACStr, majorStruct);
    free(ethernetMACStr);

    //Add the system version string:
    PsychCocoaGetOSXVersion(&osMajor, &osMinor, &osBugfix);
    sprintf(systemVersionStr, "Mac OS %i.%i.%i", osMajor, osMinor, osBugfix);

    //embed it in the return struct
    PsychSetStructArrayStringElement("system", 0, systemVersionStr, majorStruct);

    return(PsychError_none);
}
PsychError SCREENComputer(void)
{
    //    const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "kern", "hw", "processUserLongName", 
    //    "processUserShortName", "consoleUserName", "machineName", "localHostName", "location", "MACAddress", "system" };
    const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "kern", "hw", "system", "machineName", "localHostName", "MACAddress", "gstreamer", "supported"};

    const char *kernStructFieldNames[]={"ostype", "osrelease", "osrevision", "version","hostname"};
    const char *hwStructFieldNames[]={"machine", "model", "ncpu", "physmem", "usermem", "busfreq", "cpufreq"};
    int numMajorStructDimensions=-1, numKernStructDimensions=-1, numHwStructDimensions=-1;
    int numMajorStructFieldNames=12, numKernStructFieldNames=5, numHwStructFieldNames=7;
    char ethernetMACStr[20];
    struct ifreq devea;
    int s, i;
    PsychGenericScriptType	*kernStruct, *hwStruct, *majorStruct;
    struct utsname unameresult;
    char tmpString[1024];

    //all subfunctions should have these two lines
    PsychPushHelp(useString, synopsisString, seeAlsoString);
    if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};

    PsychErrorExit(PsychCapNumOutputArgs(1));
    PsychErrorExit(PsychCapNumInputArgs(0));

    //fill the major struct 
    PsychAllocOutStructArray(1, FALSE, numMajorStructDimensions, numMajorStructFieldNames, majorStructFieldNames, &majorStruct);
    PsychSetStructArrayDoubleElement("macintosh", 0, 0, majorStruct);
    PsychSetStructArrayDoubleElement("windows", 0, 0, majorStruct);
    PsychSetStructArrayDoubleElement("linux", 0, 1, majorStruct);
    PsychSetStructArrayDoubleElement("osx", 0, 0, majorStruct);

    // Official support status:
    PsychSetStructArrayStringElement("supported", 0, (char*) PsychSupportStatus(), majorStruct);

    // GStreamer availability and rough version:
    #if defined(PTB_USE_GSTREAMER)
        #if GST_CHECK_VERSION(1,0,0)
        PsychSetStructArrayDoubleElement("gstreamer", 0, 1 * 10000 + 0 * 100 + 0, majorStruct);
        #else
        PsychSetStructArrayDoubleElement("gstreamer", 0, 0 * 10000 + 10 * 100 + 0, majorStruct);
        #endif
    #else
        PsychSetStructArrayDoubleElement("gstreamer", 0, 0, majorStruct);
    #endif

    // Query hardware MAC address of primary ethernet interface: This is a unique id of the computer,
    // good enough to disambiguate our statistics:
    sprintf(ethernetMACStr, "00:00:00:00:00:00");

    s = socket(PF_INET, SOCK_DGRAM, 0);
    if (s >= 0) {
        // Probe eth0 to eth99 for a valid network interface:
        for (i = 0; i < 100; i++) {
            sprintf(devea.ifr_name, "eth%d", i);
            if (ioctl(s, SIOCGIFHWADDR, &devea) >= 0) {
                // Success: Use its MAC address and be done:
                sprintf(ethernetMACStr, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
                        devea.ifr_ifru.ifru_hwaddr.sa_data[0]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[1]&0xff,
                        devea.ifr_ifru.ifru_hwaddr.sa_data[2]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[3]&0xff,
                        devea.ifr_ifru.ifru_hwaddr.sa_data[4]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[5]&0xff);
                break;
            }
        }
        close(s);
    }

    PsychSetStructArrayStringElement("MACAddress", 0, ethernetMACStr, majorStruct);

    uname(&unameresult);
    sprintf(tmpString, "Linux %s", unameresult.release);
    PsychSetStructArrayStringElement("system", 0, tmpString, majorStruct);

    // Fill the kern struct and implant it within the major struct
    PsychAllocOutStructArray(-1, FALSE, numKernStructDimensions, numKernStructFieldNames, kernStructFieldNames, &kernStruct);
    PsychSetStructArrayStringElement("ostype", 0, unameresult.sysname, kernStruct);
    PsychSetStructArrayStringElement("osrelease", 0, unameresult.release, kernStruct);
    PsychSetStructArrayDoubleElement("osrevision", 0, 0, kernStruct);
    sprintf(tmpString, "%s Kernel Version %s: %s", unameresult.sysname, unameresult.release, unameresult.version);
    PsychSetStructArrayStringElement("version", 0, tmpString, kernStruct);
    PsychSetStructArrayStringElement("hostname", 0, unameresult.nodename, kernStruct);
    PsychSetStructArrayStructElement("kern",0, kernStruct, majorStruct);

    PsychSetStructArrayStringElement("localHostName", 0, unameresult.nodename, majorStruct);
    PsychSetStructArrayStringElement("machineName", 0, unameresult.nodename, majorStruct);

    // Fill the hw struct and implant it within the major struct:
    PsychAllocOutStructArray(-1, FALSE, numHwStructDimensions, numHwStructFieldNames, hwStructFieldNames, &hwStruct);
    PsychSetStructArrayStringElement("machine", 0, unameresult.machine, hwStruct);
    PsychSetStructArrayStringElement("model", 0, "", hwStruct);
    PsychSetStructArrayDoubleElement("ncpu", 0, (double) sysconf(_SC_NPROCESSORS_ONLN), hwStruct);
    PsychSetStructArrayDoubleElement("physmem", 0, ((double) sysconf(_SC_PHYS_PAGES)) * ((double) sysconf(_SC_PAGESIZE)), hwStruct);
    PsychSetStructArrayDoubleElement("usermem", 0, ((double) sysconf(_SC_AVPHYS_PAGES)) * ((double) sysconf(_SC_PAGESIZE)), hwStruct);
    PsychSetStructArrayDoubleElement("busfreq", 0, 0, hwStruct);
    PsychSetStructArrayDoubleElement("cpufreq", 0, 0, hwStruct);
    PsychSetStructArrayStructElement("hw",0, hwStruct, majorStruct);

    return(PsychError_none);
}