示例#1
0
/*
  FUNCTION: smpd_service_stop

  PURPOSE: Stops the service

  PARAMETERS:
    none

  RETURN VALUE:
    none

  COMMENTS:
    If a ServiceStop procedure is going to
    take longer than 3 seconds to execute,
    it should spawn a thread to execute the
    stop code, and return.  Otherwise, the
    ServiceControlManager will believe that
    the service has stopped responding.
*/    
void smpd_service_stop()
{
    SMPDU_Sock_set_t set;
    SMPDU_Sock_t sock;
    SMPDU_Sock_event_t event;
    char host[SMPD_MAX_HOST_LENGTH];
    int iter;
    DWORD dwThreadID;
    int result;

    for (iter=0; iter<10; iter++)
    {
	smpd_process.hBombThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)smpd_bomb_thread, NULL, 0, &dwThreadID);
	if (smpd_process.hBombThread != NULL)
	    break;
	Sleep(250);
    }

    /* stop the main thread */
    smpd_process.service_stop = SMPD_TRUE;
    smpd_get_hostname(host, SMPD_MAX_HOST_LENGTH);
    result = SMPDU_Sock_create_set(&set);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("SMPDU_Sock_create_set failed,\nsock error: %s\n", get_sock_error_string(result));
	SetEvent(smpd_process.hBombDiffuseEvent);
	WaitForSingleObject(smpd_process.hBombThread, (DWORD)3000);
	CloseHandle(smpd_process.hBombThread);
	ExitProcess((UINT)-1);
    }
    result = SMPDU_Sock_post_connect(set, NULL, host, smpd_process.port, &sock);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("Unable to connect to '%s:%d',\nsock error: %s\n",
	    smpd_process.host_list->host, smpd_process.port, get_sock_error_string(result));
	SetEvent(smpd_process.hBombDiffuseEvent);
	WaitForSingleObject(smpd_process.hBombThread, (DWORD)3000);
	CloseHandle(smpd_process.hBombThread);
	ExitProcess((UINT)-1);
    }
    result = SMPDU_Sock_wait(set, SMPDU_SOCK_INFINITE_TIME, &event);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("Unable to connect to '%s:%d',\nsock error: %s\n",
	    smpd_process.host_list->host, smpd_process.port, get_sock_error_string(result));
	SetEvent(smpd_process.hBombDiffuseEvent);
	WaitForSingleObject(smpd_process.hBombThread, (DWORD)3000);
	CloseHandle(smpd_process.hBombThread);
	ExitProcess((UINT)-1);
    }
}
示例#2
0
int smpd_parse_command_args(int *argcp, char **argvp[])
{
    int result = 0;
#ifdef HAVE_WINDOWS_H
    char str[20], read_handle_str[20], write_handle_str[20];
    int port;
    SMPDU_Sock_t listener;
    SMPDU_Sock_set_t set;
    HANDLE hWrite, hRead;
    DWORD num_written, num_read;
#endif
    int dbg_flag;
    char domain[SMPD_MAX_HOST_LENGTH];
    char opt[SMPD_MAX_NAME_LENGTH];
    char opt_val[SMPD_MAX_VALUE_LENGTH];
    char filename[SMPD_MAX_FILENAME];
    int i;

    smpd_enter_fn(FCNAME);

    /* check for help option */
    if (
#ifndef HAVE_WINDOWS_H
	*argcp < 2 || /* unix: print the options if no arguments are supplied */
#endif
	smpd_get_opt(argcp, argvp, "-help") || smpd_get_opt(argcp, argvp, "-?"))
    {
	smpd_print_options();
	smpd_exit(0);
    }

    /* check for the printprocs option */
    if (smpd_get_opt(argcp, argvp, "-printprocs"))
    {
	smpd_watch_processes();
	smpd_exit(0);
    }

    if (smpd_get_opt(argcp, argvp, "-hosts"))
    {
	char first_host[SMPD_MAX_HOST_LENGTH], host[SMPD_MAX_HOST_LENGTH], alt_host[SMPD_MAX_HOST_LENGTH];

	smpd_get_default_hosts();

	result = smpd_get_next_hostname(first_host, alt_host);
	if (result != SMPD_SUCCESS)
	    smpd_exit(result);
	printf("%s\n", first_host);
	result = smpd_get_next_hostname(host, alt_host);
	if (result != SMPD_SUCCESS)
	    smpd_exit(result);
	while (strcmp(host, first_host) != 0)
	{
	    printf("%s\n", host);
	    result = smpd_get_next_hostname(host, alt_host);
	    if (result != SMPD_SUCCESS)
		smpd_exit(result);
	}
	smpd_exit(0);
    }

    if (smpd_get_opt(argcp, argvp, "-sethosts"))
    {
	char *buffer, *iter;
	int i, length;

	length = (*argcp) * SMPD_MAX_HOST_LENGTH;
	buffer = MPIU_Malloc(length);
	if (buffer == NULL)
	{
	    smpd_err_printf("unable to allocate memory to store the host names.\n");
	    smpd_exit(-1);
	}
	iter = buffer;
	for (i=1; i<*argcp; i++)
	{
	    result = MPIU_Str_add_string(&iter, &length, (*argvp)[i]);
	    if (result)
	    {
		printf("unable to add host #%d, %s\n", i, (*argvp)[i]);
		MPIU_Free(buffer);
		smpd_exit(-1);
	    }
	}
	/*printf("hosts: %s\n", buffer);*/
	result = smpd_set_smpd_data("hosts", buffer);
	if (result == SMPD_SUCCESS)
	{
	    printf("hosts data saved successfully.\n");
	}
	else
	{
	    printf("Error: unable to save the hosts data.\n");
	}
	MPIU_Free(buffer);
	smpd_exit(0);
    }

    if (smpd_get_opt_two_strings(argcp, argvp, "-set", opt, SMPD_MAX_NAME_LENGTH, opt_val, SMPD_MAX_VALUE_LENGTH))
    {
	/* The do loop allows for multiple -set operations to be specified on the command line */
	do
	{
	    if (strlen(opt) == 0)
	    {
		printf("invalid option specified.\n");
		smpd_exit(-1);
	    }
	    if (strlen(opt_val) == 0)
	    {
		result = smpd_delete_smpd_data(opt);
	    }
	    else
	    {
		result = smpd_set_smpd_data(opt, opt_val);
	    }
	    if (result == SMPD_SUCCESS)
	    {
		printf("%s = %s\n", opt, opt_val);
	    }
	    else
	    {
		printf("unable to set %s option.\n", opt);
	    }
	} while (smpd_get_opt_two_strings(argcp, argvp, "-set", opt, SMPD_MAX_NAME_LENGTH, opt_val, SMPD_MAX_VALUE_LENGTH));
	smpd_exit(0);
    }

    if (smpd_get_opt_string(argcp, argvp, "-get", opt, SMPD_MAX_NAME_LENGTH))
    {
	if (strlen(opt) == 0)
	{
	    printf("invalid option specified.\n");
	    smpd_exit(-1);
	}
	result = smpd_get_smpd_data(opt, opt_val, SMPD_MAX_VALUE_LENGTH);
	if (result == SMPD_SUCCESS)
	{
	    printf("%s\n", opt_val);
	}
	else
	{
	    printf("default\n");
	}
	smpd_exit(0);
    }

    /* If we've made it here and there still is "-set" or "-get" on the command line then the user
     * probably didn't supply the correct number of parameters.  So print the usage message
     * and exit.
     */
    if (smpd_get_opt(argcp, argvp, "-set") || smpd_get_opt(argcp, argvp, "-get"))
    {
	smpd_print_options();
	smpd_exit(-1);
    }

    if (smpd_get_opt(argcp, argvp, "-enumerate") || smpd_get_opt(argcp, argvp, "-enum"))
    {
	smpd_data_t *data;
	if (smpd_get_all_smpd_data(&data) == SMPD_SUCCESS)
	{
	    smpd_data_t *iter = data;
	    while (iter != NULL)
	    {
		printf("%s\n%s\n", iter->name, iter->value);
		iter = iter->next;
	    }
	    while (data != NULL)
	    {
		iter = data;
		data = data->next;
		MPIU_Free(iter);
	    }
	}
	smpd_exit(0);
    }

    if (smpd_get_opt_string(argcp, argvp, "-query", domain, SMPD_MAX_HOST_LENGTH))
    {
	printf("querying hosts in the %s domain:\n", domain);
	printf("Not implemented.\n");
	smpd_exit(0);
    }
    if (smpd_get_opt(argcp, argvp, "-query"))
    {
	printf("querying hosts in the default domain:\n");
	printf("Not implemented.\n");
	smpd_exit(0);
    }

    /* check for the service/silent option */
#ifdef HAVE_WINDOWS_H
    smpd_process.bService = SMPD_TRUE;
#endif

    if (smpd_get_opt(argcp, argvp, "-s"))
    {
#ifdef HAVE_WINDOWS_H
	printf("The -s option is only available under unix.\n");
	smpd_print_options();
	smpd_exit(0);
#else
	smpd_process.bNoTTY = SMPD_TRUE;
#endif
    }

    if (smpd_get_opt(argcp, argvp, "-r"))
    {
#ifdef HAVE_WINDOWS_H
	printf("The -r option is only available under unix.\n");
	smpd_print_options();
#else
	printf("The -r root option is not yet implemented.\n");
#endif
	smpd_exit(0);
    }

    /* check for debug option */
    if (smpd_get_opt_int(argcp, argvp, "-d", &dbg_flag))
    {
	smpd_process.dbg_state = dbg_flag;
	smpd_process.bNoTTY = SMPD_FALSE;
	smpd_process.bService = SMPD_FALSE;
    }
    if (smpd_get_opt(argcp, argvp, "-d"))
    {
	smpd_process.dbg_state = SMPD_DBG_STATE_ERROUT | SMPD_DBG_STATE_STDOUT | SMPD_DBG_STATE_PREPEND_RANK | SMPD_DBG_STATE_TRACE;
	smpd_process.bNoTTY = SMPD_FALSE;
	smpd_process.bService = SMPD_FALSE;
    }
    if (smpd_get_opt_int(argcp, argvp, "-debug", &dbg_flag))
    {
	smpd_process.dbg_state = dbg_flag;
	smpd_process.bNoTTY = SMPD_FALSE;
	smpd_process.bService = SMPD_FALSE;
    }
    if (smpd_get_opt(argcp, argvp, "-debug"))
    {
	smpd_process.dbg_state = SMPD_DBG_STATE_ERROUT | SMPD_DBG_STATE_STDOUT | SMPD_DBG_STATE_PREPEND_RANK | SMPD_DBG_STATE_TRACE;
	smpd_process.bNoTTY = SMPD_FALSE;
	smpd_process.bService = SMPD_FALSE;
    }

    /* check for port option */
    smpd_get_opt_int(argcp, argvp, "-p", &smpd_process.port);
    smpd_get_opt_int(argcp, argvp, "-port", &smpd_process.port);
    if (smpd_get_opt(argcp, argvp, "-anyport"))
    {
	smpd_process.port = 0;
	smpd_process.dbg_state = 0; /* turn of debugging or you won't be able to read the port from stdout */
	smpd_process.bNoTTY = SMPD_FALSE;
	smpd_process.bService = SMPD_FALSE;
    }

    smpd_process.noprompt = smpd_get_opt(argcp, argvp, "-noprompt");

#ifdef HAVE_WINDOWS_H

    /* check for service options */
    if (smpd_get_opt(argcp, argvp, "-remove") ||
	smpd_get_opt(argcp, argvp, "-unregserver") ||
	smpd_get_opt(argcp, argvp, "-uninstall") ||
	smpd_get_opt(argcp, argvp, "/Remove") ||
	smpd_get_opt(argcp, argvp, "/Uninstall"))
    {
	/*RegDeleteKey(HKEY_CURRENT_USER, MPICHKEY);*/
	smpd_remove_service(SMPD_TRUE);
	ExitProcess(0);
    }
    if (smpd_get_opt(argcp, argvp, "-install") ||
	smpd_get_opt(argcp, argvp, "-regserver") ||
	smpd_get_opt(argcp, argvp, "/Install") ||
	smpd_get_opt(argcp, argvp, "/install") ||
	smpd_get_opt(argcp, argvp, "/RegServer"))
    {
	char phrase[SMPD_PASSPHRASE_MAX_LENGTH]="", port_str[SMPD_MAX_PORT_STR_LENGTH]="";

	if (smpd_remove_service(SMPD_FALSE) == SMPD_FALSE)
	{
	    printf("Unable to remove the previous installation, install failed.\n");
	    ExitProcess(0);
	}

	if (smpd_get_opt_string(argcp, argvp, "-phrase", phrase, SMPD_PASSPHRASE_MAX_LENGTH) ||
	    smpd_get_win_opt_string(argcp, argvp, "/phrase", phrase, SMPD_PASSPHRASE_MAX_LENGTH))
	{
	    smpd_set_smpd_data("phrase", phrase);
	}
	if (smpd_get_opt(argcp, argvp, "-getphrase"))
	{
	    printf("passphrase for smpd: ");fflush(stdout);
	    smpd_get_password(phrase);
	    smpd_set_smpd_data("phrase", phrase);
	}
	if (smpd_process.port != SMPD_LISTENER_PORT)
	{
        snprintf(port_str, SMPD_MAX_PORT_STR_LENGTH, "%d", smpd_process.port);
	    smpd_set_smpd_data("port", port_str);
	}

	smpd_install_service(SMPD_FALSE, SMPD_TRUE, smpd_get_opt(argcp, argvp, "-delegation"));
	smpd_set_smpd_data("version", SMPD_VERSION);
	ExitProcess(0);
    }
    if (smpd_get_opt(argcp, argvp, "-start"))
    {
	smpd_start_service();
	ExitProcess(0);
    }
    if (smpd_get_opt(argcp, argvp, "-stop"))
    {
	smpd_stop_service();
	ExitProcess(0);
    }
    if (smpd_get_opt(argcp, argvp, "-register_spn"))
    {
        char filename[SMPD_MAX_FILENAME];

        if(smpd_get_opt_string(argcp, argvp, "-f", filename, SMPD_MAX_FILENAME)){
            result = smpd_setup_scps_with_file(filename);
            if(result != SMPD_SUCCESS){
                printf("Failed to register smpd's Service Principal Names (at least one failed) with Domain Controller\n");
                ExitProcess((UINT )-1);
            }
        }
        else{
            result = smpd_setup_scp(NULL);
            if(result != SMPD_SUCCESS){
                printf("Failed to register smpd's Service Principal Name with Domain Controller\n");
                ExitProcess((UINT )-1);
            }
        }
        printf("Service Principal Name registered with the domain controller.\n");
        printf("SMPD is now capable of launching processes using passwordless delegation.\n");
        printf("The system administrator must ensure the following:\n");
        printf(" 1) This host is trusted for delegation in Active Directory\n");
        printf(" 2) All users who will run jobs are trusted for delegation.\n");
        printf("Domain administrators can enable these options for hosts and users\nin Active Directory on the domain controller.\n");
        ExitProcess(0);
    }
    if (smpd_get_opt(argcp, argvp, "-remove_spn"))
    {
        char filename[SMPD_MAX_FILENAME];
        smpd_spn_list_hnd_t hnd;

        result = smpd_spn_list_init(&hnd);
        if(result != SMPD_SUCCESS){
            printf("Unable to initialize SPN list\n");
            ExitProcess((UINT ) -1);
        }

        if(smpd_get_opt_string(argcp, argvp, "-f", filename, SMPD_MAX_FILENAME)){
            result = smpd_remove_scps_with_file(filename, hnd);
            if(result != SMPD_SUCCESS){
                printf("Failed to remove smpd's Service Principal Names (at least one failed) with Domain Controller\n");
                ExitProcess((UINT )-1);
            }
            printf("Removed smpd's Service Principal Names successfully\n");
        }
        else{
            result = smpd_remove_scp(NULL, hnd);
            if(result != SMPD_SUCCESS){
                printf("Failed to remove smpd's Service Principal Name with Domain Controller\n");
                ExitProcess((UINT )-1);
            }
            printf("Removed smpd's Service Principal Name successfully\n");
        }
        smpd_spn_list_finalize(&hnd);
        ExitProcess(0);
    }

    if (smpd_get_opt(argcp, argvp, "-mgr"))
    {
	/* Set a ctrl-handler to kill child processes if this smpd is killed */
	if (!SetConsoleCtrlHandler(smpd_ctrl_handler, TRUE))
	{
	    result = GetLastError();
	    smpd_dbg_printf("unable to set the ctrl handler for the smpd manager, error %d.\n", result);
	}
#ifdef HAVE_WINDOWS_H
    {
        BOOL ret;
        ret = smpd_init_affinity_table();
        if(!ret){
            smpd_dbg_printf("Initializing smpd affinity table failed\n");
        }
    }
#endif

	smpd_process.bService = SMPD_FALSE;
	if (!smpd_get_opt_string(argcp, argvp, "-read", read_handle_str, 20))
	{
	    smpd_err_printf("manager started without a read pipe handle.\n");
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	if (!smpd_get_opt_string(argcp, argvp, "-write", write_handle_str, 20))
	{
	    smpd_err_printf("manager started without a write pipe handle.\n");
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	hRead = smpd_decode_handle(read_handle_str);
	hWrite = smpd_decode_handle(write_handle_str);

	smpd_dbg_printf("manager creating listener and session sets.\n");

	result = SMPDU_Sock_create_set(&set);
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("SMPDU_Sock_create_set(listener) failed,\nsock error: %s\n", get_sock_error_string(result));
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	smpd_process.set = set;
	smpd_dbg_printf("created set for manager listener, %d\n", SMPDU_Sock_get_sock_set_id(set));
	port = 0;
	result = SMPDU_Sock_listen(set, NULL, &port, &listener); 
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("SMPDU_Sock_listen failed,\nsock error: %s\n", get_sock_error_string(result));
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	smpd_dbg_printf("smpd manager listening on port %d\n", port);

	result = smpd_create_context(SMPD_CONTEXT_LISTENER, set, listener, -1, &smpd_process.listener_context);
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("unable to create a context for the smpd listener.\n");
	    smpd_exit_fn(FCNAME);
	    return result;
	}
	result = SMPDU_Sock_set_user_ptr(listener, smpd_process.listener_context);
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("SMPDU_Sock_set_user_ptr failed,\nsock error: %s\n", get_sock_error_string(result));
	    smpd_exit_fn(FCNAME);
	    return result;
	}
	smpd_process.listener_context->state = SMPD_MGR_LISTENING;

	memset(str, 0, 20);
	snprintf(str, 20, "%d", port);
	smpd_dbg_printf("manager writing port back to smpd.\n");
	if (!WriteFile(hWrite, str, 20, &num_written, NULL))
	{
	    smpd_err_printf("WriteFile failed, error %d\n", GetLastError());
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	CloseHandle(hWrite);
	if (num_written != 20)
	{
	    smpd_err_printf("wrote only %d bytes of 20\n", num_written);
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	smpd_dbg_printf("manager reading account and password from smpd.\n");
	if (!ReadFile(hRead, smpd_process.UserAccount, SMPD_MAX_ACCOUNT_LENGTH, &num_read, NULL))
	{
	    smpd_err_printf("ReadFile failed, error %d\n", GetLastError());
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	if (num_read != SMPD_MAX_ACCOUNT_LENGTH)
	{
	    smpd_err_printf("read only %d bytes of %d\n", num_read, SMPD_MAX_ACCOUNT_LENGTH);
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	if (!ReadFile(hRead, smpd_process.UserPassword, SMPD_MAX_PASSWORD_LENGTH, &num_read, NULL))
	{
	    smpd_err_printf("ReadFile failed, error %d\n", GetLastError());
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	if (num_read != SMPD_MAX_PASSWORD_LENGTH)
	{
	    smpd_err_printf("read only %d bytes of %d\n", num_read, SMPD_MAX_PASSWORD_LENGTH);
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	if (!ReadFile(hRead, smpd_process.passphrase, SMPD_PASSPHRASE_MAX_LENGTH, &num_read, NULL))
	{
	    smpd_err_printf("ReadFile failed, error %d\n", GetLastError());
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	if (num_read != SMPD_PASSPHRASE_MAX_LENGTH)
	{
	    smpd_err_printf("read only %d bytes of %d\n", num_read, SMPD_PASSPHRASE_MAX_LENGTH);
	    smpd_exit_fn(FCNAME);
	    return SMPD_FAIL;
	}
	smpd_process.credentials_prompt = SMPD_FALSE;

	result = smpd_enter_at_state(set, SMPD_MGR_LISTENING);
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("state machine failed.\n");
	}

	/*
	result = SMPDU_Sock_finalize();
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("SMPDU_Sock_finalize failed,\nsock error: %s\n", get_sock_error_string(result));
	}
	*/
	smpd_exit(0);
	smpd_exit_fn(FCNAME);
	ExitProcess(0);
    }
#endif

    /* check for the status option */
    if (smpd_get_opt_string(argcp, argvp, "-status", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
    {
	smpd_process.do_console = 1;
	smpd_process.builtin_cmd = SMPD_CMD_DO_STATUS;
    }
    else if (smpd_get_opt(argcp, argvp, "-status"))
    {
	smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
	smpd_process.do_console = 1;
	smpd_process.builtin_cmd = SMPD_CMD_DO_STATUS;
    }

    /* check for console options */
    if (smpd_get_opt_string(argcp, argvp, "-console", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
    {
	smpd_process.do_console = 1;
    }
    else if (smpd_get_opt(argcp, argvp, "-console"))
    {
	smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
	smpd_process.do_console = 1;
    }
    if (smpd_process.do_console)
    {
	/* This may need to be changed to avoid conflict */
	if (smpd_get_opt(argcp, argvp, "-p"))
	{
	    smpd_process.use_process_session = 1;
	}
    }

    if (smpd_get_opt_string(argcp, argvp, "-shutdown", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
    {
	smpd_process.do_console = 1;
	smpd_process.builtin_cmd = SMPD_CMD_SHUTDOWN;
    }
    else if (smpd_get_opt(argcp, argvp, "-shutdown"))
    {
	smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
	smpd_process.do_console = 1;
	smpd_process.builtin_cmd = SMPD_CMD_SHUTDOWN;
    }

    if (smpd_get_opt_string(argcp, argvp, "-restart", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
    {
	smpd_process.do_console = 1;
	smpd_process.builtin_cmd = SMPD_CMD_RESTART;
    }
    else if (smpd_get_opt(argcp, argvp, "-restart"))
    {
#ifdef HAVE_WINDOWS_H
	printf("restarting the smpd service...\n");
	smpd_stop_service();
	Sleep(1000);
	smpd_start_service();
	smpd_exit(0);
#else
	smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
	smpd_process.do_console = 1;
	smpd_process.builtin_cmd = SMPD_CMD_RESTART;
#endif
    }

    if (smpd_get_opt_string(argcp, argvp, "-version", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
    {
	smpd_process.do_console = 1;
	smpd_process.builtin_cmd = SMPD_CMD_VERSION;
    }
    else if (smpd_get_opt(argcp, argvp, "-version"))
    {
	printf("%s\n", SMPD_VERSION);
	fflush(stdout);
	smpd_exit(0);
    }

    /* These commands are handled by mpiexec although doing them here is an alternate solution.
    if (smpd_get_opt_two_strings(argcp, argvp, "-add_job", smpd_process.job_key, SMPD_MAX_NAME_LENGTH, smpd_process.job_key_account, SMPD_MAX_ACCOUNT_LENGTH))
    {
	if (!smpd_get_opt_string(argcp, argvp, "-host", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
	    smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
	if (smpd_get_opt_string(argcp, argvp, "-password", smpd_process.job_key_password, SMPD_MAX_PASSWORD_LENGTH)
	    smpd_process.builtin_cmd = SMPD_CMD_ADD_JOB_KEY_AND_PASSWORD;
	else
	    smpd_process.builtin_cmd = SMPD_CMD_ADD_JOB_KEY;
	smpd_process.do_console = 1;
    }

    if (smpd_get_opt_string(argcp, argvp, "-remove_job", smpd_process.job_key, SMPD_MAX_NAME_LENGTH))
    {
	if (!smpd_get_opt_string(argcp, argvp, "-host", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
	    smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
	smpd_process.do_console = 1;
	smpd_process.builtin_cmd = SMPD_CMD_REMOVE_JOB_KEY;
    }

    if (smpd_get_opt_string(argcp, argvp, "-associate_job", smpd_process.job_key, SMPD_MAX_NAME_LENGTH))
    {
	if (!smpd_get_opt_string(argcp, argvp, "-host", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
	    smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
	smpd_process.do_console = 1;
	smpd_process.builtin_cmd = SMPD_CMD_ASSOCIATE_JOB_KEY;
    }
    */

    smpd_get_opt_string(argcp, argvp, "-phrase", smpd_process.passphrase, SMPD_PASSPHRASE_MAX_LENGTH);
    if (smpd_get_opt(argcp, argvp, "-getphrase"))
    {
	printf("passphrase for smpd: ");fflush(stdout);
	smpd_get_password(smpd_process.passphrase);
    }

    if (smpd_get_opt_string(argcp, argvp, "-smpdfile", smpd_process.smpd_filename, SMPD_MAX_FILENAME))
    {
	struct stat s;

	if (stat(smpd_process.smpd_filename, &s) == 0)
	{
	    if (s.st_mode & 00077)
	    {
		printf(".smpd file cannot be readable by anyone other than the current user.\n");
		smpd_exit_fn(FCNAME);
		return SMPD_FAIL;
	    }
	}
    }

    if (smpd_get_opt_string(argcp, argvp, "-traceon", filename, SMPD_MAX_FILENAME))
    {
	smpd_process.do_console_returns = SMPD_TRUE;
	if (*argcp > 1)
	{
	    for (i=1; i<*argcp; i++)
	    {
		strcpy(smpd_process.console_host, (*argvp)[i]);

		smpd_process.do_console = 1;
		smpd_process.builtin_cmd = SMPD_CMD_SET;
		strcpy(smpd_process.key, "logfile");
		strcpy(smpd_process.val, filename);
		result = smpd_do_console();
		if (result != SMPD_SUCCESS)
		{
		    smpd_err_printf("Unable to set the logfile name on host '%s'\n", smpd_process.console_host);
		    smpd_exit_fn(FCNAME);
		    return result;
		}

		smpd_process.do_console = 1;
		smpd_process.builtin_cmd = SMPD_CMD_SET;
		strcpy(smpd_process.key, "log");
		strcpy(smpd_process.val, "yes");
		result = smpd_do_console();
		if (result != SMPD_SUCCESS)
		{
		    smpd_err_printf("Unable to set the log option on host '%s'\n", smpd_process.console_host);
		    smpd_exit_fn(FCNAME);
		    return result;
		}

		smpd_process.do_console = 1;
		smpd_process.builtin_cmd = SMPD_CMD_RESTART;
		result = smpd_do_console();
		if (result != SMPD_SUCCESS)
		{
		    smpd_err_printf("Unable to restart the smpd on host '%s'\n", smpd_process.console_host);
		    smpd_exit_fn(FCNAME);
		    return result;
		}
	    }
	}
	else
	{
	    result = smpd_set_smpd_data("logfile", filename);
	    result = smpd_set_smpd_data("log", "yes");

#ifdef HAVE_WINDOWS_H
	    printf("restarting the smpd service...\n");
	    smpd_stop_service();
	    Sleep(1000);
	    smpd_start_service();
#else
	    smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
	    smpd_process.do_console = 1;
	    smpd_process.builtin_cmd = SMPD_CMD_RESTART;
	    result = smpd_do_console();
	    if (result != SMPD_SUCCESS)
	    {
		smpd_err_printf("Unable to restart the smpd on host '%s'\n", smpd_process.console_host);
		smpd_exit_fn(FCNAME);
		return result;
	    }
#endif
	}
	smpd_exit_fn(FCNAME);
	smpd_exit(result);
    }

    if (smpd_get_opt(argcp, argvp, "-traceoff"))
    {
	smpd_process.do_console_returns = SMPD_TRUE;
	if (*argcp > 1)
	{
	    for (i=1; i<*argcp; i++)
	    {
		strcpy(smpd_process.console_host, (*argvp)[i]);

		smpd_process.do_console = 1;
		smpd_process.builtin_cmd = SMPD_CMD_SET;
		strcpy(smpd_process.key, "log");
		strcpy(smpd_process.val, "no");
		result = smpd_do_console();
		if (result != SMPD_SUCCESS)
		{
		    smpd_err_printf("Unable to set the log option on host '%s'\n", smpd_process.console_host);
		    smpd_exit_fn(FCNAME);
		    return result;
		}

		smpd_process.do_console = 1;
		smpd_process.builtin_cmd = SMPD_CMD_RESTART;
		result = smpd_do_console();
		if (result != SMPD_SUCCESS)
		{
		    smpd_err_printf("Unable to restart the smpd on host '%s'\n", smpd_process.console_host);
		    smpd_exit_fn(FCNAME);
		    return result;
		}
	    }
	}
	else
	{
	    result = smpd_set_smpd_data("log", "no");

#ifdef HAVE_WINDOWS_H
	    printf("restarting the smpd service...\n");
	    smpd_stop_service();
	    Sleep(1000);
	    smpd_start_service();
#else
	    smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
	    smpd_process.do_console = 1;
	    smpd_process.builtin_cmd = SMPD_CMD_RESTART;
	    result = smpd_do_console();
	    if (result != SMPD_SUCCESS)
	    {
		smpd_err_printf("Unable to restart the smpd on host '%s'\n", smpd_process.console_host);
		smpd_exit_fn(FCNAME);
		return result;
	    }
#endif
	}
	smpd_exit_fn(FCNAME);
	smpd_exit(result);
    }

    if (smpd_process.do_console)
    {
	result = smpd_do_console();
	smpd_exit_fn(FCNAME);
	return result;
    }

    smpd_exit_fn(FCNAME);
    return SMPD_SUCCESS;
}
int smpd_do_console()
{
    int result = -1;
    smpd_context_t *context;
    SMPDU_Sock_set_t set;
    SMPDU_Sock_t sock;
    SMPD_BOOL no_smpd = SMPD_FALSE;
    int saved_state = 0;
    int exit_code = 0;

    smpd_enter_fn(FCNAME);

    /* make sure we have a passphrase to authenticate connections to the smpds */
    if (smpd_process.passphrase[0] == '\0')
	smpd_get_smpd_data("phrase", smpd_process.passphrase, SMPD_PASSPHRASE_MAX_LENGTH);
    if (smpd_process.passphrase[0] == '\0')
    {
	if (smpd_process.noprompt)
	{
	    printf("Error: No smpd passphrase specified through the registry or .smpd file, exiting.\n");
	    goto quit_job;
	}
	printf("Please specify an authentication passphrase for smpd: ");
	fflush(stdout);
	smpd_get_password(smpd_process.passphrase);
    }

    result = SMPDU_Sock_create_set(&set);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("SMPDU_Sock_create_set failed,\nsock error: %s\n", get_sock_error_string(result));
	goto quit_job;
    }
    smpd_process.set = set;

    /* set the id of the mpiexec node to zero */
    smpd_process.id = 0;

    /* turn off output if do_status is selected to supress error messages */
    if (smpd_process.builtin_cmd == SMPD_CMD_DO_STATUS)
    {
	saved_state = smpd_process.dbg_state;
	smpd_process.dbg_state = 0;
    }

    /* start connecting the tree by posting a connect to the first host */
    result = smpd_create_context(SMPD_CONTEXT_LEFT_CHILD, set, SMPDU_SOCK_INVALID_SOCK/*sock*/, 1, &context);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("Unable to create a context.\n");
	goto quit_job;
    }

    result = SMPDU_Sock_post_connect(set, context, smpd_process.console_host, smpd_process.port, &sock);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("Unable to connect to '%s:%d',\nsock error: %s\n",
	    smpd_process.console_host, smpd_process.port, get_sock_error_string(result));
	no_smpd = SMPD_TRUE;
	goto quit_job;
    }
    context->sock = sock;

    /* turn output back on */
    if (smpd_process.builtin_cmd == SMPD_CMD_DO_STATUS)
	smpd_process.dbg_state = saved_state;

    context->state = SMPD_MPIEXEC_CONNECTING_SMPD;
    smpd_process.left_context = context;

    /* turn off output if do_status is selected to supress error messages */
    if (smpd_process.builtin_cmd == SMPD_CMD_DO_STATUS)
	smpd_process.dbg_state = 0;
    result = smpd_enter_at_state(set, SMPD_MPIEXEC_CONNECTING_SMPD);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("state machine failed.\n");
	no_smpd = SMPD_TRUE;
	goto quit_job;
    }
    /* turn output back on */
    if (smpd_process.builtin_cmd == SMPD_CMD_DO_STATUS)
	smpd_process.dbg_state = saved_state;

quit_job:

    if (result != SMPD_SUCCESS)
    {
	exit_code = result;
    }

    if (smpd_process.builtin_cmd == SMPD_CMD_DO_STATUS && (no_smpd || smpd_process.state_machine_ret_val != SMPD_SUCCESS))
    {
	printf("no smpd running on %s\n", smpd_process.console_host);
	smpd_process.dbg_state = saved_state;
    }

    if (smpd_process.do_console_returns == SMPD_TRUE)
    {
	smpd_exit_fn(FCNAME);
	return exit_code;
    }

    /* finalize */
    /*
    smpd_dbg_printf("calling SMPDU_Sock_finalize\n");
    result = SMPDU_Sock_finalize();
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("SMPDU_Sock_finalize failed,\nsock error: %s\n", get_sock_error_string(result));
    }
    */

#ifdef HAVE_WINDOWS_H
    if (smpd_process.hCloseStdinThreadEvent)
	SetEvent(smpd_process.hCloseStdinThreadEvent);
    if (smpd_process.hStdinThread != NULL)
    {
	/* close stdin so the input thread will exit */
	CloseHandle(GetStdHandle(STD_INPUT_HANDLE));
	if (WaitForSingleObject(smpd_process.hStdinThread, 3000) != WAIT_OBJECT_0)
	{
	    TerminateThread(smpd_process.hStdinThread, 321);
	}
	CloseHandle(smpd_process.hStdinThread);
    }
    if (smpd_process.hCloseStdinThreadEvent)
    {
	CloseHandle(smpd_process.hCloseStdinThreadEvent);
	smpd_process.hCloseStdinThreadEvent = NULL;
    }
#elif defined(USE_PTHREAD_STDIN_REDIRECTION)
    smpd_cancel_stdin_thread();
#endif
    smpd_exit_fn(FCNAME);
    smpd_exit(exit_code);
    return SMPD_SUCCESS;
}
示例#4
0
static int setup_stdin_redirection(smpd_process_t *process, SMPDU_Sock_set_t set)
{
    int result;
    smpd_context_t *context_in;
    SMPDU_SOCK_NATIVE_FD stdin_fd;
    SMPDU_Sock_t insock;
#ifdef HAVE_WINDOWS_H
    DWORD dwThreadID;
    SOCKET hWrite;
#endif

    smpd_enter_fn("setup_stdin_redirection");

    /* get a handle to stdin */
#ifdef HAVE_WINDOWS_H
    result = smpd_make_socket_loop((SOCKET*)&stdin_fd, &hWrite);
    if (result)
    {
	smpd_err_printf("Unable to make a local socket loop to forward stdin.\n");
	smpd_exit_fn("setup_stdin_redirection");
	return SMPD_FAIL;
    }
#else
    stdin_fd = fileno(stdin);
#endif

    /* convert the native handle to a sock */
    result = SMPDU_Sock_native_to_sock(set, stdin_fd, NULL, &insock);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("unable to create a sock from stdin,\nsock error: %s\n", get_sock_error_string(result));
	smpd_exit_fn("setup_stdin_redirection");
	return SMPD_FAIL;
    }
    /* create a context for reading from stdin */
    result = smpd_create_context(SMPD_CONTEXT_MPIEXEC_STDIN_RSH, set, insock, -1, &context_in);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("unable to create a context for stdin.\n");
	smpd_exit_fn("setup_stdin_redirection");
	return SMPD_FAIL;
    }
    SMPDU_Sock_set_user_ptr(insock, context_in);
    context_in->process = process;

#ifdef HAVE_WINDOWS_H
    /* unfortunately, we cannot use stdin directly as a sock.  So, use a thread to read and forward
    stdin to a sock */
    smpd_process.hCloseStdinThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (smpd_process.hCloseStdinThreadEvent == NULL)
    {
	smpd_err_printf("Unable to create the stdin thread close event, error %d\n", GetLastError());
	smpd_exit_fn("setup_stdin_redirection");
	return SMPD_FAIL;
    }
    smpd_process.hStdinThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)smpd_stdin_thread, (void*)hWrite, 0, &dwThreadID);
    if (smpd_process.hStdinThread == NULL)
    {
	smpd_err_printf("Unable to create a thread to read stdin, error %d\n", GetLastError());
	smpd_exit_fn("setup_stdin_redirection");
	return SMPD_FAIL;
    }
#endif
    /* set this variable first before posting the first read to avoid a race condition? */
    smpd_process.stdin_redirecting = SMPD_TRUE;
    /* post a read for a user command from stdin */
    context_in->read_state = SMPD_READING_STDIN;
    result = SMPDU_Sock_post_read(insock, context_in->read_cmd.cmd, 1, 1, NULL);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("unable to post a read on stdin for an incoming user command, error:\n%s\n",
	    get_sock_error_string(result));
	smpd_exit_fn("setup_stdin_redirection");
	return SMPD_FAIL;
    }
    smpd_exit_fn("setup_stdin_redirection");
    return SMPD_SUCCESS;
}
示例#5
0
int smpd_init_context(smpd_context_t *context, smpd_context_type_t type, SMPDU_Sock_set_t set, SMPDU_Sock_t sock, int id)
{
    int result;

    smpd_enter_fn(FCNAME);
    context->type = type;
    context->target = SMPD_TARGET_UNDETERMINED;
    context->access = SMPD_ACCESS_USER_PROCESS;/*SMPD_ACCESS_NONE;*/
    context->host[0] = '\0';
    context->id = id;
    context->rank = 0;
    context->write_list = NULL;
    context->wait_list = NULL;
    smpd_init_command(&context->read_cmd);
    context->next = NULL;
    context->set = set;
    context->sock = sock;
    context->state = SMPD_IDLE;
    context->read_state = SMPD_IDLE;
    context->write_state = SMPD_IDLE;
    context->account[0] = '\0';
    context->domain[0] = '\0';
    context->full_domain[0] = '\0';
    context->connect_return_id = -1;
    context->connect_return_tag = -1;
    context->connect_to = NULL;
    context->spawn_context = NULL;
    context->cred_request[0] = '\0';
    context->password[0] = '\0';
    context->encrypted_password[0] = '\0';
    context->port_str[0] = '\0';
    context->pszChallengeResponse[0] = '\0';
    context->pszCrypt[0] = '\0';
    context->pwd_request[0] = '\0';
    context->session[0] = '\0';
    context->session_header[0] = '\0';
    context->singleton_init_hostname[0] = '\0';
    context->singleton_init_kvsname[0] = '\0';
    context->singleton_init_domainname[0] = '\0';
    context->singleton_init_pm_port = -1;
    context->smpd_pwd[0] = '\0';
#ifdef HAVE_WINDOWS_H
    context->wait.hProcess = NULL;
    context->wait.hThread = NULL;
#else
    context->wait = 0;
#endif
    context->process = NULL;
    context->sspi_header[0] = '\0';
    context->sspi_context = NULL;
    context->sspi_type = SMPD_SSPI_DELEGATE;
    context->sspi_job_key[0] = '\0';
    context->first_output_stderr = SMPD_TRUE;
    context->first_output_stdout = SMPD_TRUE;

    if (sock != SMPDU_SOCK_INVALID_SOCK)
    {
	result = SMPDU_Sock_set_user_ptr(sock, context);
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("unable to set the sock user ptr while initializing context,\nsock error: %s\n",
		get_sock_error_string(result));
	}
    }

    smpd_exit_fn(FCNAME);
    return SMPD_SUCCESS;
}
示例#6
0
int main(int argc, char* argv[])
{
    int result = SMPD_SUCCESS;
    smpd_host_node_t *host_node_ptr;
    smpd_launch_node_t *launch_node_ptr;
    smpd_context_t *context;
    SMPDU_Sock_set_t set;
    SMPDU_Sock_t sock = SMPDU_SOCK_INVALID_SOCK;
    smpd_state_t state;

    smpd_enter_fn("main");

    /* catch an empty command line */
    if (argc < 2)
    {
	mp_print_options();
	exit(0);
    }

    smpd_process.mpiexec_argv0 = argv[0];

    /* initialize */
    /* FIXME: Get rid of this hack - we already create 
     * local KVS for all singleton clients by default
     */
    putenv("PMI_SMPD_FD=0");
    result = PMPI_Init(&argc, &argv);
    /* SMPD_CS_ENTER(); */
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("SMPD_Init failed,\nerror: %d\n", result);
	smpd_exit_fn("main");
	return result;
    }

    result = SMPDU_Sock_init();
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("SMPDU_Sock_init failed,\nsock error: %s\n",
		      get_sock_error_string(result));
	smpd_exit_fn("main");
	return result;
    }

    result = smpd_init_process();
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("smpd_init_process failed.\n");
	goto quit_job;
    }

    smpd_process.dbg_state = SMPD_DBG_STATE_ERROUT;

    /* parse the command line */
    smpd_dbg_printf("parsing the command line.\n");
    result = mp_parse_command_args(&argc, &argv);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("Unable to parse the mpiexec command arguments.\n");
	goto quit_job;
    }

    /* If we are using MS HPC job scheduler we only connect
     * to the local SMPD
     */
    if(smpd_process.use_ms_hpc){
        char host[100];
        int id;
        /* Free the current host list */
        result = smpd_free_host_list();
        if(result != SMPD_SUCCESS){
            smpd_err_printf("Unable to free the global host list\n");
            goto quit_job;
        }
        /* Add local host to the host list */
        result = smpd_get_hostname(host, 100);
        if(result != SMPD_SUCCESS){
            smpd_err_printf("Unable to get the local hostname\n");
            goto quit_job;
        }
	    result = smpd_get_host_id(host, &id);
        if(result != SMPD_SUCCESS){
            smpd_err_printf("Unable to get host id for local host\n");
            goto quit_job;
        }
        /* Set the number of PMI procs since they are not launched by mpiexec */
        smpd_process.nproc = smpd_process.launch_list->nproc;
        smpd_dbg_printf("Adding (%s:%d) == (localhost) to the host list\n", host, id);
    }

    /* print and see what we've got */
    /* debugging output *************/
    smpd_dbg_printf("host tree:\n");
    host_node_ptr = smpd_process.host_list;
    if (!host_node_ptr)
	smpd_dbg_printf("<none>\n");
    while (host_node_ptr)
    {
	smpd_dbg_printf(" host: %s, parent: %d, id: %d\n",
	    host_node_ptr->host,
	    host_node_ptr->parent, host_node_ptr->id);
	host_node_ptr = host_node_ptr->next;
    }
    smpd_dbg_printf("launch nodes:\n");
    launch_node_ptr = smpd_process.launch_list;
    if (!launch_node_ptr)
	smpd_dbg_printf("<none>\n");
    while (launch_node_ptr)
    {
	smpd_dbg_printf(" iproc: %d, id: %d, exe: %s\n",
	    launch_node_ptr->iproc, launch_node_ptr->host_id,
	    launch_node_ptr->exe);
	launch_node_ptr = launch_node_ptr->next;
    }
    /* end debug output *************/

    /* set the id of the mpiexec node to zero */
    smpd_process.id = 0;

    result = SMPDU_Sock_create_set(&set);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("SMPDU_Sock_create_set failed,\nsock error: %s\n", get_sock_error_string(result));
	goto quit_job;
    }
    smpd_process.set = set;

    /* Check to see if the user wants to use a remote shell mechanism for launching the processes
     * instead of using the smpd process managers.
     */
    if (smpd_process.rsh_mpiexec == SMPD_TRUE)
    {
	/* Do rsh or localonly stuff */
	result = mpiexec_rsh();

	/* skip over the non-rsh code and go to the cleanup section */
	goto quit_job;
    }

    /* Start the timeout mechanism if specified */
    /* This code occurs after the rsh_mpiexec option check because the rsh code implementes timeouts differently */
    if (smpd_process.timeout > 0)
    {
#ifdef HAVE_WINDOWS_H
	/* create a Windows thread to sleep until the timeout expires */
	if (smpd_process.timeout_thread == NULL)
	{
	    smpd_process.timeout_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)timeout_thread, NULL, 0, NULL);
	    if (smpd_process.timeout_thread == NULL)
	    {
		printf("Error: unable to create a timeout thread, errno %d.\n", GetLastError());
		smpd_exit_fn("mp_parse_command_args");
		return SMPD_FAIL;
	    }
	}
#elif defined(SIGALRM)
	/* create an alarm to signal mpiexec when the timeout expires */
	smpd_signal(SIGALRM, timeout_function);
	alarm(smpd_process.timeout);
#elif defined(HAVE_PTHREAD_H)
	/* create a pthread to sleep until the timeout expires */
	result = pthread_create(&smpd_process.timeout_thread, NULL, timeout_thread, NULL);
	if (result != 0)
	{
	    printf("Error: unable to create a timeout thread, errno %d.\n", result);
	    smpd_exit_fn("mp_parse_command_args");
	    return SMPD_FAIL;
	}
#else
	/* no timeout mechanism available */
#endif
    }

    /* make sure we have a passphrase to authenticate connections to the smpds */
    if (smpd_process.passphrase[0] == '\0')
	smpd_get_smpd_data("phrase", smpd_process.passphrase, SMPD_PASSPHRASE_MAX_LENGTH);
    if (smpd_process.passphrase[0] == '\0')
    {
	if (smpd_process.noprompt)
	{
	    printf("Error: No smpd passphrase specified through the registry or .smpd file, exiting.\n");
	    result = SMPD_FAIL;
	    goto quit_job;
	}
	printf("Please specify an authentication passphrase for smpd: ");
	fflush(stdout);
	smpd_get_password(smpd_process.passphrase);
    }

    /* set the state to create a console session or a job session */
    state = smpd_process.do_console ? SMPD_MPIEXEC_CONNECTING_SMPD : SMPD_MPIEXEC_CONNECTING_TREE;

    result = smpd_create_context(SMPD_CONTEXT_LEFT_CHILD, set, sock, 1, &context);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("unable to create a context for the first host in the tree.\n");
	goto quit_job;
    }
