winscard_msg.c

Go to the documentation of this file.
00001 /*
00002  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
00003  *
00004  * Copyright (C) 2001-2004
00005  *  David Corcoran <corcoran@linuxnet.com>
00006  *  Damien Sauveron <damien.sauveron@labri.fr>
00007  *  Ludoic Rousseau <ludovic.rousseau@free.fr>
00008  *
00009  * $Id: winscard_msg.c 1827 2006-01-24 14:49:52Z rousseau $
00010  */
00011 
00021 #include "config.h"
00022 #include <fcntl.h>
00023 #include <unistd.h>
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <sys/socket.h>
00027 #include <sys/time.h>
00028 #include <sys/un.h>
00029 #include <sys/ioctl.h>
00030 #include <errno.h>
00031 #include <stdio.h>
00032 #include <time.h>
00033 #include <string.h>
00034 #ifdef HAVE_SYS_FILIO_H
00035 #include <sys/filio.h>
00036 #endif
00037 
00038 #include "misc.h"
00039 #include "pcsclite.h"
00040 #include "winscard.h"
00041 #include "debuglog.h"
00042 #include "winscard_msg.h"
00043 #include "sys_generic.h"
00044 
00056 INTERNAL int SHMClientRead(psharedSegmentMsg msgStruct, DWORD dwClientID, int blockamount)
00057 {
00058     return SHMMessageReceive(msgStruct, dwClientID, blockamount);
00059 }
00060 
00074 INTERNAL int SHMClientSetupSession(PDWORD pdwClientID)
00075 {
00076     struct sockaddr_un svc_addr;
00077     int one;
00078 
00079     if ((*pdwClientID = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
00080     {
00081         Log2(PCSC_LOG_CRITICAL, "Error: create on client socket: %s",
00082             strerror(errno));
00083         return -1;
00084     }
00085 
00086     svc_addr.sun_family = AF_UNIX;
00087     strncpy(svc_addr.sun_path, PCSCLITE_CSOCK_NAME,
00088         sizeof(svc_addr.sun_path));
00089 
00090     if (connect(*pdwClientID, (struct sockaddr *) &svc_addr,
00091             sizeof(svc_addr.sun_family) + strlen(svc_addr.sun_path) + 1) < 0)
00092     {
00093         Log2(PCSC_LOG_CRITICAL, "Error: connect to client socket: %s",
00094             strerror(errno));
00095         SYS_CloseFile(*pdwClientID);
00096         return -1;
00097     }
00098 
00099     one = 1;
00100     if (ioctl(*pdwClientID, FIONBIO, &one) < 0)
00101     {
00102         Log2(PCSC_LOG_CRITICAL, "Error: cannot set socket nonblocking: %s",
00103             strerror(errno));
00104         SYS_CloseFile(*pdwClientID);
00105         return -1;
00106     }
00107 
00108     return 0;
00109 }
00110 
00118 INTERNAL int SHMClientCloseSession(DWORD dwClientID)
00119 {
00120     SYS_CloseFile(dwClientID);
00121     return 0;
00122 }
00123 
00138 INTERNAL int SHMMessageSend(psharedSegmentMsg msgStruct, int filedes,
00139     int blockAmount)
00140 {
00141     /*
00142      * default is success 
00143      */
00144     int retval = 0;
00145     /*
00146      * record the time when we started 
00147      */
00148     time_t start = time(0);
00149     /*
00150      * data to be written 
00151      */
00152     unsigned char *buffer = (unsigned char *) msgStruct;
00153     /*
00154      * how many bytes remains to be written 
00155      */
00156     size_t remaining = sizeof(sharedSegmentMsg);
00157 
00158     /*
00159      * repeat until all data is written 
00160      */
00161     while (remaining > 0)
00162     {
00163         fd_set write_fd;
00164         struct timeval timeout;
00165         int selret;
00166 
00167         FD_ZERO(&write_fd);
00168         FD_SET(filedes, &write_fd);
00169 
00170         timeout.tv_usec = 0;
00171         if ((timeout.tv_sec = start + blockAmount - time(0)) < 0)
00172         {
00173             /*
00174              * we already timed out 
00175              */
00176             retval = -1;
00177             break;
00178         }
00179 
00180         selret = select(filedes + 1, NULL, &write_fd, NULL, &timeout);
00181 
00182         /*
00183          * try to write only when the file descriptor is writable 
00184          */
00185         if (selret > 0)
00186         {
00187             int written;
00188 
00189             if (!FD_ISSET(filedes, &write_fd))
00190             {
00191                 /*
00192                  * very strange situation. it should be an assert really 
00193                  */
00194                 retval = -1;
00195                 break;
00196             }
00197             written = write(filedes, buffer, remaining);
00198 
00199             if (written > 0)
00200             {
00201                 /*
00202                  * we wrote something 
00203                  */
00204                 buffer += written;
00205                 remaining -= written;
00206             } else if (written == 0)
00207             {
00208                 /*
00209                  * peer closed the socket 
00210                  */
00211                 retval = -1;
00212                 break;
00213             } else
00214             {
00215                 /*
00216                  * we ignore the signals and socket full situations, all
00217                  * other errors are fatal 
00218                  */
00219                 if (errno != EINTR && errno != EAGAIN)
00220                 {
00221                     retval = -1;
00222                     break;
00223                 }
00224             }
00225         } else if (selret == 0)
00226         {
00227             /*
00228              * timeout 
00229              */
00230             retval = -1;
00231             break;
00232         } else
00233         {
00234             /*
00235              * ignore signals 
00236              */
00237             if (errno != EINTR)
00238             {
00239                 Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00240                     strerror(errno));
00241                 retval = -1;
00242                 break;
00243             }
00244         }
00245     }
00246 
00247     return retval;
00248 }
00249 
00264 INTERNAL int SHMMessageReceive(psharedSegmentMsg msgStruct, int filedes,
00265     int blockAmount)
00266 {
00267     /*
00268      * default is success 
00269      */
00270     int retval = 0;
00271     /*
00272      * record the time when we started 
00273      */
00274     time_t start = time(0);
00275     /*
00276      * buffer where we place the readed bytes 
00277      */
00278     unsigned char *buffer = (unsigned char *) msgStruct;
00279     /*
00280      * how many bytes we must read 
00281      */
00282     size_t remaining = sizeof(sharedSegmentMsg);
00283 
00284     /*
00285      * repeate until we get the whole message 
00286      */
00287     while (remaining > 0)
00288     {
00289         fd_set read_fd;
00290         struct timeval timeout;
00291         int selret;
00292 
00293         FD_ZERO(&read_fd);
00294         FD_SET(filedes, &read_fd);
00295 
00296         timeout.tv_usec = 0;
00297         if ((timeout.tv_sec = start + blockAmount - time(0)) < 0)
00298         {
00299             /*
00300              * we already timed out 
00301              */
00302             retval = -1;
00303             break;
00304         }
00305 
00306         selret = select(filedes + 1, &read_fd, NULL, NULL, &timeout);
00307 
00308         /*
00309          * try to read only when socket is readable 
00310          */
00311         if (selret > 0)
00312         {
00313             int readed;
00314 
00315             if (!FD_ISSET(filedes, &read_fd))
00316             {
00317                 /*
00318                  * very strange situation. it should be an assert really 
00319                  */
00320                 retval = -1;
00321                 break;
00322             }
00323             readed = read(filedes, buffer, remaining);
00324 
00325             if (readed > 0)
00326             {
00327                 /*
00328                  * we got something 
00329                  */
00330                 buffer += readed;
00331                 remaining -= readed;
00332             } else if (readed == 0)
00333             {
00334                 /*
00335                  * peer closed the socket 
00336                  */
00337                 retval = -1;
00338                 break;
00339             } else
00340             {
00341                 /*
00342                  * we ignore the signals and empty socket situations, all
00343                  * other errors are fatal 
00344                  */
00345                 if (errno != EINTR && errno != EAGAIN)
00346                 {
00347                     retval = -1;
00348                     break;
00349                 }
00350             }
00351         } else if (selret == 0)
00352         {
00353             /*
00354              * timeout 
00355              */
00356             retval = -1;
00357             break;
00358         } else
00359         {
00360             /*
00361              * we ignore signals, all other errors are fatal 
00362              */
00363             if (errno != EINTR)
00364             {
00365                 Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00366                     strerror(errno));
00367                 retval = -1;
00368                 break;
00369             }
00370         }
00371     }
00372 
00373     return retval;
00374 }
00375 
00391 INTERNAL int WrapSHMWrite(unsigned int command, DWORD dwClientID,
00392     unsigned int size, unsigned int blockAmount, void *data)
00393 {
00394     sharedSegmentMsg msgStruct;
00395 
00396     /*
00397      * Set the appropriate packet parameters 
00398      */
00399 
00400     memset(&msgStruct, 0, sizeof(msgStruct));
00401     msgStruct.mtype = CMD_FUNCTION;
00402     msgStruct.user_id = SYS_GetUID();
00403     msgStruct.group_id = SYS_GetGID();
00404     msgStruct.command = command;
00405     msgStruct.date = time(NULL);
00406     memcpy(msgStruct.data, data, size);
00407 
00408     return SHMMessageSend(&msgStruct, dwClientID, blockAmount);
00409 }
00410 
00420 INTERNAL void SHMCleanupSharedSegment(int sockValue, char *pcFilePath)
00421 {
00422     SYS_CloseFile(sockValue);
00423     SYS_Unlink(pcFilePath);
00424 }
00425 

Generated on Fri Mar 24 04:30:06 2006 for pcsc-lite by  doxygen 1.4.6