/**
 * 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;
}
Example #3
0
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
}