void DJCheckValidComputerName( PCSTR pszComputerName, LWException **exc) { size_t dwLen; size_t i; if (IsNullOrEmptyString(pszComputerName)) { LW_RAISE_EX(exc, ERROR_INVALID_COMPUTERNAME, "Invalid hostname", "Hostname is empty"); goto cleanup; } dwLen = strlen(pszComputerName); //Zero length hostnames are already handled above if (dwLen > 63) { LW_RAISE_EX(exc, ERROR_INVALID_COMPUTERNAME, "Invalid hostname", "The name '%s' is %d characters long. Hostnames may only be up to 63 characters long.", pszComputerName, dwLen); goto cleanup; } if (!strcasecmp(pszComputerName, "linux") || !strcasecmp(pszComputerName, "localhost")) { LW_RAISE_EX(exc, ERROR_INVALID_COMPUTERNAME, "Invalid hostname", "The hostname may not be 'linux' or 'localhost'."); goto cleanup; } if (pszComputerName[0] == '-' || pszComputerName[dwLen - 1] == '-') { LW_RAISE_EX(exc, ERROR_INVALID_COMPUTERNAME, "Invalid hostname", "The hostname may not start or end with a hyphen."); goto cleanup; } for(i = 0; i < dwLen; i++) { char c = pszComputerName[i]; if (!(c == '-' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))) { LW_RAISE_EX(exc, ERROR_INVALID_COMPUTERNAME, "Invalid hostname", "The given hostname, '%s', contains a '%c'. Valid hostnames may only contain hyphens, letters, and digits.", pszComputerName, c); goto cleanup; } } cleanup: ; }
static QueryResult QueryStopDaemons(const JoinProcessOptions *options, LWException **exc) { DWORD dwError = 0; BOOLEAN running; QueryResult result = FullyConfigured; if (options->enableMultipleJoins) { result = NotApplicable; goto cleanup; } /* Check for gpagentd */ dwError = DJGetServiceStatus("gpagent", &running); if (dwError == LW_ERROR_NO_SUCH_SERVICE) { /* The gpagentd may not be installed so ignore */ running = FALSE; dwError = 0; } if (dwError) { LW_RAISE_EX(exc, dwError, "Received error while querying lwsmd.", "Received error while querying lwsmd."); goto cleanup; } if(running) result = NotConfigured; cleanup: return result; }
static QueryResult QueryStartDaemons(const JoinProcessOptions *options, LWException **exc) { DWORD dwError = 0; BOOLEAN running; QueryResult result = FullyConfigured; const ModuleState *stopState = DJGetModuleStateByName((JoinProcessOptions *)options, "stop"); if(!options->joiningDomain) { result = NotApplicable; goto cleanup; } dwError = DJGetServiceStatus("gpagent", &running); if (dwError == LW_ERROR_NO_SUCH_SERVICE) { /* The gpagentd may not be installed so ignore */ running = TRUE; dwError = 0; } if (dwError) { LW_RAISE_EX(exc, dwError, "Received error while querying lwsmd.", "Received error while querying lwsmd."); goto cleanup; } if(!running) result = NotConfigured; if(stopState != NULL && stopState->runModule) result = NotConfigured; cleanup: return result; }
BOOLEAN FindSshAndConfig( PCSTR pSshOrSshd, PSTR *ppSshBinary, PSTR *ppSshConfig, LWException **ppExc) { DWORD ceError = ERROR_SUCCESS; /* Mac OS X stores the configuration in /etc */ /* CSW ssh on Solaris uses /opt/csw/etc/ssh */ const PCSTR ppSshConfigPaths[] = { "/etc/ssh", "/opt/ssh/etc", "/usr/local/etc", "/etc", "/etc/openssh", "/usr/openssh/etc", "/opt/csw/etc/ssh", NULL }; DWORD foundConfigCount = 0; PSTR* ppFoundConfigs = NULL; /* Solaris Sparc 10 stores sshd in /usr/lib/ssh */ /* Experian says their sshd is at /usr/openssh/sbin/sshd */ /* CSW ssh on Solaris uses /opt/csw/sbin/sshd */ const PCSTR ppSshBinaryPaths[] = { "/usr/sbin", "/opt/ssh/sbin", "/usr/local/sbin", "/usr/bin", "/opt/ssh/bin", "/usr/local/bin", "/usr/lib/ssh", "/usr/openssh/sbin", "/usr/openssh/bin", "/opt/csw/sbin", "/opt/csw/bin", "/opt/ssh/hpux64/sbin", NULL }; DWORD foundBinaryCount = 0; PSTR* ppFoundBinaries = NULL; PSTR pConfigFilename = NULL; PSTR pBinaryFilename = NULL; PSTR pFoundConfigList = NULL; PSTR pFoundBinaryList = NULL; DWORD index = 0; *ppSshBinary = NULL; *ppSshConfig = NULL; LW_CLEANUP_CTERR(ppExc, CTAllocateStringPrintf( &pConfigFilename, "%s_config", pSshOrSshd)); LW_CLEANUP_CTERR(ppExc, CTAllocateStringPrintf( &pBinaryFilename, "%s", pSshOrSshd)); ceError = LwFindFilesInPaths( pConfigFilename, LWFILE_REGULAR, ppSshConfigPaths, &foundConfigCount, &ppFoundConfigs); LW_CLEANUP_CTERR(ppExc, ceError); ceError = LwRemoveDuplicateInodes( &foundConfigCount, ppFoundConfigs); LW_CLEANUP_CTERR(ppExc, ceError); ceError = LwFindFilesInPaths( pBinaryFilename, LWFILE_REGULAR, ppSshBinaryPaths, &foundBinaryCount, &ppFoundBinaries); LW_CLEANUP_CTERR(ppExc, ceError); ceError = LwRemoveDuplicateInodes( &foundBinaryCount, ppFoundBinaries); LW_CLEANUP_CTERR(ppExc, ceError); // Ssh version A.04.40.005 on HP-UX Itanimum has these paths: // /opt/ssh/hpux64/sbin/sshd (ELF-64 IA64) // /opt/ssh/sbin/sshd (ELF-32 IA64) // /usr/sbin/sshd (symlink to /opt/ssh/hpux64/sbin/sshd) // // Ssh version A.04.30.007 on HP-UX Itanimum has these paths: // /opt/ssh/hpux64/sbin/sshd (ELF-64 IA64) // /opt/ssh/sbin/sshd (ELF-32 IA64) // /usr/sbin/sshd (symlink to /opt/ssh/sbin/sshd) // // Both files point to the same config path. An exception must exist for // this case since the inodes are different for the two architectures. // // The symlink at /usr/sbin/sshd wins the duplication removal process. So // if it is found, the other path must be removed. for (index = 0; index < foundBinaryCount; index++) { if (!strcmp(ppFoundBinaries[index], "/usr/sbin/sshd")) { // Remove /opt/ssh/sbin/sshd or /opt/ssh/hpux64/sbin/sshd if they // are in the list for (index = 0; index < foundBinaryCount; index++) { if (!strcmp(ppFoundBinaries[index], "/opt/ssh/sbin/sshd") || !strcmp(ppFoundBinaries[index], "/opt/ssh/hpux64/sbin/sshd")) { LW_SAFE_FREE_STRING(ppFoundBinaries[index]); memmove(&ppFoundBinaries[index], &ppFoundBinaries[index+1], (foundBinaryCount - index - 1) * sizeof(ppFoundBinaries[index])); foundBinaryCount--; break; } } break; } } if ((foundConfigCount | foundBinaryCount) > 0 && foundConfigCount != foundBinaryCount) { ceError = CombinePaths( foundConfigCount, ppFoundConfigs, &pFoundConfigList); LW_CLEANUP_CTERR(ppExc, ceError); ceError = CombinePaths( foundBinaryCount, ppFoundBinaries, &pFoundBinaryList); LW_CLEANUP_CTERR(ppExc, ceError); if ((foundConfigCount | foundBinaryCount) == 1) { ceError = ERROR_FILE_NOT_FOUND; } else { ceError = ERROR_DUPLICATE_SERVICE_NAME; } LW_RAISE_EX(ppExc, ceError, "Unable to find ssh binary", "A %s config file was at %s, and a %s binary file was found at %s. Exactly one config file and one binary must exist on the system in a standard location. Uninstall any unused copies of ssh.", pSshOrSshd, pFoundConfigList, pSshOrSshd, pFoundBinaryList); } if (foundConfigCount == 1) { DJ_LOG_INFO("Found config file %s", ppFoundConfigs[0]); *ppSshConfig = ppFoundConfigs[0]; ppFoundConfigs[0] = NULL; } if (foundBinaryCount == 1) { DJ_LOG_INFO("Found binary %s", ppFoundBinaries[0]); *ppSshBinary = ppFoundBinaries[0]; ppFoundBinaries[0] = NULL; } cleanup: if (ppFoundConfigs) { LwFreeStringArray( ppFoundConfigs, foundConfigCount); } if (ppFoundBinaries) { LwFreeStringArray( ppFoundBinaries, foundBinaryCount); } LW_SAFE_FREE_STRING(pConfigFilename); LW_SAFE_FREE_STRING(pBinaryFilename); LW_SAFE_FREE_STRING(pFoundConfigList); LW_SAFE_FREE_STRING(pFoundBinaryList); return (foundConfigCount == 1); }
void DJManageDaemons( BOOLEAN bStart, LWException **exc ) { BOOLEAN bFileExists = TRUE; FILE* fp = NULL; LWException *innerExc = NULL; int i; PLSA_LOG_INFO pLogInfo = NULL; BOOLEAN bLsassContacted = FALSE; DWORD dwError = 0; LW_HANDLE hLsa = NULL; LW_CLEANUP_CTERR(exc, CTCheckFileExists(PWGRD, &bFileExists)); if(bFileExists) { //Shutdown pwgr (a nscd-like daemon) on HP-UX because it only handles //usernames up to 8 characters in length. LW_TRY(exc, DJStartStopDaemon("pwgr", FALSE, &LW_EXC)); LW_CLEANUP_CTERR(exc, CTRunSedOnFile(PWGRD, PWGRD, FALSE, "s/=1/=0/")); } if(bStart) { // Set registry value for gpagentd to autostart. dwError = SetBooleanRegistryValue("Services\\gpagent", "Autostart", TRUE); // Trigger gpagentd start dwError = DJStartService("gpagent"); // Make sure lsass is responding bLsassContacted = FALSE; for (i = 0; !bLsassContacted && i < 30; i++) { DJ_LOG_INFO("Trying to contact lsassd"); if (hLsa) { LsaCloseServer(hLsa); hLsa = NULL; } dwError = LsaOpenServer(&hLsa); if (dwError == ERROR_FILE_NOT_FOUND || dwError == LW_ERROR_ERRNO_ECONNREFUSED) { DJ_LOG_INFO("Failed with %d", dwError); dwError = 0; sleep(1); continue; } LW_CLEANUP_CTERR(exc, dwError); LW_CLEANUP_CTERR(exc, LsaGetLogInfo(hLsa, &pLogInfo)); bLsassContacted = TRUE; } if (!bLsassContacted) { LW_RAISE_EX(exc, ERROR_SERVICE_NOT_ACTIVE, "Unable to reach lsassd", "The lsass daemon could not be reached for 30 seconds after trying to start it. Please verify it is running."); goto cleanup; } } else { dwError = SetBooleanRegistryValue("Services\\gpagent", "Autostart", FALSE); dwError = DJStopService("gpagent"); } cleanup: CTSafeCloseFile(&fp); if (pLogInfo) { LsaFreeLogInfo(pLogInfo); } if (hLsa) { LsaCloseServer(hLsa); } LW_HANDLE(&innerExc); }
void DoLeaveNew(int argc, char **argv, int columns, LWException **exc) { JoinProcessOptions options; BOOLEAN advanced = FALSE; BOOLEAN preview = FALSE; DynamicArray enableModules, disableModules, ignoreModules; DynamicArray detailModules; size_t i; PSTR moduleDetails = NULL; PSTR wrapped = NULL; int passwordIndex = -1; DJZeroJoinProcessOptions(&options); memset(&enableModules, 0, sizeof(enableModules)); memset(&disableModules, 0, sizeof(disableModules)); memset(&ignoreModules, 0, sizeof(ignoreModules)); memset(&detailModules, 0, sizeof(detailModules)); while(argc > 0 && CTStrStartsWith(argv[0], "--")) { if(!strcmp(argv[0], "--advanced")) advanced = TRUE; else if(!strcmp(argv[0], "--preview")) preview = TRUE; else if(argc < 2) { LW_RAISE(exc, LW_ERROR_SHOW_USAGE); goto cleanup; } else if(!strcmp(argv[0], "--enable")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&enableModules, sizeof(PCSTR *), &argv[1], 1)); argv++; argc--; } else if(!strcmp(argv[0], "--disable")) { if(!strcmp(argv[1], "ssh")){ options.ignoreSsh = TRUE; } else { options.ignoreSsh = FALSE; LW_CLEANUP_CTERR(exc, CTArrayAppend(&disableModules, sizeof(PCSTR *), &argv[1], 1)); } argv++; argc--; } else if(!strcmp(argv[0], "--ignore")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&ignoreModules, sizeof(PCSTR *), &argv[1], 1)); argv++; argc--; } else if(!strcmp(argv[0], "--details")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&detailModules, sizeof(PCSTR *), &argv[1], 1)); argv++; argc--; } else if(!strcmp(argv[0], "--multiple")) { options.enableMultipleJoins = TRUE; LW_CLEANUP_CTERR(exc, CTStrdup(argv[1], &options.domainName)); argv++; argc--; } else { LW_RAISE(exc, LW_ERROR_SHOW_USAGE); goto cleanup; } argv++; argc--; } if(argc == 2) { LW_CLEANUP_CTERR(exc, CTStrdup(argv[1], &options.password)); passwordIndex = 1; } else if(argc > 2) { LW_RAISE(exc, LW_ERROR_SHOW_USAGE); goto cleanup; } options.joiningDomain = FALSE; DJ_LOG_INFO("Domainjoin invoked with %d arg(s) to the leave command:", argc); for(i = 0; i < argc; i++) { DJ_LOG_INFO(" [%s]", i == passwordIndex ? "<password>" : argv[i]); } if(argc > 0) { LW_CLEANUP_CTERR(exc, CTStrdup(argv[0], &options.username)); } options.warningCallback = PrintWarning; options.showTraces = advanced; LW_CLEANUP_CTERR(exc, DJGetComputerName(&options.computerName)); LW_TRY(exc, DJInitModuleStates(&options, &LW_EXC)); for(i = 0; i < enableModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &enableModules, i, sizeof(PCSTR)); if(CTArrayFindString(&disableModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being disabled and enabled", module); goto cleanup; } if(CTArrayFindString(&ignoreModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being ignored and enabled", module); goto cleanup; } LW_TRY(exc, DJSetModuleDisposition(&options, module, EnableModule, &LW_EXC)); } for(i = 0; i < disableModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &disableModules, i, sizeof(PCSTR)); if(CTArrayFindString(&enableModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being disabled and enabled", module); goto cleanup; } if(CTArrayFindString(&ignoreModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being disabled and ignored", module); goto cleanup; } LW_TRY(exc, DJSetModuleDisposition(&options, module, DisableModule, &LW_EXC)); } for(i = 0; i < ignoreModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &ignoreModules, i, sizeof(PCSTR)); if(CTArrayFindString(&enableModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being ignored and enabled", module); goto cleanup; } if(CTArrayFindString(&disableModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being ignored and disabled", module); goto cleanup; } LW_TRY(exc, DJSetModuleDisposition(&options, module, IgnoreModule, &LW_EXC)); } for(i = 0; i < detailModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &detailModules, i, sizeof(PCSTR)); ModuleState *state = DJGetModuleStateByName(&options, module); if(state == NULL) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Unable to find module.", "Please check the spelling of '%s'. This module cannot be found", module); goto cleanup; } PrintModuleState(state); } if(detailModules.size > 0) { PrintStateKey(); } for(i = 0; i < detailModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &detailModules, i, sizeof(PCSTR)); ModuleState *state = DJGetModuleStateByName(&options, module); CT_SAFE_FREE_STRING(moduleDetails); CT_SAFE_FREE_STRING(wrapped); LW_TRY(exc, moduleDetails = state->module->GetChangeDescription(&options, &LW_EXC)); LW_CLEANUP_CTERR(exc, CTWordWrap(moduleDetails, &wrapped, 4, columns)); fprintf(stdout, "\nDetails for '%s':\n%s\n", state->module->longName, wrapped); } if(detailModules.size > 0) goto cleanup; LW_TRY(exc, PrintJoinHeader(&options, &LW_EXC)); if(preview) { PrintModuleStates(advanced, &options); if(!advanced) LW_TRY(exc, DJCheckRequiredEnabled(&options, &LW_EXC)); goto cleanup; } LW_TRY(exc, DJCheckRequiredEnabled(&options, &LW_EXC)); if (options.username != NULL && IsNullOrEmptyString(options.password)) { CT_SAFE_FREE_STRING(options.password); LW_CLEANUP_CTERR(exc, FillMissingPassword(options.username, &options.password)); } LW_TRY(exc, DJRunJoinProcess(&options, &LW_EXC)); fprintf(stdout, "SUCCESS\n"); cleanup: DJFreeJoinProcessOptions(&options); CTArrayFree(&enableModules); CTArrayFree(&disableModules); CTArrayFree(&ignoreModules); CTArrayFree(&detailModules); CT_SAFE_FREE_STRING(moduleDetails); CT_SAFE_FREE_STRING(wrapped); }
void DoJoin(int argc, char **argv, int columns, LWException **exc) { JoinProcessOptions options; BOOLEAN advanced = FALSE; BOOLEAN preview = FALSE; DynamicArray enableModules, disableModules, ignoreModules; DynamicArray detailModules; size_t i; int passwordIndex = -1; PSTR moduleDetails = NULL; PSTR wrapped = NULL; DJZeroJoinProcessOptions(&options); memset(&enableModules, 0, sizeof(enableModules)); memset(&disableModules, 0, sizeof(disableModules)); memset(&ignoreModules, 0, sizeof(ignoreModules)); memset(&detailModules, 0, sizeof(detailModules)); while(argc > 0 && CTStrStartsWith(argv[0], "--")) { if(!strcmp(argv[0], "--advanced")) advanced = TRUE; else if(!strcmp(argv[0], "--preview")) preview = TRUE; else if(!strcmp(argv[0], "--ignore-firewall-ntp")) { printf("Warning: --ignore-firewall-ntp is deprecated. This behavior is now default.\n"); } else if(!strcmp(argv[0], "--ignore-pam")) options.ignorePam = TRUE; else if(!strcmp(argv[0], "--notimesync")) options.disableTimeSync = TRUE; else if(!strcmp(argv[0], "--multiple")) options.enableMultipleJoins = TRUE; else if(!strcmp(argv[0], "--nohosts")) { PCSTR module = "hostname"; LW_CLEANUP_CTERR(exc, CTArrayAppend(&disableModules, sizeof(PCSTR), &module, 1)); } else if(argc < 2) { LW_RAISE(exc, LW_ERROR_SHOW_USAGE); goto cleanup; } else if(!strcmp(argv[0], "--enable")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&enableModules, sizeof(PCSTR), &argv[1], 1)); argv++; argc--; } else if(!strcmp(argv[0], "--disable")) { if(!strcmp(argv[1], "ssh")){ options.ignoreSsh = TRUE; } else { options.ignoreSsh = FALSE; LW_CLEANUP_CTERR(exc, CTArrayAppend(&disableModules, sizeof(PCSTR), &argv[1], 1)); } argv++; argc--; } else if(!strcmp(argv[0], "--ignore")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&ignoreModules, sizeof(PCSTR), &argv[1], 1)); argv++; argc--; } else if(!strcmp(argv[0], "--details")) { LW_CLEANUP_CTERR(exc, CTArrayAppend(&detailModules, sizeof(PCSTR), &argv[1], 1)); argv++; argc--; } else if(!strcmp(argv[0], "--ou")) { DJ_LOG_INFO("Domainjoin invoked with option --ou %s", argv[1]); CT_SAFE_FREE_STRING(options.ouName); LW_CLEANUP_CTERR(exc, CTStrdup(argv[1], &options.ouName)); argv++; argc--; } else if(!strcmp(argv[0], "--uac-flags")) { DJ_LOG_INFO("Domainjoin invoked with option --uac-flags %s", argv[1]); CT_SAFE_FREE_STRING(options.ouName); options.uacFlags = strtoul(argv[1], NULL, 0); argv++; argc--; } else if(!strcmp(argv[0], "--assumeDefaultDomain")) { DJ_LOG_INFO("Domainjoin invoked with option --assumeDefaultDomain"); options.setAssumeDefaultDomain = TRUE; if (!strcasecmp(argv[1], "yes") || !strcasecmp(argv[1], "true") || !strcasecmp(argv[1], "on")) { options.assumeDefaultDomain = TRUE; } else if (!strcasecmp(argv[1], "no") || !strcasecmp(argv[1], "false") || !strcasecmp(argv[1], "off")) { options.assumeDefaultDomain = FALSE; } else { LW_RAISE(exc, LW_ERROR_SHOW_USAGE); goto cleanup; } argv++; argc--; } else if(!strcmp(argv[0], "--userDomainPrefix")) { DJ_LOG_INFO("Domainjoin invoked with option --userDomainPrefix %s", argv[1]); options.setAssumeDefaultDomain = TRUE; options.assumeDefaultDomain = TRUE; CT_SAFE_FREE_STRING(options.userDomainPrefix); LW_CLEANUP_CTERR(exc, CTStrdup(argv[1], &options.userDomainPrefix)); CTStrToUpper(options.userDomainPrefix); argv++; argc--; } else { LW_RAISE(exc, LW_ERROR_SHOW_USAGE); goto cleanup; } argv++; argc--; } if(argc == 3) { LW_CLEANUP_CTERR(exc, CTStrdup(argv[2], &options.password)); passwordIndex = 2; } // The join username is not required in preview or details mode. else if(argc == 1 && (preview || detailModules.size != 0) ) ; else if(argc != 2) { LW_RAISE(exc, LW_ERROR_SHOW_USAGE); goto cleanup; } options.joiningDomain = TRUE; DJ_LOG_INFO("Domainjoin invoked with %d arg(s) to the join command:", argc); for(i = 0; i < argc; i++) { DJ_LOG_INFO(" [%s]", i == passwordIndex ? "<password>" : argv[i]); } LW_CLEANUP_CTERR(exc, CTStrdup( argv[0], &options.domainName)); if(argc > 1) { LW_CLEANUP_CTERR(exc, CTStrdup(argv[1], &options.username)); } options.warningCallback = PrintWarning; options.showTraces = advanced; LW_CLEANUP_CTERR(exc, DJGetComputerName(&options.computerName)); LW_TRY(exc, DJInitModuleStates(&options, &LW_EXC)); for(i = 0; i < enableModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &enableModules, i, sizeof(PCSTR)); if(CTArrayFindString(&disableModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being disabled and enabled", module); goto cleanup; } if(CTArrayFindString(&ignoreModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being ignored and enabled", module); goto cleanup; } LW_TRY(exc, DJSetModuleDisposition(&options, module, EnableModule, &LW_EXC)); } for(i = 0; i < disableModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &disableModules, i, sizeof(PCSTR)); if(CTArrayFindString(&enableModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being disabled and enabled", module); goto cleanup; } if(CTArrayFindString(&ignoreModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being ignored and enabled", module); goto cleanup; } LW_TRY(exc, DJSetModuleDisposition(&options, module, DisableModule, &LW_EXC)); } for(i = 0; i < ignoreModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &ignoreModules, i, sizeof(PCSTR)); if(CTArrayFindString(&enableModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being enabled and ignored", module); goto cleanup; } if(CTArrayFindString(&disableModules, module) != -1) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Module already specified", "The module '%s' is listed as being disabled and ignored", module); goto cleanup; } LW_TRY(exc, DJSetModuleDisposition(&options, module, IgnoreModule, &LW_EXC)); } for(i = 0; i < detailModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &detailModules, i, sizeof(PCSTR)); ModuleState *state = DJGetModuleStateByName(&options, module); if(state == NULL) { LW_RAISE_EX(exc, ERROR_INVALID_PARAMETER, "Unable to find module.", "Please check the spelling of '%s'. This module cannot be found", module); goto cleanup; } PrintModuleState(state); } if(detailModules.size > 0) { PrintStateKey(); } for(i = 0; i < detailModules.size; i++) { PCSTR module = *(PCSTR *)CTArrayGetItem( &detailModules, i, sizeof(PCSTR)); ModuleState *state = DJGetModuleStateByName(&options, module); CT_SAFE_FREE_STRING(moduleDetails); CT_SAFE_FREE_STRING(wrapped); LW_TRY(exc, moduleDetails = state->module->GetChangeDescription(&options, &LW_EXC)); LW_CLEANUP_CTERR(exc, CTWordWrap(moduleDetails, &wrapped, 4, columns)); fprintf(stdout, "\nDetails for '%s':\n%s\n", state->module->longName, wrapped); } if(detailModules.size > 0) goto cleanup; LW_TRY(exc, PrintJoinHeader(&options, &LW_EXC)); if(preview) { PrintModuleStates(advanced, &options); if(!advanced) LW_TRY(exc, DJCheckRequiredEnabled(&options, &LW_EXC)); goto cleanup; } LW_TRY(exc, DJCheckRequiredEnabled(&options, &LW_EXC)); if (IsNullOrEmptyString(options.password)) { CT_SAFE_FREE_STRING(options.password); LW_CLEANUP_CTERR(exc, FillMissingPassword(options.username, &options.password)); } LW_TRY(exc, DJRunJoinProcess(&options, &LW_EXC)); fprintf(stdout, "SUCCESS\n"); cleanup: DJFreeJoinProcessOptions(&options); CTArrayFree(&enableModules); CTArrayFree(&disableModules); CTArrayFree(&ignoreModules); CTArrayFree(&detailModules); CT_SAFE_FREE_STRING(moduleDetails); CT_SAFE_FREE_STRING(wrapped); }