unsigned int Service::getFreePort(unsigned int startingPort) { unsigned int port = 0; unsigned int searchPort = startingPort; WSADATA info; if (WSAStartup(MAKEWORD(1, 1), &info) != 0) { return (port = 0); } SOCKET s; struct sockaddr_in sa; struct hostent *hp; memset(&sa, 0, sizeof(struct sockaddr_in)); hp = gethostbyname("localhost"); if (hp == NULL) { ::WSACleanup(); return (port = 0); } for (;searchPort < 65000; searchPort++) { sa.sin_family = hp->h_addrtype; sa.sin_port = htons(searchPort); s = socket(AF_INET, SOCK_STREAM, 0); if (s == INVALID_SOCKET) { port = 0; #ifdef WARNING logUser("Service::getFreePort: invalid socket."); #endif break; } if (bind(s, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { closesocket(s); port = 0; continue; } port = searchPort; closesocket(s); break; } ::WSACleanup(); #ifdef WARNING logUser("Service::getFreePort: found port[%d]", port); #endif return port; }
int main(int argc, char** argv) { // // Be sure all files are only readable // by the user. // umask(0077); char *programName = NULL; if (argc > 1) { switch(parseArguments(programName, argc, argv)) { case LIST: if (listServices(programName)) { return 1; } break; case START: if (startService(programName, argc, argv)) { return 1; } break; case STOP: if (stopService(programName, argc, argv)) { return 1; } break; case CLEANUP: if (cleanupDirectories()) { return 1; } break; case CHECK: logUser("NXSERVICE - is running"); break; case PROGRAM_VERSION: logUser("NXSERVICE - version %s", VERSION); break; case UNKNOWN: default: logUser("Error: unknown parameter."); return 1; } } else { logUser("Error: Wrong parameters."); return 1; } return 0; }
Mode parseArguments(char*& programName, int argc, char** argv) { char *arg = argv[1]; programName = NULL; serviceId = NULL; Mode mode = UNKNOWN; if (strcmp(arg,"--list") == 0) { mode = LIST; } else if (strcmp(arg, "--start") == 0) { mode = START; } else if (strcmp(arg, "--stop") == 0) { mode = STOP; } else if (strcmp(arg, "--cleanup") == 0) { mode = CLEANUP; } else if (strcmp(arg, "--version") == 0) { mode = PROGRAM_VERSION; } else if (strcmp(arg, "--check") == 0) { mode = CHECK; } else { mode = UNKNOWN; } if (argc > 2) { programName = strdup(argv[2]); logUser("\nInfo: Service name: %s [%s].", programName, strTimestamp()); if (argc > 4 && strcmp(argv[3], "--id") == 0) { serviceId = argv[4]; logUser("Info: Service id: %s.", serviceId); } } return mode; }
void Service::addArgument(const char *arg) { if (argumentsNumber_ < MAX_ARGUMENTS) { logUser("Service::addArgument[%d][%s]", argumentsNumber_, arg); arguments_[argumentsNumber_++] = arg; } else { logUser("Service::addArgument: Error cannot add: [%d][%s]", argumentsNumber_, arg); } }
int Service::logCheck(const char *file, const char *search) { FILE *fp; char line[DEFAULT_STRING_LENGTH]; int found; if (file == NULL) { #ifdef WARNING logUser("Service::logCheck: WARNING! No file specified."); #endif return 0; } fp = fopen(file, "r"); if (fp == NULL) { #ifdef WARNING logUser("Service::logCheck: WARNING! Cannot open the file: (error %d) %s", EGET(), ESTR()); #endif return 0; } // // TODO: This function could be optimized using // the search stream direction. // found = 0; while (!feof(fp)) { fgets(line, DEFAULT_STRING_LENGTH-1, fp); #ifdef TEST logUser("Service::logCheck: Going to examine line [%s].", line); #endif if (strstr(line, search) != NULL) { found = 1; break; } } fclose(fp); return (found); }
bool MetaTestPublisher::init() { ParticipantAttributes Patt; Patt.rtps.builtin.domainId = 50; Patt.rtps.builtin.leaseDuration = c_TimeInfinite; Patt.rtps.setName("MetaPublisher"); mp_par = Domain::createParticipant(Patt); if(mp_par == nullptr) return false; Domain::registerType(mp_par,&m_dataType); PublisherAttributes Wparam; Wparam.topic.topicName = "metaTest_P2S"; Wparam.topic.topicDataType = "MetaTestType"; Wparam.topic.historyQos.kind = KEEP_LAST_HISTORY_QOS; Wparam.topic.historyQos.depth = 1; mp_pub = Domain::createPublisher(mp_par,Wparam,&m_publisten); SubscriberAttributes Rparam; Rparam.topic.topicName = "metaTest_S2P"; Rparam.topic.topicDataType = "MetaTestType"; mp_sub = Domain::createSubscriber(mp_par,Rparam,&m_sublisten); if(mp_par == nullptr || mp_pub == nullptr || mp_sub == nullptr) return false; logUser("MetaTest Publisher initialized"); return true; }
int Service::waitFork() { int limit = RETRY_FORK_LIMIT; int timeout = RETRY_FORK_INTERVAL; int pid; for (int i = 0; i < limit; i++) { // // It could optionally try again only if the // error code is 11, 'Resource temporarily // unavailable'. // if ((pid = fork()) >= 0) { break; } else if (i < limit - 1) { #ifdef TEST logUser("Service::waitFork:fork: Function " "fork failed. Retrying..."); #endif usleep(timeout * 1000); } } return pid; }
int Service::stop() { int ret; if (pid_ == -1) { #ifdef WARNING logUser("Service::stop: WARNING! No process running"); #endif // // Let's say kill() succeded. // ret = 0; } else { ret = kill(pid_, SIGTERM); } if (ret == 0) { renameDirectory("T-"); } else { renameDirectory("F-"); } return (ret == 0); }
int ServiceManager::cleanupDirectories() { DIR *rootDir = opendir(root_); logUser("Info::ServiceManager cleanup"); if (rootDir != NULL) { dirent *dirEntry = NULL; while ((dirEntry = readdir(rootDir)) != NULL) { char *name = dirEntry->d_name; if (name != NULL && name[0] != '.' && strncmp(name, "D-", 2) == 0) { char *path = new char[strlen(root_) + strlen("/") + strlen(name) + 1]; if (path != NULL) { strcpy(path, root_); strcat(path, "/"); strcat(path, name); Service service(path,""); service.load(); if (!service.isRunning()) { // // it was not started or stopped properly and is not running so it means // we should move it as failed. // service.renameFailed(); } delete [] path; } } } } else { logUser("Error: Cannot open root directory '%s'.",root_); return -1; } return 0; }
int Service::setupPaths(const char* filepath) { memset(arguments_, '\0', MAX_ARGUMENTS * sizeof(char *)); memset(executablePath_, '\0', DEFAULT_STRING_LENGTH); memset(rootPath_, '\0', DEFAULT_STRING_LENGTH); memset(typePath_, '\0', DEFAULT_STRING_LENGTH); memset(optionsPath_, '\0', DEFAULT_STRING_LENGTH); memset(sessionPath_, '\0', DEFAULT_STRING_LENGTH); memset(pidPath_, '\0', DEFAULT_STRING_LENGTH); memset(commandPath_, '\0', DEFAULT_STRING_LENGTH); memset(portPath_, '\0', DEFAULT_STRING_LENGTH); memset(winlogPath_, '\0', DEFAULT_STRING_LENGTH); #ifdef DEBUG logUser("Service::setupPaths filepath='%s'", filepath); #endif strncpy(rootPath_, filepath, DEFAULT_STRING_LENGTH); strncpy(typePath_, rootPath_, DEFAULT_STRING_LENGTH); strncat(typePath_, "/type", DEFAULT_STRING_LENGTH - strlen(rootPath_) -1); strncpy(optionsPath_, rootPath_, DEFAULT_STRING_LENGTH); strncat(optionsPath_, "/options", DEFAULT_STRING_LENGTH - strlen(rootPath_) -1); strncpy(sessionPath_, rootPath_, DEFAULT_STRING_LENGTH); strncat(sessionPath_, "/session", DEFAULT_STRING_LENGTH - strlen(rootPath_) -1); strncpy(pidPath_, rootPath_, DEFAULT_STRING_LENGTH); strncat(pidPath_, "/pid", DEFAULT_STRING_LENGTH - strlen(rootPath_) -1); strncpy(commandPath_, rootPath_, DEFAULT_STRING_LENGTH); strncat(commandPath_, "/command", DEFAULT_STRING_LENGTH - strlen(rootPath_) -1); strncpy(portPath_, rootPath_, DEFAULT_STRING_LENGTH); strncat(portPath_, "/port", DEFAULT_STRING_LENGTH - strlen(rootPath_) -1); strncpy(winlogPath_, rootPath_, DEFAULT_STRING_LENGTH); strncat(winlogPath_, "/winlog", DEFAULT_STRING_LENGTH - strlen(rootPath_) -1); #ifdef DEBUG logUser("Service::setupPaths rootPath='%s'", rootPath_); #endif return 0; }
int ServiceManager::list(const char *type) { DIR *rootDir = opendir(root_); logUser("Info::ServiceManager list '%s'", type); if (rootDir != NULL) { dirent *dirEntry = NULL; while ((dirEntry = readdir(rootDir)) != NULL) { char *name = dirEntry->d_name; if (name != NULL && name[0] != '.' && strncmp(name, "D-", 2) == 0) { char *path = new char[strlen(root_) + strlen("/") + strlen(name) + 1]; if (path != NULL) { strcpy(path, root_); strcat(path, "/"); strcat(path, name); Service service(path,""); service.load(); if (type == NULL || (type != NULL && strcmp(type, service.getType())==0) || strlen(service.getType())==0)// && service.isRunning()) { logUser("%d %s %s is %s", service.getPid(), service.getType(), name, (service.isRunning() ? "running" : "not running")); } delete [] path; } } } } else { logUser("Error: Cannot open root directory '%s'.",root_); return -1; } return 0; }
std::string MetaTestPublisher::t_rtps_socket() { logUser("Starting TEST RTPS SOCKET"); MetaTestType testinfo; SampleInfo_t sampleinfo; std::string ip_string = "239.255.1.4"; uint32_t port = 22222; //TEST T_RTPS_SOCKET testinfo.kind(T_RTPS_SOCKET); testinfo.ip_string(ip_string); testinfo.ip_port(port); mp_pub->write(&testinfo); mp_sub->waitForUnreadMessage(); if(mp_sub->takeNextData(&testinfo,&sampleinfo)) { if(testinfo.status() == T_SUB_READY) { TestWriterSocket tsocket; if(tsocket.init("239.255.1.4",port)) { tsocket.run(10); eClock::my_sleep(150); testinfo.status(T_PUB_FINISH); testinfo.samples(10); mp_pub->write(&testinfo); mp_sub->waitForUnreadMessage(); if(mp_sub->takeNextData(&testinfo,&sampleinfo)) { if(testinfo.status() == T_SUB_OK) return "OK"; else { std::stringstream ss; ss << "FAILED "<<testinfo.comment(); return ss.str(); } } } else { return "Writer FAILED Initialization"; } } else if(testinfo.status() == T_SUB_FAILED) { std::stringstream ss; ss << "FAILED "<<testinfo.comment(); return ss.str(); } } return "META ERROR"; }
std::string MetaTestPublisher::t_client_server() { logUser("Starting TEST CLIENT SERVER"); int samples = 20; MetaTestType testinfo; SampleInfo_t sampleinfo; testinfo.kind(T_CLIENT_SERVER); testinfo.samples(samples); mp_pub->write(&testinfo); EprosimaClient client; if(client.init()) { mp_sub->waitForUnreadMessage(); if(mp_sub->takeNextData(&testinfo,&sampleinfo)) { if(testinfo.status() == T_SUB_READY) { int32_t res; while(!client.isReady()) { eClock::my_sleep(100); } cout << "Running client for "<< samples << " samples"<<endl; for(int i = 0;i<samples;++i) { if(client.calculate(Operation::ADDITION,10,20,&res) != Result::GOOD_RESULT) return "Bad Calculation performed"; } testinfo.status(T_PUB_FINISH); mp_pub->write(&testinfo); mp_sub->waitForUnreadMessage(); if(mp_sub->takeNextData(&testinfo,&sampleinfo)) { if(testinfo.status() == T_SUB_OK) return "OK"; else return "Subscriber Failed"; } return "META ERROR"; } else if(testinfo.status() == T_SUB_FAILED) { std::stringstream ss; ss << "FAILED "<<testinfo.comment(); return ss.str(); } } return "Meta Error"; } return " Client not initialized"; }
std::string MetaTestPublisher::t_hello_world() { logUser("Starting TEST HELLO WORLD"); int samples = 10; MetaTestType testinfo; SampleInfo_t sampleinfo; testinfo.kind(T_HELLO_WORLD); testinfo.samples(samples); mp_pub->write(&testinfo); HelloWorldPublisher hwpub; if(hwpub.init()) { mp_sub->waitForUnreadMessage(); if(mp_sub->takeNextData(&testinfo,&sampleinfo)) { if(testinfo.status() == T_SUB_READY) { printf("Running\n"); hwpub.run(samples); printf("Finished"); eClock::my_sleep(200); testinfo.status(T_PUB_FINISH); testinfo.samples(samples); mp_pub->write(&testinfo); mp_sub->waitForUnreadMessage(); if(mp_sub->takeNextData(&testinfo,&sampleinfo)) { if(testinfo.status() == T_SUB_OK) return "OK"; else { std::stringstream ss; ss << "FAILED "<<testinfo.comment(); return ss.str(); } } return "META ERROR"; } else if(testinfo.status() == T_SUB_FAILED) { std::stringstream ss; ss << "FAILED "<<testinfo.comment(); return ss.str(); } } return "META ERROR"; } return " HelloWorld Publisher not initialized"; }
std::string MetaTestPublisher::t_rtps_registered() { logUser("Starting TEST RTPS REGISTERED"); MetaTestType testinfo; SampleInfo_t sampleinfo; testinfo.kind(T_RTPS_REG); mp_pub->write(&testinfo); TestWriterRegistered twreg; if(twreg.init() && twreg.reg()) { mp_sub->waitForUnreadMessage(); if(mp_sub->takeNextData(&testinfo,&sampleinfo)) { if(testinfo.status() == T_SUB_READY) { twreg.run(10); eClock::my_sleep(150); testinfo.status(T_PUB_FINISH); testinfo.samples(10); mp_pub->write(&testinfo); mp_sub->waitForUnreadMessage(); if(mp_sub->takeNextData(&testinfo,&sampleinfo)) { if(testinfo.status() == T_SUB_OK) return "OK"; else return "Subscriber Failed"; } return "META ERROR"; } else if(testinfo.status() == T_SUB_FAILED) { std::stringstream ss; ss << "FAILED "<<testinfo.comment(); return ss.str(); } } return "META ERROR"; } return " Writer not initialized"; }
void MetaTestPublisher::run() { while(m_publisten.n_matched == 0 || m_sublisten.n_matched == 0) eClock::my_sleep(300); std::stringstream ss; //RUN ALL TESTS ss << "T_RTPS_REGISTERED: " << t_rtps_registered() << endl; clean(); ss << "T_RTPS_SOCKET : " << t_rtps_socket() << endl; clean(); ss << "T_CLIENT_SERVER : " << t_client_server() << endl; clean(); ss << "T_HELLO_WORLD : " << t_hello_world() << endl; clean(); MetaTestType testinfo; testinfo.kind(STOP_ALL_TESTS); mp_pub->write(&testinfo); logUser("TEST SUMMARY"<<endl<<ss.str()); }
int ServiceManager::stop(const char *type, int argc, char** argv) { DIR *rootDir = opendir(root_); char * id = NULL; logUser("Info::ServiceManager stop '%s'", type); // // let's check if we have the id for the service // if (argc > 3 && strcmp(argv[3],"--id") == 0) { if (argc == 5) id = argv[4]; if (id == NULL || strlen(id) == 0) { /* * we quit as we don't know which process to stop */ logUser("Error: id value empty"); fflush(NULL); return 0; } else { logUser("Info: id value '%s'", id); fflush(NULL); } } if (rootDir != NULL) { dirent *dirEntry = NULL; while ((dirEntry = readdir(rootDir)) != NULL) { char *name = dirEntry->d_name; if (name != NULL && name[0] != '.' && strncmp(name, "D-", 2) == 0) { char *path = new char[strlen(root_) + strlen("/") + strlen(name) + 1]; if (path != NULL) { strcpy(path, root_); strcat(path, "/"); strcat(path, name); Service service(path,""); service.load(); if (type != NULL && strcmp(type, service.getType())==0 && service.isRunning()) { /* * if id was not specified we stop all the services of one kind * */ if (!id || (id && strcmp(service.getID(), id) == 0)) { logUser("Info: Stopping pid '%d'.",service.getPid()); service.stop(); } } delete [] path; } } } } else { logUser("Error: Cannot open root directory '%s'.", root_); return -1; } return 0; }
void Service::checkServiceStart(void) { int status = 0; int wpid; int options = WNOHANG | WUNTRACED; static int timeout; // // The child is the service launched by nxservice. // Each second we check for the child exit status. // If the child doesn't return, we use its logs to // retrieve the status. // #ifdef DEBUG logUser("Service::checkServiceStart: going to check the '%s' service status", getType()); #endif for (;;) { #ifdef TEST logUser("Service::checkServiceStart: waiting for child pid %d.", getPid()); #endif wpid = waitpid(getPid(), &status, options); if (wpid == -1) { #ifdef WARNING logUser("WARNING! Waitpid returns error: %d.", EGET()); #endif // // "The process specified does not exist or is not // a child of the calling process." // We don't know why this happened, but we can try // to return a successful state. // exit(0); } else if (wpid == 0) { // // The child's state is not changed. Let's check // if there is a reason to believe it is running. // if (checkStart()) { #ifdef DEBUG logUser("Service::checkServiceStart: '%s' successfully starts after waiting " "for %d seconds.", getType(), timeout / 1000); #endif exit(0); } } else { // // The child's state changes, let's figure out why. // if (WIFSTOPPED(status)) { #ifdef DEBUG logUser("Service::checkServiceStart: '%s' service has been stopped with signal %d " "after waiting for %d seconds.", getType(), WSTOPSIG(status), timeout / 1000); #endif exit(0); } else if (WIFEXITED(status)) { #ifdef DEBUG logUser("Service::checkServiceStart: '%s' service exits with status %d after " "waiting for %d seconds.", getType(), WEXITSTATUS(status), timeout / 1000); #endif exit(WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { #ifdef DEBUG logUser("Service::checkServiceStart: '%s' service terminates with signal %d after " "waiting for %d seconds.", getType(), WTERMSIG(status), timeout / 1000); #endif // // FIXME: Do we need to better classify the signals? // switch (WTERMSIG(status)) { case SIGABRT: case SIGSEGV: case SIGKILL: exit(1); default: exit(0); } } else { #ifdef WARNING logUser("Service::checkServiceStart: WARNING! Waitpid returns an unknown status: " "%d.", status); #endif } } usleep(SERVICE_START_INTERVAL * 1000); timeout += SERVICE_START_INTERVAL; if (timeout / 1000 >= getTimeout()) { #ifdef WARNING logUser("Service::checkServiceStart: WARNING! Assuming the '%s' starts after " "waiting for %d seconds.", getType(), timeout / 1000); #endif exit(0); } } }
int Service::run() { writeCommandFile(); writeOptionsFile(); logUser("Info: Starting daemon: '%s'", getID()); #ifdef __CYGWIN32__ if ((pid_ = waitFork()) != 0) #else if ((pid_ = fork()) != 0) #endif { if (pid_ < 0) { logUser("Error: Fork failed."); } else { #ifdef DEBUG logUser("Info: Created process with pid=%d", pid_); #endif } writePidFile(); // // The parent waits for a signal or a log // to know if its child (the service) starts // successfully. // if (pid_ > 0) { checkServiceStart(); } return pid_; } #ifdef DEBUG logUser("Info: Executing child with pid=%d and ppid=%d", getpid(), getppid()); #endif if (execvp(executablePath_, (char *const *) arguments_) == -1) { logUser("Error: Cannot execute '%s'. Error: '%s'", executablePath_, strerror(errno)); exit(-1); } /* * checkServiceStart() get rid of this. * exit(0); */ // // just to shut up the compiler // return 0; }
int startService(char* programName, int argc, char** argv) { if (programName) { char *path = createServiceDirectory(); char newEnv[DEFAULT_STRING_LENGTH]; // // This is a fatal error. // if (!path) { return -1; } logUser("Info: Using directory: '%s'", path); sprintf(newEnv, "NX_TEMP=%s", path); putenv(newEnv); Service *service = NULL; switch (getService(programName)) { case SERVICE_AUDIO: service = new ServiceAudio(path); break; case SERVICE_DISPLAY: service = new ServiceDisplay(path, argc, argv, nolisten); break; default: logUser("Error: Unknown service."); delete [] path; return -1; } if (service) { if (service->start()) { logUser("Error: Service start failed."); delete [] path; return -1; } else { logUser("Info: Service start."); } } delete [] path; } else { logUser("Error: Unknown service."); return -1; } return 0; }
int Service::renameDirectory(const char* prefix) { char *slash = NULL; char path[DEFAULT_STRING_LENGTH]; strncpy(path, rootPath_, DEFAULT_STRING_LENGTH); slash = strrchr(path, '/'); if (slash == NULL) { return -1; } char *name = new char[strlen(slash) + strlen(prefix) + 1]; if (name == NULL) { return -1; } strcpy(name, prefix); // // this is safe in the worst case slash + 1 will be '\0' // strcat(name, slash + 1); #ifdef DEBUG logUser("Info: renameDirectory: name='%s'",name); #endif if (strlen(path) + strlen(prefix) > DEFAULT_STRING_LENGTH) { return -1; } strcpy(slash + 1, name); // // FIXME: Sometimes we try to rename the session directories // before a service closes its log file. Should we retry // until the rename succeded? // if (rename((const char*)rootPath_, (const char*)path)) { logUser("Error: Cannot rename '%s' to '%s'. Error is '%s'", rootPath_, path, strerror(errno)); return -1; } else { return -1; } setupPaths(path); delete [] name; return 0; }
char* createServiceDirectory() { const char *rootPath = getRootDir(); char hostname[DEFAULT_STRING_LENGTH]; int serviceDirLength; if (rootPath == NULL) { // // exit! // logUser("Error: Cannot get the root directory."); return NULL; } if (gethostname(hostname, DEFAULT_STRING_LENGTH) == -1) { // // we cannot get hostname, we return - maybe we should just // set it localhost? // logUser("Error: Cannot retrieve the hostname."); return NULL; } #define MD5_LENGTH 16 char md5[(MD5_LENGTH * 2) + 1]; memset(md5, '\0', (MD5_LENGTH * 2) + 1); if (serviceId == NULL) { srandom(time(0) * getpid()); long int a = random(); char *astr = new char[sizeof(a) + 1]; strncpy(astr,(char *)&a, sizeof(a)); md5_state_t *md5_state = new md5_state_t(); unsigned char *md5_digest = new unsigned char[MD5_LENGTH]; md5_init(md5_state); md5_append(md5_state, (const unsigned char *)astr, sizeof(astr)); md5_finish(md5_state, md5_digest); int di = 0; for (di = 0; di < MD5_LENGTH; ++di) { sprintf(md5 + (di * 2), "%02X", md5_digest[di]); } *(md5 + (di * 2)) = '\0'; delete [] md5_state; delete [] md5_digest; delete [] astr; } else { strncpy(md5, serviceId, MD5_LENGTH * 2); } logUser("Info: Service directory MD5 %s.", md5); serviceDirLength = strlen(rootPath) + strlen("/D-") + strlen(hostname) + strlen("-") + strlen(md5) + 1; // // In no case the service directory path can // be longer than DEFAULT_STRING_LENGTH chars. // if (serviceDirLength > DEFAULT_STRING_LENGTH) { logUser("PANIC: Service directory name would exceed length of %d characters.", DEFAULT_STRING_LENGTH); return NULL; } // // If the service directory path is longer than // MAX_SERVICE_DIR_LENGTH, we opened only the TCP // socket connection to avoid the creation of a // UNIX socket file. Read the comments in // ServiceDisplay::start() about the -nolisten // option for more details. // if (serviceDirLength > MAX_SERVICE_DIR_LENGTH) { logUser("Warning: Service directory path too long. Listening on AF_INET socket."); nolisten = AF_UNIX; } char *path = new char[strlen(rootPath) + strlen("/D-") + strlen(hostname) + strlen("-") + strlen(md5) + 1]; // // Transform name in a fully qualified name. // strcpy(path, rootPath); strcat(path, "/D-"); strcat(path, hostname); strcat(path, "-"); strcat(path, md5); if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR)) { // // we cannot create the directory // int errorNumber = errno; logUser("Error: Cannot create directory '%s'",path); logUser("Error: because of '%s'", strerror(errorNumber)); if (errorNumber == EEXIST) { logUser("Error: Directory exists already, we can use it!"); } else { delete [] path; path = NULL; } } return path; }