/** * Invokes euca_execvp_fd with passed command * @param command that should be executed with parameters. Parameters must be separated by one space. * @return exit code from executed script */ int euca_exec(const char *command) { int result = 0; pid_t pid; int pStatus = -1; char **args = strsplit_on_space(command); result = euca_execvp_fd(&pid, NULL, NULL, NULL, args); if (result == EUCA_OK) { result = euca_waitpid(pid, &pStatus); } else { LOGERROR("Failed to run %s\n", command); } free_char_list(args); return result; }
int euca_exec_no_wait(const char *file, ...) { int result = 0; char **argv = NULL; { va_list va; va_start(va, file); argv = build_argv(file, va); va_end(va); if (argv == NULL) return EUCA_INVALID_ERROR; } pid_t pid; result = euca_execvp_fd(&pid, NULL, NULL, NULL, argv); free_char_list(argv); return result; }
void free_macro_list(macro_list *pList) { macro_list *pFree = NULL; if(pList == NULL) { return; } while(pList) { pFree = pList; pList = pList->m_pNext; pFree->m_pNext = NULL; free_char_list(pFree->m_pValue); pFree->m_pValue = NULL; free(pFree->m_pMacro); pFree->m_pMacro = NULL; free(pFree); pFree = NULL; } }
//! //! Run a daemonized program and maintain its state. If a PID file is given, it will check if the //! process is currently running and if the running process matches the given program. If not, the //! current process will be terminated and restarted with the new program. If the process is running //! and matche our program name, it will be left alone. If the process is not currently running, //! it will be started. //! //! @param[in] psPidFilePath a constant string pointer to the PID file path //! @param[in] psRootWrap a constant string pointer to the rootwrap program location //! @param[in] force set to TRUE if we want to kill the process regardless of its state and restart it. Otherwise set to FALSE. //! @param[in] psProgram a constant string pointer to the pathname of a program which is to be executed //! @param[in] ... the list of string arguments to pass to the program //! //! @return 0 on success or 1 on failure //! //! @pre //! - psProgram should not be NULL //! - There more be more than 1 variable argument provided //! //! @post //! On success, the program is executed and its PID is recorded in the psPidFilePath location if provided. If //! the process is already running, nothing will change. On failure, depending of where it occured, the system //! is left into a non-deterministic state from the caller's perspective. //! //! @note //! //! @todo //! We should move this to something more global under util/euca_system.[ch] //! int eucanetd_run_program(const char *psPidFilePath, const char *psRootWrap, boolean force, const char *psProgram, ...) { #define PID_STRING_LEN 32 int i = 0; int rc = 0; char *psPidId = NULL; char *pString = NULL; char **argv = NULL; char sPid[PID_STRING_LEN] = ""; char sFilePath[EUCA_MAX_PATH] = ""; char sCommand[EUCA_MAX_PATH] = ""; const char *psProgramName = psProgram; FILE *pFh = NULL; pid_t pid = 0; boolean found = FALSE; va_list va = { {0} }; // Make sure we know what app we are running if (!psProgram) { return (1); } // turn variable arguments into a array of strings for the euca_execvp_fd() va_start(va, psProgram); { argv = build_argv(psProgram, va); } va_end(va); // Make sure we have a valid arg list if (argv == NULL) return (1); // // Set the psProgramName properly. If its currently the rootwrap program, then move to the // next argument in the list // if (!strcmp(psProgram, psRootWrap)) { // We should have another argument or I don't see how we can run rootwrap without something else?!?!? if (argv[1] == NULL) { free_char_list(argv); return (1); } // We're good, use the next argument psProgramName = argv[1]; } // Do we need to check if we have the exact same program running? if (psPidFilePath) { found = FALSE; // Does the PID file exists? if ((rc = check_file(psPidFilePath)) == 0) { // // read and make sure the command matches. If it does not match, we will need to restart. // if ((psPidId = file2str(psPidFilePath)) != NULL) { snprintf(sFilePath, EUCA_MAX_PATH, "/proc/%s/cmdline", psPidId); // Check if the process is running if (check_file(sFilePath) == 0) { // read the old command and make sure we have the same command running if ((pFh = fopen(sFilePath, "r")) != NULL) { if (fgets(sCommand, EUCA_MAX_PATH, pFh)) { if (strstr(sCommand, psProgramName)) { // process is running, and is indeed psProgram found = TRUE; } } fclose(pFh); } } EUCA_FREE(psPidId); } if (found) { // pidfile passed in and process is already running if (force) { // kill process and remove pidfile LOGTRACE("Stopping '%s'\n", psProgramName); rc = safekillfile(psPidFilePath, psProgramName, 9, psRootWrap); } else { // nothing to do LOGTRACE("Program '%s' running properly. Nothing to do.\n", psProgramName); free_char_list(argv); return (0); } } else { // pidfile passed in but process is not running unlink(psPidFilePath); } } } // Build the command string for debugging purpose for (i = 0, pString = sCommand; argv[i] != NULL; i++) { pString += snprintf(pString, (EUCA_MAX_PATH - (pString - sCommand)), "%s ", argv[i]); } rc = euca_execvp_fd(&pid, NULL, NULL, NULL, argv); LOGTRACE("Executed '%s'. PID=%d, RC=%d\n", sCommand, pid, rc); free_char_list(argv); if (psPidFilePath) { snprintf(sPid, PID_STRING_LEN, "%d", pid); rc = write2file(psPidFilePath, sPid); } return (rc); #undef PID_STRING_LEN }