#ifdef HAVE_WINDOWS_H
    if (!smpd_process.local_root)
    {
#endif
	/* start connecting the tree by posting a connect to the first host */
	result = SMPDU_Sock_post_connect(set, context, smpd_process.host_list->host, smpd_process.port, &sock);
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("Unable to connect to '%s:%d',\nsock error: %s\n",
		smpd_process.host_list->host, smpd_process.port, get_sock_error_string(result));
	    goto quit_job;
	}
#ifdef HAVE_WINDOWS_H
    }
#endif
    context->sock = sock;
    context->state = state;
    context->connect_to = smpd_process.host_list;
#ifdef HAVE_WINDOWS_H
    if (smpd_process.local_root)
    {
	int port;
	smpd_context_t *rc_context;

	/* The local_root option is implemented by having mpiexec act as the smpd
	 * and launch the smpd manager.  Then mpiexec connects to this manager just
	 * as if it had been created by a real smpd.  This causes all the processes
	 * destined for the first smpd host to be launched by this child process of
	 * mpiexec and not the smpd service.  This allows for these processes to
	 * create windows that are visible to the interactive user.  It also means 
	 * that the job cannot be run in the context of a user other than the user
	 * running mpiexec. */

	/* get the path to smpd.exe because pszExe is currently mpiexec.exe */
	smpd_get_smpd_data("binary", smpd_process.pszExe, SMPD_MAX_EXE_LENGTH);

	/* launch the manager process */
	result = smpd_start_win_mgr(context, SMPD_FALSE);
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("unable to start the local smpd manager.\n");
	    goto quit_job;
	}

	/* connect to the manager */
	smpd_dbg_printf("connecting a new socket.\n");
	port = atol(context->port_str);
	if (port < 1)
	{
	    smpd_err_printf("Invalid reconnect port read: %d\n", port);
	    goto quit_job;
	}
	result = smpd_create_context(context->type, context->set, SMPDU_SOCK_INVALID_SOCK, context->id, &rc_context);
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("unable to create a new context for the reconnection.\n");
	    goto quit_job;
	}
	rc_context->state = context->state;
	rc_context->write_state = SMPD_RECONNECTING;
	context->state = SMPD_CLOSING;
	rc_context->connect_to = context->connect_to;
	rc_context->connect_return_id = context->connect_return_id;
	rc_context->connect_return_tag = context->connect_return_tag;
	strcpy(rc_context->host, context->host);
	smpd_process.left_context = rc_context;
	smpd_dbg_printf("posting a re-connect to %s:%d in %s context.\n", rc_context->connect_to->host, port, smpd_get_context_str(rc_context));
	result = SMPDU_Sock_post_connect(rc_context->set, rc_context, rc_context->connect_to->host, port, &rc_context->sock);
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("Unable to post a connect to '%s:%d',\nsock error: %s\n",
		rc_context->connect_to->host, port, get_sock_error_string(result));
	    if (smpd_post_abort_command("Unable to connect to '%s:%d',\nsock error: %s\n",
		rc_context->connect_to->host, port, get_sock_error_string(result)) != SMPD_SUCCESS)
	    {
		goto quit_job;
	    }
	}
    }
    else
    {
#endif
	smpd_process.left_context = context;
	result = SMPDU_Sock_set_user_ptr(sock, context);
	if (result != SMPD_SUCCESS)
	{
	    smpd_err_printf("unable to set the smpd sock user pointer,\nsock error: %s\n",
		get_sock_error_string(result));
	    goto quit_job;
	}
#ifdef HAVE_WINDOWS_H
    }
