1/* 2 * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. 3 * The contents of this file constitute Original Code as defined in and are 4 * subject to the Apple Public Source License Version 1.2 (the 'License'). 5 * You may not use this file except in compliance with the License. Please 6 * obtain a copy of the License at http://www.apple.com/publicsource and 7 * read it before using this file. 8 * 9 * This Original Code and all software distributed under the License are 10 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 11 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 12 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 13 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please 14 * see the License for the specific language governing rights and 15 * limitations under the License. 16 */ 17 18/****************************************************************** 19 20 Title : winscard_msg.c 21 Package: PC/SC Lite 22 Author : David Corcoran 23 Date : 04/19/01 24 License: Copyright (C) 2001 David Corcoran 25 <corcoran@linuxnet.com> 26 Purpose: This is responsible for client/server transport. 27 28$Id: winscard_msg.c 123 2010-03-27 10:50:42Z ludovic.rousseau@gmail.com $ 29 30********************************************************************/ 31 32#include <fcntl.h> 33#include <unistd.h> 34#include <sys/types.h> 35#include <sys/stat.h> 36#include <sys/mman.h> 37#include <sys/socket.h> 38#include <sys/time.h> 39#include <sys/un.h> 40#include <sys/ioctl.h> 41#include <errno.h> 42#include <stdio.h> 43#include <time.h> 44#include <string.h> 45#include <stdlib.h> 46 47#include "config.h" 48 49#ifdef PCSC_TARGET_SOLARIS 50#include <sys/filio.h> 51#endif 52 53#include "wintypes.h" 54#include "pcsclite.h" 55#include "winscard.h" 56#include "winscard_msg.h" 57#include "sys_generic.h" 58#include "debuglog.h" 59 60int MSGSendData(int filedes, int blockAmount, const void *data, 61 unsigned int dataSize) 62{ 63 /* 64 * default is success 65 */ 66 int retval = 0; 67 /* 68 * record the time when we started 69 */ 70 time_t start = time(0); 71 /* 72 * data to be written 73 */ 74 unsigned char *buffer = (unsigned char *) data; 75 /* 76 * how many bytes remains to be written 77 */ 78 size_t remaining = dataSize; 79 80 /* 81 * repeat until all data is written 82 */ 83 while (remaining > 0) 84 { 85 fd_set write_fd; 86 struct timeval timeout; 87 int selret; 88 89 FD_ZERO(&write_fd); 90 FD_SET(filedes, &write_fd); 91 92 timeout.tv_usec = 0; 93 if ((timeout.tv_sec = start + blockAmount - time(0)) < 0) 94 { 95 /* 96 * we already timed out 97 */ 98 retval = -1; 99 break; 100 } 101 102 selret = select(filedes + 1, NULL, &write_fd, NULL, &timeout); 103 104 /* 105 * try to write only when the file descriptor is writable 106 */ 107 if (selret > 0) 108 { 109 int written; 110 111 if (!FD_ISSET(filedes, &write_fd)) 112 { 113 /* 114 * very strange situation. it should be an assert really 115 */ 116 retval = -1; 117 break; 118 } 119 written = write(filedes, buffer, remaining); 120 121 if (written > 0) 122 { 123 /* 124 * we wrote something 125 */ 126 buffer += written; 127 remaining -= written; 128 } else if (written == 0) 129 { 130 /* 131 * peer closed the socket 132 */ 133 retval = -1; 134 break; 135 } else 136 { 137 /* 138 * we ignore the signals and socket full situations, all 139 * other errors are fatal 140 */ 141 if (errno != EINTR && errno != EAGAIN) 142 { 143 retval = -1; 144 break; 145 } 146 } 147 } else if (selret == 0) 148 { 149 /* 150 * timeout 151 */ 152 retval = -1; 153 break; 154 } else 155 { 156 /* 157 * ignore signals 158 */ 159 if (errno != EINTR) 160 { 161 DebugLogB 162 ("MSGServerProcessEvents: Select returns with failure: %s", 163 strerror(errno)); 164 retval = -1; 165 break; 166 } 167 } 168 } 169 170 return retval; 171} 172 173int MSGRecieveData(int filedes, int blockAmount, void *data, 174 unsigned int dataSize) 175{ 176 /* 177 * default is success 178 */ 179 int retval = 0; 180 /* 181 * record the time when we started 182 */ 183 time_t start = time(0); 184 /* 185 * buffer where we place the readed bytes 186 */ 187 unsigned char *buffer = (unsigned char *) data; 188 /* 189 * how many bytes we must read 190 */ 191 size_t remaining = dataSize; 192 193 /* 194 * repeat until we get the whole message 195 */ 196 while (remaining > 0) 197 { 198 fd_set read_fd; 199 struct timeval timeout; 200 int selret; 201 202 FD_ZERO(&read_fd); 203 FD_SET(filedes, &read_fd); 204 205 timeout.tv_usec = 0; 206 if ((timeout.tv_sec = start + blockAmount - time(0)) < 0) 207 { 208 /* 209 * we already timed out 210 */ 211 retval = -1; 212 break; 213 } 214 215 selret = select(filedes + 1, &read_fd, NULL, NULL, &timeout); 216 217 /* 218 * try to read only when socket is readable 219 */ 220 if (selret > 0) 221 { 222 int readed; 223 224 if (!FD_ISSET(filedes, &read_fd)) 225 { 226 /* 227 * very strange situation. it should be an assert really 228 */ 229 retval = -1; 230 break; 231 } 232 readed = read(filedes, buffer, remaining); 233 234 if (readed > 0) 235 { 236 /* 237 * we got something 238 */ 239 buffer += readed; 240 remaining -= readed; 241 } else if (readed == 0) 242 { 243 /* 244 * peer closed the socket 245 */ 246 retval = -1; 247 break; 248 } else 249 { 250 /* 251 * we ignore the signals and empty socket situations, all 252 * other errors are fatal 253 */ 254 if (errno != EINTR && errno != EAGAIN) 255 { 256 retval = -1; 257 break; 258 } 259 } 260 } else if (selret == 0) 261 { 262 /* 263 * timeout 264 */ 265 retval = -1; 266 break; 267 } else 268 { 269 /* 270 * we ignore signals, all other errors are fatal 271 */ 272 if (errno != EINTR) 273 { 274 DebugLogB 275 ("MSGServerProcessEvents: Select returns with failure: %s", 276 strerror(errno)); 277 retval = -1; 278 break; 279 } 280 } 281 } 282 283 return retval; 284} 285