/* TODO : this function hasn't really been tested */ int readerGetContactlessStatus( tReaderManager *pManager, tReader *pReader ) { DWORD dwRecvLength; BYTE pbRecvBuffer[20]; LONG rv; int i; BOOL automatic; /* Duh. If you pass me a NULL pointer then I'm out of here */ if ( ( pManager == NULL ) || ( pManager->hContext == NULL ) ) return( SCARD_E_INVALID_PARAMETER ); automatic = readersSettingBitmapBitTest( pManager, READER_BIT_AUTO ); if ( automatic ) { /* re-enumerate the readers in the system as it may have changed */ rv = readersConnect( pManager ); if ( rv != SCARD_S_SUCCESS ) return( rv ); } sprintf(messageString, "Requesting contactles status"); readersLogMessage( pManager, LOG_INFO, 2, messageString); /* then check all readers we were ABLE to connect to */ for ( i = 0; i < pManager->nbReaders; i++ ) { /* check we have connected and have a driver for this reader */ if ( ( pReader[i].hCard != NULL ) && ( pReader[i].pDriver != NULL ) && ( automatic || readersSettingBitmapNumberTest( pManager, i ) ) ) { dwRecvLength = sizeof(pbRecvBuffer); rv = ((tReaderDriver *)(pReader[i].pDriver))->getContactlessStatus(pReader, pbRecvBuffer, &dwRecvLength); if ( rv == SCARD_S_SUCCESS ) { if (pManager->libVerbosityLevel) { sprintf(messageString, "Reader %d Status: ", i); sPrintBufferHex( (messageString + strlen("Reader %d Status: ") ), dwRecvLength, pbRecvBuffer); readersLogMessage( pManager, LOG_INFO, 2, messageString); sprintf(messageString, "Number of Tags = %d", pbRecvBuffer[4]); readersLogMessage( pManager, LOG_INFO, 2, messageString); } } else PCSC_ERROR( pManager, rv, "driver->getConnectlessStatus:"); } } return (rv); }
/************************* READER MANAGER DISCONNECT ***********/ int readersManagerDisconnect( tReaderManager *pManager ) { LONG rv; if ( pManager == NULL ) return( SCARD_E_INVALID_PARAMETER ); if ( pManager->hContext ) { readersLogMessage( pManager, LOG_INFO, 2, "Disconnecting from pcscd server"); rv = SCardReleaseContext( (SCARDCONTEXT) (pManager->hContext) ); if ( rv != SCARD_S_SUCCESS ) PCSC_ERROR( pManager, rv, "SCardReleaseContext"); /* libreate memory that was allocated when we connected to manager */ if (pManager->mszReaders) { free(pManager->mszReaders); pManager->mszReaders = NULL; } } else rv = SCARD_E_INVALID_PARAMETER; /* now it should be NULL either way */ pManager->hContext = NULL; eventDispatch( PCSCD_DISCONNECT, NULL, 0, pManager ); return( rv ); }
/************************ STOP DAEMON **************/ void stopDaemon( const tReaderManager *pManager ){ char messageString[MAX_LOG_MESSAGE]; char pidString[20]; int pid; /* open lock file to get PID */ sprintf(lockFilename, "%s/%s.lock", DEFAULT_LOCK_FILE_DIR, DAEMON_NAME); lockFile = open( lockFilename, O_RDONLY, 0 ); if (lockFile == -1) { sprintf(messageString, "Could not open lock file %s, exiting", lockFilename); readersLogMessage( pManager, LOG_ERR, 0, messageString); sprintf(messageString, "Check you have the necessary permission for it"); readersLogMessage( pManager, LOG_ERR, 0, messageString); exit( EXIT_FAILURE ); } /* get the running PID in the lockfile */ if (read(lockFile, pidString, 19) == -1) { sprintf(messageString, "Could not read PID from lock file %s, exiting", lockFilename); readersLogMessage( pManager, LOG_ERR, 0, messageString); exit( EXIT_FAILURE ); } close( lockFile ); if (sscanf( pidString, "%d\n", &pid ) != 1) { sprintf(messageString, "Could not read PID from lock file %s, exiting", lockFilename); readersLogMessage( pManager, LOG_ERR, 0, messageString); exit( EXIT_FAILURE ); } sprintf(messageString, "Stopping daemon with PID = %d", pid ); readersLogMessage( pManager, LOG_INFO, 1, messageString); /* might need to be root for this to work ? - try and kill nicely*/ kill (pid, SIGTERM); /* TODO else, use a bit more brute force */ /* check if running? */ /* remove the lock file myself if I can ! */ sleep(1); remove( lockFilename ); }
void daemonTerminate( const tReaderManager *pManager ){ if ( runningAsDaemon ) { readersLogMessage( pManager, LOG_INFO, 1, "Closing and removing lockfile, closing log. Bye."); close( lockFile ); remove( lockFilename ); } }
/* make sure we are the only running copy for this reader number */ static void getLockOrDie( const tReaderManager *pManager ){ char pidString[20]; char messageString[MAX_LOG_MESSAGE]; struct flock lock; sprintf(lockFilename, "%s/%s.lock", DEFAULT_LOCK_FILE_DIR, DAEMON_NAME ); lockFile = open( lockFilename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); if ( lockFile == -1 ) { sprintf(messageString, "Could not open lock file %s, check permissions or run as root, exiting", lockFilename); readersLogMessage( pManager, LOG_ERR, 0, messageString); exit( EXIT_FAILURE ); } /* Initialize the flock structure. */ memset (&lock, 0, sizeof(lock)); lock.l_type = F_WRLCK; /* try and get the lock file, non-blocking */ if ( fcntl(lockFile, F_SETLK, &lock) == -1 ) { sprintf(messageString, "Could not lock file %s", lockFilename); readersLogMessage( pManager, LOG_ERR, 0, messageString); sprintf(messageString, "Probably indicates a previous copy is still running or crashed"); readersLogMessage( pManager, LOG_ERR, 0, messageString); sprintf(messageString, "Find PID using \"cat %s\" or \"ps -ef | grep %s\". Exiting.", lockFilename, DAEMON_NAME); readersLogMessage( pManager, LOG_ERR, 0, messageString); exit( EXIT_FAILURE ); } /* store the running PID in the lockfile */ sprintf( pidString, "%d\n", getpid()); if (write(lockFile, pidString, strlen(pidString)) != strlen(pidString) ) { sprintf(messageString, "Could not write PID to lock file %s", lockFilename); readersLogMessage( pManager, LOG_ERR, 0, messageString); exit( EXIT_FAILURE ); } }
/************************ READER DISCONNECT ********************/ void readersDisconnect( tReaderManager *pManager ) { LONG rv; int i; /* Duh. If you pass me a NULL pointer then I'm out of here */ if ( ( pManager == NULL ) || ( pManager->hContext == NULL ) ) return; if ( readersSettingBitmapBitTest( pManager, READER_BIT_AUTO ) ) { /* re-enumerate the readers in the system as it may have changed */ rv = readersEnumerate( pManager ); if ( rv != SCARD_S_SUCCESS ) return; } /* then check all readers we were ABLE to connect to */ for ( i = 0; i < pManager->nbReaders; i++ ) { if ( pManager->readers[i].hCard != NULL ) { sprintf(messageString, "Disconnecting from reader %d", i ); readersLogMessage( pManager, LOG_INFO, 2, messageString); rv = SCardDisconnect( (SCARDHANDLE) (pManager->readers[i].hCard), SCARD_UNPOWER_CARD); RESET_READER( pManager->readers[i] ); eventDispatch( READER_DISCONNECT, NULL, i, pManager ); if ( rv != SCARD_S_SUCCESS ) PCSC_ERROR( pManager, rv, "SCardDisconnect"); } } }
/* function allocates the memory for the list you must handle it!*/ int readersGetTagList( tReaderManager *pManager ) { LONG rv = SCARD_S_SUCCESS; tTag *pTags[MAX_NUM_READERS]; /* an array of pointers to tags (that act like arrays) ! */ int i, j; int uniqueListIndex; BOOL automatic; char *namePointer; /* Duh. If you pass me a NULL pointer then I'm out of here */ if ( ( pManager == NULL ) || ( pManager->hContext == NULL ) ) return( SCARD_E_INVALID_PARAMETER ); automatic = readersSettingBitmapBitTest( pManager, READER_BIT_AUTO ); if ( automatic ) { /* re-connect the readers in the system as it may have changed */ rv = readersConnect( pManager ); if ( rv != SCARD_S_SUCCESS ) return( rv ); } /* before we start, reset the total count to 0 */ pManager->tagList.numTags = 0; /* for all readers we were connected to PREVIOUSLY or are now after AUTMATIC reconnect */ for ( i = 0; i < pManager->nbReaders; i++ ) { /* make sure it's initialized, as depending on reader settings we may skip over */ /* one of these pointers in the array and later try to free an invalid pointer */ pTags[i] = NULL; pManager->readers[i].tagList.numTags = 0; /* check we are connected, have a driver and should be reading it */ if ( ( pManager->readers[i].hCard != NULL ) && ( pManager->readers[i].pDriver != NULL ) && ( automatic || readersSettingBitmapNumberTest( pManager, i ) ) ) { /* I'd normally check if a tag is present using readerGetContactlessStatus() before */ /* querying the tag list, but all my testing to date has failed to get the contactless */ /* status APDU to work, it always returns D5 05 00 00 00 80 90 00 to indicate no tag */ /* is present. I have reported this issue to ACS by e-mail - Andrew */ /* allocate the structure for this reader to read tag list into upto max size */ pTags[i] = (tTag *)malloc( ( ((tReaderDriver *)(pManager->readers[i].pDriver))->maxTags ) * sizeof(tTag) ); /* call the reader's associated driver's function to read the tag list */ rv = ((tReaderDriver *)(pManager->readers[i].pDriver))->getTagList( &(pManager->readers[i]), pTags[i] ); if ( rv != SCARD_S_SUCCESS ) { PCSC_ERROR( pManager, rv, "driver->getTagList():"); RESET_READER( pManager->readers[i] ); if ( pTags[i] != NULL ) free( pTags[i] ); pTags[i] = NULL; } /* accumulate the total number of tags found */ pManager->tagList.numTags += pManager->readers[i].tagList.numTags; } } /* now mash them all up into one big list */ pManager->tagList.pTags = NULL; /* for the zero tag case */ uniqueListIndex = 0; if ( pManager->tagList.numTags > 0 ) { pManager->tagList.pTags = (tTag *)malloc( (pManager->tagList.numTags) * sizeof( tTag ) ); /* copy all the individual lists across into the unique list */ for( i = 0; i < pManager->nbReaders; i++) { /* make the pointer in the per-reader structure point to it's parts of the overall list */ pManager->readers[i].tagList.pTags = &(pManager->tagList.pTags[uniqueListIndex]); /* for each of the tags detected in this reader */ for ( j = 0; j < pManager->readers[i].tagList.numTags; j++ ) { /* copy the tag from the tempory list to the unique one */ pManager->tagList.pTags[uniqueListIndex] = (pTags[i])[j]; TAG_TYPE_NAME_FROM_ENUM( pManager->tagList.pTags[uniqueListIndex].tagType, namePointer ); sprintf(messageString, "Tag ID: %s\tType: %s", pManager->tagList.pTags[uniqueListIndex].uid, namePointer); readersLogMessage( pManager, LOG_INFO, 2, messageString); uniqueListIndex++; } /* free the space allocated for that list, even if it was never filled with anything */ if ( pTags[i] ) free( pTags[i] ); } } sprintf( messageString, "Total Number of tags: %d", (int)(pManager->tagList.numTags) ); readersLogMessage( pManager, LOG_INFO, 2, messageString ); return (rv); }
/************************* READER CONNECT **********************/ int readersConnect ( tReaderManager *pManager ) { LONG rv; BOOL readerSupported; DWORD dwActiveProtocol; int i, num; BOOL automatic; /* Duh. If you pass me a NULL pointer then I'm out of here */ if ( pManager == NULL ) return( SCARD_E_INVALID_PARAMETER ); automatic = ( readersSettingBitmapBitTest( pManager, READER_BIT_AUTO ) != 0 ); if ( automatic ) { /* re-enumerate the readers in the system as it may have changed */ rv = readersEnumerate( pManager ); if ( rv != SCARD_S_SUCCESS ) return( rv ); } if ( pManager->nbReaders == 0 ) return( SCARD_E_NO_READERS_AVAILABLE ); /* try and connect to all readers that are present according to readerSetting */ for ( num = 0; num < pManager->nbReaders; num++ ) { /* if we are not already connected and should be trying then do so */ if ( ( pManager->readers[num].hCard == NULL) && ( automatic || readersSettingBitmapNumberTest( pManager, num ) ) ) { dwActiveProtocol = -1; rv = SCardConnect( (SCARDCONTEXT)(pManager->hContext), pManager->readers[num].name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 , (LPSCARDHANDLE) &(pManager->readers[num].hCard), &dwActiveProtocol); if (rv == SCARD_S_SUCCESS) { eventDispatch( READER_DETECTED, NULL, num, pManager ); /* Query the drivers in the list until one of them can handle the reader */ i = 0; readerSupported = FALSE; /* call the function to check if this driver works with this reader */ while ( (readerDriverTable[i] != NULL) && (readerSupported == FALSE) ) rv = readerDriverTable[i++]->readerCheck( &(pManager->readers[num]), &readerSupported ); if ( rv != SCARD_S_SUCCESS ) { RESET_READER( pManager->readers[num] ); PCSC_ERROR( pManager, rv, "readerCheck:" ); return( rv ); } /* we couldn't find a driver that knows how to handle this reader... */ if ( ( readerSupported == FALSE) ) { pManager->readers[num].pDriver = NULL; sprintf(messageString, "Reader (%s) not supported by any known driver", pManager->readers[num].name ); readersLogMessage( pManager, LOG_ERR, 0, messageString); return (SCARD_E_UNKNOWN_READER); } else { /* if we got this far then a driver was successfully found, remember it! */ pManager->readers[num].pDriver = readerDriverTable[i -1]; pManager->readers[num].driverDescriptor = readerDriverTable[i -1]->driverDescriptor; eventDispatch( READER_DETECTED, NULL, num, pManager ); } } else RESET_READER( pManager->readers[num] ); } } return ( SCARD_S_SUCCESS ); }
/*************************** READERS ENUMERATE *****************/ static int readersEnumerate( tReaderManager *pManager ) { LONG rv; DWORD dwReaders; char *ptr; int i, previousNumReaders; /* remember how many readers there used to be */ previousNumReaders = pManager->nbReaders; /* Call with a null buffer to get the number of bytes to allocate */ rv = SCardListReaders( (SCARDCONTEXT)(pManager->hContext), NULL, NULL, &dwReaders); if ( rv != SCARD_S_SUCCESS ) { /* if there are no readers, then zero everything out but don't report an error */ if ( rv == SCARD_E_NO_READERS_AVAILABLE ) { pManager->nbReaders = 0; if ( pManager->mszReaders ) free( pManager->mszReaders ); pManager->mszReaders = NULL; readersLogMessage( pManager, LOG_INFO, 2, "Found 0 Readers" ); } else PCSC_ERROR( pManager, rv, "SCardListReaders"); return ( rv ); } /* if array already exists, then liberate it and alloc a new one for the */ /* number of readers reported from SCardListReader */ if ( pManager->mszReaders ) free( pManager->mszReaders ); /* malloc enough memory for dwReader string */ pManager->mszReaders = malloc(sizeof(char)*dwReaders); /* now get the list into the mszReaders array */ rv = SCardListReaders( (SCARDCONTEXT)(pManager->hContext), NULL, pManager->mszReaders, &dwReaders); if (rv != SCARD_S_SUCCESS) { /* Avoid reporting an error just because no reader is connected */ if ( rv != SCARD_E_NO_READERS_AVAILABLE ) PCSC_ERROR( pManager, rv, "SCardListReaders"); return (rv); } /* Extract readers from the null separated string and get the total * number of readers */ pManager->nbReaders = 0; ptr = pManager->mszReaders; while (*ptr != '\0') { ptr += strlen(ptr)+1; (pManager->nbReaders)++; } sprintf(messageString, "Found %d Readers", pManager->nbReaders); readersLogMessage( pManager, LOG_INFO, 2, messageString); /* fill the array of readers with pointers to the appropriate point */ /* in the long mszReaders multi-string */ pManager->nbReaders = 0; ptr = pManager->mszReaders; while (*ptr != '\0') { sprintf(messageString, "Reader [%d]: %s", pManager->nbReaders, ptr); readersLogMessage( pManager, LOG_INFO, 3, messageString); pManager->readers[pManager->nbReaders].name = ptr; ptr += strlen(ptr)+1; (pManager->nbReaders)++; } /* if we have fewer readers than we used to then zero out the "lost ones" */ if ( pManager->nbReaders < previousNumReaders ) for ( i = pManager->nbReaders; i < previousNumReaders; i++ ) RESET_READER( pManager->readers[i] ); return( SCARD_S_SUCCESS ); }
/************************ READER CHECK ***************************/ LONG acr122UReaderCheck( tReader *pReader, BOOL *pReaderSupported ) { static char pbReader[MAX_READERNAME] = ""; DWORD dwAtrLen, dwReaderLen, dwState, dwProt; DWORD dwRecvLength; BYTE pbAtr[MAX_ATR_SIZE] = ""; int i; LONG rv; BYTE pbRecvBuffer[MAX_FIRMWARE_STRING_LENGTH]; *pReaderSupported = FALSE; /* First check the name reported by pcscd to see if it's possible supported */ for (i = 0; (i < SUPPORTED_READER_NAME_ARRAY_COUNT) & (*pReaderSupported == FALSE) ; i++) { if ( strncmp( pReader->name, SUPPORTED_READER_NAME_ARRAY[i], sizeof(SUPPORTED_READER_NAME_ARRAY[i])-1) == 0 ) *pReaderSupported = TRUE; } /* If even the name is not supported, then we're done */ if ( *pReaderSupported == FALSE ) return (SCARD_S_SUCCESS ); /* just because the name was OK, doesn't mean it'll actually work! */ *pReaderSupported = FALSE; /* Get firmware version and check it's really a ACR122* */ dwRecvLength = sizeof(pbRecvBuffer); rv = apduSend(pReader->hCard, APDU_GET_READER_FIRMWARE, sizeof(APDU_GET_READER_FIRMWARE), pbRecvBuffer, &dwRecvLength); if (rv != SCARD_S_SUCCESS) return (rv); /* Search the list of supported firmware versions (reader versions) */ /* to check we are compatible with it - or have tested with it */ /* NULL terminate the BYTE array for subsequent string compares */ pbRecvBuffer[dwRecvLength] = '\0'; for (i = 0; (i < SUPPORTED_READER_FIRMWARE_ARRAY_COUNT) & (*pReaderSupported == FALSE) ; i++) { if ( strncmp( ((char *)pbRecvBuffer), SUPPORTED_READER_FIRMWARE_ARRAY[i], sizeof(SUPPORTED_READER_FIRMWARE_ARRAY[i])-1) == 0 ) *pReaderSupported = TRUE; } /* if we didn't find that we support it, then we're done */ if ( *pReaderSupported == FALSE ) return( SCARD_S_SUCCESS ); /* no actual communication errors to report */ /* If we got this far then the general name and specific firmware version is supported */ /* Get ATR so we can tell if there is a SAM in the reader */ dwAtrLen = sizeof(pbAtr); dwReaderLen = sizeof(pbReader); SCardStatus( (SCARDHANDLE) (pReader->hCard), pbReader, &dwReaderLen, &dwState, &dwProt, pbAtr, &dwAtrLen); dwRecvLength = sizeof(pbRecvBuffer); rv = apduSend(pReader->hCard, APDU_SET_RETRY, sizeof(APDU_SET_RETRY), pbRecvBuffer, &dwRecvLength); if (rv != SCARD_S_SUCCESS) return (rv); /* get card status ATR first two bytes = ACS_NO_SAM= '3B00' */ if ( (pbAtr[SW1] != 0x3B) || (pbAtr[SW2] != 0x00) ) { dwRecvLength = sizeof(pbRecvBuffer); rv = apduSend(pReader->hCard, APDU_GET_SAM_SERIAL, sizeof(APDU_GET_SAM_SERIAL), pbRecvBuffer, &dwRecvLength); if (rv == SCARD_S_SUCCESS) { sPrintBufferHex(pReader->SAM_serial, dwRecvLength, pbRecvBuffer); #if 0 sprintf(messageString, "SAM Serial: %s", pReader->SAM_serial); readersLogMessage(LOG_INFO, 1, messageString); #endif } else return (rv); dwRecvLength = sizeof(pbRecvBuffer); rv = apduSend(pReader->hCard, APDU_GET_SAM_ID, sizeof(APDU_GET_SAM_ID), pbRecvBuffer, &dwRecvLength); if (rv == SCARD_S_SUCCESS) { sPrintBufferHex(pReader->SAM_id, dwRecvLength, pbRecvBuffer); #if 0 sprintf(messageString, "SAM ID: %s", pReader->SAM_id); readersLogMessage(LOG_INFO, 1, messageString); #endif } else return( rv ); pReader->SAM = TRUE; } /* Turning RATS off thus a JCOP tag will be detected as emulating a DESFIRE */ apduSend(pReader->hCard, APDU_RATS_14443_4_OFF, sizeof(APDU_RATS_14443_4_OFF), pbRecvBuffer, &dwRecvLength); return( SCARD_S_SUCCESS ); }
/**************************** APDU SEND ************************/ static LONG apduSend ( tCardHandle hCard, const BYTE *apdu, DWORD apduLength, BYTE *pbRecvBuffer, DWORD *dwRecvLength ) { LONG rv; SCARD_IO_REQUEST pioRecvPci; BYTE pbSendBuffer[40]; DWORD dwSendLength = 0; DWORD rBufferMax; BOOL psuedoAPDU = FALSE; /* remember the size of the input buffer passed to us, so we don't exceed */ rBufferMax = *dwRecvLength; /* The special psuedo APDU's to talk to a tag, need to have their */ /* response read back in two chunks, using GET_RESPONSE for the second */ if (apdu[0] == 0xd4) { psuedoAPDU = TRUE; /* prepend the DIRECT_TRANSMIT APDU */ memcpy(pbSendBuffer, APDU_DIRECT_TRANSMIT, sizeof(APDU_DIRECT_TRANSMIT)); /* then a byte that tells it the length of the psuedo APDU to follow */ pbSendBuffer[sizeof(APDU_DIRECT_TRANSMIT)] = (BYTE)apduLength; dwSendLength += (sizeof(APDU_DIRECT_TRANSMIT) + 1); } /* Add the APDU that was requested to be sent and increase length to send */ memcpy((pbSendBuffer + dwSendLength), apdu, apduLength); dwSendLength += apduLength; #if 0 sprintf(messageString, "APDU: "); sPrintBufferHex((messageString + strlen("APDU: ")), dwSendLength, pbSendBuffer); readersLogMessage( pManager, LOG_INFO, 3, messageString); #endif rv = SCardTransmit((SCARDHANDLE) hCard, pioSendPci, pbSendBuffer, dwSendLength, &pioRecvPci, pbRecvBuffer, dwRecvLength); /* if it was a psuedo APDU then we need to get the response */ if ( (rv == SCARD_S_SUCCESS) && psuedoAPDU ) { #if 0 sprintf(messageString, "Received: "); sPrintBufferHex((messageString + strlen("Received: ")), *dwRecvLength, pbRecvBuffer); readersLogMessage(LOG_INFO, 3, messageString); #endif /* command went OK? */ if (pbRecvBuffer[SW1] != SW1_SUCCESS) { #if 0 sprintf(messageString, "APDU failed: SW1 = %02X", pbRecvBuffer[SW1]); readersLogMessage(LOG_ERR, 0, messageString); #endif return ( SCARD_F_COMM_ERROR ); } /* are their response bytes to get? */ if (pbRecvBuffer[SW2] > 0) { #if 0 sprintf(messageString, "Requesting Response Data (%d)", pbRecvBuffer[SW2]); readersLogMessage(LOG_INFO, 3, messageString); #endif /* copy the get_response APDU into the first bytes */ memcpy(pbSendBuffer, APDU_GET_RESPONSE, sizeof(APDU_GET_RESPONSE)); /* the second response byte tells us how many bytes are pending */ /* add that value at the end of the GET_RESPONSE APDU */ pbSendBuffer[sizeof(APDU_GET_RESPONSE)] = pbRecvBuffer[SW2]; dwSendLength = sizeof(APDU_GET_RESPONSE) + 1; /* specify the maximum size of the buffer that was passed in */ *dwRecvLength = rBufferMax; rv = SCardTransmit((SCARDCONTEXT)hCard, pioSendPci, pbSendBuffer, dwSendLength, &pioRecvPci, pbRecvBuffer, dwRecvLength ); #if 0 PCSC_ERROR(rv, "SCardTransmit"); sprintf(messageString, "Received: "); sPrintBufferHex(messageString, rBufferMax, pbRecvBuffer); readersLogMessage(LOG_INFO, 3, messageString); #endif } else *dwRecvLength = 0; } return(rv); }
/************************ DAEMONIZE *************************/ void daemonize( tReaderManager *pManager ){ int pid; char messageString[MAX_LOG_MESSAGE]; /* fork a copy of myself */ pid = fork(); if ( pid < 0 ) { /* fork error */ sprintf(messageString, "Error forking daemon %s, exiting", DAEMON_NAME); readersLogMessage( pManager, LOG_ERR, 0, messageString); exit( EXIT_FAILURE ); } if ( pid > 0 ) { /* fork worked, this is the parent process so exit */ sprintf(messageString, "Started daemon %s with PID=%d, see /var/log/syslog", DAEMON_NAME, pid ); readersLogMessage( pManager, LOG_INFO, 1, messageString); exit( EXIT_FAILURE ); } /* from here on I must be a successfully forked child */ runningAsDaemon = TRUE; /* tell the library we are now going to be calling it from a daemon */ readersSetOptions( pManager, IGNORE_OPTION, runningAsDaemon ); /* set umask for creating files */ umask(0); /* start logging --> /var/log/syslog on my system */ openlog(DAEMON_NAME, LOG_PID, LOG_DAEMON); /* get a new process group for daemon */ if ( setsid() < 0 ) { sprintf(messageString, "Error creating new SID for daemon process %s with PID=%d, see in /var/log/syslog", DAEMON_NAME, pid ); readersLogMessage( pManager, LOG_ERR, 0, messageString); exit( EXIT_FAILURE ); } /* change working directory to / */ if ( (chdir("/")) < 0 ) exit( EXIT_FAILURE ); /* These following lines to close open filedescriptors are recommended for daemons, but it */ /* seems to cause problems for executing some xternal scripts with system() so they are avoided */ #if 0 /* close unneeded descriptions in the deamon child process */ for (i = getdtablesize(); i >= 0; i--) close( i ); /* close stdio */ close ( STDIN_FILENO ); close ( STDOUT_FILENO ); close ( STDERR_FILENO ); #endif /* make sure Iḿ the only one reading from this reader */ getLockOrDie( pManager ); /* ignore TTY related signales */ signal( SIGTSTP, SIG_IGN ); signal( SIGTTOU, SIG_IGN ); signal( SIGTTIN, SIG_IGN ); sprintf(messageString, "Daemon Started" ); readersLogMessage( pManager, LOG_INFO, 1, messageString); }