1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3  *  (C) 2001 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6 
7 #include <stdio.h>
8 #include "mpiexec.h"
9 #include "smpd.h"
10 #include <stdlib.h>
11 #ifdef HAVE_STRING_H
12 #include <string.h>
13 #endif
14 #ifdef HAVE_SYS_TYPES_H
15 #include <sys/types.h>
16 #endif
17 #ifdef HAVE_SYS_STAT_H
18 #include <sys/stat.h>
19 #endif
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #if defined(HAVE_DIRECT_H) || defined(HAVE_WINDOWS_H)
24 #include <direct.h>
25 #endif
26 #ifdef HAVE_WINDOWS_H
27 #include <crtdbg.h>
28 #endif
29 #ifdef HAVE_CTYPE_H
30 #include <ctype.h>
31 #endif
32 
33 /* The supported values right now are "newtcp" & "nd" */
34 #define SMPD_MAX_NEMESIS_NETMOD_LENGTH  10
35 
mp_print_options(void)36 void mp_print_options(void)
37 {
38     printf("\n");
39     printf("Usage:\n");
40     printf("mpiexec -n <maxprocs> [options] executable [args ...]\n");
41     printf("mpiexec [options] executable [args ...] : [options] exe [args] : ...\n");
42     printf("mpiexec -configfile <configfile>\n");
43     printf("\n");
44     printf("options:\n");
45     printf("\n");
46     printf("standard:\n");
47     printf("-n <maxprocs>\n");
48     printf("-wdir <working directory>\n");
49     printf("-configfile <filename> -\n");
50     printf("       each line contains a complete set of mpiexec options\n");
51     printf("       including the executable and arguments\n");
52     printf("-host <hostname>\n");
53     /*
54     printf("-soft <Fortran90 triple> - acceptable number of processes up to maxprocs\n");
55     printf("       a or a:b or a:b:c where\n");
56     printf("       1) a = a\n");
57     printf("       2) a:b = a, a+1, a+2, ..., b\n");
58     printf("       3) a:b:c = a, a+c, a+2c, a+3c, ..., a+kc\n");
59     printf("          where a+kc <= b if c>0\n");
60     printf("                a+kc >= b if c<0\n");
61     */
62     printf("-path <search path for executable, ; separated>\n");
63     /*printf("-arch <architecture> - sun, linux, rs6000, ...\n");*/
64     printf("\n");
65     printf("extensions:\n");
66     printf("-env <variable value>\n");
67     printf("-hosts <n host1 host2 ... hostn>\n");
68     printf("-hosts <n host1 m1 host2 m2 ... hostn mn>\n");
69     printf("-machinefile <filename> - one host per line, #commented\n");
70     printf("-localonly <numprocs>\n");
71     printf("-exitcodes - print the exit codes of processes as they exit\n");
72     /*
73     printf("-genvall - pass all env vars in current environment\n");
74     printf("-genvnone - pass no env vars\n");
75     */
76     printf("-genvlist <list of env var names a,b,c,...> - pass current values of these vars\n");
77     printf("-g<local arg name> - global version of local options\n");
78     printf("  genv, gwdir, ghost, gpath, gmap\n");
79     printf("-file <filename> - old mpich1 job configuration file\n");
80     printf("\n");
81     printf("examples:\n");
82     printf("mpiexec -n 4 cpi\n");
83     printf("mpiexec -n 1 -host foo master : -n 8 worker\n");
84     printf("\n");
85     printf("For a list of all mpiexec options, execute 'mpiexec -help2'\n");
86 }
87 
mp_print_extra_options(void)88 void mp_print_extra_options(void)
89 {
90     printf("\n");
91     printf("All options to mpiexec:\n");
92     printf("\n");
93     printf("-n x\n");
94     printf("-np x\n");
95     printf("  launch x processes\n");
96     printf("-localonly x\n");
97     printf("-n x -localonly\n");
98     printf("  launch x processes on the local machine\n");
99     printf("-machinefile filename\n");
100     printf("  use a file to list the names of machines to launch on\n");
101     printf("-host hostname\n");
102     printf("-hosts n host1 host2 ... hostn\n");
103     printf("-hosts n host1 m1 host2 m2 ... hostn mn\n");
104     printf("  launch on the specified hosts\n");
105     printf("  In the second version the number of processes = m1 + m2 + ... + mn\n");
106     printf("-binding proc_binding_scheme\n");
107     printf("  Set the proc binding for each of the launched processes to a single core.\n");
108     printf("  Currently \"auto\" and \"user\" are supported as the proc_binding_schemes \n");
109     printf("-map drive:\\\\host\\share\n");
110     printf("  map a drive on all the nodes\n");
111     printf("  this mapping will be removed when the processes exit\n");
112     printf("-mapall\n");
113     printf("  map all of the current network drives\n");
114     printf("  this mapping will be removed when the processes exit\n");
115     printf("  (Available currently only on windows)\n");
116     printf("-dir drive:\\my\\working\\directory\n");
117     printf("-wdir /my/working/directory\n");
118     printf("  launch processes in the specified directory\n");
119     printf("-env var val\n");
120     printf("  set environment variable before launching the processes\n");
121     printf("-logon\n");
122     printf("  prompt for user account and password\n");
123     printf("-pwdfile filename\n");
124     printf("  read the account and password from the file specified\n");
125     printf("  put the account on the first line and the password on the second\n");
126     /*
127     printf("-nocolor\n");
128     printf("  don't use process specific output coloring\n");
129     */
130     printf("-nompi\n");
131     printf("  launch processes without the mpi startup mechanism\n");
132     /*
133     printf("-nomapping\n");
134     printf("  don't try to map the current directory on the remote nodes\n");
135     */
136     printf("-nopopup_debug\n");
137     printf("  disable the system popup dialog if the process crashes\n");
138     /*
139     printf("-dbg\n");
140     printf("  catch unhandled exceptions\n");
141     */
142     printf("-exitcodes\n");
143     printf("  print the process exit codes when each process exits.\n");
144     printf("-noprompt\n");
145     printf("  prevent mpiexec from prompting for user credentials.\n");
146     printf("-priority class[:level]\n");
147     printf("  set the process startup priority class and optionally level.\n");
148     printf("  class = 0,1,2,3,4   = idle, below, normal, above, high\n");
149     printf("  level = 0,1,2,3,4,5 = idle, lowest, below, normal, above, highest\n");
150     printf("  the default is -priority 1:3\n");
151     printf("-localroot\n");
152     printf("  launch the root process directly from mpiexec if the host is local.\n");
153     printf("  (This allows the root process to create windows and be debugged.)\n");
154     printf("-port port\n");
155     printf("-p port\n");
156     printf("  specify the port that smpd is listening on.\n");
157     printf("-phrase passphrase\n");
158     printf("  specify the passphrase to authenticate connections to smpd with.\n");
159     printf("-smpdfile filename\n");
160     printf("  specify the file where the smpd options are stored including the passphrase.\n");
161     /*
162     printf("-soft Fortran90_triple\n");
163     printf("  acceptable number of processes to launch up to maxprocs\n");
164     */
165     printf("-path search_path\n");
166     printf("  search path for executable, ; separated\n");
167     /*
168     printf("-arch architecture\n");
169     printf("  sun, linux, rs6000, ...\n");
170     */
171     printf("-register [-user n]\n");
172     printf("  encrypt a user name and password to the Windows registry.\n");
173     printf("  optionally specify a user slot index\n");
174     printf("-remove [-user n]\n");
175     printf("  delete the encrypted credentials from the Windows registry.\n");
176     printf("  If no user index is specified then all entries are removed.\n");
177     printf("-validate [-user n] [-host hostname]\n");
178     printf("  validate the encrypted credentials for the current or specified host.\n");
179     printf("  A specific user index can be specified otherwise index 0 is the default.\n");
180     printf("-user n\n");
181     printf("  use the registered user credentials from slot n to launch the job.\n");
182     printf("-timeout seconds\n");
183     printf("  timeout for the job.\n");
184     printf("-plaintext\n");
185     printf("  don't encrypt the data on the wire.\n");
186     printf("-delegate\n");
187     printf("  use passwordless delegation to launch processes\n");
188     printf("-impersonate\n");
189     printf("  use passwordless authentication to launch processes\n");
190     printf("-add_job <job_name> <domain\\user>\n");
191     printf("-add_job <job_name> <domain\\user> -host <hostname>\n");
192     printf("  add a job key for the specified domain user on the local or specified host\n");
193     printf("  requires administrator privileges\n");
194     printf("-remove_job <name>\n");
195     printf("-remove_job <name> -host <hostname>\n");
196     printf("  remove a job key from the local or specified host\n");
197     printf("  requires administrator privileges\n");
198     printf("-associate_job <name>\n");
199     printf("-associate_job <name> -host <hostname>\n");
200     printf("  associate the current user's token with the specified job on the local or specified host\n");
201     printf("-job <name>\n");
202     printf("  launch the processes in the context of the specified job\n");
203     printf("-whomai\n");
204     printf("  print the current user name\n");
205     printf("-l\n");
206     printf("  prefix output with the process number. (This option is a lowercase L not the number one)\n");
207 }
208 
209 #ifdef HAVE_WINDOWS_H
210 
211 /* check to see if a path is on a network mapped drive and would need to be mapped on a remote system */
NeedToMap(char * pszFullPath,char * pDrive,char * pszShare)212 SMPD_BOOL NeedToMap(char *pszFullPath, char *pDrive, char *pszShare)
213 {
214     DWORD dwResult;
215     DWORD dwLength;
216     char pBuffer[4096];
217     REMOTE_NAME_INFO *info = (REMOTE_NAME_INFO*)pBuffer;
218     char pszTemp[SMPD_MAX_EXE_LENGTH];
219 
220     if (*pszFullPath == '"')
221     {
222 	strncpy(pszTemp, &pszFullPath[1], SMPD_MAX_EXE_LENGTH);
223 	pszTemp[SMPD_MAX_EXE_LENGTH-1] = '\0';
224 	if (pszTemp[strlen(pszTemp)-1] == '"')
225 	    pszTemp[strlen(pszTemp)-1] = '\0';
226 	pszFullPath = pszTemp;
227     }
228     dwLength = 4096;
229     info->lpConnectionName = NULL;
230     info->lpRemainingPath = NULL;
231     info->lpUniversalName = NULL;
232     dwResult = WNetGetUniversalName(pszFullPath, REMOTE_NAME_INFO_LEVEL, info, &dwLength);
233     if (dwResult == NO_ERROR)
234     {
235 	*pDrive = *pszFullPath;
236 	strcpy(pszShare, info->lpConnectionName);
237 	return SMPD_TRUE;
238     }
239 
240     /*printf("WNetGetUniversalName: '%s'\n error %d\n", pszExe, dwResult);*/
241     return SMPD_FALSE;
242 }
243 
244 /* convert an executable name to a universal naming convention version so that it can be used on a remote system */
ExeToUnc(char * pszExe,int length)245 void ExeToUnc(char *pszExe, int length)
246 {
247     DWORD dwResult;
248     DWORD dwLength;
249     char pBuffer[4096];
250     REMOTE_NAME_INFO *info = (REMOTE_NAME_INFO*)pBuffer;
251     char pszTemp[SMPD_MAX_EXE_LENGTH];
252     SMPD_BOOL bQuoted = SMPD_FALSE;
253     char *pszOriginal;
254 
255     pszOriginal = pszExe;
256 
257     if (*pszExe == '"')
258     {
259 	bQuoted = SMPD_TRUE;
260 	strncpy(pszTemp, &pszExe[1], SMPD_MAX_EXE_LENGTH);
261 	pszTemp[SMPD_MAX_EXE_LENGTH-1] = '\0';
262 	if (pszTemp[strlen(pszTemp)-1] == '"')
263 	    pszTemp[strlen(pszTemp)-1] = '\0';
264 	pszExe = pszTemp;
265     }
266     dwLength = 4096;
267     info->lpConnectionName = NULL;
268     info->lpRemainingPath = NULL;
269     info->lpUniversalName = NULL;
270     dwResult = WNetGetUniversalName(pszExe, REMOTE_NAME_INFO_LEVEL, info, &dwLength);
271     if (dwResult == NO_ERROR)
272     {
273 	if (bQuoted)
274 	    snprintf(pszOriginal, length, "\"%s\"", info->lpUniversalName);
275 	else
276 	{
277 	    strncpy(pszOriginal, info->lpUniversalName, length);
278 	    pszOriginal[length-1] = '\0';
279 	}
280     }
281 }
282 
283 #endif
284 
strip_args(int * argcp,char ** argvp[],int n)285 static int strip_args(int *argcp, char **argvp[], int n)
286 {
287     int i;
288 
289     if (n+1 > (*argcp))
290     {
291 	printf("Error: cannot strip %d args, only %d left.\n", n, (*argcp)-1);
292 	return SMPD_FAIL;
293     }
294     for (i=n+1; i<=(*argcp); i++)
295     {
296 	(*argvp)[i-n] = (*argvp)[i];
297     }
298     (*argcp) -= n;
299     return SMPD_SUCCESS;
300 }
301 
smpd_isnumber(char * str)302 static SMPD_BOOL smpd_isnumber(char *str)
303 {
304     size_t i, n = strlen(str);
305     for (i=0; i<n; i++)
306     {
307 	if (!isdigit(str[i]))
308 	    return SMPD_FALSE;
309     }
310     return SMPD_TRUE;
311 }
312 
313 #ifdef HAVE_WINDOWS_H
mpiexec_assert_hook(int reportType,char * message,int * returnValue)314 static int mpiexec_assert_hook( int reportType, char *message, int *returnValue )
315 {
316     SMPD_UNREFERENCED_ARG(reportType);
317 
318     fprintf(stderr, "%s", message);
319     if (returnValue != NULL)
320 	exit(*returnValue);
321     exit(-1);
322 }
323 
324 /* This function reads the user binding option and sets the affinity map.
325  * The user option is of the form "user:a,b,c" where a, b, c are integers denoting
326  * the cores in the affinity map
327  */
read_user_affinity_map(char * option)328 static int read_user_affinity_map(char *option)
329 {
330     char *p = NULL, *q = NULL, *context = NULL;
331     int i=0, map_sz = 0;
332 
333     if(smpd_process.affinity_map != NULL){
334         printf("Error: duplicate user affinity map option\n");
335         return SMPD_FAIL;
336     }
337     if(option == NULL){
338         printf("Error: NULL user affinity option\n");
339         return SMPD_FAIL;
340     }
341 
342     /* option = "user:1,2,3" */
343     p = option;
344     p = strtok_s(p, ":", &context);
345     if(p == NULL){
346         printf("Error parsing user affinity map\n");
347         return SMPD_FAIL;
348     }
349     p = strtok_s(NULL, ":", &context);
350     if(p == NULL){
351         printf("Error parsing user affinity map\n");
352         return SMPD_FAIL;
353     }
354 
355     /* p should now point to the affinity map separated by comma's */
356     map_sz = 1;
357     q = p;
358     /* parse to find the number of elements in the map */
359     while(*q != '\0'){
360         if(*q == ','){
361             map_sz++;
362         }
363         q++;
364     }
365 
366     /* Allocate the mem for map */
367     smpd_process.affinity_map = (int *)MPIU_Malloc(sizeof(int) * map_sz);
368     if(smpd_process.affinity_map == NULL){
369         printf("Unable to allocate memory for affinity map\n");
370         return SMPD_FAIL;
371     }
372     smpd_process.affinity_map_sz = map_sz;
373 
374     context = NULL;
375     p = strtok_s(p, ",", &context);
376     i = 0;
377     while(p != NULL){
378         /* FIXME: We don't detect overflow case in atoi */
379         smpd_process.affinity_map[i++] = atoi(p);
380         p = strtok_s(NULL, ",", &context);
381     }
382 
383     smpd_dbg_printf("The user affinity map is : [ ");
384     for(i=0; i<map_sz; i++){
385         smpd_dbg_printf(" %d ,",smpd_process.affinity_map[i]);
386     }
387     smpd_dbg_printf(" ] \n");
388 
389     return SMPD_SUCCESS;
390 }
391 #endif
392 
393 #undef FCNAME
394 #define FCNAME "mp_parse_command_args"
mp_parse_command_args(int * argcp,char ** argvp[])395 int mp_parse_command_args(int *argcp, char **argvp[])
396 {
397     int cur_rank;
398     int affinity_map_index;
399     int argc, next_argc;
400     char **next_argv;
401     char *exe_ptr;
402     int num_args_to_strip;
403     int nproc;
404     char machine_file_name[SMPD_MAX_FILENAME];
405     int use_machine_file = SMPD_FALSE;
406     smpd_map_drive_node_t *map_node, *drive_map_list;
407     smpd_map_drive_node_t *gmap_node, *gdrive_map_list;
408     smpd_env_node_t *env_node, *env_list;
409     smpd_env_node_t *genv_list;
410     char *env_str, env_data[SMPD_MAX_ENV_LENGTH];
411     char wdir[SMPD_MAX_DIR_LENGTH];
412     char gwdir[SMPD_MAX_DIR_LENGTH];
413     int use_debug_flag;
414     char pwd_file_name[SMPD_MAX_FILENAME];
415     int use_pwd_file;
416     smpd_host_node_t *host_node_ptr, *host_list, *host_node_iter;
417     smpd_host_node_t *ghost_list;
418     int no_drive_mapping;
419     int n_priority_class, n_priority;
420     int index, i;
421     char configfilename[SMPD_MAX_FILENAME];
422     int use_configfile, delete_configfile;
423     char exe[SMPD_MAX_EXE_LENGTH], *exe_iter;
424     char exe_path[SMPD_MAX_EXE_LENGTH], *namepart;
425     smpd_launch_node_t *launch_node, *launch_node_iter;
426     int exe_len_remaining;
427     char path[SMPD_MAX_PATH_LENGTH];
428     char gpath[SMPD_MAX_PATH_LENGTH];
429     char temp_password[SMPD_MAX_PASSWORD_LENGTH];
430     FILE *fin_config = NULL;
431     int result;
432     int maxlen;
433     int appnum = 0;
434     char channel[SMPD_MAX_NAME_LENGTH] = "";
435     /* smpd configured settings */
436     char smpd_setting_tmp_buffer[20];
437     char smpd_setting_channel[20] = "";
438     char smpd_setting_internode_channel[20] = "";
439     SMPD_BOOL smpd_setting_timeout = SMPD_INVALID_SETTING;
440     SMPD_BOOL smpd_setting_priority_class = SMPD_INVALID_SETTING;
441     SMPD_BOOL smpd_setting_priority = SMPD_INVALID_SETTING;
442     char smpd_setting_path[SMPD_MAX_PATH_LENGTH] = "";
443     SMPD_BOOL smpd_setting_localonly = SMPD_INVALID_SETTING;
444     char nemesis_netmod[SMPD_MAX_NEMESIS_NETMOD_LENGTH];
445 
446 #ifdef HAVE_WINDOWS_H
447     int user_index;
448     char user_index_str[20];
449 #endif
450 
451     smpd_enter_fn(FCNAME);
452 
453 #ifdef HAVE_WINDOWS_H
454     /* prevent mpiexec from bringing up an error message window if it crashes */
455     _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
456     _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
457     _CrtSetReportHook(mpiexec_assert_hook);
458 
459     /* check for windows specific arguments */
460     if (*argcp > 1)
461     {
462 	if (strcmp((*argvp)[1], "-register") == 0)
463 	{
464         char register_filename[SMPD_MAX_FILENAME];
465 	    user_index = 0;
466 	    smpd_get_opt_int(argcp, argvp, "-user", &user_index);
467 	    if (user_index < 0)
468 	    {
469 		user_index = 0;
470 	    }
471         register_filename[0] = '\0';
472         if(smpd_get_opt_string(argcp, argvp, "-file", register_filename, SMPD_MAX_FILENAME))
473         {
474             smpd_dbg_printf("Registering username/password to a file\n");
475         }
476 	    for (;;)
477 	    {
478 		smpd_get_account_and_password(smpd_process.UserAccount, smpd_process.UserPassword);
479 		fprintf(stderr, "confirm password: ");fflush(stderr);
480 		smpd_get_password(temp_password);
481 		if (strcmp(smpd_process.UserPassword, temp_password) == 0)
482 		    break;
483 		printf("passwords don't match, please try again.\n");
484 	    }
485         if(strlen(register_filename) > 0)
486         {
487             if(smpd_save_cred_to_file(register_filename, smpd_process.UserAccount, smpd_process.UserPassword))
488             {
489                 printf("Username/password encrypted and saved to registry file\n");
490             }
491             else
492             {
493                 smpd_err_printf("Error saving username/password to registry file\n");
494             }
495             smpd_exit(0);
496         }
497 	    if (smpd_save_password_to_registry(user_index, smpd_process.UserAccount, smpd_process.UserPassword, SMPD_TRUE))
498 	    {
499 		printf("Password encrypted into the Registry.\n");
500 		smpd_delete_cached_password();
501 	    }
502 	    else
503 	    {
504 		printf("Error: Unable to save encrypted password.\n");
505 	    }
506 	    fflush(stdout);
507 	    smpd_exit(0);
508 	}
509 	if ( (strcmp((*argvp)[1], "-remove") == 0) || (strcmp((*argvp)[1], "-unregister") == 0) )
510 	{
511 	    user_index = 0;
512 	    if (smpd_get_opt_string(argcp, argvp, "-user", user_index_str, 20))
513 	    {
514 		if (user_index_str[0] == 'a' && user_index_str[1] == 'l' && user_index_str[2] == 'l' && user_index_str[3] == '\0')
515 		{
516 		    user_index = -1;
517 		}
518 		else
519 		{
520 		    user_index = atoi(user_index_str);
521 		    if (user_index < 0)
522 		    {
523 			user_index = 0;
524 		    }
525 		}
526 	    }
527 	    if (smpd_delete_current_password_registry_entry(user_index))
528 	    {
529 		smpd_delete_cached_password();
530 		printf("Account and password removed from the Registry.\n");
531 	    }
532 	    else
533 	    {
534 		printf("ERROR: Unable to remove the encrypted password.\n");
535 	    }
536 	    fflush(stdout);
537 	    smpd_exit(0);
538 	}
539 	if (strcmp((*argvp)[1], "-validate") == 0)
540 	{
541 	    user_index = 0;
542 	    smpd_get_opt_int(argcp, argvp, "-user", &user_index);
543 	    if (user_index < 0)
544 	    {
545 		user_index = 0;
546 	    }
547 	    if (smpd_read_password_from_registry(user_index, smpd_process.UserAccount, smpd_process.UserPassword))
548 	    {
549 		if (!smpd_get_opt_string(argcp, argvp, "-host", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
550 		{
551 		    smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
552 		}
553 		smpd_get_opt_int(argcp, argvp, "-port", &smpd_process.port);
554 		smpd_get_opt_string(argcp, argvp, "-phrase", smpd_process.passphrase, SMPD_PASSPHRASE_MAX_LENGTH);
555 		smpd_process.builtin_cmd = SMPD_CMD_VALIDATE;
556 		smpd_do_console();
557 	    }
558 	    else
559 	    {
560 		printf("FAIL: Unable to read the credentials from the registry.\n");fflush(stdout);
561 	    }
562 	    fflush(stdout);
563 	    smpd_exit(0);
564 	}
565 	if (strcmp((*argvp)[1], "-whoami") == 0)
566 	{
567 	    char username[100] = "";
568 	    ULONG len = 100;
569 	    if (GetUserNameEx(NameSamCompatible, username, &len))
570 	    {
571 		printf("%s\n", username);
572 	    }
573 	    else if (GetUserName(username, &len))
574 	    {
575 		printf("%s\n", username);
576 	    }
577 	    else
578 	    {
579 		printf("ERROR: Unable to determine the current username.\n");
580 	    }
581 	    fflush(stdout);
582 	    smpd_exit(0);
583 	}
584 
585 	if (strcmp((*argvp)[1], "-add_job") == 0)
586 	{
587 	    if (smpd_get_opt(argcp, argvp, "-verbose"))
588 	    {
589 		smpd_process.verbose = SMPD_TRUE;
590 		smpd_process.dbg_state |= SMPD_DBG_STATE_ERROUT | SMPD_DBG_STATE_STDOUT | SMPD_DBG_STATE_TRACE;
591 	    }
592 
593 	    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))
594 	    {
595 		if (!smpd_get_opt_string(argcp, argvp, "-host", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
596 		{
597 		    smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
598 		}
599 		smpd_get_opt_int(argcp, argvp, "-port", &smpd_process.port);
600 		smpd_get_opt_string(argcp, argvp, "-phrase", smpd_process.passphrase, SMPD_PASSPHRASE_MAX_LENGTH);
601 		if (smpd_get_opt_string(argcp, argvp, "-password", smpd_process.job_key_password, SMPD_MAX_PASSWORD_LENGTH))
602 		{
603 		    smpd_process.builtin_cmd = SMPD_CMD_ADD_JOB_AND_PASSWORD;
604 		}
605 		else
606 		{
607 		    smpd_process.builtin_cmd = SMPD_CMD_ADD_JOB;
608 		}
609 		smpd_do_console();
610 		fflush(stdout);
611 		smpd_exit(0);
612 	    }
613 	    printf("Invalid number of arguments passed to -add_job <job_key> <user_account>\n");
614 	    fflush(stdout);
615 	    smpd_exit(-1);
616 	}
617 
618 	if (strcmp((*argvp)[1], "-remove_job") == 0)
619 	{
620 	    if (smpd_get_opt(argcp, argvp, "-verbose"))
621 	    {
622 		smpd_process.verbose = SMPD_TRUE;
623 		smpd_process.dbg_state |= SMPD_DBG_STATE_ERROUT | SMPD_DBG_STATE_STDOUT | SMPD_DBG_STATE_TRACE;
624 	    }
625 
626 	    if (smpd_get_opt_string(argcp, argvp, "-remove_job", smpd_process.job_key, SMPD_MAX_NAME_LENGTH))
627 	    {
628 		if (!smpd_get_opt_string(argcp, argvp, "-host", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
629 		{
630 		    smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
631 		}
632 		smpd_get_opt_int(argcp, argvp, "-port", &smpd_process.port);
633 		smpd_get_opt_string(argcp, argvp, "-phrase", smpd_process.passphrase, SMPD_PASSPHRASE_MAX_LENGTH);
634 		smpd_process.builtin_cmd = SMPD_CMD_REMOVE_JOB;
635 		smpd_do_console();
636 		fflush(stdout);
637 		smpd_exit(0);
638 	    }
639 	    printf("Invalid number of arguments passed to -remove_job <job_key>\n");
640 	    fflush(stdout);
641 	    smpd_exit(-1);
642 	}
643 
644 	if (strcmp((*argvp)[1], "-associate_job") == 0)
645 	{
646 	    if (smpd_get_opt(argcp, argvp, "-verbose"))
647 	    {
648 		smpd_process.verbose = SMPD_TRUE;
649 		smpd_process.dbg_state |= SMPD_DBG_STATE_ERROUT | SMPD_DBG_STATE_STDOUT | SMPD_DBG_STATE_TRACE;
650 	    }
651 
652 	    if (smpd_get_opt_string(argcp, argvp, "-associate_job", smpd_process.job_key, SMPD_MAX_NAME_LENGTH))
653 	    {
654 		if (!smpd_get_opt_string(argcp, argvp, "-host", smpd_process.console_host, SMPD_MAX_HOST_LENGTH))
655 		{
656 		    smpd_get_hostname(smpd_process.console_host, SMPD_MAX_HOST_LENGTH);
657 		}
658 		smpd_get_opt_int(argcp, argvp, "-port", &smpd_process.port);
659 		smpd_get_opt_string(argcp, argvp, "-phrase", smpd_process.passphrase, SMPD_PASSPHRASE_MAX_LENGTH);
660 		smpd_process.builtin_cmd = SMPD_CMD_ASSOCIATE_JOB;
661 		smpd_do_console();
662 		fflush(stdout);
663 		smpd_exit(0);
664 	    }
665 	    printf("Invalid number of arguments passed to -associate_job <job_key>\n");
666 	    fflush(stdout);
667 	    smpd_exit(-1);
668 	}
669     }
670 #endif
671 
672     if ((*argcp == 2) &&
673 	((strcmp((*argvp)[1], "-pmiserver") == 0) || (strcmp((*argvp)[1], "-pmi_server") == 0)))
674     {
675 	smpd_err_printf("Error: No number of processes specified after the %s option\n", (*argvp)[1]);
676 	return SMPD_FAIL;
677     }
678 
679     if (*argcp >= 3)
680     {
681 	if ((strcmp((*argvp)[1], "-pmiserver") == 0) || (strcmp((*argvp)[1], "-pmi_server") == 0))
682 	{
683 	    char host[100];
684 	    int id;
685 
686         smpd_process.use_pmi_server = SMPD_TRUE;
687 
688 	    if (smpd_get_opt(argcp, argvp, "-verbose"))
689 	    {
690 		smpd_process.verbose = SMPD_TRUE;
691 		smpd_process.dbg_state |= SMPD_DBG_STATE_ERROUT | SMPD_DBG_STATE_STDOUT | SMPD_DBG_STATE_TRACE;
692 	    }
693 
694         if(smpd_get_opt(argcp, argvp, "-hide_console")){
695 #ifdef HAVE_WINDOWS_H
696             FreeConsole();
697 #endif
698         }
699 
700 #ifdef HAVE_WINDOWS_H
701         if(smpd_get_opt(argcp, argvp, "-impersonate"))
702         {
703             smpd_process.use_sspi = SMPD_TRUE;
704             smpd_process.use_delegation = SMPD_FALSE;
705         }
706         if(smpd_get_opt(argcp, argvp, "-delegate"))
707         {
708             smpd_process.use_sspi = SMPD_TRUE;
709             smpd_process.use_delegation = SMPD_TRUE;
710         }
711 #endif
712 	    smpd_process.nproc = atoi((*argvp)[2]);
713 	    if (smpd_process.nproc < 1)
714 	    {
715 		smpd_err_printf("invalid number of processes: %s\n", (*argvp)[2]);
716 		return SMPD_FAIL;
717 	    }
718 
719 	    /* set up the host list to connect to only the local host */
720 	    smpd_get_hostname(host, 100);
721 	    result = smpd_get_host_id(host, &id);
722 	    if (result != SMPD_SUCCESS)
723 	    {
724 		smpd_err_printf("unable to get a id for host %s\n", host);
725 		return SMPD_FAIL;
726 	    }
727 
728         if (*argcp >= 5){
729     	    smpd_process.singleton_client_port = atoi((*argvp)[4]);
730             if(smpd_process.singleton_client_port < 1){
731                 smpd_err_printf("Invalid singleton client port = %d\n",
732                                     smpd_process.singleton_client_port);
733                 return SMPD_FAIL;
734             }
735         }
736 
737 	    /* Return without creating any launch_nodes.  This will result in an mpiexec connected to the local smpd
738 	     * and no processes launched.
739 	     */
740 	    return SMPD_SUCCESS;
741 	}
742     }
743 
744     /* Get settings saved in smpd */
745     /* These settings have the lowest priority.
746      * First are settings on the command line,
747      * second are settings from environment variables and
748      * these are last.
749      */
750     result = smpd_get_smpd_data("channel", smpd_setting_channel, 20);
751     result = smpd_get_smpd_data("internode_channel", smpd_setting_internode_channel, 20);
752     smpd_setting_tmp_buffer[0] = '\0';
753     result = smpd_get_smpd_data("timeout", smpd_setting_tmp_buffer, 20);
754     if (result == SMPD_SUCCESS)
755     {
756 	smpd_setting_timeout = atoi(smpd_setting_tmp_buffer);
757 	if (smpd_setting_timeout < 1)
758 	{
759 	    smpd_setting_timeout = SMPD_INVALID_SETTING;
760 	}
761     }
762     smpd_process.output_exit_codes = smpd_option_on("exitcodes");
763     if (smpd_option_on("noprompt") == SMPD_TRUE)
764     {
765 	smpd_process.noprompt = SMPD_TRUE;
766 	smpd_process.credentials_prompt = SMPD_FALSE;
767     }
768     env_str = getenv("MPIEXEC_NOPROMPT");
769     if (env_str)
770     {
771 	smpd_process.noprompt = SMPD_TRUE;
772 	smpd_process.credentials_prompt = SMPD_FALSE;
773     }
774     smpd_setting_tmp_buffer[0] = '\0';
775     result = smpd_get_smpd_data("priority", smpd_setting_tmp_buffer, 20);
776     if (result == SMPD_SUCCESS)
777     {
778 	if (smpd_isnumbers_with_colon(smpd_setting_tmp_buffer))
779 	{
780 	    char *str;
781 	    smpd_setting_priority_class = atoi(smpd_setting_tmp_buffer); /* This assumes atoi will stop at the colon and return a number */
782 	    str = strchr(smpd_setting_tmp_buffer, ':');
783 	    if (str)
784 	    {
785 		str++;
786 		smpd_setting_priority = atoi(str);
787 	    }
788 	    else
789 	    {
790 		smpd_setting_priority = SMPD_DEFAULT_PRIORITY;
791 	    }
792 	    if (smpd_setting_priority_class < 0 || smpd_setting_priority_class > 4 || smpd_setting_priority < 0 || smpd_setting_priority > 5)
793 	    {
794 		/* ignore invalid priority settings */
795 		smpd_setting_priority_class = SMPD_INVALID_SETTING;
796 		smpd_setting_priority = SMPD_INVALID_SETTING;
797 	    }
798 	}
799     }
800     result = smpd_get_smpd_data("app_path", smpd_setting_path, SMPD_MAX_PATH_LENGTH);
801     smpd_process.plaintext = smpd_option_on("plaintext");
802     smpd_setting_localonly = smpd_option_on("localonly");
803     result = smpd_get_smpd_data("port", smpd_setting_tmp_buffer, 20);
804     if (result == SMPD_SUCCESS)
805     {
806 	if (smpd_isnumber(smpd_setting_tmp_buffer))
807 	{
808 	    result = atoi(smpd_setting_tmp_buffer);
809 	    if (result != 0)
810 		smpd_process.port = result;
811 	}
812     }
813 
814     env_str = getenv("MPIEXEC_SMPD_PORT");
815     if (env_str)
816     {
817 	if (smpd_isnumber(env_str))
818 	{
819 	    result = atoi(env_str);
820 	    if (result != 0)
821 		smpd_process.port = result;
822 	}
823     }
824 
825     /* check for mpi options */
826     /*
827      * Required:
828      * -n <maxprocs>
829      * -host <hostname>
830      * -soft <Fortran90 triple> - represents allowed number of processes up to maxprocs
831      *        a or a:b or a:b:c where
832      *        1) a = a
833      *        2) a:b = a, a+1, a+2, ..., b
834      *        3) a:b:c = a, a+c, a+2c, a+3c, ..., a+kc
835      *           where a+kc <= b if c>0
836      *                 a+kc >= b if c<0
837      * -wdir <working directory>
838      * -path <search path for executable>
839      * -arch <architecture> - sun, linux, rs6000, ...
840      * -configfile <filename> - each line contains a complete set of mpiexec options, #commented
841      *
842      * Extensions:
843      * -env <variable=value>
844      * -env <variable=value;variable2=value2;...>
845      * -hosts <n host1 host2 ... hostn>
846      * -hosts <n host1 m1 host2 m2 ... hostn mn>
847      * -machinefile <filename> - one host per line, #commented
848      * -localonly <numprocs>
849      * -nompi - don't require processes to be SMPD processes (don't have to call SMPD_Init or PMI_Init)
850      * -exitcodes - print the exit codes of processes as they exit
851      * -verbose - same as setting environment variable to SMPD_DBG_OUTPUT=stdout
852      * -quiet_abort - minimize the output when a job is aborted
853      * -file - mpich1 job configuration file
854      *
855      * Windows extensions:
856      * -map <drive:\\host\share>
857      * -pwdfile <filename> - account on the first line and password on the second
858      * -nomapping - don't copy the current directory mapping on the remote nodes
859      * -dbg - debug
860      * -noprompt - don't prompt for user credentials, fail with an error message
861      * -logon - force the prompt for user credentials
862      * -priority <class[:level]> - set the process startup priority class and optionally level.
863      *            class = 0,1,2,3,4   = idle, below, normal, above, high
864      *            level = 0,1,2,3,4,5 = idle, lowest, below, normal, above, highest
865      * -localroot - launch the root process without smpd if the host is local.
866      *              (This allows the root process to create windows and be debugged.)
867      *
868      * Backwards compatibility
869      * -np <numprocs>
870      * -dir <working directory>
871      */
872 
873     /* Get a list of hosts from a file or the registry to be used with the -n,-np options */
874     smpd_get_default_hosts();
875 
876     cur_rank = 0;
877     affinity_map_index = 0;
878     gdrive_map_list = NULL;
879     genv_list = NULL;
880     gwdir[0] = '\0';
881     gpath[0] = '\0';
882     ghost_list = NULL;
883     next_argc = *argcp;
884     next_argv = *argvp + 1;
885     exe_ptr = **argvp;
886     do
887     {
888 	/* calculate the current argc and find the next argv */
889 	argc = 1;
890 	while ( (*next_argv) != NULL && (**next_argv) != ':')
891 	{
892 	    argc++;
893 	    next_argc--;
894 	    next_argv++;
895 	}
896 	if ( (*next_argv) != NULL && (**next_argv) == ':')
897 	{
898 	    (*next_argv) = NULL;
899 	    next_argv++;
900 	}
901 	argcp = &argc;
902 
903 	/* reset block global variables */
904 	use_configfile = SMPD_FALSE;
905 	delete_configfile = SMPD_FALSE;
906 configfile_loop:
907 	nproc = 0;
908 	drive_map_list = NULL;
909 	env_list = NULL;
910 	wdir[0] = '\0';
911 	use_debug_flag = SMPD_FALSE;
912 	use_pwd_file = SMPD_FALSE;
913 	host_list = NULL;
914 	no_drive_mapping = SMPD_FALSE;
915 	n_priority_class = (smpd_setting_priority_class == SMPD_INVALID_SETTING) ? SMPD_DEFAULT_PRIORITY_CLASS : smpd_setting_priority_class;
916 	n_priority = (smpd_setting_priority == SMPD_INVALID_SETTING) ? SMPD_DEFAULT_PRIORITY : smpd_setting_priority;
917 	use_machine_file = SMPD_FALSE;
918 	if (smpd_setting_path[0] != '\0')
919 	{
920 	    strncpy(path, smpd_setting_path, SMPD_MAX_PATH_LENGTH);
921 	}
922 	else
923 	{
924 	    path[0] = '\0';
925 	}
926 
927 	/* Check for the -configfile option.  It must be the first and only option in a group. */
928 	if ((*argvp)[1] && (*argvp)[1][0] == '-')
929 	{
930 	    if ((*argvp)[1][1] == '-')
931 	    {
932 		/* double -- option provided, trim it to a single - */
933 		index = 2;
934 		while ((*argvp)[1][index] != '\0')
935 		{
936 		    (*argvp)[1][index-1] = (*argvp)[1][index];
937 		    index++;
938 		}
939 		(*argvp)[1][index-1] = '\0';
940 	    }
941 	    if (strcmp(&(*argvp)[1][1], "configfile") == 0)
942 	    {
943 		if (use_configfile)
944 		{
945 		    printf("Error: -configfile option is not valid from within a configuration file.\n");
946 		    smpd_exit_fn(FCNAME);
947 		    return SMPD_FAIL;
948 		}
949 		if (argc < 3)
950 		{
951 		    printf("Error: no filename specifed after -configfile option.\n");
952 		    smpd_exit_fn(FCNAME);
953 		    return SMPD_FAIL;
954 		}
955 		strncpy(configfilename, (*argvp)[2], SMPD_MAX_FILENAME);
956 		use_configfile = SMPD_TRUE;
957 		fin_config = fopen(configfilename, "r");
958 		if (fin_config == NULL)
959 		{
960 		    printf("Error: unable to open config file '%s'\n", configfilename);
961 		    smpd_exit_fn(FCNAME);
962 		    return SMPD_FAIL;
963 		}
964 		if (!smpd_get_argcv_from_file(fin_config, argcp, argvp))
965 		{
966 		    fclose(fin_config);
967 		    printf("Error: unable to parse config file '%s'\n", configfilename);
968 		    smpd_exit_fn(FCNAME);
969 		    return SMPD_FAIL;
970 		}
971 	    }
972 	    if (strcmp(&(*argvp)[1][1], "file") == 0)
973 	    {
974 		if (argc < 3)
975 		{
976 		    printf("Error: no filename specifed after -file option.\n");
977 		    smpd_exit_fn(FCNAME);
978 		    return SMPD_FAIL;
979 		}
980 		mp_parse_mpich1_configfile((*argvp)[2], configfilename, SMPD_MAX_FILENAME);
981 		delete_configfile = SMPD_TRUE;
982 		use_configfile = SMPD_TRUE;
983 		fin_config = fopen(configfilename, "r");
984 		if (fin_config == NULL)
985 		{
986 		    printf("Error: unable to open config file '%s'\n", configfilename);
987 		    smpd_exit_fn(FCNAME);
988 		    return SMPD_FAIL;
989 		}
990 		if (!smpd_get_argcv_from_file(fin_config, argcp, argvp))
991 		{
992 		    fclose(fin_config);
993 		    printf("Error: unable to parse config file '%s'\n", configfilename);
994 		    smpd_exit_fn(FCNAME);
995 		    return SMPD_FAIL;
996 		}
997 	    }
998 	}
999 
1000 	/* parse the current block */
1001 
1002 	/* parse the mpiexec options */
1003 	while ((*argvp)[1] && (*argvp)[1][0] == '-')
1004 	{
1005 	    if ((*argvp)[1][1] == '-')
1006 	    {
1007 		/* double -- option provided, trim it to a single - */
1008 		index = 2;
1009 		while ((*argvp)[1][index] != '\0')
1010 		{
1011 		    (*argvp)[1][index-1] = (*argvp)[1][index];
1012 		    index++;
1013 		}
1014 		(*argvp)[1][index-1] = '\0';
1015 	    }
1016 
1017 	    num_args_to_strip = 1;
1018 	    if ((strcmp(&(*argvp)[1][1], "np") == 0) || (strcmp(&(*argvp)[1][1], "n") == 0))
1019 	    {
1020 		if (nproc != 0)
1021 		{
1022 		    printf("Error: only one option is allowed to determine the number of processes.\n");
1023 		    printf("       -hosts, -n, -np and -localonly x are mutually exclusive\n");
1024 		    smpd_exit_fn(FCNAME);
1025 		    return SMPD_FAIL;
1026 		}
1027 		if (argc < 3)
1028 		{
1029 		    printf("Error: no number specified after %s option.\n", (*argvp)[1]);
1030 		    smpd_exit_fn(FCNAME);
1031 		    return SMPD_FAIL;
1032 		}
1033 		nproc = atoi((*argvp)[2]);
1034 		if (nproc < 1)
1035 		{
1036 		    printf("Error: must specify a number greater than 0 after the %s option\n", (*argvp)[1]);
1037 		    smpd_exit_fn(FCNAME);
1038 		    return SMPD_FAIL;
1039 		}
1040 		num_args_to_strip = 2;
1041 	    }
1042 	    else if (strcmp(&(*argvp)[1][1], "localonly") == 0)
1043 	    {
1044 		/* check to see if there is a number after the localonly option */
1045 		if (argc > 2)
1046 		{
1047 		    if (smpd_isnumber((*argvp)[2]))
1048 		    {
1049 			if (nproc != 0)
1050 			{
1051 			    printf("Error: only one option is allowed to determine the number of processes.\n");
1052 			    printf("       -hosts, -n, -np and -localonly x are mutually exclusive\n");
1053 			    smpd_exit_fn(FCNAME);
1054 			    return SMPD_FAIL;
1055 			}
1056 			nproc = atoi((*argvp)[2]);
1057 			if (nproc < 1)
1058 			{
1059 			    printf("Error: If you specify a number after -localonly option,\n        it must be greater than 0.\n");
1060 			    smpd_exit_fn(FCNAME);
1061 			    return SMPD_FAIL;
1062 			}
1063 			num_args_to_strip = 2;
1064 		    }
1065 		}
1066 		/* Use localroot to implement localonly */
1067 		smpd_process.local_root = SMPD_TRUE;
1068 		/* create a host list of one and set nproc to -1 to be replaced by nproc after parsing the block */
1069 		host_list = (smpd_host_node_t*)MPIU_Malloc(sizeof(smpd_host_node_t));
1070 		if (host_list == NULL)
1071 		{
1072 		    printf("failed to allocate memory for a host node.\n");
1073 		    smpd_exit_fn(FCNAME);
1074 		    return SMPD_FAIL;
1075 		}
1076 		host_list->next = NULL;
1077 		host_list->left = NULL;
1078 		host_list->right = NULL;
1079 		host_list->connected = SMPD_FALSE;
1080 		host_list->connect_cmd_tag = -1;
1081 		host_list->connect_cmd_tag = -1;
1082 		host_list->nproc = -1;
1083 		host_list->alt_host[0] = '\0';
1084 		smpd_get_hostname(host_list->host, SMPD_MAX_HOST_LENGTH);
1085 	    }
1086 	    else if (strcmp(&(*argvp)[1][1], "machinefile") == 0)
1087 	    {
1088 		if (smpd_process.s_host_list != NULL)
1089 		{
1090 		    printf("Error: -machinefile can only be specified once per section.\n");
1091 		    smpd_exit_fn(FCNAME);
1092 		    return SMPD_FAIL;
1093 		}
1094 		if (argc < 3)
1095 		{
1096 		    printf("Error: no filename specified after -machinefile option.\n");
1097 		    smpd_exit_fn(FCNAME);
1098 		    return SMPD_FAIL;
1099 		}
1100 		strncpy(machine_file_name, (*argvp)[2], SMPD_MAX_FILENAME);
1101 		use_machine_file = SMPD_TRUE;
1102 		smpd_parse_machine_file(machine_file_name);
1103 		num_args_to_strip = 2;
1104 	    }
1105 #ifdef HAVE_WINDOWS_H
1106         else if (strcmp(&(*argvp)[1][1], "binding") == 0)
1107         {
1108             if(strcmp(&(*argvp)[2][0], "auto") == 0)
1109             {
1110                 smpd_process.set_affinity = TRUE;
1111                 smpd_process.affinity_map = NULL;
1112                 smpd_process.affinity_map_sz = 0;
1113             }
1114             else if(strncmp(&(*argvp)[2][0], "user", 4) == 0)
1115             {
1116                 smpd_process.set_affinity = TRUE;
1117                 if(read_user_affinity_map(&(*argvp)[2][0]) != SMPD_SUCCESS)
1118                 {
1119                     printf("Error parsing user binding scheme\n");
1120                     smpd_exit_fn(FCNAME);
1121                 }
1122             }
1123             else
1124             {
1125                 printf("Error: Process binding schemes supported are \"auto\", \"user\" \n");
1126                 smpd_exit_fn(FCNAME);
1127                 return SMPD_FAIL;
1128             }
1129             num_args_to_strip = 2;
1130         }
1131 #endif
1132 	    else if (strcmp(&(*argvp)[1][1], "map") == 0)
1133 	    {
1134 		if (argc < 3)
1135 		{
1136 		    printf("Error: no drive specified after -map option.\n");
1137 		    smpd_exit_fn(FCNAME);
1138 		    return SMPD_FAIL;
1139 		}
1140 		if (smpd_parse_map_string((*argvp)[2], &drive_map_list) != SMPD_SUCCESS)
1141 		{
1142 		    printf("Error: unable to parse the drive mapping option - '%s'\n", (*argvp)[2]);
1143 		    smpd_exit_fn(FCNAME);
1144 		    return SMPD_FAIL;
1145 		}
1146 		num_args_to_strip = 2;
1147 	    }
1148         else if (strcmp(&(*argvp)[1][1], "mapall") == 0){
1149 #ifdef HAVE_WINDOWS_H
1150             if(smpd_mapall(&drive_map_list) != SMPD_SUCCESS){
1151 		    printf("Error: unable to map all network drives");
1152 		    smpd_exit_fn(FCNAME);
1153 		    return SMPD_FAIL;
1154             }
1155 #endif
1156         num_args_to_strip = 1;
1157         }
1158 	    else if (strcmp(&(*argvp)[1][1], "gmap") == 0)
1159 	    {
1160 		if (argc < 3)
1161 		{
1162 		    printf("Error: no drive specified after -gmap option.\n");
1163 		    smpd_exit_fn(FCNAME);
1164 		    return SMPD_FAIL;
1165 		}
1166 		if (smpd_parse_map_string((*argvp)[2], &gdrive_map_list) != SMPD_SUCCESS)
1167 		{
1168 		    printf("Error: unable to parse the drive mapping option - '%s'\n", (*argvp)[2]);
1169 		    smpd_exit_fn(FCNAME);
1170 		    return SMPD_FAIL;
1171 		}
1172 		num_args_to_strip = 2;
1173 	    }
1174 	    else if ( (strcmp(&(*argvp)[1][1], "dir") == 0) || (strcmp(&(*argvp)[1][1], "wdir") == 0) )
1175 	    {
1176 		if (argc < 3)
1177 		{
1178 		    printf("Error: no directory after %s option\n", (*argvp)[1]);
1179 		    smpd_exit_fn(FCNAME);
1180 		    return SMPD_FAIL;
1181 		}
1182 		strncpy(wdir, (*argvp)[2], SMPD_MAX_DIR_LENGTH);
1183 		num_args_to_strip = 2;
1184 	    }
1185 	    else if ( (strcmp(&(*argvp)[1][1], "gdir") == 0) || (strcmp(&(*argvp)[1][1], "gwdir") == 0) )
1186 	    {
1187 		if (argc < 3)
1188 		{
1189 		    printf("Error: no directory after %s option\n", (*argvp)[1]);
1190 		    smpd_exit_fn(FCNAME);
1191 		    return SMPD_FAIL;
1192 		}
1193 		strncpy(gwdir, (*argvp)[2], SMPD_MAX_DIR_LENGTH);
1194 		num_args_to_strip = 2;
1195 	    }
1196 	    else if (strcmp(&(*argvp)[1][1], "env") == 0)
1197 	    {
1198 		if (argc < 4)
1199 		{
1200 		    printf("Error: no environment variable after -env option\n");
1201 		    smpd_exit_fn(FCNAME);
1202 		    return SMPD_FAIL;
1203 		}
1204 		env_node = (smpd_env_node_t*)MPIU_Malloc(sizeof(smpd_env_node_t));
1205 		if (env_node == NULL)
1206 		{
1207 		    printf("Error: malloc failed to allocate structure to hold an environment variable.\n");
1208 		    smpd_exit_fn(FCNAME);
1209 		    return SMPD_FAIL;
1210 		}
1211 		strncpy(env_node->name, (*argvp)[2], SMPD_MAX_NAME_LENGTH);
1212 		strncpy(env_node->value, (*argvp)[3], SMPD_MAX_VALUE_LENGTH);
1213 		env_node->next = env_list;
1214 		env_list = env_node;
1215 		if (strcmp(env_node->name, "MPI_DLL_NAME") == 0)
1216 		{
1217 		    MPIU_Strncpy(smpd_process.env_dll, env_node->value, SMPD_MAX_FILENAME);
1218 		}
1219 		if (strcmp(env_node->name, "MPI_WRAP_DLL_NAME") == 0)
1220 		{
1221 		    MPIU_Strncpy(smpd_process.env_wrap_dll, env_node->value, SMPD_MAX_FILENAME);
1222 		}
1223 #ifdef HAVE_WINDOWS_H
1224 		if ((strcmp(env_node->name, "MPICH_CHOP_ERROR_STACK") == 0) && ((env_node->value[0] == '\0') || (env_node->value[0] == '-')))
1225 		{
1226 		    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
1227 		    if (hConsole != INVALID_HANDLE_VALUE)
1228 		    {
1229 			CONSOLE_SCREEN_BUFFER_INFO info;
1230 			if (GetConsoleScreenBufferInfo(hConsole, &info))
1231 			{
1232 			    /* The user chose default so set the value to the width of the current output console window */
1233 			    snprintf(env_node->value, SMPD_MAX_VALUE_LENGTH, "%d", info.dwMaximumWindowSize.X);
1234 			    /*printf("width = %d\n", info.dwMaximumWindowSize.X);*/
1235 			}
1236 		    }
1237 		}
1238 #endif
1239 		num_args_to_strip = 3;
1240 	    }
1241 	    else if (strcmp(&(*argvp)[1][1], "envlist") == 0){
1242             char *str, *token, *value;
1243 		    if (argc < 4){
1244 		        printf("Error: no environment variable after -envlist option\n");
1245 		        smpd_exit_fn(FCNAME);
1246 		        return SMPD_FAIL;
1247 		    }
1248 		    str = MPIU_Strdup((*argvp)[2]);
1249 		    if (str == NULL){
1250 		        printf("Error: unable to allocate memory for copying envlist - '%s'\n", (*argvp)[2]);
1251 		        smpd_exit_fn(FCNAME);
1252 		        return SMPD_FAIL;
1253 		    }
1254 		    token = strtok(str, ",");
1255 		    while (token){
1256 		        value = getenv(token);
1257 		        if (value != NULL){
1258 			        env_node = (smpd_env_node_t*)MPIU_Malloc(sizeof(smpd_env_node_t));
1259 			        if (env_node == NULL){
1260 			            printf("Error: malloc failed to allocate structure to hold an environment variable.\n");
1261 			            smpd_exit_fn(FCNAME);
1262 			            return SMPD_FAIL;
1263 			        }
1264 			        strncpy(env_node->name, token, SMPD_MAX_NAME_LENGTH);
1265 			        strncpy(env_node->value, value, SMPD_MAX_VALUE_LENGTH);
1266 			        env_node->next = env_list;
1267 			        env_list = env_node;
1268 		        }
1269                 else{
1270                     printf("Error: Cannot obtain value of env variable : %s\n", token);
1271                 }
1272 		        token = strtok(NULL, ",");
1273 		    }
1274 		    MPIU_Free(str);
1275 		    num_args_to_strip = 2;
1276         }
1277 	    else if (strcmp(&(*argvp)[1][1], "envnone") == 0){
1278             printf("-envnone option is not implemented\n");
1279             num_args_to_strip = 1;
1280         }
1281 	    else if (strcmp(&(*argvp)[1][1], "genv") == 0)
1282 	    {
1283 		if (argc < 4)
1284 		{
1285 		    printf("Error: no environment variable after -genv option\n");
1286 		    smpd_exit_fn(FCNAME);
1287 		    return SMPD_FAIL;
1288 		}
1289 		env_node = (smpd_env_node_t*)MPIU_Malloc(sizeof(smpd_env_node_t));
1290 		if (env_node == NULL)
1291 		{
1292 		    printf("Error: malloc failed to allocate structure to hold an environment variable.\n");
1293 		    smpd_exit_fn(FCNAME);
1294 		    return SMPD_FAIL;
1295 		}
1296 		strncpy(env_node->name, (*argvp)[2], SMPD_MAX_NAME_LENGTH);
1297 		strncpy(env_node->value, (*argvp)[3], SMPD_MAX_VALUE_LENGTH);
1298 		env_node->next = genv_list;
1299 		genv_list = env_node;
1300 #ifdef HAVE_WINDOWS_H
1301 		if ((strcmp(env_node->name, "MPICH_CHOP_ERROR_STACK") == 0) && ((env_node->value[0] == '\0') || (env_node->value[0] == '-')))
1302 		{
1303 		    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
1304 		    if (hConsole != INVALID_HANDLE_VALUE)
1305 		    {
1306 			CONSOLE_SCREEN_BUFFER_INFO info;
1307 			if (GetConsoleScreenBufferInfo(hConsole, &info))
1308 			{
1309 			    /* The user chose default so set the value to the width of the current output console window */
1310 			    snprintf(env_node->value, SMPD_MAX_VALUE_LENGTH, "%d", info.dwMaximumWindowSize.X);
1311 			    /*printf("width = %d\n", info.dwMaximumWindowSize.X);*/
1312 			}
1313 		    }
1314 		}
1315 #endif
1316 		num_args_to_strip = 3;
1317 	    }
1318 	    else if (strcmp(&(*argvp)[1][1], "genvall") == 0)
1319 	    {
1320 		printf("-genvall option not implemented\n");
1321         num_args_to_strip = 1;
1322 	    }
1323 	    else if (strcmp(&(*argvp)[1][1], "genvnone") == 0)
1324 	    {
1325 		printf("-genvnone option not implemented\n");
1326         num_args_to_strip = 1;
1327 	    }
1328 	    else if (strcmp(&(*argvp)[1][1], "genvlist") == 0)
1329 	    {
1330 		char *str, *token, *value;
1331 		if (argc < 4)
1332 		{
1333 		    printf("Error: no environment variables after -genvlist option\n");
1334 		    smpd_exit_fn(FCNAME);
1335 		    return SMPD_FAIL;
1336 		}
1337 		str = MPIU_Strdup((*argvp)[2]);
1338 		if (str == NULL)
1339 		{
1340 		    printf("Error: unable to allocate memory for a string - '%s'\n", (*argvp)[2]);
1341 		    smpd_exit_fn(FCNAME);
1342 		    return SMPD_FAIL;
1343 		}
1344 		token = strtok(str, ",");
1345 		while (token)
1346 		{
1347 		    value = getenv(token);
1348 		    if (value != NULL)
1349 		    {
1350 			env_node = (smpd_env_node_t*)MPIU_Malloc(sizeof(smpd_env_node_t));
1351 			if (env_node == NULL)
1352 			{
1353 			    printf("Error: malloc failed to allocate structure to hold an environment variable.\n");
1354 			    smpd_exit_fn(FCNAME);
1355 			    return SMPD_FAIL;
1356 			}
1357 			strncpy(env_node->name, token, SMPD_MAX_NAME_LENGTH);
1358 			strncpy(env_node->value, value, SMPD_MAX_VALUE_LENGTH);
1359 			env_node->next = genv_list;
1360 			genv_list = env_node;
1361 		    }
1362 		    token = strtok(NULL, ",");
1363 		}
1364 		MPIU_Free(str);
1365 		num_args_to_strip = 2;
1366 	    }
1367 	    else if ( (strcmp(&(*argvp)[1][1], "logon") == 0) || (strcmp(&(*argvp)[1][1], "login") == 0) )
1368 	    {
1369 		smpd_process.logon = SMPD_TRUE;
1370 	    }
1371 	    else if ( (strcmp(&(*argvp)[1][1], "impersonate") == 0) || (strcmp(&(*argvp)[1][1], "impersonation") == 0) )
1372 	    {
1373 		smpd_process.use_sspi = SMPD_TRUE;
1374 		smpd_process.use_delegation = SMPD_FALSE;
1375 	    }
1376 	    else if ( (strcmp(&(*argvp)[1][1], "delegate") == 0) || (strcmp(&(*argvp)[1][1], "delegation") == 0) )
1377 	    {
1378 		smpd_process.use_sspi = SMPD_TRUE;
1379 		smpd_process.use_delegation = SMPD_TRUE;
1380 	    }
1381 	    else if (strcmp(&(*argvp)[1][1], "job") == 0)
1382 	    {
1383 		smpd_process.use_delegation = SMPD_FALSE;
1384 		smpd_process.use_sspi_job_key = SMPD_TRUE;
1385 		if (argc < 3)
1386 		{
1387 		    printf("Error: no job key specified after the -job option\n");
1388 		    smpd_exit_fn(FCNAME);
1389 		    return SMPD_FAIL;
1390 		}
1391 		strncpy(smpd_process.job_key, (*argvp)[2], SMPD_SSPI_JOB_KEY_LENGTH);
1392 		num_args_to_strip = 2;
1393 	    }
1394 	    else if (strcmp(&(*argvp)[1][1], "dbg") == 0)
1395 	    {
1396 		use_debug_flag = SMPD_TRUE;
1397 	    }
1398 	    else if (strcmp(&(*argvp)[1][1], "pwdfile") == 0)
1399 	    {
1400 		use_pwd_file = SMPD_TRUE;
1401 		if (argc < 3)
1402 		{
1403 		    printf("Error: no filename specified after -pwdfile option\n");
1404 		    smpd_exit_fn(FCNAME);
1405 		    return SMPD_FAIL;
1406 		}
1407 		strncpy(pwd_file_name, (*argvp)[2], SMPD_MAX_FILENAME);
1408 		smpd_get_pwd_from_file(pwd_file_name);
1409 		num_args_to_strip = 2;
1410 	    }
1411 #ifdef HAVE_WINDOWS_H
1412 	    else if (strcmp(&(*argvp)[1][1], "registryfile") == 0)
1413 	    {
1414         char reg_file_name[SMPD_MAX_FILENAME];
1415 		if (argc < 3)
1416 		{
1417 		    printf("Error: no filename specified after -registryfile option\n");
1418 		    smpd_exit_fn(FCNAME);
1419 		    return SMPD_FAIL;
1420 		}
1421 		strncpy(reg_file_name, (*argvp)[2], SMPD_MAX_FILENAME);
1422         if(!smpd_read_cred_from_file(reg_file_name, smpd_process.UserAccount, SMPD_MAX_ACCOUNT_LENGTH, smpd_process.UserPassword, SMPD_MAX_PASSWORD_LENGTH)){
1423             printf("Error: Could not read credentials from registry file\n");
1424             smpd_exit_fn(FCNAME);
1425             return SMPD_FAIL;
1426         }
1427 		num_args_to_strip = 2;
1428 	    }
1429 #endif
1430 	    else if (strcmp(&(*argvp)[1][1], "configfile") == 0)
1431 	    {
1432 		printf("Error: The -configfile option must be the first and only option specified in a block.\n");
1433 		smpd_exit_fn(FCNAME);
1434 		return SMPD_FAIL;
1435 		/*
1436 		if (argc < 3)
1437 		{
1438 		    printf("Error: no filename specifed after -configfile option.\n");
1439 		    smpd_exit_fn(FCNAME);
1440 		    return SMPD_FAIL;
1441 		}
1442 		strncpy(configfilename, (*argvp)[2], SMPD_MAX_FILENAME);
1443 		use_configfile = SMPD_TRUE;
1444 		num_args_to_strip = 2;
1445 		*/
1446 	    }
1447 	    else if (strcmp(&(*argvp)[1][1], "file") == 0)
1448 	    {
1449 		printf("Error: The -file option must be the first and only option specified in a block.\n");
1450 		smpd_exit_fn(FCNAME);
1451 		return SMPD_FAIL;
1452 		/*
1453 		if (argc < 3)
1454 		{
1455 		    printf("Error: no filename specifed after -file option.\n");
1456 		    smpd_exit_fn(FCNAME);
1457 		    return SMPD_FAIL;
1458 		}
1459 		strncpy(configfilename, (*argvp)[2], SMPD_MAX_FILENAME);
1460 		use_configfile = SMPD_TRUE;
1461 		num_args_to_strip = 2;
1462 		*/
1463 	    }
1464 	    else if (strcmp(&(*argvp)[1][1], "host") == 0)
1465 	    {
1466 		if (argc < 3)
1467 		{
1468 		    printf("Error: no host specified after -host option.\n");
1469 		    smpd_exit_fn(FCNAME);
1470 		    return SMPD_FAIL;
1471 		}
1472 		if (host_list != NULL)
1473 		{
1474 		    printf("Error: -host option can only be specified once and it cannot be combined with -hosts.\n");
1475 		    smpd_exit_fn(FCNAME);
1476 		    return SMPD_FAIL;
1477 		}
1478 		/* create a host list of one and set nproc to -1 to be replaced by
1479 		   nproc after parsing the block */
1480 		host_list = (smpd_host_node_t*)MPIU_Malloc(sizeof(smpd_host_node_t));
1481 		if (host_list == NULL)
1482 		{
1483 		    printf("failed to allocate memory for a host node.\n");
1484 		    smpd_exit_fn(FCNAME);
1485 		    return SMPD_FAIL;
1486 		}
1487 		host_list->next = NULL;
1488 		host_list->left = NULL;
1489 		host_list->right = NULL;
1490 		host_list->connected = SMPD_FALSE;
1491 		host_list->connect_cmd_tag = -1;
1492 		host_list->nproc = -1;
1493 		host_list->alt_host[0] = '\0';
1494 		strncpy(host_list->host, (*argvp)[2], SMPD_MAX_HOST_LENGTH);
1495 		num_args_to_strip = 2;
1496 		smpd_add_host_to_default_list((*argvp)[2]);
1497 	    }
1498 	    else if (strcmp(&(*argvp)[1][1], "ghost") == 0)
1499 	    {
1500 		if (argc < 3)
1501 		{
1502 		    printf("Error: no host specified after -ghost option.\n");
1503 		    smpd_exit_fn(FCNAME);
1504 		    return SMPD_FAIL;
1505 		}
1506 		if (ghost_list != NULL)
1507 		{
1508 		    printf("Error: -ghost option can only be specified once.\n");
1509 		    smpd_exit_fn(FCNAME);
1510 		    return SMPD_FAIL;
1511 		}
1512 		/* create a host list of one and set nproc to -1 to be replaced by
1513 		   nproc after parsing the block */
1514 		ghost_list = (smpd_host_node_t*)MPIU_Malloc(sizeof(smpd_host_node_t));
1515 		if (ghost_list == NULL)
1516 		{
1517 		    printf("failed to allocate memory for a host node.\n");
1518 		    smpd_exit_fn(FCNAME);
1519 		    return SMPD_FAIL;
1520 		}
1521 		ghost_list->next = NULL;
1522 		ghost_list->left = NULL;
1523 		ghost_list->right = NULL;
1524 		ghost_list->connected = SMPD_FALSE;
1525 		ghost_list->connect_cmd_tag = -1;
1526 		ghost_list->nproc = -1;
1527 		ghost_list->alt_host[0] = '\0';
1528 		strncpy(ghost_list->host, (*argvp)[2], SMPD_MAX_HOST_LENGTH);
1529 		num_args_to_strip = 2;
1530 		smpd_add_host_to_default_list((*argvp)[2]);
1531 	    }
1532 #ifdef HAVE_WINDOWS_H
1533         else if (strcmp(&(*argvp)[1][1], "ms_hpc") == 0)
1534         {
1535             smpd_process.use_ms_hpc = SMPD_TRUE;
1536             /* Enable SSPI for authenticating PMs */
1537             smpd_process.use_sspi = SMPD_TRUE;
1538             smpd_process.use_delegation = SMPD_FALSE;
1539             /* Use mpiexec as PMI server */
1540             smpd_process.use_pmi_server = SMPD_TRUE;
1541 
1542             num_args_to_strip = 1;
1543         }
1544 #endif
1545 	    else if (strcmp(&(*argvp)[1][1], "hosts") == 0)
1546 	    {
1547 		if (nproc != 0)
1548 		{
1549 		    printf("Error: only one option is allowed to determine the number of processes.\n");
1550 		    printf("       -hosts, -n, -np and -localonly x are mutually exclusive\n");
1551 		    smpd_exit_fn(FCNAME);
1552 		    return SMPD_FAIL;
1553 		}
1554 		if (host_list != NULL)
1555 		{
1556 		    printf("Error: -hosts option can only be called once and it cannot be combined with -host.\n");
1557 		    smpd_exit_fn(FCNAME);
1558 		    return SMPD_FAIL;
1559 		}
1560 		if (argc > 2)
1561 		{
1562 		    if (smpd_isnumber((*argvp)[2]))
1563 		    {
1564 			/* initially set nproc to be the number of hosts */
1565 			nproc = atoi((*argvp)[2]);
1566 			if (nproc < 1)
1567 			{
1568 			    printf("Error: You must specify a number greater than 0 after -hosts.\n");
1569 			    smpd_exit_fn(FCNAME);
1570 			    return SMPD_FAIL;
1571 			}
1572 			num_args_to_strip = 2 + nproc;
1573 			index = 3;
1574 			for (i=0; i<nproc; i++)
1575 			{
1576 			    if (index >= argc)
1577 			    {
1578 				printf("Error: missing host name after -hosts option.\n");
1579 				smpd_exit_fn(FCNAME);
1580 				return SMPD_FAIL;
1581 			    }
1582 			    host_node_ptr = (smpd_host_node_t*)MPIU_Malloc(sizeof(smpd_host_node_t));
1583 			    if (host_node_ptr == NULL)
1584 			    {
1585 				printf("failed to allocate memory for a host node.\n");
1586 				smpd_exit_fn(FCNAME);
1587 				return SMPD_FAIL;
1588 			    }
1589 			    host_node_ptr->next = NULL;
1590 			    host_node_ptr->left = NULL;
1591 			    host_node_ptr->right = NULL;
1592 			    host_node_ptr->connected = SMPD_FALSE;
1593 			    host_node_ptr->connect_cmd_tag = -1;
1594 			    host_node_ptr->nproc = 1;
1595 			    host_node_ptr->alt_host[0] = '\0';
1596 			    strncpy(host_node_ptr->host, (*argvp)[index], SMPD_MAX_HOST_LENGTH);
1597 			    smpd_add_host_to_default_list((*argvp)[index]);
1598 			    index++;
1599 			    if (argc > index)
1600 			    {
1601 				if (smpd_isnumber((*argvp)[index]))
1602 				{
1603 				    host_node_ptr->nproc = atoi((*argvp)[index]);
1604 				    index++;
1605 				    num_args_to_strip++;
1606 				}
1607 			    }
1608 			    if (host_list == NULL)
1609 			    {
1610 				host_list = host_node_ptr;
1611 			    }
1612 			    else
1613 			    {
1614 				host_node_iter = host_list;
1615 				while (host_node_iter->next)
1616 				    host_node_iter = host_node_iter->next;
1617 				host_node_iter->next = host_node_ptr;
1618 			    }
1619 			}
1620 
1621 			/* adjust nproc to be the actual number of processes */
1622 			host_node_iter = host_list;
1623 			nproc = 0;
1624 			while (host_node_iter)
1625 			{
1626 			    nproc += host_node_iter->nproc;
1627 			    host_node_iter = host_node_iter->next;
1628 			}
1629 		    }
1630 		    else
1631 		    {
1632 			printf("Error: You must specify the number of hosts after the -hosts option.\n");
1633 			smpd_exit_fn(FCNAME);
1634 			return SMPD_FAIL;
1635 		    }
1636 		}
1637 		else
1638 		{
1639 		    printf("Error: not enough arguments specified for -hosts option.\n");
1640 		    smpd_exit_fn(FCNAME);
1641 		    return SMPD_FAIL;
1642 		}
1643 	    }
1644 	    else if (strcmp(&(*argvp)[1][1], "nocolor") == 0)
1645 	    {
1646 		smpd_process.do_multi_color_output = SMPD_FALSE;
1647 	    }
1648 	    else if (strcmp(&(*argvp)[1][1], "nompi") == 0)
1649 	    {
1650 		smpd_process.no_mpi = SMPD_TRUE;
1651 	    }
1652 	    else if (strcmp(&(*argvp)[1][1], "nomapping") == 0)
1653 	    {
1654 		no_drive_mapping = SMPD_TRUE;
1655 	    }
1656 	    else if (strcmp(&(*argvp)[1][1], "nopopup_debug") == 0)
1657 	    {
1658 #ifdef HAVE_WINDOWS_H
1659 		SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
1660 #endif
1661 	    }
1662 	    else if (strcmp(&(*argvp)[1][1], "help") == 0 || (*argvp)[1][1] == '?')
1663 	    {
1664 		mp_print_options();
1665 		exit(0);
1666 	    }
1667 	    else if (strcmp(&(*argvp)[1][1], "help2") == 0)
1668 	    {
1669 		mp_print_extra_options();
1670 		exit(0);
1671 	    }
1672 	    else if (strcmp(&(*argvp)[1][1], "exitcodes") == 0)
1673 	    {
1674 		smpd_process.output_exit_codes = SMPD_TRUE;
1675 	    }
1676 	    else if (strcmp(&(*argvp)[1][1], "localroot") == 0)
1677 	    {
1678 		smpd_process.local_root = SMPD_TRUE;
1679 	    }
1680 	    else if (strcmp(&(*argvp)[1][1], "priority") == 0)
1681 	    {
1682 		if (argc < 3)
1683 		{
1684 		    printf("Error: you must specify a priority after the -priority option.\n");
1685 		    smpd_exit_fn(FCNAME);
1686 		    return SMPD_FAIL;
1687 		}
1688 		if (smpd_isnumbers_with_colon((*argvp)[2]))
1689 		{
1690 		    char *str;
1691 		    n_priority_class = atoi((*argvp)[2]); /* This assumes atoi will stop at the colon and return a number */
1692 		    str = strchr((*argvp)[2], ':');
1693 		    if (str)
1694 		    {
1695 			str++;
1696 			n_priority = atoi(str);
1697 		    }
1698 		    if (n_priority_class < 0 || n_priority_class > 4 || n_priority < 0 || n_priority > 5)
1699 		    {
1700 			printf("Error: priorities must be between 0-4:0-5\n");
1701 			smpd_exit_fn(FCNAME);
1702 			return SMPD_FAIL;
1703 		    }
1704 		}
1705 		else
1706 		{
1707 		    printf("Error: you must specify a priority after the -priority option.\n");
1708 		    smpd_exit_fn(FCNAME);
1709 		    return SMPD_FAIL;
1710 		}
1711 		smpd_dbg_printf("priorities = %d:%d\n", n_priority_class, n_priority);
1712 		num_args_to_strip = 2;
1713 	    }
1714 	    else if (strcmp(&(*argvp)[1][1], "iproot") == 0)
1715 	    {
1716 		smpd_process.use_iproot = SMPD_TRUE;
1717 	    }
1718 	    else if (strcmp(&(*argvp)[1][1], "noiproot") == 0)
1719 	    {
1720 		smpd_process.use_iproot = SMPD_FALSE;
1721 	    }
1722 	    else if (strcmp(&(*argvp)[1][1], "verbose") == 0)
1723 	    {
1724 		smpd_process.verbose = SMPD_TRUE;
1725 		smpd_process.dbg_state |= SMPD_DBG_STATE_ERROUT | SMPD_DBG_STATE_STDOUT | SMPD_DBG_STATE_TRACE;
1726 	    }
1727 	    else if ( (strcmp(&(*argvp)[1][1], "p") == 0) || (strcmp(&(*argvp)[1][1], "port") == 0))
1728 	    {
1729 		if (argc > 2)
1730 		{
1731 		    if (smpd_isnumber((*argvp)[2]))
1732 		    {
1733 			smpd_process.port = atoi((*argvp)[2]);
1734 		    }
1735 		    else
1736 		    {
1737 			printf("Error: you must specify the port smpd is listening on after the %s option.\n", (*argvp)[1]);
1738 			smpd_exit_fn(FCNAME);
1739 			return SMPD_FAIL;
1740 		    }
1741 		}
1742 		else
1743 		{
1744 		    printf("Error: you must specify the port smpd is listening on after the %s option.\n", (*argvp)[1]);
1745 		    smpd_exit_fn(FCNAME);
1746 		    return SMPD_FAIL;
1747 		}
1748 		num_args_to_strip = 2;
1749 	    }
1750 	    else if (strcmp(&(*argvp)[1][1], "path") == 0)
1751 	    {
1752 		if (argc < 3)
1753 		{
1754 		    printf("Error: no path specifed after -path option.\n");
1755 		    smpd_exit_fn(FCNAME);
1756 		    return SMPD_FAIL;
1757 		}
1758 		strncpy(path, (*argvp)[2], SMPD_MAX_PATH_LENGTH);
1759 		num_args_to_strip = 2;
1760 	    }
1761 	    else if (strcmp(&(*argvp)[1][1], "gpath") == 0)
1762 	    {
1763 		if (argc < 3)
1764 		{
1765 		    printf("Error: no path specifed after -gpath option.\n");
1766 		    smpd_exit_fn(FCNAME);
1767 		    return SMPD_FAIL;
1768 		}
1769 		strncpy(gpath, (*argvp)[2], SMPD_MAX_PATH_LENGTH);
1770 		num_args_to_strip = 2;
1771 	    }
1772 	    else if (strcmp(&(*argvp)[1][1], "noprompt") == 0)
1773 	    {
1774 		smpd_process.noprompt = SMPD_TRUE;
1775 		smpd_process.credentials_prompt = SMPD_FALSE;
1776 	    }
1777 	    else if (strcmp(&(*argvp)[1][1], "phrase") == 0)
1778 	    {
1779 		if (argc < 3)
1780 		{
1781 		    printf("Error: no passphrase specified afterh -phrase option.\n");
1782 		    smpd_exit_fn(FCNAME);
1783 		    return SMPD_FAIL;
1784 		}
1785 		strncpy(smpd_process.passphrase, (*argvp)[2], SMPD_PASSPHRASE_MAX_LENGTH);
1786 		num_args_to_strip = 2;
1787 	    }
1788 	    else if (strcmp(&(*argvp)[1][1], "smpdfile") == 0)
1789 	    {
1790 		if (argc < 3)
1791 		{
1792 		    printf("Error: no file name specified after -smpdfile option.\n");
1793 		    smpd_exit_fn(FCNAME);
1794 		    return SMPD_FAIL;
1795 		}
1796 		strncpy(smpd_process.smpd_filename, (*argvp)[2], SMPD_MAX_FILENAME);
1797 		{
1798 		    struct stat s;
1799 
1800 		    if (stat(smpd_process.smpd_filename, &s) == 0)
1801 		    {
1802 			if (s.st_mode & 00077)
1803 			{
1804 			    printf("Error: .smpd file cannot be readable by anyone other than the current user.\n");
1805 			    smpd_exit_fn(FCNAME);
1806 			    return SMPD_FAIL;
1807 			}
1808 		    }
1809 		}
1810 		num_args_to_strip = 2;
1811 	    }
1812 	    else if (strcmp(&(*argvp)[1][1], "timeout") == 0)
1813 	    {
1814 		if (argc < 3)
1815 		{
1816 		    printf("Error: no timeout specified after -timeout option.\n");
1817 		    smpd_exit_fn(FCNAME);
1818 		    return SMPD_FAIL;
1819 		}
1820 		smpd_process.timeout = atoi((*argvp)[2]);
1821 		if (smpd_process.timeout < 1)
1822 		{
1823 		    printf("Warning: invalid timeout specified, ignoring timeout value of '%s'\n", (*argvp)[2]);
1824 		    smpd_process.timeout = -1;
1825 		}
1826 		num_args_to_strip = 2;
1827 	    }
1828 	    else if (strcmp(&(*argvp)[1][1], "hide_console") == 0)
1829 	    {
1830 #ifdef HAVE_WINDOWS_H
1831 		FreeConsole();
1832 #endif
1833 	    }
1834 	    else if (strcmp(&(*argvp)[1][1], "quiet_abort") == 0)
1835 	    {
1836 		smpd_process.verbose_abort_output = SMPD_FALSE;
1837 	    }
1838 	    else if ((strcmp(&(*argvp)[1][1], "rsh") == 0) || (strcmp(&(*argvp)[1][1], "ssh") == 0))
1839 	    {
1840 		smpd_process.rsh_mpiexec = SMPD_TRUE;
1841 		if (smpd_process.mpiexec_inorder_launch == SMPD_FALSE)
1842 		{
1843 		    smpd_launch_node_t *temp_node, *ordered_list = NULL;
1844 		    /* sort any existing reverse order nodes to be in order */
1845 		    while (smpd_process.launch_list)
1846 		    {
1847 			temp_node = smpd_process.launch_list->next;
1848 			smpd_process.launch_list->next = ordered_list;
1849 			ordered_list = smpd_process.launch_list;
1850 			smpd_process.launch_list = temp_node;
1851 		    }
1852 		    smpd_process.launch_list = ordered_list;
1853 		}
1854 		smpd_process.mpiexec_inorder_launch = SMPD_TRUE;
1855 	    }
1856 	    else if ((strcmp(&(*argvp)[1][1], "nosmpd") == 0) || (strcmp(&(*argvp)[1][1], "no_smpd") == 0) || (strcmp(&(*argvp)[1][1], "nopm") == 0))
1857 	    {
1858 		smpd_process.use_pmi_server = SMPD_FALSE;
1859 	    }
1860 	    else if (strcmp(&(*argvp)[1][1], "plaintext") == 0)
1861 	    {
1862 		smpd_process.plaintext = SMPD_TRUE;
1863 	    }
1864 	    else if (strcmp(&(*argvp)[1][1], "channel") == 0)
1865 	    {
1866 		if (argc < 3)
1867 		{
1868 		    printf("Error: no name specified after -channel option.\n");
1869 		    smpd_exit_fn(FCNAME);
1870 		    return SMPD_FAIL;
1871 		}
1872 		strncpy(channel, (*argvp)[2], SMPD_MAX_NAME_LENGTH);
1873         if((strcmp(channel, "shm") == 0) || (strcmp(channel, "ssm") == 0))
1874         {
1875             printf("WARNING: SHM & SSM channels are no longer available. Use the NEMESIS channel instead.\n");
1876             return SMPD_FAIL;
1877         }
1878 		num_args_to_strip = 2;
1879 	    }
1880 	    else if (strcmp(&(*argvp)[1][1], "log") == 0)
1881 	    {
1882 		/* -log is a shortcut to create log files using the mpe wrapper dll */
1883 		env_node = (smpd_env_node_t*)MPIU_Malloc(sizeof(smpd_env_node_t));
1884 		if (env_node == NULL)
1885 		{
1886 		    printf("Error: malloc failed to allocate structure to hold an environment variable.\n");
1887 		    smpd_exit_fn(FCNAME);
1888 		    return SMPD_FAIL;
1889 		}
1890 		strncpy(env_node->name, "MPI_WRAP_DLL_NAME", SMPD_MAX_NAME_LENGTH);
1891 		strncpy(env_node->value, "mpe", SMPD_MAX_VALUE_LENGTH);
1892 		env_node->next = env_list;
1893 		env_list = env_node;
1894 	    }
1895 #ifdef HAVE_WINDOWS_H
1896 	    else if (strcmp(&(*argvp)[1][1], "user") == 0)
1897 	    {
1898 		if (argc < 3)
1899 		{
1900 		    printf("Error: no index specified after -user option.\n");
1901 		    smpd_exit_fn(FCNAME);
1902 		    return SMPD_FAIL;
1903 		}
1904 		smpd_process.user_index = atoi((*argvp)[2]);
1905 		if (smpd_process.user_index < 0)
1906 		    smpd_process.user_index = 0;
1907 		num_args_to_strip = 2;
1908 		smpd_delete_cached_password();
1909 	    }
1910 #endif
1911 	    else if (strcmp(&(*argvp)[1][1], "l") == 0)
1912 	    {
1913 		smpd_process.prefix_output = SMPD_TRUE;
1914 	    }
1915 	    else
1916 	    {
1917 		printf("Unknown option: %s\n", (*argvp)[1]);
1918 	    }
1919 	    strip_args(argcp, argvp, num_args_to_strip);
1920 	}
1921 
1922 	/* check to see if a timeout is specified by the environment variable only if
1923 	 * a timeout has not been specified on the command line
1924 	 */
1925 	if (smpd_process.timeout == -1)
1926 	{
1927 	    char *p = getenv("MPIEXEC_TIMEOUT");
1928 	    if (p)
1929 	    {
1930 		smpd_process.timeout = atoi(p);
1931 		if (smpd_process.timeout < 1)
1932 		{
1933 		    smpd_process.timeout = -1;
1934 		}
1935 	    }
1936 	    else
1937 	    {
1938 		/* If a timeout is specified in the smpd settings but not in an env variable and not on the command line then use it. */
1939 		if (smpd_setting_timeout != SMPD_INVALID_SETTING)
1940 		{
1941 		    smpd_process.timeout = smpd_setting_timeout;
1942 		}
1943 	    }
1944 	}
1945 
1946 	/* Check to see if the environment wants all processes to run locally.
1947 	 * This is useful for test scripts.
1948 	 */
1949 	env_str = getenv("MPIEXEC_LOCALONLY");
1950 	if (env_str == NULL && smpd_setting_localonly == SMPD_TRUE)
1951 	{
1952 	    smpd_setting_tmp_buffer[0] = '1';
1953 	    smpd_setting_tmp_buffer[1] = '\0';
1954 	    env_str = smpd_setting_tmp_buffer;
1955 	}
1956 	if (env_str != NULL)
1957 	{
1958 	    if (smpd_is_affirmative(env_str) || strcmp(env_str, "1") == 0)
1959 	    {
1960 #if 1
1961 		/* This block creates a host list of one host to implement -localonly */
1962 
1963 		if (host_list == NULL)
1964 		{
1965 		    /* Use localroot to implement localonly */
1966 		    smpd_process.local_root = SMPD_TRUE;
1967 		    /* create a host list of one and set nproc to -1 to be replaced by
1968 		       nproc after parsing the block */
1969 		    host_list = (smpd_host_node_t*)MPIU_Malloc(sizeof(smpd_host_node_t));
1970 		    if (host_list == NULL)
1971 		    {
1972 			printf("failed to allocate memory for a host node.\n");
1973 			smpd_exit_fn(FCNAME);
1974 			return SMPD_FAIL;
1975 		    }
1976 		    host_list->next = NULL;
1977 		    host_list->left = NULL;
1978 		    host_list->right = NULL;
1979 		    host_list->connected = SMPD_FALSE;
1980 		    host_list->connect_cmd_tag = -1;
1981 		    host_list->nproc = -1;
1982 		    host_list->alt_host[0] = '\0';
1983 		    smpd_get_hostname(host_list->host, SMPD_MAX_HOST_LENGTH);
1984 		}
1985 		else
1986 		{
1987 		    smpd_dbg_printf("host_list not null, not using localonly\n");
1988 		}
1989 #else
1990 		/* This block uses the rsh code to implement -localonly */
1991 
1992 		smpd_process.mpiexec_run_local = SMPD_TRUE;
1993 		smpd_process.rsh_mpiexec = SMPD_TRUE;
1994 		if (smpd_process.mpiexec_inorder_launch == SMPD_FALSE)
1995 		{
1996 		    smpd_launch_node_t *temp_node, *ordered_list = NULL;
1997 		    /* sort any existing reverse order nodes to be in order */
1998 		    while (smpd_process.launch_list)
1999 		    {
2000 			temp_node = smpd_process.launch_list->next;
2001 			smpd_process.launch_list->next = ordered_list;
2002 			ordered_list = smpd_process.launch_list;
2003 			smpd_process.launch_list = temp_node;
2004 		    }
2005 		    smpd_process.launch_list = ordered_list;
2006 		}
2007 		smpd_process.mpiexec_inorder_launch = SMPD_TRUE;
2008 #endif
2009 	    }
2010 	    else
2011 	    {
2012 		smpd_dbg_printf("MPIEXEC_LOCALONLY env is not affirmative: '%s'\n", env_str);
2013 	    }
2014 	}
2015 
2016 	/* remaining args are the executable and it's args */
2017 	if (argc < 2)
2018 	{
2019 	    printf("Error: no executable specified\n");
2020 	    smpd_exit_fn(FCNAME);
2021 	    return SMPD_FAIL;
2022 	}
2023 
2024 	exe_iter = exe;
2025 	exe_len_remaining = SMPD_MAX_EXE_LENGTH;
2026 	if (!((*argvp)[1][0] == '\\' && (*argvp)[1][1] == '\\') && (*argvp)[1][0] != '/' &&
2027 	    !(strlen((*argvp)[1]) > 3 && (*argvp)[1][1] == ':' && (*argvp)[1][2] == '\\') )
2028 	{
2029 	    /* an absolute path was not specified so find the executable an save the path */
2030 	    if (smpd_get_full_path_name((*argvp)[1], SMPD_MAX_EXE_LENGTH, exe_path, &namepart))
2031 	    {
2032 		if (path[0] != '\0')
2033 		{
2034 		    if (strlen(path) < SMPD_MAX_PATH_LENGTH)
2035 		    {
2036 			strcat(path, ";");
2037 			strncat(path, exe_path, SMPD_MAX_PATH_LENGTH - strlen(path));
2038 			path[SMPD_MAX_PATH_LENGTH-1] = '\0';
2039 		    }
2040 		}
2041 		else
2042 		{
2043 		    strncpy(path, exe_path, SMPD_MAX_PATH_LENGTH);
2044 		}
2045 		result = MPIU_Str_add_string(&exe_iter, &exe_len_remaining, namepart);
2046 		if (result != MPIU_STR_SUCCESS)
2047 		{
2048 		    printf("Error: insufficient buffer space for the command line.\n");
2049 		    smpd_exit_fn(FCNAME);
2050 		    return SMPD_FAIL;
2051 		}
2052 	    }
2053 	    else
2054 	    {
2055 		result = MPIU_Str_add_string(&exe_iter, &exe_len_remaining, (*argvp)[1]);
2056 		if (result != MPIU_STR_SUCCESS)
2057 		{
2058 		    printf("Error: insufficient buffer space for the command line.\n");
2059 		    smpd_exit_fn(FCNAME);
2060 		    return SMPD_FAIL;
2061 		}
2062 	    }
2063 	}
2064 	else
2065 	{
2066 	    /* an absolute path was specified */
2067 #ifdef HAVE_WINDOWS_H
2068 	    char *pTemp = (char*)MPIU_Malloc(SMPD_MAX_EXE_LENGTH);
2069 	    if (pTemp == NULL)
2070 	    {
2071 		smpd_exit_fn(FCNAME);
2072 		return SMPD_FAIL;
2073 	    }
2074 	    strncpy(pTemp, (*argvp)[1], SMPD_MAX_EXE_LENGTH);
2075 	    pTemp[SMPD_MAX_EXE_LENGTH-1] = '\0';
2076 	    ExeToUnc(pTemp, SMPD_MAX_EXE_LENGTH);
2077 	    result = MPIU_Str_add_string(&exe_iter, &exe_len_remaining, pTemp);
2078 	    MPIU_Free(pTemp);
2079 	    if (result != MPIU_STR_SUCCESS)
2080 	    {
2081 		printf("Error: insufficient buffer space for the command line.\n");
2082 		smpd_exit_fn(FCNAME);
2083 		return SMPD_FAIL;
2084 	    }
2085 #else
2086 	    result = MPIU_Str_add_string(&exe_iter, &exe_len_remaining, (*argvp)[1]);
2087 	    if (result != MPIU_STR_SUCCESS)
2088 	    {
2089 		printf("Error: insufficient buffer space for the command line.\n");
2090 		smpd_exit_fn(FCNAME);
2091 		return SMPD_FAIL;
2092 	    }
2093 #endif
2094 	}
2095 	for (i=2; i<argc; i++)
2096 	{
2097 	    result = MPIU_Str_add_string(&exe_iter, &exe_len_remaining, (*argvp)[i]);
2098 	}
2099 	/* remove the trailing space */
2100 	exe[strlen(exe)-1] = '\0';
2101 	smpd_dbg_printf("handling executable:\n%s\n", exe);
2102 
2103 	if (nproc == 0){
2104     /* By default assume "mpiexec foo" => "mpiexec -n 1 foo" */
2105         nproc = 1;
2106 	}
2107 	if (ghost_list != NULL && host_list == NULL && use_machine_file != SMPD_TRUE)
2108 	{
2109 	    host_list = (smpd_host_node_t*)MPIU_Malloc(sizeof(smpd_host_node_t));
2110 	    if (host_list == NULL)
2111 	    {
2112 		printf("failed to allocate memory for a host node.\n");
2113 		smpd_exit_fn(FCNAME);
2114 		return SMPD_FAIL;
2115 	    }
2116 	    host_list->next = NULL;
2117 	    host_list->left = NULL;
2118 	    host_list->right = NULL;
2119 	    host_list->connected = SMPD_FALSE;
2120 	    host_list->connect_cmd_tag = -1;
2121 	    host_list->nproc = -1;
2122 	    host_list->alt_host[0] = '\0';
2123 	    strncpy(host_list->host, ghost_list->host, SMPD_MAX_HOST_LENGTH);
2124 	}
2125 	if (host_list != NULL && host_list->nproc == -1)
2126 	{
2127 	    /* -host specified, replace nproc field */
2128 	    host_list->nproc = nproc;
2129 	}
2130 
2131     smpd_dbg_printf("Processing environment variables \n");
2132 	/* add environment variables */
2133 	env_data[0] = '\0';
2134 	env_str = env_data;
2135 	maxlen = SMPD_MAX_ENV_LENGTH;
2136 	/* add and destroy the local environment variable list */
2137 	while (env_list)
2138 	{
2139 	    MPIU_Str_add_string_arg(&env_str, &maxlen, env_list->name, env_list->value);
2140 	    /*
2141 	    env_str += snprintf(env_str,
2142 		SMPD_MAX_ENV_LENGTH - (env_str - env_data),
2143 		"%s=%s", env_list->name, env_list->value);
2144 	    if (env_list->next)
2145 	    {
2146 		env_str += snprintf(env_str, SMPD_MAX_ENV_LENGTH - (env_str - env_data), ";");
2147 	    }
2148 	    */
2149 	    env_node = env_list;
2150 	    env_list = env_list->next;
2151 	    MPIU_Free(env_node);
2152 	}
2153 	/* add the global environment variable list */
2154 	env_node = genv_list;
2155 	while (env_node)
2156 	{
2157 	    MPIU_Str_add_string_arg(&env_str, &maxlen, env_node->name, env_node->value);
2158 	    env_node = env_node->next;
2159 	}
2160 	if (env_str > env_data)
2161 	{
2162 	    /* trim the trailing white space */
2163 	    env_str--;
2164 	    *env_str = '\0';
2165 	}
2166 
2167     smpd_dbg_printf("Processing drive mappings\n");
2168 	/* merge global drive mappings with the local drive mappings */
2169 	gmap_node = gdrive_map_list;
2170 	while (gmap_node)
2171 	{
2172 	    map_node = drive_map_list;
2173 	    while (map_node)
2174 	    {
2175 		if (map_node->drive == gmap_node->drive)
2176 		{
2177 		    /* local option trumps the global option */
2178 		    break;
2179 		}
2180 		if (map_node->next == NULL)
2181 		{
2182 		    /* add a copy of the global node to the end of the list */
2183 		    map_node->next = (smpd_map_drive_node_t*)MPIU_Malloc(sizeof(smpd_map_drive_node_t));
2184 		    if (map_node->next == NULL)
2185 		    {
2186 			printf("Error: malloc failed to allocate map structure.\n");
2187 			smpd_exit_fn(FCNAME);
2188 			return SMPD_FAIL;
2189 		    }
2190 		    map_node = map_node->next;
2191 		    map_node->ref_count = 0;
2192 		    map_node->drive = gmap_node->drive;
2193 		    strncpy(map_node->share, gmap_node->share, SMPD_MAX_EXE_LENGTH);
2194 		    map_node->next = NULL;
2195 		    break;
2196 		}
2197 		map_node = map_node->next;
2198 	    }
2199 	    if (drive_map_list == NULL)
2200 	    {
2201 		map_node = (smpd_map_drive_node_t*)MPIU_Malloc(sizeof(smpd_map_drive_node_t));
2202 		if (map_node == NULL)
2203 		{
2204 		    printf("Error: malloc failed to allocate map structure.\n");
2205 		    smpd_exit_fn(FCNAME);
2206 		    return SMPD_FAIL;
2207 		}
2208 		map_node->ref_count = 0;
2209 		map_node->drive = gmap_node->drive;
2210 		strncpy(map_node->share, gmap_node->share, SMPD_MAX_EXE_LENGTH);
2211 		map_node->next = NULL;
2212 		drive_map_list = map_node;
2213 	    }
2214 	    gmap_node = gmap_node->next;
2215 	}
2216 
2217     smpd_dbg_printf("Creating launch nodes (%d)\n", nproc);
2218 	for (i=0; i<nproc; i++)
2219 	{
2220 	    /* create a launch_node */
2221 	    launch_node = (smpd_launch_node_t*)MPIU_Malloc(sizeof(smpd_launch_node_t));
2222 	    if (launch_node == NULL)
2223 	    {
2224 		smpd_err_printf("unable to allocate a launch node structure.\n");
2225 		smpd_exit_fn(FCNAME);
2226 		return SMPD_FAIL;
2227 	    }
2228 	    launch_node->clique[0] = '\0';
2229 	    smpd_get_next_host(&host_list, launch_node);
2230         smpd_dbg_printf("Adding host (%s) to launch list \n", launch_node->hostname);
2231 	    launch_node->iproc = cur_rank++;
2232 #ifdef HAVE_WINDOWS_H
2233         if(smpd_process.affinity_map_sz > 0){
2234             launch_node->binding_proc =
2235                 smpd_process.affinity_map[affinity_map_index % smpd_process.affinity_map_sz];
2236             affinity_map_index++;
2237         }
2238         else{
2239             launch_node->binding_proc = -1;
2240         }
2241 #endif
2242 	    launch_node->appnum = appnum;
2243 	    launch_node->priority_class = n_priority_class;
2244 	    launch_node->priority_thread = n_priority;
2245 	    launch_node->env = launch_node->env_data;
2246 	    strcpy(launch_node->env_data, env_data);
2247 	    if (launch_node->alt_hostname[0] != '\0')
2248 	    {
2249 		if (smpd_append_env_option(launch_node->env_data, SMPD_MAX_ENV_LENGTH, "MPICH_INTERFACE_HOSTNAME", launch_node->alt_hostname) != SMPD_SUCCESS)
2250 		{
2251 		    smpd_err_printf("unable to add the MPICH_INTERFACE_HOSTNAME environment variable to the launch command.\n");
2252 		    smpd_exit_fn(FCNAME);
2253 		    return SMPD_FAIL;
2254 		}
2255 	    }
2256 	    if (wdir[0] != '\0')
2257 	    {
2258 		strcpy(launch_node->dir, wdir);
2259 	    }
2260 	    else
2261 	    {
2262 		if (gwdir[0] != '\0')
2263 		{
2264 		    strcpy(launch_node->dir, gwdir);
2265 		}
2266 		else
2267 		{
2268 		    launch_node->dir[0] = '\0';
2269 		    getcwd(launch_node->dir, SMPD_MAX_DIR_LENGTH);
2270 		}
2271 	    }
2272 	    if (path[0] != '\0')
2273 	    {
2274 		strcpy(launch_node->path, path);
2275 		/* should the gpath be appended to the local path? */
2276 	    }
2277 	    else
2278 	    {
2279 		if (gpath[0] != '\0')
2280 		{
2281 		    strcpy(launch_node->path, gpath);
2282 		}
2283 		else
2284 		{
2285 		    launch_node->path[0] = '\0';
2286 		}
2287 	    }
2288 	    launch_node->map_list = drive_map_list;
2289 	    if (drive_map_list)
2290 	    {
2291 		/* ref count the list so when freeing the launch_node it can be known when to free the list */
2292 		drive_map_list->ref_count++;
2293 	    }
2294 	    strcpy(launch_node->exe, exe);
2295 	    launch_node->args[0] = '\0';
2296 	    if (smpd_process.mpiexec_inorder_launch == SMPD_TRUE)
2297 	    {
2298 		/* insert the node in order */
2299 		launch_node->next = NULL;
2300 		if (smpd_process.launch_list == NULL)
2301 		{
2302 		    smpd_process.launch_list = launch_node;
2303 		    launch_node->prev = NULL;
2304 		}
2305 		else
2306 		{
2307 		    launch_node_iter = smpd_process.launch_list;
2308 		    while (launch_node_iter->next)
2309 			launch_node_iter = launch_node_iter->next;
2310 		    launch_node_iter->next = launch_node;
2311 		    launch_node->prev = launch_node_iter;
2312 		}
2313 	    }
2314 	    else
2315 	    {
2316 		/* insert the node in reverse order */
2317 		launch_node->next = smpd_process.launch_list;
2318 		if (smpd_process.launch_list)
2319 		    smpd_process.launch_list->prev = launch_node;
2320 		smpd_process.launch_list = launch_node;
2321 		launch_node->prev = NULL;
2322 	    }
2323 	}
2324 
2325 	/* advance the application number for each : separated command line block or line in a configuration file */
2326 	appnum++;
2327 
2328 	if (smpd_process.s_host_list)
2329 	{
2330 	    /* free the current host list */
2331 	    while (smpd_process.s_host_list)
2332 	    {
2333 		host_node_iter = smpd_process.s_host_list;
2334 		smpd_process.s_host_list = smpd_process.s_host_list->next;
2335 		MPIU_Free(host_node_iter);
2336 	    }
2337 	}
2338 
2339 	if (use_configfile)
2340 	{
2341 	    if (smpd_get_argcv_from_file(fin_config, argcp, argvp))
2342 	    {
2343 		/* FIXME: How do we tell the difference between an error parsing the file and parsing the last entry? */
2344 		goto configfile_loop;
2345 	    }
2346 	    fclose(fin_config);
2347 	    if (delete_configfile)
2348 	    {
2349 		unlink(configfilename);
2350 	    }
2351 	}
2352 
2353 	/* move to the next block */
2354 	*argvp = next_argv - 1;
2355 	if (*next_argv)
2356 	    **argvp = exe_ptr;
2357     } while (*next_argv);
2358 
2359     launch_node_iter = smpd_process.launch_list;
2360     while (launch_node_iter)
2361     {
2362         /* add nproc to all the launch nodes */
2363         launch_node_iter->nproc = cur_rank;
2364     	launch_node_iter = launch_node_iter->next;
2365     }
2366 
2367     /* create the cliques */
2368     smpd_create_cliques(smpd_process.launch_list);
2369 
2370     if (smpd_process.launch_list != NULL)
2371     {
2372 	if ((channel[0] == '\0') && (smpd_setting_channel[0] != '\0'))
2373 	{
2374 	    /* channel specified in the smpd settings */
2375 	    strncpy(channel, smpd_setting_channel, 20);
2376 	}
2377 	if (channel[0] != '\0')
2378 	{
2379 	    smpd_launch_node_t *iter;
2380 	    /* If the user specified auto channel selection then set the channel here */
2381 	    /* shm < 8 processes on one node
2382 	    * ssm multiple nodes
2383 	    */
2384 	    if ((strcmp(channel, "auto") == 0) && (smpd_process.launch_list != NULL))
2385 	    {
2386             strncpy(channel, "nemesis", SMPD_MAX_NAME_LENGTH);
2387 	    }
2388 
2389         nemesis_netmod[0] = '\0';
2390 #ifdef HAVE_WINDOWS_H
2391         /* See if there is a netmod specified with the channel
2392          * eg: -channel nemesis:newtcp | -channel nemesis:nd | -channel nemesis:none
2393          */
2394         if(strlen(channel) > 0){
2395             char seps[]=":";
2396             char *tok, *ctxt;
2397 
2398             tok = strtok_s(channel, seps, &ctxt);
2399             if(tok != NULL){
2400                 tok = strtok_s(NULL, seps, &ctxt);
2401                 if(tok != NULL){
2402                     MPIU_Strncpy(nemesis_netmod, tok, SMPD_MAX_NEMESIS_NETMOD_LENGTH);
2403                 }
2404             }
2405         }
2406 #endif
2407 
2408 	    /* add the channel to the environment of each process */
2409 	    iter = smpd_process.launch_list;
2410 	    while (iter)
2411 	    {
2412 		maxlen = (int)strlen(iter->env);
2413 		env_str = &iter->env[maxlen];
2414 		maxlen = SMPD_MAX_ENV_LENGTH - maxlen - 1;
2415 
2416 		if (maxlen > 15) /* At least 16 characters are needed to store MPICH2_CHANNEL=x */
2417 		{
2418 		    *env_str = ' ';
2419 		    env_str++;
2420 		    MPIU_Str_add_string_arg(&env_str, &maxlen, "MPICH2_CHANNEL", channel);
2421 		    /* trim the trailing white space */
2422 		    env_str--;
2423 		    *env_str = '\0';
2424 		}
2425 		if ((strlen(nemesis_netmod) > 0) && (maxlen > 32)) /* At least 31 characters are needed to store " MPICH_NEMESIS_NETMOD=x" */
2426 		{
2427 		    *env_str = ' ';
2428 		    env_str++;
2429 		    MPIU_Str_add_string_arg(&env_str, &maxlen, "MPICH_NEMESIS_NETMOD", nemesis_netmod);
2430 		    /* trim the trailing white space */
2431 		    env_str--;
2432 		    *env_str = '\0';
2433 		}
2434 
2435 		iter = iter->next;
2436 	    }
2437 
2438 	    /* Save the channel to be used by spawn commands */
2439 	    MPIU_Strncpy(smpd_process.env_channel, channel, 10);
2440         if(strlen(nemesis_netmod) > 0){
2441             MPIU_Strncpy(smpd_process.env_netmod, nemesis_netmod, 10);
2442         }
2443 	}
2444     }
2445 
2446     smpd_fix_up_host_tree(smpd_process.host_list);
2447 
2448     smpd_exit_fn(FCNAME);
2449     return SMPD_SUCCESS;
2450 }
2451