#endif

#ifdef HAVE_WINDOWS_H
    {
	/* Create a break handler and a socket to handle aborting the job when mpiexec receives break signals */
	smpd_context_t *reader_context;
	SMPDU_Sock_t sock_reader;
	SMPDU_SOCK_NATIVE_FD reader, writer;

	smpd_make_socket_loop((SOCKET*)&reader, (SOCKET*)&writer);
	result = SMPDU_Sock_native_to_sock(set, reader, NULL, &sock_reader);
	result = SMPDU_Sock_native_to_sock(set, writer, NULL, &smpd_process.mpiexec_abort_sock);
	result = smpd_create_context(SMPD_CONTEXT_MPIEXEC_ABORT, set, sock_reader, -1, &reader_context);
	reader_context->read_state = SMPD_READING_MPIEXEC_ABORT;
	result = SMPDU_Sock_post_read(sock_reader, &reader_context->read_cmd.cmd, 1, 1, NULL);

	if (!SetConsoleCtrlHandler(mpiexec_ctrl_handler, TRUE))
	{
	    /* Don't error out; allow the job to run without a ctrl handler? */
	    result = GetLastError();
	    smpd_dbg_printf("unable to set a ctrl handler for mpiexec, error %d\n", result);
	}
    }
#endif

    result = smpd_enter_at_state(set, state);
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("state machine failed.\n");
	goto quit_job;
    }

