summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRüdiger Timm <rt@openoffice.org>2004-07-23 09:08:56 +0000
committerRüdiger Timm <rt@openoffice.org>2004-07-23 09:08:56 +0000
commit7d6c646ec244f9ea1db9b5bd160ecfc43ac27f13 (patch)
treee9378bc7e090ef2ddef558de4139e52885499afb
parent45551df64a4072446dd8686c172f104f0cd64f4b (diff)
INTEGRATION: CWS vcl24 (1.3.14); FILE MERGED
2004/07/12 16:03:43 pl 1.3.14.3: fix a crash 2004/07/08 15:50:51 pl 1.3.14.2: #i28763# workaround possibly hanging CUPS calls 2004/06/30 17:35:57 pl 1.3.14.1: #i30914# #i30917# handle queue instances correctly
-rw-r--r--psprint/source/printer/cupsmgr.cxx393
1 files changed, 264 insertions, 129 deletions
diff --git a/psprint/source/printer/cupsmgr.cxx b/psprint/source/printer/cupsmgr.cxx
index 191ed8ca8336..145ba7313ba4 100644
--- a/psprint/source/printer/cupsmgr.cxx
+++ b/psprint/source/printer/cupsmgr.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: cupsmgr.cxx,v $
*
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
*
- * last change: $Author: kz $ $Date: 2004-05-18 10:46:09 $
+ * last change: $Author: rt $ $Date: 2004-07-23 10:08:56 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -70,6 +70,8 @@ typedef void cups_option_t;
#include <osl/thread.h>
#include <osl/diagnose.h>
+#include <osl/conditn.hxx>
+#include <rtl/ustrbuf.hxx>
#include <cupsmgr.hxx>
namespace psp
@@ -77,20 +79,21 @@ namespace psp
class CUPSWrapper
{
oslModule m_pLib;
+ osl::Mutex m_aGetPPDMutex;
int (*m_pcupsPrintFile)(const char*, const char*, const char*, int, cups_option_t*);
int (*m_pcupsGetDests)(cups_dest_t**);
void (*m_pcupsSetDests)(int,cups_dest_t*);
void (*m_pcupsFreeDests)(int,cups_dest_t*);
- const char* (*m_pcupsGetPPD)(const char*);
+ const char* (*m_pcupsGetPPD)(const char*);
int (*m_pcupsMarkOptions)(ppd_file_t*,int,cups_option_t*);
int (*m_pcupsAddOption)(const char*,const char*,int,cups_option_t**);
void (*m_pcupsFreeOptions)(int,cups_option_t*);
ppd_file_t* (*m_pppdOpenFile)(const char* pFile);
void (*m_pppdClose)(ppd_file_t*);
- const char* (*m_pcupsServer)();
+ const char* (*m_pcupsServer)();
void (*m_pcupsSetPasswordCB)(const char*(cb)(const char*));
- const char* (*m_pcupsUser)();
+ const char* (*m_pcupsUser)();
void (*m_pcupsSetUser)(const char*);
void* loadSymbol( const char* );
@@ -116,8 +119,7 @@ public:
cups_option_t* pOptions )
{ return m_pcupsPrintFile( pPrinter, pFileName, pTitle, nOptions, pOptions ); }
- const char* cupsGetPPD( const char* pPrinter )
- { return m_pcupsGetPPD( pPrinter ); }
+ const char* cupsGetPPD( const char* pPrinter );
int cupsMarkOptions(ppd_file_t* pPPD, int nOptions, cups_option_t* pOptions )
{ return m_pcupsMarkOptions(pPPD, nOptions, pOptions); }
@@ -250,6 +252,70 @@ bool CUPSWrapper::isValid()
return m_pLib != NULL;
}
+static struct GetPPDAttribs
+{
+ const char* (*pFunction)(const char*);
+ osl::Condition m_aCondition;
+ const char* m_pParameter;
+ const char* m_pResult;
+ oslThread m_aThread;
+} *pAttribs = NULL;
+
+extern "C" {
+ static void getPPDWorker(void*)
+ {
+ pAttribs->m_pResult = pAttribs->pFunction( pAttribs->m_pParameter );
+ if( pAttribs->m_aCondition.check() )
+ {
+ // timed out, unlink file
+ if( pAttribs->m_pResult )
+ unlink( pAttribs->m_pResult );
+ delete pAttribs;
+ pAttribs = NULL;
+ }
+ else
+ pAttribs->m_aCondition.set();
+ }
+}
+
+const char* CUPSWrapper::cupsGetPPD( const char* pPrinter )
+{
+ const char* pResult = NULL;
+
+ // if one thread hangs in cupsGetPPD already, don't start another
+ if( ! pAttribs )
+ {
+ pAttribs = new GetPPDAttribs();
+ pAttribs->pFunction = m_pcupsGetPPD;
+ pAttribs->m_aCondition.reset();
+ pAttribs->m_pParameter = pPrinter;
+ pAttribs->m_pResult = NULL;
+ pAttribs->m_aThread = osl_createThread( getPPDWorker, NULL );
+
+ TimeValue aValue;
+ aValue.Seconds = 5;
+ aValue.Nanosec = 0;
+ if( pAttribs->m_aCondition.wait( &aValue ) == Condition::result_ok )
+ {
+ osl_destroyThread( pAttribs->m_aThread );
+ pResult = pAttribs->m_pResult;
+ delete pAttribs;
+ pAttribs = NULL;
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "cupsGetPPD %s timed out\n", pPrinter );
+#endif
+ // should the thread awake again notify it to clean up itself
+ pAttribs->m_aCondition.set();
+ osl_destroyThread( pAttribs->m_aThread );
+ }
+ }
+
+ return pResult;
+}
+
static const char* setPasswordCallback( const char* pIn )
{
const char* pRet = NULL;
@@ -275,66 +341,91 @@ CUPSManager* CUPSManager::tryLoadCUPS()
// try to load CUPS
CUPSWrapper* pWrapper = new CUPSWrapper();
if( pWrapper->isValid() )
- {
- // check if there are any dests; if not
- // CUPS is unconfigured (at least) and
- // should not be used
- cups_dest_t* pDests = NULL;
- int nDests = pWrapper->cupsGetDests( &pDests );
- if( nDests && pDests )
- pManager = new CUPSManager( pWrapper, nDests, pDests );
-#if OSL_DEBUG_LEVEL > 1
- else
- fprintf( stderr, "CUPS loaded but no dests -> CUPS disabled\n" );
-#endif
- }
- // something failed, don't use CUPS
- if( ! pManager )
+ pManager = new CUPSManager( pWrapper );
+ else
delete pWrapper;
}
#endif
return pManager;
}
-CUPSManager::CUPSManager( CUPSWrapper* pWrapper, int nDests, void* pDests ) :
+CUPSManager::CUPSManager( CUPSWrapper* pWrapper ) :
PrinterInfoManager( CUPS ),
m_pCUPSWrapper( pWrapper ),
- m_nDests( nDests ),
- m_pDests( pDests )
+ m_nDests( 0 ),
+ m_pDests( NULL ),
+ m_bNewDests( false )
{
- m_bFirstDest = (nDests && pDests);
+ m_aDestThread = osl_createThread( runDestThread, this );
}
CUPSManager::~CUPSManager()
{
+ if( m_aDestThread )
+ {
+ // if the thread is still running here, then
+ // cupsGetDests is hung; terminate the thread instead of joining
+ osl_terminateThread( m_aDestThread );
+ osl_destroyThread( m_aDestThread );
+ }
+
if( m_nDests && m_pDests )
m_pCUPSWrapper->cupsFreeDests( m_nDests, (cups_dest_t*)m_pDests );
delete m_pCUPSWrapper;
}
+void CUPSManager::runDestThread( void* pThis )
+{
+ ((CUPSManager*)pThis)->runDests();
+}
+
+void CUPSManager::runDests()
+{
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "starting cupsGetDests\n" );
+#endif
+ osl::MutexGuard aGuard( m_aCUPSMutex );
+
+ m_nDests = m_pCUPSWrapper->cupsGetDests( (cups_dest_t**)&m_pDests );
+ m_bNewDests = true;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "finished cupsGetDests\n" );
+#endif
+}
+
void CUPSManager::initialize()
{
+ // get normal printers, clear printer list
+ PrinterInfoManager::initialize();
+
#ifdef ENABLE_CUPS
- // there may have been a previous run
- if( m_nDests && m_pDests && !m_bFirstDest )
- m_pCUPSWrapper->cupsFreeDests( m_nDests, (cups_dest_t*)m_pDests );
- m_aPrinters.clear();
- m_aCUPSDestMap.clear();
+ // check whether thread has completed
+ // if not behave like old printing system
+ osl::MutexGuard aGuard( m_aCUPSMutex );
- // get normal printers
- PrinterInfoManager::initialize();
+ if( ! (m_nDests && m_pDests ) )
+ return;
- rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
- int nPrinter = 0;
+ // dest thread has run, clean up
+ if( m_aDestThread )
+ {
+ osl_joinWithThread( m_aDestThread );
+ osl_destroyThread( m_aDestThread );
+ m_aDestThread = NULL;
+ }
- // get CUPS dests if this is not the first run after the constructor
- // in which case m_pDests was already intialized
- if( m_bFirstDest && m_nDests && m_pDests )
- nPrinter = m_nDests;
- else
- m_nDests = nPrinter = m_pCUPSWrapper->cupsGetDests( (cups_dest_t**)&m_pDests );
+ // clear old stuff
+ m_aCUPSDestMap.clear();
+
+#if 0
+ // update dests
+ m_pCUPSWrapper->cupsFreeDests( m_nDests, (cups_dest_t*)m_pDests );
+ m_nDests = m_pCUPSWrapper->cupsGetDests( (cups_dest_t**)&m_pDests );
+#endif
+ m_bNewDests = false;
- m_bFirstDest = false;
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ int nPrinter = m_nDests;
// add CUPS printers, should there be a printer
// with the same name as a CUPS printer, overwrite it
@@ -342,18 +433,25 @@ void CUPSManager::initialize()
{
cups_dest_t* pDest = ((cups_dest_t*)m_pDests)+nPrinter;
OUString aPrinterName = OStringToOUString( pDest->name, aEncoding );
+ if( pDest->instance && *pDest->instance )
+ {
+ OUStringBuffer aBuf( 256 );
+ aBuf.append( aPrinterName );
+ aBuf.append( sal_Unicode( '/' ) );
+ aBuf.append( OStringToOUString( pDest->instance, aEncoding ) );
+ aPrinterName = aBuf.makeStringAndClear();
+ }
// initialize printer with possible configuration from psprint.conf
Printer aPrinter = m_aPrinters[ aPrinterName ];
aPrinter.m_aInfo.m_aPrinterName = aPrinterName;
- if( pDest->instance && *pDest->instance )
- aPrinter.m_aInfo.m_aLocation = OStringToOUString( pDest->instance, aEncoding );
if( pDest->is_default )
m_aDefaultPrinter = aPrinterName;
- OUString aPPD( RTL_CONSTASCII_USTRINGPARAM( "CUPS:" ) );
- aPPD = aPPD + aPrinterName;
+ OUStringBuffer aBuf( 256 );
+ aBuf.appendAscii( "CUPS:" );
+ aBuf.append( aPrinterName );
// note: the parser that goes with the PrinterInfo
// is created implicitly by the JobData::operator=()
// when it detects the NULL ptr m_pParser.
@@ -363,7 +461,7 @@ void CUPSManager::initialize()
// behaviour
aPrinter.m_aInfo.m_pParser = NULL;
aPrinter.m_aInfo.m_aContext.setParser( NULL );
- aPrinter.m_aInfo.m_aDriverName = aPPD;
+ aPrinter.m_aInfo.m_aDriverName = aBuf.makeStringAndClear();
aPrinter.m_bModified = false;
m_aPrinters[ aPrinter.m_aInfo.m_aPrinterName ] = aPrinter;
@@ -456,55 +554,60 @@ const PPDParser* CUPSManager::createCUPSParser( const OUString& rPrinter )
aPrinter = rPrinter;
#ifdef ENABLE_CUPS
- rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
- OString aPrinterName( OUStringToOString( aPrinter, aEncoding ) );
-
- const char* pPPDFile = m_pCUPSWrapper->cupsGetPPD( aPrinterName.getStr() );
-#if OSL_DEBUG_LEVEL > 1
- fprintf( stderr, "PPD for %s is %s\n", aPrinterName.getStr(), pPPDFile );
-#endif
- if( pPPDFile )
+ if( m_aCUPSMutex.tryToAcquire() && m_nDests && m_pDests )
{
- OUString aFileName( OStringToOUString( pPPDFile, aEncoding ) );
- // create the new parser
- pNewParser = new PPDParser( aFileName );
-
std::hash_map< OUString, int, OUStringHash >::iterator dest_it =
m_aCUPSDestMap.find( aPrinter );
-
if( dest_it != m_aCUPSDestMap.end() )
{
cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + dest_it->second;
- // update the printer info with context information
- ppd_file_t* pPPD = m_pCUPSWrapper->ppdOpenFile( pPPDFile );
- /*int nConflicts =*/ m_pCUPSWrapper->cupsMarkOptions( pPPD, pDest->num_options, pDest->options );
+ const char* pPPDFile = m_pCUPSWrapper->cupsGetPPD( pDest->name );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "PPD for %s is %s\n", OUStringToOString( aPrinter, osl_getThreadTextEncoding() ).getStr(), pPPDFile );
+#endif
+ if( pPPDFile )
+ {
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ OUString aFileName( OStringToOUString( pPPDFile, aEncoding ) );
+ // create the new parser
+ PPDParser* pCUPSParser = new PPDParser( aFileName );
+ pCUPSParser->m_aFile = rPrinter;
+ pNewParser = pCUPSParser;
+
+ // update the printer info with context information
+ ppd_file_t* pPPD = m_pCUPSWrapper->ppdOpenFile( pPPDFile );
+ /*int nConflicts =*/ m_pCUPSWrapper->cupsMarkOptions( pPPD, pDest->num_options, pDest->options );
#if OSL_DEBUG_LEVEL > 1
- fprintf( stderr, "processing the following options for printer %s (instance %s):\n",
- pDest->name, pDest->instance );
- for( int k = 0; k < pDest->num_options; k++ )
- fprintf( stderr, " \"%s\" = \"%s\"\n",
- pDest->options[k].name,
- pDest->options[k].value );
+ fprintf( stderr, "processing the following options for printer %s (instance %s):\n",
+ pDest->name, pDest->instance );
+ for( int k = 0; k < pDest->num_options; k++ )
+ fprintf( stderr, " \"%s\" = \"%s\"\n",
+ pDest->options[k].name,
+ pDest->options[k].value );
#endif
- PrinterInfo& rInfo = m_aPrinters[ aPrinter ].m_aInfo;
+ PrinterInfo& rInfo = m_aPrinters[ aPrinter ].m_aInfo;
- rInfo.m_pParser = pNewParser;
- rInfo.m_aContext.setParser( pNewParser );
- for( int i = 0; i < pPPD->num_groups; i++ )
- updatePrinterContextInfo( pPPD->groups + i, rInfo );
+ rInfo.m_pParser = pNewParser;
+ rInfo.m_aContext.setParser( pNewParser );
+ for( int i = 0; i < pPPD->num_groups; i++ )
+ updatePrinterContextInfo( pPPD->groups + i, rInfo );
- // clean up the mess
- m_pCUPSWrapper->ppdClose( pPPD );
- }
+ // clean up the mess
+ m_pCUPSWrapper->ppdClose( pPPD );
+
+ // remove temporary PPD file
+ unlink( pPPDFile );
+ }
#if OSL_DEBUG_LEVEL > 1
- else
- fprintf( stderr, "no dest found for printer %s\n", aPrinterName.getStr() );
+ else
+ fprintf( stderr, "no dest found for printer %s\n", OUStringToOString( aPrinter, osl_getThreadTextEncoding() ).getStr() );
#endif
- // remove temporary PPD file
- unlink( pPPDFile );
+ }
+ m_aCUPSMutex.release();
}
- else
#endif // ENABLE_CUPS
+
+ if( ! pNewParser )
{
// get the default PPD
pNewParser = PPDParser::getParser( String( RTL_CONSTASCII_USTRINGPARAM( "SGENPRT" ) ) );
@@ -577,20 +680,32 @@ int CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTit
fclose( pFile );
rtl_TextEncoding aEnc = osl_getThreadTextEncoding();
- nJobID = m_pCUPSWrapper->cupsPrintFile( OUStringToOString( rPrintername, aEnc ).getStr(),
- it->second.getStr(),
- OUStringToOString( rJobTitle, aEnc ).getStr(),
- 0, NULL );
+ osl::MutexGuard aGuard( m_aCUPSMutex );
+
+ std::hash_map< OUString, int, OUStringHash >::iterator dest_it =
+ m_aCUPSDestMap.find( rPrintername );
+ if( dest_it != m_aCUPSDestMap.end() )
+ {
+ cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + dest_it->second;
+ nJobID = m_pCUPSWrapper->cupsPrintFile( pDest->name,
+ it->second.getStr(),
+ OUStringToOString( rJobTitle, aEnc ).getStr(),
+ 0, NULL );
#if OSL_DEBUG_LEVEL > 1
- fprintf( stderr, "cupsPrintFile( %s, %s, %s, 0, 0 ) returns %d\n",
- OUStringToOString( rPrintername, aEnc ).getStr(),
- it->second.getStr(),
- OUStringToOString( rJobTitle, aEnc ).getStr(),
- nJobID );
- OString aCmd( "cp " );
- aCmd = aCmd + it->second;
- aCmd = aCmd + OString( " $HOME/cupsprint.ps" );
- system( aCmd.getStr() );
+ fprintf( stderr, "cupsPrintFile( %s, %s, %s, 0, 0 ) returns %d\n",
+ pDest->name,
+ it->second.getStr(),
+ OUStringToOString( rJobTitle, aEnc ).getStr(),
+ nJobID );
+ OString aCmd( "cp " );
+ aCmd = aCmd + it->second;
+ aCmd = aCmd + OString( " $HOME/cupsprint.ps" );
+ system( aCmd.getStr() );
+#endif
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ fprintf( stderr, "Error: no CUPS dest for %s found, discarding job\n", OUStringToOString( rPrintername, aEnc ).getStr() );
#endif
unlink( it->second.getStr() );
@@ -609,7 +724,18 @@ void CUPSManager::changePrinterInfo( const OUString& rPrinter, const PrinterInfo
bool CUPSManager::checkPrintersChanged()
{
- return PrinterInfoManager::checkPrintersChanged();
+ bool bChanged = false;
+ if( m_aCUPSMutex.tryToAcquire() )
+ {
+ bChanged = m_bNewDests;
+ m_aCUPSMutex.release();
+ initialize();
+ }
+
+ if( ! bChanged )
+ bChanged = PrinterInfoManager::checkPrintersChanged();
+
+ return bChanged;
}
bool CUPSManager::addPrinter( const OUString& rName, const OUString& rDriver )
@@ -632,23 +758,23 @@ bool CUPSManager::removePrinter( const OUString& rName, bool bCheck )
bool CUPSManager::setDefaultPrinter( const OUString& rName )
{
+ bool bSuccess = false;
#ifdef ENABLE_CUPS
std::hash_map< OUString, int, OUStringHash >::iterator nit =
m_aCUPSDestMap.find( rName );
- if( nit == m_aCUPSDestMap.end() )
- return false;
-
- cups_dest_t* pDests = (cups_dest_t*)m_pDests;
- for( int i = 0; i < m_nDests; i++ )
- pDests[i].is_default = 0;
- pDests[ nit->second ].is_default = 1;
- m_pCUPSWrapper->cupsSetDests( m_nDests, (cups_dest_t*)m_pDests );
- m_aDefaultPrinter = rName;
-
- return true;
-#else
- return false;
+ if( nit != m_aCUPSDestMap.end() && m_aCUPSMutex.tryToAcquire() )
+ {
+ cups_dest_t* pDests = (cups_dest_t*)m_pDests;
+ for( int i = 0; i < m_nDests; i++ )
+ pDests[i].is_default = 0;
+ pDests[ nit->second ].is_default = 1;
+ m_pCUPSWrapper->cupsSetDests( m_nDests, (cups_dest_t*)m_pDests );
+ m_aDefaultPrinter = rName;
+ m_aCUPSMutex.release();
+ bSuccess = true;
+ }
#endif
+ return bSuccess;
}
bool CUPSManager::writePrinterConfig()
@@ -668,32 +794,39 @@ bool CUPSManager::writePrinterConfig()
if( ! prt->second.m_bModified )
continue;
- bDestModified = true;
- cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + nit->second;
- PrinterInfo& rInfo = prt->second.m_aInfo;
-
- // create new option list
- int nNewOptions = 0;
- cups_option_t* pNewOptions = NULL;
- int nValues = rInfo.m_aContext.countValuesModified();
- for( int i = 0; i < nValues; i++ )
+ if( m_aCUPSMutex.tryToAcquire() )
{
- const PPDKey* pKey = rInfo.m_aContext.getModifiedKey( i );
- const PPDValue* pValue = rInfo.m_aContext.getValue( pKey );
- if( pKey && pValue ) // sanity check
+ bDestModified = true;
+ cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + nit->second;
+ PrinterInfo& rInfo = prt->second.m_aInfo;
+
+ // create new option list
+ int nNewOptions = 0;
+ cups_option_t* pNewOptions = NULL;
+ int nValues = rInfo.m_aContext.countValuesModified();
+ for( int i = 0; i < nValues; i++ )
{
- OString aName = OUStringToOString( pKey->getKey(), aEncoding );
- OString aValue = OUStringToOString( pValue->m_aOption, aEncoding );
- nNewOptions = m_pCUPSWrapper->cupsAddOption( aName.getStr(), aValue.getStr(), nNewOptions, &pNewOptions );
+ const PPDKey* pKey = rInfo.m_aContext.getModifiedKey( i );
+ const PPDValue* pValue = rInfo.m_aContext.getValue( pKey );
+ if( pKey && pValue ) // sanity check
+ {
+ OString aName = OUStringToOString( pKey->getKey(), aEncoding );
+ OString aValue = OUStringToOString( pValue->m_aOption, aEncoding );
+ nNewOptions = m_pCUPSWrapper->cupsAddOption( aName.getStr(), aValue.getStr(), nNewOptions, &pNewOptions );
+ }
}
+ // set PPD options on CUPS dest
+ m_pCUPSWrapper->cupsFreeOptions( pDest->num_options, pDest->options );
+ pDest->num_options = nNewOptions;
+ pDest->options = pNewOptions;
+ m_aCUPSMutex.release();
}
- // set PPD options on CUPS dest
- m_pCUPSWrapper->cupsFreeOptions( pDest->num_options, pDest->options );
- pDest->num_options = nNewOptions;
- pDest->options = pNewOptions;
}
- if( bDestModified )
+ if( bDestModified && m_aCUPSMutex.tryToAcquire() )
+ {
m_pCUPSWrapper->cupsSetDests( m_nDests, (cups_dest_t*)m_pDests );
+ m_aCUPSMutex.release();
+ }
#endif // ENABLE_CUPS
return PrinterInfoManager::writePrinterConfig();
@@ -715,6 +848,8 @@ const char* CUPSManager::authenticateUser( const char* pIn )
(bool(*)(const OString&,OString&,OString&))osl_getSymbol( pLib, aSym.pData );
if( getpw )
{
+ osl::MutexGuard aGuard( m_aCUPSMutex );
+
OString aUser = m_pCUPSWrapper->cupsUser();
OString aServer = m_pCUPSWrapper->cupsServer();
OString aPassword;