optstate = PL_CreateOptState(argc, argv, "d:i:sen:p:t:");
optstate = PL_CreateOptState(argc, argv, "d:i:sen:p:t:h:k:w:gx:");
main(int argc, char **argv){    TimingContext *	  timeCtx;    SECKEYPublicKey *	  pubHighKey;    NSSLOWKEYPrivateKey * privKey;    NSSLOWKEYPublicKey *  pubKey;    CERTCertificate *	  cert;    char *		  progName;    char *		  secDir 	= NULL;    char *		  nickname 	= NULL;    RSAOp                 fn;    void *                rsaKey;    PLOptState *          optstate;    PLOptStatus           optstatus;    long 		  iters 	= DEFAULT_ITERS;    int		 	  i;    PRBool 		  doPriv 	= PR_FALSE;    PRBool 		  doPub 	= PR_FALSE;    int 		  rv;    CERTCertDBHandle 	* certdb;    unsigned char 	  buf[1024];    unsigned char 	  buf2[1024];    int                   seconds = DEFAULT_DURATION;    PRBool                doIters = PR_FALSE;    PRBool                doTime = PR_FALSE;    int                   threadNum     = DEFAULT_THREADS;    ThreadRunData      ** runDataArr = NULL;    PRThread           ** threadsArr = NULL;    int                   calcThreads = 0;    PRTime                startTimeAcc = 0;    PRTime                stopTimeAcc = 0;    progName = strrchr(argv[0], '/');    if (!progName)	progName = strrchr(argv[0], '\\');    progName = progName ? progName+1 : argv[0];    optstate = PL_CreateOptState(argc, argv, "d:i:sen:p:t:");    while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {	switch (optstate->option) {	case '?':	    Usage(progName);	    break;	case 'd':	    secDir = PORT_Strdup(optstate->value);	    break;	case 'i':	    iters = (atol(optstate->value)>0?atol(optstate->value):iters);	    doIters = PR_TRUE;	    break;	case 's':	    doPriv = PR_TRUE;	    break;	case 'e':	    doPub = PR_TRUE;	    break;	case 'n':	    nickname = PORT_Strdup(optstate->value);	    break;        case 'p':            seconds = (atol(optstate->value)>0?atol(optstate->value):DEFAULT_DURATION);            doTime = PR_TRUE;            break;	case 't':	    threadNum = (atoi(optstate->value) > 0) ? atoi(optstate->value) : DEFAULT_THREADS;	    break;	}    }    if (optstatus == PL_OPT_BAD)	Usage(progName);    if ((doPriv && doPub) || (nickname == NULL)) Usage(progName);    if (!doPriv && !doPub) doPriv = PR_TRUE;    if (doIters && doTime) Usage(progName);    if (!doTime) {        doIters = PR_TRUE;    }    PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);    secDir = SECU_ConfigDirectory(secDir);    if (strcmp(nickname, "none")) {	rv = NSS_Init(secDir);	if (rv != SECSuccess) {	    fprintf(stderr, "NSS_Init failed.\n");	    exit(1);	}	certdb = CERT_GetDefaultCertDB();    } else {	rv = NSS_NoDB_Init(secDir);	if (rv != SECSuccess) {	    fprintf(stderr, "NSS_NoDB_Init failed.\n");	    exit(1);	}    }#if defined(SECU_GetPassword)    if (doPub) {	if (!strcmp(nickname, "none")) {	    pubKey = getDefaultRSAPublicKey();	} else {	    cert = CERT_FindCertByNickname(certdb, nickname);	    if (cert == NULL) {		fprintf(stderr,			"Can't find certificate by name \"%s\"\n", nickname);		exit(1);	    }	    pubHighKey = CERT_ExtractPublicKey(cert);	    pubKey = SECU_ConvHighToLow(pubHighKey);	}	if (pubKey == NULL) {	    fprintf(stderr, "Can't extract public key from certificate");	    exit(1);	}	fn = (RSAOp)RSA_PublicKeyOp;	rsaKey = (void *)(&pubKey->u.rsa);    }    if (doPriv) {	if (!strcmp(nickname, "none")) {	    privKey = getDefaultRSAPrivateKey();	} else {	    cert = CERT_FindCertByNickname(certdb, nickname);	    if (cert == NULL) {		fprintf(stderr,			"Can't find certificate by name \"%s\"\n", nickname);		exit(1);	    }	    privKey = SECKEY_FindKeyByCert(keydb, cert, SECU_GetPassword, NULL);	}	if (privKey == NULL) {	    fprintf(stderr,		    "Can't find private key by name \"%s\"\n", nickname);	    exit(1);	}	fn = (RSAOp)RSA_PrivateKeyOp;	rsaKey = (void *)(&privKey->u.rsa);    }#else    if (doPub) {	pubKey = getDefaultRSAPublicKey();	fn = (RSAOp)RSA_PublicKeyOp;	rsaKey = (void *)(&pubKey->u.rsa);    }    if (doPriv) {	privKey = getDefaultRSAPrivateKey();	fn = (RSAOp)RSA_PrivateKeyOp;	rsaKey = (void *)(&privKey->u.rsa);    }#endif    memset(buf, 1, sizeof buf);    rv = fn(rsaKey, buf2, buf);    if (rv != SECSuccess) {	PRErrorCode errNum;	const char * errStr = NULL;	errNum = PORT_GetError();	if (errNum)	    errStr = SECU_Strerror(errNum);	else	    errNum = rv;	if (!errStr)	    errStr = "(null)";	fprintf(stderr, "Error in RSA operation: %d : %s\n", errNum, errStr);	exit(1);    }/*  printf("START\n");	*/    threadsArr = (PRThread**)PORT_Alloc(threadNum*sizeof(PRThread*));    runDataArr = (ThreadRunData**)PORT_Alloc(threadNum*sizeof(ThreadRunData*));    for (i = 0;i < threadNum;i++) {        runDataArr[i] = (ThreadRunData*)PORT_Alloc(sizeof(ThreadRunData));        runDataArr[i]->fn = fn;        runDataArr[i]->buf = buf;        runDataArr[i]->doIters = &doIters;        runDataArr[i]->rsaKey = rsaKey;        runDataArr[i]->seconds = seconds;        runDataArr[i]->iters = iters;        threadsArr[i] =             PR_CreateThread(PR_USER_THREAD,                 ThreadExecFunction,                 (void*) runDataArr[i],                 PR_PRIORITY_NORMAL,                 PR_GLOBAL_THREAD,                 PR_JOINABLE_THREAD,                 0);    }    iters = 0;    calcThreads = 0;    stopTimeAcc = startTimeAcc = 0;    for (i = 0;i < threadNum;i++, calcThreads++)    {        PR_JoinThread(threadsArr[i]);        if (runDataArr[i]->status != SECSuccess) {            const char * errStr = SECU_Strerror(runDataArr[i]->errNum);            fprintf(stderr, "Thread %d: Error in RSA operation: %d : %s\n",                     i, runDataArr[i]->errNum, errStr);            calcThreads -= 1;        } else {            startTimeAcc += runDataArr[i]->tstart;            stopTimeAcc  += runDataArr[i]->tstop;            iters += runDataArr[i]->iterRes;        }        PORT_Free((void*)runDataArr[i]);    }    PORT_Free(runDataArr);    PORT_Free(threadsArr);        LL_DIV(startTimeAcc, startTimeAcc, (PRInt64)calcThreads);    LL_DIV(stopTimeAcc, stopTimeAcc, (PRInt64)calcThreads);    timeCtx = CreateTimingContext();    TimingBegin(timeCtx, startTimeAcc);    TimingEnd(timeCtx, stopTimeAcc);        printf("%ld iterations in %s\n",	   iters, TimingGenerateString(timeCtx));    printf("%.2f operations/s .\n", ((double)(iters)*(double)1000000.0) / (double)timeCtx->interval );    TimingDivide(timeCtx, iters);    printf("one operation every %s\n", TimingGenerateString(timeCtx));    if (NSS_Shutdown() != SECSuccess) {        exit(1);    }    return 0;}