"2:3DL:M:NP:RTbc:d:e:f:hi:lmn:op:rt:vw:xy");
"2:3DL:M:NP:RSTbc:d:e:f:hi:lmn:op:rt:vw:xy");
main(int argc, char **argv){    char *               progName    = NULL;    char *               nickName    = NULL;#ifdef NSS_ENABLE_ECC    char *               ecNickName   = NULL;#endif    char *               fNickName   = NULL;    const char *         fileName    = NULL;    char *               cipherString= NULL;    const char *         dir         = ".";    char *               passwd      = NULL;    const char *         pidFile     = NULL;    char *               tmp;    char *               envString;    PRFileDesc *         listen_sock;    CERTCertificate *    cert   [kt_kea_size] = { NULL };    SECKEYPrivateKey *   privKey[kt_kea_size] = { NULL };    int                  optionsFound = 0;    int                  maxProcs     = 1;    unsigned short       port        = 0;    SECStatus            rv;    PRStatus             prStatus;    PRBool               bindOnly = PR_FALSE;    PRBool               useExportPolicy = PR_FALSE;    PRBool               useLocalThreads = PR_FALSE;    PLOptState		*optstate;    PLOptStatus          status;    PRThread             *loggerThread;    PRBool               debugCache = PR_FALSE; /* bug 90518 */    char*                certPrefix = "";    tmp = strrchr(argv[0], '/');    tmp = tmp ? tmp + 1 : argv[0];    progName = strrchr(tmp, '\\');    progName = progName ? progName + 1 : tmp;    PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);    /* please keep this list of options in ASCII collating sequence.    ** numbers, then capital letters, then lower case, alphabetical.     */    optstate = PL_CreateOptState(argc, argv,     	"2:3DL:M:NP:RTbc:d:e:f:hi:lmn:op:rt:vw:xy");    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {	++optionsFound;	switch(optstate->option) {	case '2': fileName = optstate->value; break;	case '3': disableSSL3 = PR_TRUE; break;	case 'D': noDelay = PR_TRUE; break;        case 'L':            logStats = PR_TRUE;	    if (optstate->value == NULL) {	    	logPeriod = 30;	    } else {                logPeriod  = PORT_Atoi(optstate->value);                if (logPeriod <= 0) logPeriod = 30;	    }            break;	case 'M': 	    maxProcs = PORT_Atoi(optstate->value); 	    if (maxProcs < 1)         maxProcs = 1;	    if (maxProcs > MAX_PROCS) maxProcs = MAX_PROCS;	    break;	case 'N': NoReuse = PR_TRUE; break;	case 'R': disableRollBack = PR_TRUE; break;	case 'T': disableTLS = PR_TRUE; break;	case 'b': bindOnly = PR_TRUE; break;	case 'c': cipherString = strdup(optstate->value); break;	case 'd': dir = optstate->value; break;#ifdef NSS_ENABLE_ECC	case 'e': ecNickName = strdup(optstate->value); break;#endif /* NSS_ENABLE_ECC */	case 'f': fNickName = strdup(optstate->value); break;	case 'h': Usage(progName); exit(0); break;	case 'i': pidFile = optstate->value; break;        case 'l': useLocalThreads = PR_TRUE; break;	case 'm': useModelSocket = PR_TRUE; break;        case 'n': nickName = strdup(optstate->value); break;        case 'P': certPrefix = strdup(optstate->value); break;	case 'o': MakeCertOK = 1; break;	case 'p': port = PORT_Atoi(optstate->value); break;	case 'r': ++requestCert; break;	case 't':	    maxThreads = PORT_Atoi(optstate->value);	    if ( maxThreads > MAX_THREADS ) maxThreads = MAX_THREADS;	    if ( maxThreads < MIN_THREADS ) maxThreads = MIN_THREADS;	    break;	case 'v': verbose++; break;	case 'w': passwd = strdup(optstate->value); break;	case 'x': useExportPolicy = PR_TRUE; break;	case 'y': debugCache = PR_TRUE; break;	default:	case '?':	    fprintf(stderr, "Unrecognized or bad option specified.\n");	    fprintf(stderr, "Run '%s -h' for usage information.\n", progName);	    exit(4);	    break;	}    }    PL_DestroyOptState(optstate);    if (status == PL_OPT_BAD) {	fprintf(stderr, "Unrecognized or bad option specified.\n");	fprintf(stderr, "Run '%s -h' for usage information.\n", progName);	exit(5);    }    if (!optionsFound) {	Usage(progName);	exit(51);    }     /* The -b (bindOnly) option is only used by the ssl.sh test     * script on Linux to determine whether a previous selfserv     * process has fully died and freed the port.  (Bug 129701)     */    if (bindOnly) {	listen_sock = getBoundListenSocket(port);	if (!listen_sock) {	    exit(1);	}	PR_Close(listen_sock);	exit(0);    }    if ((nickName == NULL) && (fNickName == NULL)) {	fprintf(stderr, "Required arg '-n' (rsa nickname) not supplied.\n");	fprintf(stderr, "Run '%s -h' for usage information.\n", progName);        exit(6);    }    if (port == 0) {	fprintf(stderr, "Required argument 'port' must be non-zero value\n");	exit(7);    }    if (NoReuse && maxProcs > 1) {	fprintf(stderr, "-M and -N options are mutually exclusive.\n");	exit(14);    }    if (pidFile) {	FILE *tmpfile=fopen(pidFile,"w+");	if (tmpfile) {	    fprintf(tmpfile,"%d",getpid());	    fclose(tmpfile);	}    }    envString = getenv(envVarName);    tmp = getenv("TMP");    if (!tmp)	tmp = getenv("TMPDIR");    if (!tmp)	tmp = getenv("TEMP");    if (envString) {	/* we're one of the children in a multi-process server. */	listen_sock = PR_GetInheritedFD(inheritableSockName);	if (!listen_sock)	    errExit("PR_GetInheritedFD");#ifndef WINNT	/* we can't do this on NT because it breaks NSPR and	PR_Accept will fail on the socket in the child process if	the socket state is change to non inheritable	It is however a security issue to leave it accessible,	but it is OK for a test server such as selfserv.	NSPR should fix it eventually . see bugzilla 101617	and 102077	*/	prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE);	if (prStatus != PR_SUCCESS)	    errExit("PR_SetFDInheritable");#endif#ifdef DEBUG_nelsonb	WaitForDebugger();#endif	rv = SSL_InheritMPServerSIDCache(envString);	if (rv != SECSuccess)	    errExit("SSL_InheritMPServerSIDCache");    	hasSidCache = PR_TRUE;    } else if (maxProcs > 1) {	/* we're going to be the parent in a multi-process server.  */	listen_sock = getBoundListenSocket(port);	rv = SSL_ConfigMPServerSIDCache(NUM_SID_CACHE_ENTRIES, 0, 0, tmp);	if (rv != SECSuccess)	    errExit("SSL_ConfigMPServerSIDCache");    	hasSidCache = PR_TRUE;	beAGoodParent(argc, argv, maxProcs, listen_sock);	exit(99); /* should never get here */    } else {	/* we're an ordinary single process server. */	listen_sock = getBoundListenSocket(port);	prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE);	if (prStatus != PR_SUCCESS)	    errExit("PR_SetFDInheritable");	if (!NoReuse) {	    rv = SSL_ConfigServerSessionIDCache(NUM_SID_CACHE_ENTRIES, 	                                        0, 0, tmp);	    if (rv != SECSuccess)		errExit("SSL_ConfigServerSessionIDCache");	    hasSidCache = PR_TRUE;	}    }    lm = PR_NewLogModule("TestCase");    if (fileName)    	readBigFile(fileName);    /* set our password function */    PK11_SetPasswordFunc( passwd ? ownPasswd : SECU_GetModulePassword);    /* Call the libsec initialization routines */    rv = NSS_Initialize(dir, certPrefix, certPrefix, SECMOD_DB, NSS_INIT_READONLY);    if (rv != SECSuccess) {    	fputs("NSS_Init failed.\n", stderr);		exit(8);    }    /* set the policy bits true for all the cipher suites. */    if (useExportPolicy)	NSS_SetExportPolicy();    else	NSS_SetDomesticPolicy();    /* all the SSL2 and SSL3 cipher suites are enabled by default. */    if (cipherString) {    	int ndx;	/* disable all the ciphers, then enable the ones we want. */	disableAllSSLCiphers();	while (0 != (ndx = *cipherString++)) {	    const int *cptr;	    int  cipher;	    if (! isalpha(ndx)) {		fprintf(stderr, 			"Non-alphabetic char in cipher string (-c arg).\n");		exit(9);	    }	    cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;	    for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; ) 		/* do nothing */;	    if (cipher) {		SECStatus status;		status = SSL_CipherPrefSetDefault(cipher, SSL_ALLOWED);		if (status != SECSuccess) 		    SECU_PrintError(progName, "SSL_CipherPrefSet()");	    }	}    }    if (nickName) {	cert[kt_rsa] = PK11_FindCertFromNickname(nickName, passwd);	if (cert[kt_rsa] == NULL) {	    fprintf(stderr, "selfserv: Can't find certificate %s\n", nickName);	    exit(10);	}	privKey[kt_rsa] = PK11_FindKeyByAnyCert(cert[kt_rsa], passwd);	if (privKey[kt_rsa] == NULL) {	    fprintf(stderr, "selfserv: Can't find Private Key for cert %s\n", 	            nickName);	    exit(11);	}    }    if (fNickName) {	cert[kt_fortezza] = PK11_FindCertFromNickname(fNickName, NULL);	if (cert[kt_fortezza] == NULL) {	    fprintf(stderr, "selfserv: Can't find certificate %s\n", fNickName);	    exit(12);	}	privKey[kt_fortezza] = PK11_FindKeyByAnyCert(cert[kt_fortezza], NULL);    }#ifdef NSS_ENABLE_ECC    if (ecNickName) {	cert[kt_ecdh] = PK11_FindCertFromNickname(ecNickName, NULL);	if (cert[kt_ecdh] == NULL) {	    fprintf(stderr, "selfserv: Can't find certificate %s\n",		    ecNickName);	    exit(13);	}	privKey[kt_ecdh] = PK11_FindKeyByAnyCert(cert[kt_ecdh], NULL);    }#endif /* NSS_ENABLE_ECC */    /* allocate the array of thread slots, and launch the worker threads. */    rv = launch_threads(&jobLoop, 0, 0, requestCert, useLocalThreads);    if (rv == SECSuccess && logStats) {	loggerThread = PR_CreateThread(PR_SYSTEM_THREAD, 			logger, NULL, PR_PRIORITY_NORMAL,                         useLocalThreads ? PR_LOCAL_THREAD:PR_GLOBAL_THREAD,                        PR_UNJOINABLE_THREAD, 0);	if (loggerThread == NULL) {	    fprintf(stderr, "selfserv: Failed to launch logger thread!\n");	    rv = SECFailure;	}     }    if (rv == SECSuccess) {	server_main(listen_sock, requestCert, privKey, cert);    }    VLOG(("selfserv: server_thread: exiting"));    {	int i;	for (i=0; i<kt_kea_size; i++) {	    if (cert[i]) {		CERT_DestroyCertificate(cert[i]);	    }	    if (privKey[i]) {		SECKEY_DestroyPrivateKey(privKey[i]);	    }	}    }    if (debugCache) {	nss_DumpCertificateCacheInfo();    }    free(nickName);    free(passwd);    if (hasSidCache) {	SSL_ShutdownServerSessionIDCache();    }    if (NSS_Shutdown() != SECSuccess) {	SECU_PrintError(progName, "NSS_Shutdown");	PR_Cleanup();	exit(1);    }    PR_Cleanup();    printf("selfserv: normal termination\n");    return 0;}