示例#1
0
文件: ethr_aux.c 项目: easemob/otp
int
ethr_init_common__(ethr_init_data *id)
{
    int res;

    ethr_init_event__();

#if defined(ETHR_X86_RUNTIME_CONF__)
    x86_init();
#endif

    if (id) {
	ethr_thr_prepare_func__	= id->thread_create_prepare_func;
	ethr_thr_parent_func__	= id->thread_create_parent_func;
	ethr_thr_child_func__	= id->thread_create_child_func;
    }

    ethr_cpu_info__ = erts_cpu_info_create();
    if (!ethr_cpu_info__)
	return ENOMEM;

#ifdef _SC_PAGESIZE
    ethr_pagesize__ = (size_t) sysconf(_SC_PAGESIZE);
#elif defined(HAVE_GETPAGESIZE)
    ethr_pagesize__ = (size_t) getpagesize();
#else
    ethr_pagesize__ = (size_t) 4*1024; /* Guess 4 KB */
#endif

    /* User needs at least 4 KB */
    ethr_min_stack_size__ = 4*1024;
#if SIZEOF_VOID_P == 8
    /* Double that on 64-bit archs */
    ethr_min_stack_size__ *= 2;
#endif
    /* On some systems as much as about 4 KB is used by the system */
    ethr_min_stack_size__ += 4*1024;
    /* There should be room for signal handlers */
#ifdef SIGSTKSZ
    ethr_min_stack_size__ += SIGSTKSZ;
#else
    ethr_min_stack_size__ += ethr_pagesize__;
#endif
    /* The system may think that we need more stack */
#if defined(PTHREAD_STACK_MIN)
    if (ethr_min_stack_size__ < PTHREAD_STACK_MIN)
	ethr_min_stack_size__ = PTHREAD_STACK_MIN;
#elif defined(_SC_THREAD_STACK_MIN)
    {
	size_t thr_min_stk_sz = (size_t) sysconf(_SC_THREAD_STACK_MIN);
	if (ethr_min_stack_size__ < thr_min_stk_sz)
	    ethr_min_stack_size__ = thr_min_stk_sz;
    }
#endif
    /* The guard is at least on some platforms included in the stack size
       passed when creating threads */
#ifdef ETHR_STACK_GUARD_SIZE
    ethr_min_stack_size__ += ETHR_STACK_GUARD_SIZE;
#endif
    ethr_min_stack_size__ = ETHR_PAGE_ALIGN(ethr_min_stack_size__);

    ethr_min_stack_size__ = ETHR_B2KW(ethr_min_stack_size__);

#ifdef __OSE__
    /* For supervisor processes, OSE adds a number of bytes to the requested stack. With this
     * addition, the resulting size must not exceed the largest available stack size. The number
     * of bytes that will be added  is configured in the monolith and can therefore not be
     * specified here. We simply assume that it is less than 0x1000. The available stack sizes
     * are configured in the .lmconf file and the largest one is usually 65536 bytes.
     * Consequently, the requested stack size is limited to 0xF000.
     */
    ethr_max_stack_size__ = 0xF000;
#else
    ethr_max_stack_size__ = 32*1024*1024;
#endif
#if SIZEOF_VOID_P == 8
    ethr_max_stack_size__ *= 2;
#endif
    ethr_max_stack_size__ = ETHR_B2KW(ethr_max_stack_size__);

    res = ethr_init_atomics();
    if (res != 0)
	return res;

    res = ethr_mutex_lib_init(erts_get_cpu_configured(ethr_cpu_info__));
    if (res != 0)
	return res;

    xhndl_list = NULL;

    return 0;
}
示例#2
0
文件: ethr_aux.c 项目: AlainODea/otp
int
ethr_init_common__(ethr_init_data *id)
{
    int res;
    if (id) {
	ethr_thr_prepare_func__	= id->thread_create_prepare_func;
	ethr_thr_parent_func__	= id->thread_create_parent_func;
	ethr_thr_child_func__	= id->thread_create_child_func;
    }

    ethr_cpu_info__ = erts_cpu_info_create();
    if (!ethr_cpu_info__)
	return ENOMEM;

#ifdef _SC_PAGESIZE
    ethr_pagesize__ = (size_t) sysconf(_SC_PAGESIZE);
#elif defined(HAVE_GETPAGESIZE)
    ethr_pagesize__ = (size_t) getpagesize();
#else
    ethr_pagesize__ = (size_t) 4*1024; /* Guess 4 KB */
#endif

    /* User needs at least 4 KB */
    ethr_min_stack_size__ = 4*1024;
#if SIZEOF_VOID_P == 8
    /* Double that on 64-bit archs */
    ethr_min_stack_size__ *= 2;
#endif
    /* On some systems as much as about 4 KB is used by the system */
    ethr_min_stack_size__ += 4*1024;
    /* There should be room for signal handlers */
#ifdef SIGSTKSZ
    ethr_min_stack_size__ += SIGSTKSZ;
#else
    ethr_min_stack_size__ += ethr_pagesize__;
#endif
    /* The system may think that we need more stack */
#if defined(PTHREAD_STACK_MIN)
    if (ethr_min_stack_size__ < PTHREAD_STACK_MIN)
	ethr_min_stack_size__ = PTHREAD_STACK_MIN;
#elif defined(_SC_THREAD_STACK_MIN)
    {
	size_t thr_min_stk_sz = (size_t) sysconf(_SC_THREAD_STACK_MIN);
	if (ethr_min_stack_size__ < thr_min_stk_sz)
	    ethr_min_stack_size__ = thr_min_stk_sz;
    }
#endif
    /* The guard is at least on some platforms included in the stack size
       passed when creating threads */
#ifdef ETHR_STACK_GUARD_SIZE
    ethr_min_stack_size__ += ETHR_STACK_GUARD_SIZE;
#endif
    ethr_min_stack_size__ = ETHR_PAGE_ALIGN(ethr_min_stack_size__);

    ethr_min_stack_size__ = ETHR_B2KW(ethr_min_stack_size__);

    ethr_max_stack_size__ = 32*1024*1024;
#if SIZEOF_VOID_P == 8
    ethr_max_stack_size__ *= 2;
#endif
    ethr_max_stack_size__ = ETHR_B2KW(ethr_max_stack_size__);

#ifndef ETHR_HAVE_OPTIMIZED_ATOMIC_OPS
    {
	int i;
	for (i = 0; i < (1 << ETHR_ATOMIC_ADDR_BITS); i++) {
	    res = ethr_spinlock_init(&ethr_atomic_protection__[i].u.lck);
	    if (res != 0)
		return res;
	}
    }
#endif

    res = ethr_mutex_lib_init(erts_get_cpu_configured(ethr_cpu_info__));
    if (res != 0)
	return res;

    xhndl_list = NULL;

    return 0;
}
示例#3
0
int main(int argc, char **argv)
#endif
{
    int haltAfterwards = 0;	/* If true, put 's erlang halt' at the end
				 * of the arguments. */
    int isdistributed = 0;
    int no_epmd = 0;
    int i;
    char* s;
    char *epmd_prog = NULL;
    char *malloc_lib;
    int process_args = 1;
    int print_args_exit = 0;
    int print_qouted_cmd_exit = 0;
    erts_cpu_info_t *cpuinfo = NULL;

#ifdef __WIN32__
    this_module_handle = module;
    run_werl = windowed;
    /* if we started this erl just to get a detached emulator, 
     * the arguments are already prepared for beam, so we skip
     * directly to start_emulator */
    s = get_env("ERL_CONSOLE_MODE");
    if (s != NULL && strcmp(s, "detached")==0) {
	free_env_val(s);
	s = get_env("ERL_EMULATOR_DLL");
	if (s != NULL) {
	    argv[0] = strsave(s);
	} else {
	    argv[0] = strsave(EMULATOR_EXECUTABLE);
	}
	ensure_EargsSz(argc + 1);
	memcpy((void *) Eargsp, (void *) argv, argc * sizeof(char *));
	Eargsp[argc] = NULL;
	emu = argv[0];
	start_emulator_program = strsave(argv[0]);
	goto skip_arg_massage;
    }   
    free_env_val(s);
#else
    int reset_cerl_detached = 0;

    s = get_env("CERL_DETACHED_PROG");
    if (s && strcmp(s, "") != 0) {
	emu = s;
	start_detached = 1;
	reset_cerl_detached = 1;
	ensure_EargsSz(argc + 1);
	memcpy((void *) Eargsp, (void *) argv, argc * sizeof(char *));
	Eargsp[argc] = emu;
	Eargsp[argc] = NULL;
	goto skip_arg_massage;
    }
    free_env_val(s);
#endif

    initial_argv_massage(&argc, &argv); /* Merge with env; expand -args_file */

    i = 1;
#ifdef __WIN32__
    /* Not used? /rickard */
    if ((argc > 2) && (strcmp(argv[i], "-regkey") == 0)) {
	key_val_name = strsave(argv[i+1]);
	i = 3;
    }
#endif		

    get_parameters(argc, argv);
    
    /*
     * Construct the path of the executable.
     */
    cpuinfo = erts_cpu_info_create();
    /* '-smp auto' is default */ 
#ifdef ERTS_HAVE_SMP_EMU
    if (erts_get_cpu_configured(cpuinfo) > 1)
	emu_type |= EMU_TYPE_SMP;
#endif

#if defined(__WIN32__) && defined(WIN32_ALWAYS_DEBUG)
    emu_type_passed |= EMU_TYPE_DEBUG;
    emu_type |= EMU_TYPE_DEBUG;
#endif

    /* We need to do this before the ordinary processing. */
    malloc_lib = get_env("ERL_MALLOC_LIB");
    while (i < argc) {
	if (argv[i][0] == '+') {
	    if (argv[i][1] == 'M' && argv[i][2] == 'Y' && argv[i][3] == 'm') {
		if (argv[i][4] == '\0') {
		    if (++i < argc)
			malloc_lib = argv[i];
		    else
			usage("+MYm");
		}
		else
		    malloc_lib = &argv[i][4];
	    }
	}
	else if (argv[i][0] == '-') {
	    if (strcmp(argv[i], "-smp") == 0) {
		if (i + 1 >= argc)
		    goto smp;

		if (strcmp(argv[i+1], "auto") == 0) {
		    i++;
		smp_auto:
		    emu_type_passed |= EMU_TYPE_SMP;
#ifdef ERTS_HAVE_SMP_EMU
		    if (erts_get_cpu_configured(cpuinfo) > 1)
			emu_type |= EMU_TYPE_SMP;
		    else
#endif
			emu_type &= ~EMU_TYPE_SMP;
		}
		else if (strcmp(argv[i+1], "enable") == 0) {
		    i++;
		smp_enable:
		    emu_type_passed |= EMU_TYPE_SMP;
#ifdef ERTS_HAVE_SMP_EMU
		    emu_type |= EMU_TYPE_SMP;
#else
		    usage_notsup("-smp enable");
#endif
		}
		else if (strcmp(argv[i+1], "disable") == 0) {
		    i++;
		smp_disable:
		    emu_type_passed |= EMU_TYPE_SMP;
		    emu_type &= ~EMU_TYPE_SMP;
		}
		else {
		smp:

		    emu_type_passed |= EMU_TYPE_SMP;
#ifdef ERTS_HAVE_SMP_EMU
		    emu_type |= EMU_TYPE_SMP;
#else
		    usage_notsup("-smp");
#endif
		}
	    } else if (strcmp(argv[i], "-smpenable") == 0) {
		goto smp_enable;
	    } else if (strcmp(argv[i], "-smpauto") == 0) {
		goto smp_auto;
	    } else if (strcmp(argv[i], "-smpdisable") == 0) {
		goto smp_disable;
#ifdef __WIN32__
	    } else if (strcmp(argv[i], "-debug") == 0) {
		emu_type_passed |= EMU_TYPE_DEBUG;
		emu_type |= EMU_TYPE_DEBUG;
#endif
	    } else if (strcmp(argv[i], "-hybrid") == 0) {
		emu_type_passed |= EMU_TYPE_HYBRID;
#ifdef ERTS_HAVE_HYBRID_EMU
		emu_type |= EMU_TYPE_HYBRID;
#else
		usage_notsup("-hybrid");
#endif
	    } else if (strcmp(argv[i], "-extra") == 0) {
		break;
	    }
	}
	i++;
    }

    erts_cpu_info_destroy(cpuinfo);
    cpuinfo = NULL;

    if ((emu_type & EMU_TYPE_HYBRID) && (emu_type & EMU_TYPE_SMP)) {
	/*
	 * We have a conflict. Only using explicitly passed arguments
	 * may solve it...
	 */
	emu_type &= emu_type_passed;
	if ((emu_type & EMU_TYPE_HYBRID) && (emu_type & EMU_TYPE_SMP)) {
	    usage_msg("Hybrid heap emulator with SMP support selected. The "
		      "combination hybrid heap and SMP support is currently "
		      "not supported.");
	}
    }

    if (malloc_lib) {
	if (strcmp(malloc_lib, "libc") != 0)
	    usage("+MYm");
    }
    emu = add_extra_suffixes(emu, emu_type);
    sprintf(tmpStr, "%s" DIRSEP "%s" BINARY_EXT, bindir, emu);
    emu = strsave(tmpStr);

    add_Eargs(emu);		/* Will be argv[0] -- necessary! */

    /*
     * Add the bindir to the path (unless it is there already).
     */

    s = get_env("PATH");
    if (!s) {
	sprintf(tmpStr, "%s" PATHSEP "%s" DIRSEP "bin", bindir, rootdir);
    } else if (strstr(s, bindir) == NULL) {
	sprintf(tmpStr, "%s" PATHSEP "%s" DIRSEP "bin" PATHSEP "%s", bindir, 
		rootdir, s);
    } else {
	sprintf(tmpStr, "%s", s);
    }
    free_env_val(s);
    set_env("PATH", tmpStr);
    
    i = 1;

#ifdef __WIN32__
#define ADD_BOOT_CONFIG					\
    if (boot_script)					\
	add_args("-boot", boot_script, NULL);		\
    if (config_script)					\
	add_args("-config", config_script, NULL);
#else
#define ADD_BOOT_CONFIG
#endif

    get_home();
    add_args("-home", home, NULL);

    add_epmd_port();

    add_arg("--");

    while (i < argc) {
	if (!process_args) {	/* Copy arguments after '-extra' */
	    add_arg(argv[i]);
	    i++;
	} else {
	    switch (argv[i][0]) {
	      case '-':
		switch (argv[i][1]) {
#ifdef __WIN32__
		case 'b':
		    if (strcmp(argv[i], "-boot") == 0) {
			if (boot_script)
			    error("Conflicting -start_erl and -boot options");
			if (i+1 >= argc)
			    usage("-boot");
			boot_script = strsave(argv[i+1]);
			i++;
		    }
		    else {
			add_arg(argv[i]);
		    }
		    break;
#endif
		case 'c':
		    if (strcmp(argv[i], "-compile") == 0) {
			/*
			 * Note that the shell script erl.exec does an recursive call
			 * on itself here.  We'll avoid doing that.
			 */
			add_args("-noshell", "-noinput", "-s", "c", "lc_batch",
				 NULL);
			add_Eargs("-B");
			haltAfterwards = 0;
		    }
#ifdef __WIN32__
		    else if (strcmp(argv[i], "-config") == 0){
			if (config_script)
			    error("Conflicting -start_erl and -config options");
			if (i+1 >= argc)
			    usage("-config");
			config_script = strsave(argv[i+1]);
			i++;
		    }
#endif
		    else {
			add_arg(argv[i]);
		    }
		    break;

		  case 'd':
		    if (strcmp(argv[i], "-detached") != 0) {
			add_arg(argv[i]);
		    } else {
			start_detached = 1;
			add_args("-noshell", "-noinput", NULL);
		    }
		    break;

		  case 'i':
		    if (strcmp(argv[i], "-instr") == 0) {
			add_Eargs("-Mim");
			add_Eargs("true");
		    }
		    else
			add_arg(argv[i]);
		    break;

		  case 'e':
		    if (strcmp(argv[i], "-extra") == 0) {
			process_args = 0;
			ADD_BOOT_CONFIG;
			add_arg(argv[i]);
		    } else if (strcmp(argv[i], "-emu_args") == 0) { /* -emu_args */
			verbose = 1;
		    } else if (strcmp(argv[i], "-emu_args_exit") == 0) {
			print_args_exit = 1;
		    } else if (strcmp(argv[i], "-emu_qouted_cmd_exit") == 0) {
			print_qouted_cmd_exit = 1;
		    } else if (strcmp(argv[i], "-env") == 0) { /* -env VARNAME VARVALUE */
			if (i+2 >= argc)
			    usage("-env");
			set_env(argv[i+1], argv[i+2]);
			i += 2;
		    } else if (strcmp(argv[i], "-epmd") == 0) { 
			if (i+1 >= argc)
			    usage("-epmd");
			epmd_prog = argv[i+1];
			++i;
		    } else {
			add_arg(argv[i]);
		    }
		    break;
		  case 'k':
		    if (strcmp(argv[i], "-keep_window") == 0) {
			keep_window = 1;
		    } else
			add_arg(argv[i]);
		    break;

		  case 'm':
		    /*
		     * Note that the shell script erl.exec does an recursive call
		     * on itself here.  We'll avoid doing that.
		     */
		    if (strcmp(argv[i], "-make") == 0) {
			add_args("-noshell", "-noinput", "-s", "make", "all", NULL);
			add_Eargs("-B");
			haltAfterwards = 1;
			i = argc; /* Skip rest of command line */
		    } else if (strcmp(argv[i], "-man") == 0) {
#if defined(__WIN32__)
			error("-man not supported on Windows");
#else
			argv[i] = "man";
			sprintf(tmpStr, "%s/man", rootdir);
			set_env("MANPATH", tmpStr);
			execvp("man", argv+i);
			error("Could not execute the 'man' command.");
#endif
		    } else
			add_arg(argv[i]);
		    break;

		  case 'n':
		    if (strcmp(argv[i], "-name") == 0) { /* -name NAME */
			if (i+1 >= argc)
			    usage("-name");
		    
			/*
			 * Note: Cannot use add_args() here, due to non-defined
			 * evaluation order.
			 */

			add_arg(argv[i]);
			add_arg(argv[i+1]);
			isdistributed = 1;
			i++;
		    } else if (strcmp(argv[i], "-noinput") == 0) {
			add_args("-noshell", "-noinput", NULL);
		    } else if (strcmp(argv[i], "-nohup") == 0) {
			add_arg("-nohup");
			nohup = 1;
		    } else if (strcmp(argv[i], "-no_epmd") == 0) {
			add_arg("-no_epmd");
			no_epmd = 1;
		    } else {
			add_arg(argv[i]);
		    }
		    break;

		  case 's':	/* -sname NAME */
		    if (strcmp(argv[i], "-sname") == 0) {
			if (i+1 >= argc)
			    usage("-sname");
			add_arg(argv[i]);
			add_arg(argv[i+1]);
			isdistributed = 1;
			i++;
		    }
#ifdef __WIN32__
		    else if (strcmp(argv[i], "-service_event") == 0) {
			add_arg(argv[i]);
			add_arg(argv[i+1]);
			i++;
		    }		    
		    else if (strcmp(argv[i], "-start_erl") == 0) {
			if (i+1 < argc && argv[i+1][0] != '-') {
			    get_start_erl_data(argv[i+1]);
			    i++;
			} else
			    get_start_erl_data((char *) NULL);
		    }
#endif
		    else
			add_arg(argv[i]);
		
		    break;
	
		  case 'v':	/* -version */
		    if (strcmp(argv[i], "-version") == 0) {
			add_Eargs("-V");
		    } else {
			add_arg(argv[i]);
		    }
		    break;

		  default:
		    add_arg(argv[i]);
		    break;
		} /* switch(argv[i][1] */
		break;

	      case '+':
		switch (argv[i][1]) {
		  case '#':
		  case 'a':
		  case 'A':
		  case 'b':
		  case 'h':
		  case 'i':
		  case 'P':
		  case 'S':
		  case 'T':
		  case 'R':
		  case 'W':
		  case 'K':
		      if (argv[i][2] != '\0')
			  goto the_default;
		      if (i+1 >= argc)
			  usage(argv[i]);
		      argv[i][0] = '-';
		      add_Eargs(argv[i]);
		      add_Eargs(argv[i+1]);
		      i++;
		      break;
		  case 'B':
		      argv[i][0] = '-';
		      if (argv[i][2] != '\0') {
			  if ((argv[i][2] != 'i') &&
			      (argv[i][2] != 'c') &&
			      (argv[i][2] != 'd')) { 
			  usage(argv[i]);
			} else {
			  add_Eargs(argv[i]);
			  break;
			}
		      }
		      if (i+1 < argc) {
			if ((argv[i+1][0] != '-') &&
			    (argv[i+1][0] != '+')) {
			  if (argv[i+1][0] == 'i') {
			    add_Eargs(argv[i]);
			    add_Eargs(argv[i+1]);
			    i++;
			    break;
			  } else {
			    usage(argv[i]);
			  }
			}
		      }
		      add_Eargs(argv[i]);
		      break;
		  case 'M': {
		      int x;
		      for (x = 0; plusM_au_allocs[x]; x++)
			  if (plusM_au_allocs[x] == argv[i][2])
			      break;
		      if ((plusM_au_allocs[x]
			   && is_one_of_strings(&argv[i][3],
						plusM_au_alloc_switches))
			  || is_one_of_strings(&argv[i][2],
					       plusM_other_switches)) {
			  if (i+1 >= argc
			      || argv[i+1][0] == '-'
			      || argv[i+1][0] == '+')
			      usage(argv[i]);
			  argv[i][0] = '-';
			  add_Eargs(argv[i]);
			  add_Eargs(argv[i+1]);
			  i++;
		      }
		      else
			  goto the_default;
		      break;
		  }
		  case 's':
		      if (!is_one_of_strings(&argv[i][2],
					     pluss_val_switches))
			  goto the_default;
		      else {
			  if (i+1 >= argc
			      || argv[i+1][0] == '-'
			      || argv[i+1][0] == '+')
			      usage(argv[i]);
			  argv[i][0] = '-';
			  add_Eargs(argv[i]);
			  add_Eargs(argv[i+1]);
			  i++;
		      }
		      break;
		  default:
		  the_default:
		    argv[i][0] = '-'; /* Change +option to -option. */
		    add_Eargs(argv[i]);
		}
		break;
      
	      default:
		add_arg(argv[i]);
	    } /* switch(argv[i][0] */
	    i++;
	}
    }

    if (process_args) {
	ADD_BOOT_CONFIG;
    }
#undef ADD_BOOT_CONFIG

    /* Doesn't conflict with -extra, since -make skips all the rest of
       the arguments. */
    if (haltAfterwards) {
	add_args("-s", "erlang", "halt", NULL);
    }
    
    if (isdistributed && !no_epmd)
	start_epmd(epmd_prog);

#if (! defined(__WIN32__)) && defined(DEBUG)
    if (start_detached) {
	/* Start the emulator within an xterm.
	 * Move up all arguments and insert
	 * "xterm -e " first.
	 * The path must be searched for this 
	 * to work, i.e execvp() must be used. 
	 */
	ensure_EargsSz(EargsCnt+2);
	for (i = EargsCnt; i > 0; i--)
	    Eargsp[i+1] = Eargsp[i-1]; /* Two args to insert */
	EargsCnt += 2; /* Two args to insert */
	Eargsp[0] = emu = "xterm";
	Eargsp[1] = "-e";
    }    
#endif
    
    add_Eargs("--");
    add_Eargs("-root");
    add_Eargs(rootdir);
    add_Eargs("-progname");
    add_Eargs(progname);
    add_Eargs("--");
    ensure_EargsSz(EargsCnt + argsCnt + 1);
    for (i = 0; i < argsCnt; i++)
	Eargsp[EargsCnt++] = argsp[i];
    Eargsp[EargsCnt] = NULL;
    
    if (print_qouted_cmd_exit) {
	printf("\"%s\" ", emu);
	for (i = 1; i < EargsCnt; i++)
	    printf("\"%s\" ", Eargsp[i]);
	printf("\n");
	exit(0);
    }

    if (print_args_exit) {
	for (i = 1; i < EargsCnt; i++)
	    printf("%s ", Eargsp[i]);
	printf("\n");
	exit(0);
    }

    if (verbose) {
	printf("Executing: %s", emu);
	for (i = 0; i < EargsCnt; i++)
	    printf(" %s", Eargsp[i]);
	printf("\n\n");
    }

#ifdef __WIN32__

    if (EargsSz != EargsCnt + 1)
	Eargsp = (char **) erealloc((void *) Eargsp, (EargsCnt + 1) * 
				    sizeof(char *));
    efree((void *) argsp);

 skip_arg_massage:
    /*DebugBreak();*/

    if (run_werl) {
	if (start_detached) {
	    char *p;
	    /* transform werl to erl */
	    p = start_emulator_program+strlen(start_emulator_program);
	    while (--p >= start_emulator_program && *p != '/' && *p != '\\' &&
		   *p != 'W' && *p != 'w')
		;
	    if (p >= start_emulator_program && (*p == 'W' || *p == 'w') &&
		(p[1] == 'E' || p[1] == 'e') && (p[2] == 'R' || p[2] == 'r') &&
		(p[3] == 'L' || p[3] == 'l')) {
		memmove(p,p+1,strlen(p));
	    }
	}
      return start_win_emulator(emu, start_emulator_program, Eargsp, start_detached);
    } else {
      return start_emulator(emu, start_emulator_program, Eargsp, start_detached);
    }

#else

 skip_arg_massage:
    if (start_detached) {
	int status = fork();
	if (status != 0)	/* Parent */
	    return 0;

	if (reset_cerl_detached)
	    putenv("CERL_DETACHED_PROG=");

	/* Detach from controlling terminal */
#ifdef HAVE_SETSID
	setsid();
#elif defined(TIOCNOTTY)
	{
	  int fd = open("/dev/tty", O_RDWR);
	  if (fd >= 0) {
	    ioctl(fd, TIOCNOTTY, NULL);
	    close(fd);
	  }
	}
#endif

	status = fork();
	if (status != 0)	/* Parent */
	    return 0;

	/*
	 * Grandchild.
	 */
	close(0);
	open("/dev/null", O_RDONLY);
	close(1);
	open("/dev/null", O_WRONLY);
	close(2);
	open("/dev/null", O_WRONLY);
#ifdef DEBUG
	execvp(emu, Eargsp); /* "xterm ..." needs to search the path */
#endif
    } 
#ifdef DEBUG
    else
#endif
    {
	execv(emu, Eargsp);
    }
    error("Error %d executing \'%s\'.", errno, emu);
    return 1;
#endif
}