quit_job:

    if ((result != SMPD_SUCCESS) && (smpd_process.mpiexec_exit_code == 0))
    {
	smpd_process.mpiexec_exit_code = -1;
    }

    /* finalize */

    smpd_dbg_printf("calling SMPDU_Sock_finalize\n");
    result = SMPDU_Sock_finalize();
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("SMPDU_Sock_finalize failed,\nsock error: %s\n", get_sock_error_string(result));
    }

    /* SMPD_Finalize called in smpd_exit()
    smpd_dbg_printf("calling SMPD_Finalize\n");
    result = PMPI_Finalize();
    if (result != SMPD_SUCCESS)
    {
	smpd_err_printf("SMPD_Finalize failed,\nerror: %d\n", result);
    }
    */

#ifdef HAVE_WINDOWS_H
    if (smpd_process.hCloseStdinThreadEvent)
	SetEvent(smpd_process.hCloseStdinThreadEvent);
    if (smpd_process.hStdinThread != NULL)
    {
	/* close stdin so the input thread will exit */
	CloseHandle(GetStdHandle(STD_INPUT_HANDLE));
	if (WaitForSingleObject(smpd_process.hStdinThread, 3000) != WAIT_OBJECT_0)
	{
	    TerminateThread(smpd_process.hStdinThread, 321);
	}
	CloseHandle(smpd_process.hStdinThread);
    }
    if (smpd_process.hCloseStdinThreadEvent)
    {
	CloseHandle(smpd_process.hCloseStdinThreadEvent);
	smpd_process.hCloseStdinThreadEvent = NULL;
    }
#elif defined(USE_PTHREAD_STDIN_REDIRECTION)
    smpd_cancel_stdin_thread();
#endif
    smpd_exit_fn("main");
    /* SMPD_CS_EXIT(); */
    return smpd_exit(smpd_process.mpiexec_exit_code);
}