DWORD DJIsAppleADPluginInUse(BOOLEAN* pExists) { DWORD ceError = ERROR_SUCCESS; PSTR value = NULL; PSTR valueStart = NULL; BOOLEAN bInUse = FALSE; DJ_LOG_INFO("Testing to see if Apple AD plugin is already in use"); ceError = CTCaptureOutput("/usr/bin/dscl localhost -list / | grep \"^Active Directory\"", &value); if (ceError) { ceError = ERROR_SUCCESS; goto error; } CTStripWhitespace(value); valueStart = strstr(value, "Active Directory"); if (valueStart != NULL) { bInUse = TRUE; } error: CT_SAFE_FREE_STRING(value); *pExists = bInUse; return ceError; }
DWORD CTMatchProgramToPID( PCSTR pszProgramName, pid_t pid ) { DWORD ceError = ERROR_SUCCESS; CHAR szBuf[PATH_MAX+1]; FILE* pFile = NULL; #if defined(__LWI_DARWIN__) || defined(__LWI_FREEBSD__) sprintf(szBuf, "ps -p %d -o command= | grep %s", pid, pszProgramName); #elif defined(__LWI_SOLARIS__) || defined(__LWI_HP_UX__) || defined(__LWI_AIX__) sprintf(szBuf, "PS=ps; [ -x /bin/ps ] && PS=/bin/ps; UNIX95=1 $PS -p %ld -o comm= | grep %s", (long)pid, pszProgramName); #else sprintf(szBuf, "UNIX95=1 ps -p %ld -o cmd= | grep %s", (long)pid, pszProgramName); #endif pFile = popen(szBuf, "r"); if (pFile == NULL) { ceError = LwMapErrnoToLwError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } /* Assume that we won't find the process we are looking for */ ceError = ERROR_PROC_NOT_FOUND; while (TRUE) { if (NULL == fgets(szBuf, PATH_MAX, pFile)) { if (feof(pFile)) { break; } else { ceError = LwMapErrnoToLwError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } } CTStripWhitespace(szBuf); if (!IsNullOrEmptyString(szBuf)) { /* Well what do you know, it was found! */ ceError = ERROR_SUCCESS; break; } } error: if (pFile) pclose(pFile); return ceError; }
DWORD DJGetOptionValue(const DynamicArray *lines, PCSTR stanza, PCSTR name, PSTR *value) { DWORD ceError = ERROR_SUCCESS; ssize_t i = DJFindLine(lines, stanza, name); PCSTR line; PSTR _value = NULL; *value = NULL; if(i == -1) GCE(ceError = ERROR_NOT_FOUND); line = *(PCSTR *)CTArrayGetItem((DynamicArray*)lines, i, sizeof(PCSTR)); while (*line != '\0' && isspace((int)*line)) line++; line += strlen(name); while (*line != '\0' && isspace((int)*line)) line++; if(*line != '=') { GCE(ceError = ERROR_BAD_FORMAT); } line++; GCE(ceError = CTStrdup(line, &_value)); CTStripWhitespace(_value); /* Remove the quotes around the value, if they exist */ if(CTStrStartsWith(_value, "\"") && CTStrEndsWith(_value, "\"")) { size_t len = strlen(_value); memmove(_value, _value + 1, len - 2 ); _value[len - 2 ] = '\0'; } *value = _value; _value = NULL; cleanup: CT_SAFE_FREE_STRING(_value); return ceError; }
static DWORD UnsupportedSeLinuxEnabled(BOOLEAN *hasBadSeLinux) { BOOLEAN hasSeLinux; DWORD ceError = ERROR_SUCCESS; PSTR output = NULL; DistroInfo distro; *hasBadSeLinux = FALSE; memset(&distro, 0, sizeof(distro)); GCE(ceError = CTCheckFileOrLinkExists("/usr/sbin/selinuxenabled", &hasSeLinux)); if(!hasSeLinux) goto cleanup; GCE(ceError = CTCheckFileOrLinkExists("/usr/sbin/getenforce", &hasSeLinux)); if(!hasSeLinux) goto cleanup; ceError = CTRunCommand("/usr/sbin/selinuxenabled >/dev/null 2>&1"); if(ceError == ERROR_BAD_COMMAND) { //selinux is not enabled ceError = ERROR_SUCCESS; goto cleanup; } GCE(ceError); GCE(ceError = CTCaptureOutput("/usr/sbin/getenforce", &output)); CTStripWhitespace(output); if(!strcmp(output, "Permissive")) { goto cleanup; } DJ_LOG_INFO("Selinux found to be present, enabled, and enforcing."); GCE(ceError = DJGetDistroInfo("", &distro)); switch(distro.distro) { case DISTRO_CENTOS: case DISTRO_RHEL: if(distro.version[0] < '5') { DJ_LOG_INFO("Safe version of RHEL"); goto cleanup; } break; case DISTRO_FEDORA: if(atol(distro.version) < 6) { DJ_LOG_INFO("Safe version of Fedora"); goto cleanup; } break; default: goto cleanup; } *hasBadSeLinux = TRUE; cleanup: if(ceError) *hasBadSeLinux = TRUE; CT_SAFE_FREE_STRING(output); DJFreeDistroInfo(&distro); return ceError; }
// newFdqnHostname = <shortHostname>.<dnsDomainName> DWORD DJReplaceHostnameInMemory( PHOSTSFILELINE pHostsFileLineList, PCSTR oldShortHostname, PCSTR oldFqdnHostname, PCSTR shortHostname, PCSTR dnsDomainName ) { DWORD ceError = ERROR_SUCCESS; PSTR pszDomainName = NULL; PSTR pszHostName = NULL; PSTR pszCanonicalName = NULL; PHOSTSFILELINE pLine = NULL; PHOSTSFILELINE pCreatedLine = NULL; BOOLEAN bFound = FALSE; BOOLEAN bModified = FALSE; PHOSTFILEALIAS pAlias = NULL; // // Ideal algorithm: // // 1) Find any lines with hostname. // 2) Make sure the the FQDN is present as the first // name in each of those lines. // 3) If no lines were found, then add hostname to 127.0.0.1 // and put FQDN first. // 4) If 127.0.0.2 line is present, edit that to just have our info. // if (IsNullOrEmptyString(shortHostname)) { ceError = ERROR_INVALID_PARAMETER; BAIL_ON_CENTERIS_ERROR(ceError); } if (strchr(shortHostname, '.')) { ceError = ERROR_INVALID_COMPUTERNAME; BAIL_ON_CENTERIS_ERROR(ceError); } ceError = CTAllocateString(shortHostname, &pszHostName); BAIL_ON_CENTERIS_ERROR(ceError); CTStripWhitespace(pszHostName); CTStrToLower(pszHostName); if (dnsDomainName != NULL) { ceError = CTAllocateString(dnsDomainName, &pszDomainName); BAIL_ON_CENTERIS_ERROR(ceError); CTStripWhitespace(pszDomainName); CTStrToLower(pszDomainName); ceError = CTAllocateMemory(strlen(pszHostName)+strlen(pszDomainName)+2, (PVOID*)(PVOID)&pszCanonicalName); BAIL_ON_CENTERIS_ERROR(ceError); sprintf(pszCanonicalName, "%s.%s", pszHostName, pszDomainName); } else { ceError = CTAllocateString(pszHostName, &pszCanonicalName); BAIL_ON_CENTERIS_ERROR(ceError); } for (pLine = pHostsFileLineList; pLine; pLine = pLine->pNext) { if (pLine->pEntry != NULL) { if (pLine->pEntry->pszCanonicalName != NULL && (!strcasecmp(pLine->pEntry->pszCanonicalName, pszHostName) || !strcasecmp(pLine->pEntry->pszCanonicalName, oldShortHostname ? oldShortHostname : "") || !strcasecmp(pLine->pEntry->pszCanonicalName, oldFqdnHostname ? oldFqdnHostname : "") || !strcasecmp(pLine->pEntry->pszCanonicalName, pszCanonicalName))) { ceError = DJUpdateHostEntry( pLine, pszHostName, pszCanonicalName, oldShortHostname, oldFqdnHostname); BAIL_ON_CENTERIS_ERROR(ceError); bFound = TRUE; } else if (DJEntryHasAlias(pLine->pEntry->pAliasList, pszHostName)) { bFound = TRUE; ceError = DJUpdateHostEntry( pLine, pszHostName, pszCanonicalName, oldShortHostname, oldFqdnHostname); BAIL_ON_CENTERIS_ERROR(ceError); } } } if (!bFound) { //First try to setup ip address on the loop back device which are not //127.0.0.1 for (pLine = pHostsFileLineList; pLine; pLine = pLine->pNext) { if (pLine->pEntry != NULL && !strncmp(pLine->pEntry->pszIpAddress, "127.0.", strlen("127.0.")) && strcmp(pLine->pEntry->pszIpAddress, "127.0.0.1")) { ceError = DJUpdateHostEntry( pLine, pszHostName, pszCanonicalName, oldShortHostname, oldFqdnHostname); BAIL_ON_CENTERIS_ERROR(ceError); bFound = TRUE; } } if (!bFound) { //Have to add it to the 127.0.0.1 address pLine = DJFindLineByIPAddress(pHostsFileLineList, "127.0.0.1"); if(pLine == NULL) { //We have to create the 127.0.0.1 address ceError = CTAllocateMemory(sizeof(HOSTSFILELINE), (PVOID*)(PVOID)&pCreatedLine); BAIL_ON_CENTERIS_ERROR(ceError); ceError = CTAllocateMemory(sizeof(HOSTSFILEENTRY), (PVOID*)(PVOID)&pCreatedLine->pEntry); ceError = CTAllocateString("127.0.0.1", &pCreatedLine->pEntry->pszIpAddress); BAIL_ON_CENTERIS_ERROR(ceError); ceError = DJAddAlias(pCreatedLine, "localhost", FALSE, &bModified); BAIL_ON_CENTERIS_ERROR(ceError); *DJGetLastHostsLine(&pHostsFileLineList) = pCreatedLine; pLine = pCreatedLine; pCreatedLine = NULL; } ceError = DJUpdateHostEntry( pLine, pszHostName, pszCanonicalName, oldShortHostname, oldFqdnHostname); BAIL_ON_CENTERIS_ERROR(ceError); } } error: if (pAlias) DJFreeAlias(pAlias); if (pszHostName) CTFreeString(pszHostName); if (pszDomainName) CTFreeString(pszDomainName); if (pszCanonicalName) CTFreeMemory(pszCanonicalName); if(pCreatedLine) DJFreeHostsLine(pCreatedLine); return ceError; }
DWORD DJParseHostsFile( const char *filename, PHOSTSFILELINE* ppHostsFileLineList ) { DWORD ceError = ERROR_SUCCESS; PHOSTSFILELINE pLineHead = NULL; PHOSTSFILELINE pHostsLine = NULL; PHOSTFILEALIAS pAlias = NULL; FILE* fp = NULL; CHAR szBuf[1024+1]; PSTR pszTmp = NULL; DWORD iToken = 0; PHOSTSFILELINE pLineTail = NULL; BOOLEAN exists; BAIL_ON_CENTERIS_ERROR(ceError = CTCheckFileOrLinkExists(filename, &exists)); if(!exists) BAIL_ON_CENTERIS_ERROR(ceError = ERROR_FILE_NOT_FOUND); fp = fopen(filename, "r"); if (fp == NULL) { ceError = LwMapErrnoToLwError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } while (1) { if (fgets(szBuf, 1024, fp) == NULL) { if (!feof(fp)) { ceError = LwMapErrnoToLwError(errno); BAIL_ON_CENTERIS_ERROR(ceError); } else { break; } } CTStripWhitespace(szBuf); ceError = CTAllocateMemory(sizeof(HOSTSFILELINE), (PVOID*)(PVOID)&pHostsLine); BAIL_ON_CENTERIS_ERROR(ceError); pHostsLine->pEntry = NULL; pHostsLine->pszComment = NULL; pszTmp = strchr(szBuf, '#'); if (pszTmp != NULL) { ceError = CTAllocateString(pszTmp, &pHostsLine->pszComment); BAIL_ON_CENTERIS_ERROR(ceError); *pszTmp = '\0'; } if(szBuf[0] != '\0') { ceError = CTAllocateMemory(sizeof(HOSTSFILEENTRY), (PVOID*)(PVOID)&pHostsLine->pEntry); BAIL_ON_CENTERIS_ERROR(ceError); iToken = 0; pszTmp = strtok(szBuf, " \t"); while (pszTmp != NULL) { if (iToken == 0) { ceError = CTAllocateString(pszTmp, &pHostsLine->pEntry->pszIpAddress); BAIL_ON_CENTERIS_ERROR(ceError); } else if (iToken == 1) { ceError = CTAllocateString(pszTmp, &pHostsLine->pEntry->pszCanonicalName); BAIL_ON_CENTERIS_ERROR(ceError); } else { ceError = CTAllocateMemory(sizeof(HOSTFILEALIAS), (PVOID*)(PVOID)&pAlias); BAIL_ON_CENTERIS_ERROR(ceError); ceError = CTAllocateString(pszTmp, &pAlias->pszAlias); BAIL_ON_CENTERIS_ERROR(ceError); //The alias list is first built in reverse pAlias->pNext = pHostsLine->pEntry->pAliasList; pHostsLine->pEntry->pAliasList = pAlias; pAlias = NULL; } iToken++; pszTmp = strtok(NULL, " \t"); } if (pHostsLine->pEntry->pAliasList) { pHostsLine->pEntry->pAliasList = DJReverseAliasList(pHostsLine->pEntry->pAliasList); } } if(pLineTail != NULL) pLineTail->pNext = pHostsLine; else pLineHead = pHostsLine; pLineTail = pHostsLine; pHostsLine = NULL; } *ppHostsFileLineList = pLineHead; pLineHead = NULL; error: if (pAlias) DJFreeAlias(pAlias); if (pHostsLine) DJFreeHostsLine(pHostsLine); if (pLineHead) DJFreeHostsFileLineList(pLineHead); if (fp) fclose(fp); return ceError; }
static QueryResult QueryDSPlugin(const JoinProcessOptions *options, LWException **exc) { BOOLEAN exists = FALSE; QueryResult result = NotConfigured; PSTR value = NULL; PSTR valueStart = NULL; BOOLEAN bLikewisePresent = FALSE; if (options->enableMultipleJoins) { result = NotApplicable; goto cleanup; } LW_CLEANUP_CTERR(exc, CTCheckFileOrLinkExists("/usr/bin/dscl", &exists)); if(!exists) { result = NotApplicable; goto cleanup; } LW_CLEANUP_CTERR(exc, DJIsAppleADPluginInUse(&exists)); if(exists) { result = ApplePluginInUse; goto cleanup; } LW_CLEANUP_CTERR(exc, CTCaptureOutput("/usr/bin/dscl /Search -read / dsAttrTypeStandard:SearchPolicy", &value)); CTStripWhitespace(value); valueStart = value; if(CTStrStartsWith(valueStart, "SearchPolicy:")) valueStart += strlen("SearchPolicy:"); CTStripWhitespace(valueStart); if(CTStrStartsWith(valueStart, "dsAttrTypeStandard:")) valueStart += strlen("dsAttrTypeStandard:"); CTStripWhitespace(valueStart); if(options->joiningDomain) { if(strcmp(valueStart, "CSPSearchPath")) goto cleanup; } else { if(strcmp(valueStart, "NSPSearchPath")) goto cleanup; } CT_SAFE_FREE_STRING(value); LW_CLEANUP_CTERR(exc, CTCaptureOutput("/usr/bin/dscl /Search -read / dsAttrTypeStandard:CSPSearchPath", &value)); CTStripWhitespace(value); valueStart = strstr(value, LWDSPLUGIN_NAME); if (valueStart == NULL) { bLikewisePresent = FALSE; } else { switch (valueStart[strlen(LWDSPLUGIN_NAME)]) { case 0: case '\r': case '\n': bLikewisePresent = TRUE; break; default: bLikewisePresent = FALSE; } } if( (bLikewisePresent != 0) != (options->joiningDomain != 0) ) goto cleanup; CT_SAFE_FREE_STRING(value); result = FullyConfigured; cleanup: CT_SAFE_FREE_STRING(value); return result; }
DWORD CTGetLikewiseVersion( PSTR *product, PSTR *version, PSTR *build, PSTR *revision ) { FILE *versionFile = NULL; PSTR line = NULL; BOOLEAN isEndOfFile = FALSE; DWORD ceError = ERROR_SUCCESS; BOOLEAN bIsEnterprise = FALSE; PSTR _product = NULL; PSTR _version = NULL; PSTR _build = NULL; PSTR _revision = NULL; *version = NULL; *build = NULL; *revision = NULL; #ifdef MINIMAL_JOIN GCE(ceError = CTOpenFile(LOCALSTATEDIR "/VERSION", "r", &versionFile)); #else ceError = CTOpenFile(PREFIXDIR "/data/ENTERPRISE_VERSION", "r", &versionFile); if (ceError == 0) { bIsEnterprise = TRUE; } else { GCE(ceError = CTOpenFile(PREFIXDIR "/data/VERSION", "r", &versionFile)); } #endif while (TRUE) { CT_SAFE_FREE_STRING(line); GCE(ceError = CTReadNextLine(versionFile, &line, &isEndOfFile)); if (isEndOfFile) break; CTStripWhitespace(line); if (!strncmp(line, "VERSION=", sizeof("VERSION=") - 1)) { GCE(ceError = CTStrdup(line + sizeof("VERSION=") - 1, &_version)); } else if (!strncmp(line, "BUILD=", sizeof("BUILD=") - 1)) { GCE(ceError = CTStrdup(line + sizeof("BUILD=") - 1, &_build)); } else if (!strncmp(line, "REVISION=", sizeof("REVISION=") - 1)) { GCE(ceError = CTStrdup(line + sizeof("REVISION=") - 1, &_revision)); } } if (bIsEnterprise) { GCE(ceError = CTStrdup("Enterprise", &_product)); } else { GCE(ceError = CTStrdup("Open", &_product)); } if (_version == NULL) { GCE(ceError = CTStrdup("unknown", &_version)); } if (_build == NULL) { GCE(ceError = CTStrdup("unknown", &_build)); } if (_revision == NULL) { GCE(ceError = CTStrdup("unknown", &_revision)); } GCE(ceError = CTSafeCloseFile(&versionFile)); *product = _product; *version = _version; *build = _build; *revision = _revision; _product = NULL; _version = NULL; _build = NULL; _revision = NULL; cleanup: CTSafeCloseFile(&versionFile); CT_SAFE_FREE_STRING(line); CT_SAFE_FREE_STRING(_version); CT_SAFE_FREE_STRING(_build); CT_SAFE_FREE_STRING(_revision); return ceError; }
DWORD CTGetDistroInfo(const char *testPrefix, CtDistroInfo *info) { BOOLEAN exists; DWORD ceError = ERROR_SUCCESS; struct utsname unameStruct; char *path = NULL; PSTR fileContents = NULL; PSTR distroString = NULL; BOOLEAN rxAlloced = FALSE; regex_t rx; memset(info, 0, sizeof(*info)); #if defined(HAVE_SYSINFO) && defined(SI_ARCHITECTURE) char archBuffer[100]; #endif //According to the Solaris man page, any non-negative return value //indicates success. In fact, Solaris 8 returns 1, while Linux returns //0. if(uname(&unameStruct) < 0) return LwMapErrnoToLwError(errno); //Check for os override file if(testPrefix == NULL) testPrefix = ""; GCE(ceError = CTAllocateStringPrintf( &path, "%s/ostype", testPrefix)); GCE(ceError = CTCheckFileOrLinkExists( path, &exists)); if(exists) { GCE(ceError = CTReadFile( path, SIZE_MAX, &fileContents, NULL)); } if(fileContents != NULL) { CTStripWhitespace(fileContents); info->os = CTGetOSFromString(fileContents); } else info->os = CTGetOSFromString(unameStruct.sysname); CT_SAFE_FREE_STRING(fileContents); CT_SAFE_FREE_STRING(path); //Check for distro override file GCE(ceError = CTAllocateStringPrintf( &path, "%s/osdistro", testPrefix)); GCE(ceError = CTCheckFileOrLinkExists( path, &exists)); if(exists) { GCE(ceError = CTReadFile( path, SIZE_MAX, &distroString, NULL)); } CT_SAFE_FREE_STRING(path); if(distroString != NULL) { CTStripWhitespace(distroString); info->distro = CTGetDistroFromString(distroString); CT_SAFE_FREE_STRING(distroString); GCE(ceError = CTStrdup("unknown", &info->version)); } else if(info->os == OS_LINUX) { struct { CtDistroType matchDistro; const char *searchFile; const char *matchRegex; int versionMatchNum; int updateMatchNum; BOOLEAN compareCase; } const distroSearch[] = { { DISTRO_ESX, "/etc/vmware-release", /* # The format of the line is something like: # VMware ESX 4.0 (Kandinsky) */ "^[[:space:]]*VMware ESX ([[:digit:]]+(\\.[[:digit:]]+)?)" "( \\(\\S+\\))?", 1, -1, 1 }, { DISTRO_RHEL, "/etc/redhat-release", /* # The format of the line is something like: # Red Hat Enterprise Linux ES release 4 (Nahant Update 1) # Red Hat Linux Advanced Server release 2.1AS (Pensacola) # Red Hat Enterprise Linux Client release 5 (Tikanga) # Red Hat Enterprise Linux Server release 5.3 (Tikanga) # Red Hat Enterprise Linux ES release 4 (Nahant Update 8) # Red Hat Enterprise Linux Workstation release 6.0 (Santiago) # In addition, Oracle Linux reports itself as: # Enterprise Linux Enterprise Linux AS release 4 (October Update 5) */ //Find a matching distro name "^[[:space:]]*((Red Hat)|(Enterprise Linux)) ((Enterprise Linux)|(Linux (Advanced|Enterprise) Server))[[:space:]]+(AS |ES |Client |Server |Workstation )?" "release ([[:digit:]]+(\\.[[:digit:]]+)?(AS|ES)?) (\\(\\S+ Update ([[:digit:]]+)\\))?", 9, 13, 1 }, { DISTRO_REDHAT, "/etc/redhat-release", /* # The format of the line is something like: # Red Hat Linux release 7.3 (Valhala) */ "^[[:space:]]*Red Hat Linux release ([[:digit:]]+(\\.[[:digit:]]+)?)", 1, -1, 1 }, { DISTRO_FEDORA, "/etc/redhat-release", /* # The format of the line is something like: # Fedora Core release 4 (Stentz) */ "^[[:space:]]*Fedora (Core )?release (\\S+)", 2, -1, 1 }, { DISTRO_CENTOS, "/etc/redhat-release", /* # The format of the line is something like: # CentOS release 4.x (Final) */ "^[[:space:]]*(CentOS|CentOS Linux) release ([[:digit:]]+(\\.[[:digit:]]+)?)", 2, -1, 1 }, { DISTRO_SCIENTIFIC, "/etc/redhat-release", /* # The format of the line is something like: # Scientific Linux release 6.1 (Carbon) */ "^[[:space:]]*(Scientific|Scientific Linux) release ([[:digit:]]+(\\.[[:digit:]]+)?)", 2, -1, 1 }, { DISTRO_SUSE, "/etc/SuSE-release", "^[[:space:]]*SUSE LINUX ([[:digit:]]+\\.[[:digit:]]+)[[:space:]]+", 1, -1, 0 }, { DISTRO_OPENSUSE, "/etc/SuSE-release", "^[[:space:]]*openSUSE ([[:digit:]]+\\.[[:digit:]]+)[[:space:]]+", 1, -1, 0 }, { DISTRO_SLES, "/etc/SuSE-release", "^[[:space:]]*SUSE LINUX Enterprise Server ([[:digit:]]+( SP[[:digit:]]+)?)", 1, -1, 0 }, { DISTRO_SLED, "/etc/SuSE-release", "^[[:space:]]*SUSE LINUX Enterprise Desktop ([[:digit:]]+( SP[[:digit:]]+)?)", 1, -1, 0 }, { DISTRO_UBUNTU, "/etc/lsb-release", /* # The file will have lines that include: # DISTRIB_ID=Ubuntu # DISTRIB_RELEASE=6.06 */ "^[[:space:]]*DISTRIB_ID[[:space:]]*=[[:space:]]*Ubuntu[[:space:]]*\n" "(.*\n)?DISTRIB_RELEASE[[:space:]]*=[[:space:]]*(\\S+)[[:space:]]*(\n.*)?$", 2, -1, 1 }, { DISTRO_DEBIAN, "/etc/debian_version", /* # The format of the entire file is a single line like: # 3.1 # and nothing else, so that is the version */ "^[[:space:]]*(\\S+)[[:space:]]*$", 1, -1, 1 }, }; int i; regmatch_t matches[20]; info->distro = DISTRO_UNKNOWN; for(i = 0; info->distro == DISTRO_UNKNOWN; i++) { if(i == sizeof(distroSearch)/sizeof(distroSearch[0])) { //We past the last item in DistroSearch break; } GCE(ceError = CTAllocateStringPrintf( &path, "%s%s", testPrefix, distroSearch[i].searchFile)); GCE(ceError = CTCheckFileOrLinkExists(path, &exists)); if(exists) { int flags = REG_EXTENDED; if(!distroSearch[i].compareCase) flags |= REG_ICASE; GCE(ceError = CTReadFile(path, SIZE_MAX, &fileContents, NULL)); if(regcomp(&rx, distroSearch[i].matchRegex, flags) != 0) { GCE(ceError = LW_ERROR_REGEX_COMPILE_FAILED); } rxAlloced = TRUE; if(regexec(&rx, fileContents, sizeof(matches)/sizeof(matches[0]), matches, 0) == 0 && matches[distroSearch[i].versionMatchNum].rm_so != -1) { //This is the correct distro regmatch_t *ver = &matches[distroSearch[i].versionMatchNum]; regmatch_t *update = &matches[distroSearch[i].updateMatchNum]; info->distro = distroSearch[i].matchDistro; if (distroSearch[i].updateMatchNum == -1 || update->rm_so == -1) { GCE(ceError = CTStrndup(fileContents + ver->rm_so, ver->rm_eo - ver->rm_so, &info->version)); } else { GCE(ceError = CTAllocateStringPrintf( &info->version, "%.*s.%.*s", ver->rm_eo - ver->rm_so, fileContents + ver->rm_so, update->rm_eo - update->rm_so, fileContents + update->rm_so)); } } regfree(&rx); rxAlloced = FALSE; CT_SAFE_FREE_STRING(fileContents); } CT_SAFE_FREE_STRING(path); } if(info->distro == DISTRO_DEBIAN) { /* # # Debian and Ubuntu both have /etc/debian_version, # but only Ubuntu has an /etc/lsb-release # */ GCE(ceError = CTAllocateStringPrintf( &path, "%s/etc/lsb-release", testPrefix)); GCE(ceError = CTCheckFileOrLinkExists(path, &exists)); if(exists) { // CT_LOG_ERROR("Unexpected file: %s", path); info->distro = DISTRO_UNKNOWN; } CT_SAFE_FREE_STRING(path); } } else { //It's a UNIX system switch(info->os) { case OS_AIX: info->distro = DISTRO_AIX; /*Uname output from AIX 5.3: $ uname -v 5 $ uname -r 3 */ GCE(ceError = CTAllocateStringPrintf(&info->version, "%s.%s", unameStruct.version, unameStruct.release)); break; case OS_SUNOS: info->distro = DISTRO_SUNOS; /*Uname output from Solaris 8: $ uname -r 5.8 */ GCE(ceError = CTAllocateStringPrintf(&info->version, "%s", unameStruct.release)); break; case OS_DARWIN: info->distro = DISTRO_DARWIN; ceError = CTGetPListVersion(&info->version); GCE(ceError); CTStripWhitespace(info->version); break; case OS_HPUX: info->distro = DISTRO_HPUX; { const char *temp = unameStruct.release; while(!isdigit((int)*temp)) temp++; GCE(ceError = CTStrdup(temp, &info->version)); } break; case OS_FREEBSD: info->distro = DISTRO_FREEBSD; GCE(ceError = CTAllocateStringPrintf(&info->version, "%s", unameStruct.release)); break; default: info->distro = DISTRO_UNKNOWN; } } if(info->distro == DISTRO_UNKNOWN) { CT_SAFE_FREE_STRING(info->version); GCE(ceError = CTStrdup("unknown", &info->version)); } //Check for version override file GCE(ceError = CTAllocateStringPrintf( &path, "%s/osver", testPrefix)); GCE(ceError = CTCheckFileOrLinkExists( path, &exists)); if(exists) { GCE(ceError = CTReadFile( path, SIZE_MAX, &fileContents, NULL)); } if(fileContents != NULL) { CTStripWhitespace(fileContents); CT_SAFE_FREE_STRING(info->version); info->version = fileContents; fileContents = NULL; } CT_SAFE_FREE_STRING(path); /* uname -m output: Linux: x86_64 Linux: i386 Linux: i686 AIX: 00CBE1DD4C00 Solaris: sun4u Solaris: i86pc Darwin: i386 Darwin: Power Macintosh HPUX: 9000/785 uname -i output: Linux: x86_64 Linux: i386 RHEL21: not recogn AIX: not recogn Darwin: not recogn Solaris: SUNW,Ultra-4 Solaris: i86pc HPUX: 2000365584 uname -p output: Linux reads /proc/cpuinfo Linux: x86_64 Linux: i686 Linux: athlon Darwin: i386 Darwin: powerpc AIX has the value hard coded in uname AIX: powerpc Solaris uses sysinfo(SI_ARCHITECTURE, buff, sizeof(buff) Solaris: sparc Solaris: i386 HPUX: not recogn */ info->arch = ARCH_UNKNOWN; #if defined(HAVE_SYSINFO) && defined(SI_ARCHITECTURE) //Solaris has this if(info->arch == ARCH_UNKNOWN && sysinfo(SI_ARCHITECTURE, archBuffer, sizeof(archBuffer)) != -1) { info->arch = CTGetArchFromString(archBuffer); } #endif #if defined(HAVE_SYSCONF) && defined(_SC_CPU_VERSION) //HPUX uses this if(info->arch == ARCH_UNKNOWN) { switch(sysconf(_SC_CPU_VERSION)) { case CPU_PA_RISC1_0: case CPU_PA_RISC1_1: case CPU_PA_RISC1_2: case CPU_PA_RISC2_0: case CPU_PA_RISC_MAX: info->arch = ARCH_HPPA; break; #ifdef CPU_HP_INTEL_EM_1_0 case CPU_HP_INTEL_EM_1_0: #endif #ifdef CPU_IA64_ARCHREV_0 case CPU_IA64_ARCHREV_0: #endif info->arch = ARCH_IA64; break; //If it's not any of the previous values, let another test figure //it out. } } #endif if(info->arch == ARCH_UNKNOWN) { //Linux uses this, and sometimes Darwin does too. If 'uname -m' doesn't //return something meaningful on this platform, then the arch will stay //as unknown. info->arch = CTGetArchFromString(unameStruct.machine); } if(info->arch == ARCH_UNKNOWN) { //AIX and sometimes Darwin use this GCE(ceError = CTCaptureOutput("uname -p", &distroString)); CTStripWhitespace(distroString); info->arch = CTGetArchFromString(distroString); CT_SAFE_FREE_STRING(distroString); } //Check for arch override file GCE(ceError = CTAllocateStringPrintf( &path, "%s/osarch", testPrefix)); GCE(ceError = CTCheckFileOrLinkExists( path, &exists)); if(exists) { GCE(ceError = CTReadFile( path, SIZE_MAX, &fileContents, NULL)); info->arch = CTGetArchFromString(fileContents); CT_SAFE_FREE_STRING(fileContents); } CT_SAFE_FREE_STRING(path); cleanup: CT_SAFE_FREE_STRING(path); CT_SAFE_FREE_STRING(fileContents); CT_SAFE_FREE_STRING(distroString); if(rxAlloced) regfree(&rx); if(ceError) { CTFreeDistroInfo(info); } return ceError; }