bss_fd.c revision 238405
155714Skris/* crypto/bio/bss_fd.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 59109998Smarkm#include <stdio.h> 60109998Smarkm#include <errno.h> 61109998Smarkm#define USE_SOCKETS 62109998Smarkm#include "cryptlib.h" 63238405Sjkim 64238405Sjkim#if defined(OPENSSL_NO_POSIX_IO) 65160814Ssimon/* 66238405Sjkim * One can argue that one should implement dummy placeholder for 67238405Sjkim * BIO_s_fd here... 68238405Sjkim */ 69238405Sjkim#else 70238405Sjkim/* 71160814Ssimon * As for unconditional usage of "UPLINK" interface in this module. 72160814Ssimon * Trouble is that unlike Unix file descriptors [which are indexes 73160814Ssimon * in kernel-side per-process table], corresponding descriptors on 74160814Ssimon * platforms which require "UPLINK" interface seem to be indexes 75160814Ssimon * in a user-land, non-global table. Well, in fact they are indexes 76160814Ssimon * in stdio _iob[], and recall that _iob[] was the very reason why 77160814Ssimon * "UPLINK" interface was introduced in first place. But one way on 78160814Ssimon * another. Neither libcrypto or libssl use this BIO meaning that 79160814Ssimon * file descriptors can only be provided by application. Therefore 80160814Ssimon * "UPLINK" calls are due... 81160814Ssimon */ 82160814Ssimon#include "bio_lcl.h" 8355714Skris 84109998Smarkmstatic int fd_write(BIO *h, const char *buf, int num); 85109998Smarkmstatic int fd_read(BIO *h, char *buf, int size); 86109998Smarkmstatic int fd_puts(BIO *h, const char *str); 87238405Sjkimstatic int fd_gets(BIO *h, char *buf, int size); 88109998Smarkmstatic long fd_ctrl(BIO *h, int cmd, long arg1, void *arg2); 89109998Smarkmstatic int fd_new(BIO *h); 90109998Smarkmstatic int fd_free(BIO *data); 91109998Smarkmint BIO_fd_should_retry(int s); 92109998Smarkm 93109998Smarkmstatic BIO_METHOD methods_fdp= 94109998Smarkm { 95109998Smarkm BIO_TYPE_FD,"file descriptor", 96109998Smarkm fd_write, 97109998Smarkm fd_read, 98109998Smarkm fd_puts, 99238405Sjkim fd_gets, 100109998Smarkm fd_ctrl, 101109998Smarkm fd_new, 102109998Smarkm fd_free, 103109998Smarkm NULL, 104109998Smarkm }; 105109998Smarkm 106109998SmarkmBIO_METHOD *BIO_s_fd(void) 107109998Smarkm { 108109998Smarkm return(&methods_fdp); 109109998Smarkm } 110109998Smarkm 111109998SmarkmBIO *BIO_new_fd(int fd,int close_flag) 112109998Smarkm { 113109998Smarkm BIO *ret; 114109998Smarkm ret=BIO_new(BIO_s_fd()); 115109998Smarkm if (ret == NULL) return(NULL); 116109998Smarkm BIO_set_fd(ret,fd,close_flag); 117109998Smarkm return(ret); 118109998Smarkm } 119109998Smarkm 120109998Smarkmstatic int fd_new(BIO *bi) 121109998Smarkm { 122109998Smarkm bi->init=0; 123160814Ssimon bi->num=-1; 124109998Smarkm bi->ptr=NULL; 125160814Ssimon bi->flags=BIO_FLAGS_UPLINK; /* essentially redundant */ 126109998Smarkm return(1); 127109998Smarkm } 128109998Smarkm 129109998Smarkmstatic int fd_free(BIO *a) 130109998Smarkm { 131109998Smarkm if (a == NULL) return(0); 132109998Smarkm if (a->shutdown) 133109998Smarkm { 134109998Smarkm if (a->init) 135109998Smarkm { 136160814Ssimon UP_close(a->num); 137109998Smarkm } 138109998Smarkm a->init=0; 139160814Ssimon a->flags=BIO_FLAGS_UPLINK; 140109998Smarkm } 141109998Smarkm return(1); 142109998Smarkm } 143109998Smarkm 144109998Smarkmstatic int fd_read(BIO *b, char *out,int outl) 145109998Smarkm { 146109998Smarkm int ret=0; 147109998Smarkm 148109998Smarkm if (out != NULL) 149109998Smarkm { 150109998Smarkm clear_sys_error(); 151160814Ssimon ret=UP_read(b->num,out,outl); 152109998Smarkm BIO_clear_retry_flags(b); 153109998Smarkm if (ret <= 0) 154109998Smarkm { 155109998Smarkm if (BIO_fd_should_retry(ret)) 156109998Smarkm BIO_set_retry_read(b); 157109998Smarkm } 158109998Smarkm } 159109998Smarkm return(ret); 160109998Smarkm } 161109998Smarkm 162109998Smarkmstatic int fd_write(BIO *b, const char *in, int inl) 163109998Smarkm { 164109998Smarkm int ret; 165109998Smarkm clear_sys_error(); 166160814Ssimon ret=UP_write(b->num,in,inl); 167109998Smarkm BIO_clear_retry_flags(b); 168109998Smarkm if (ret <= 0) 169109998Smarkm { 170109998Smarkm if (BIO_fd_should_retry(ret)) 171109998Smarkm BIO_set_retry_write(b); 172109998Smarkm } 173109998Smarkm return(ret); 174109998Smarkm } 175109998Smarkm 176109998Smarkmstatic long fd_ctrl(BIO *b, int cmd, long num, void *ptr) 177109998Smarkm { 178109998Smarkm long ret=1; 179109998Smarkm int *ip; 180109998Smarkm 181109998Smarkm switch (cmd) 182109998Smarkm { 183109998Smarkm case BIO_CTRL_RESET: 184109998Smarkm num=0; 185109998Smarkm case BIO_C_FILE_SEEK: 186160814Ssimon ret=(long)UP_lseek(b->num,num,0); 187109998Smarkm break; 188109998Smarkm case BIO_C_FILE_TELL: 189109998Smarkm case BIO_CTRL_INFO: 190160814Ssimon ret=(long)UP_lseek(b->num,0,1); 191109998Smarkm break; 192109998Smarkm case BIO_C_SET_FD: 193109998Smarkm fd_free(b); 194109998Smarkm b->num= *((int *)ptr); 195109998Smarkm b->shutdown=(int)num; 196109998Smarkm b->init=1; 197109998Smarkm break; 198109998Smarkm case BIO_C_GET_FD: 199109998Smarkm if (b->init) 200109998Smarkm { 201109998Smarkm ip=(int *)ptr; 202109998Smarkm if (ip != NULL) *ip=b->num; 203109998Smarkm ret=b->num; 204109998Smarkm } 205109998Smarkm else 206109998Smarkm ret= -1; 207109998Smarkm break; 208109998Smarkm case BIO_CTRL_GET_CLOSE: 209109998Smarkm ret=b->shutdown; 210109998Smarkm break; 211109998Smarkm case BIO_CTRL_SET_CLOSE: 212109998Smarkm b->shutdown=(int)num; 213109998Smarkm break; 214109998Smarkm case BIO_CTRL_PENDING: 215109998Smarkm case BIO_CTRL_WPENDING: 216109998Smarkm ret=0; 217109998Smarkm break; 218109998Smarkm case BIO_CTRL_DUP: 219109998Smarkm case BIO_CTRL_FLUSH: 220109998Smarkm ret=1; 221109998Smarkm break; 222109998Smarkm default: 223109998Smarkm ret=0; 224109998Smarkm break; 225109998Smarkm } 226109998Smarkm return(ret); 227109998Smarkm } 228109998Smarkm 229109998Smarkmstatic int fd_puts(BIO *bp, const char *str) 230109998Smarkm { 231109998Smarkm int n,ret; 232109998Smarkm 233109998Smarkm n=strlen(str); 234109998Smarkm ret=fd_write(bp,str,n); 235109998Smarkm return(ret); 236109998Smarkm } 237109998Smarkm 238238405Sjkimstatic int fd_gets(BIO *bp, char *buf, int size) 239238405Sjkim { 240238405Sjkim int ret=0; 241238405Sjkim char *ptr=buf; 242238405Sjkim char *end=buf+size-1; 243238405Sjkim 244238405Sjkim while ( (ptr < end) && (fd_read(bp, ptr, 1) > 0) && (ptr[0] != '\n') ) 245238405Sjkim ptr++; 246238405Sjkim 247238405Sjkim ptr[0]='\0'; 248238405Sjkim 249238405Sjkim if (buf[0] != '\0') 250238405Sjkim ret=strlen(buf); 251238405Sjkim return(ret); 252238405Sjkim } 253238405Sjkim 254109998Smarkmint BIO_fd_should_retry(int i) 255109998Smarkm { 256109998Smarkm int err; 257109998Smarkm 258109998Smarkm if ((i == 0) || (i == -1)) 259109998Smarkm { 260109998Smarkm err=get_last_sys_error(); 261109998Smarkm 262109998Smarkm#if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */ 263109998Smarkm if ((i == -1) && (err == 0)) 264109998Smarkm return(1); 265109998Smarkm#endif 266109998Smarkm 267109998Smarkm return(BIO_fd_non_fatal_error(err)); 268109998Smarkm } 269109998Smarkm return(0); 270109998Smarkm } 271109998Smarkm 272109998Smarkmint BIO_fd_non_fatal_error(int err) 273109998Smarkm { 274109998Smarkm switch (err) 275109998Smarkm { 276109998Smarkm 277109998Smarkm#ifdef EWOULDBLOCK 278109998Smarkm# ifdef WSAEWOULDBLOCK 279109998Smarkm# if WSAEWOULDBLOCK != EWOULDBLOCK 280109998Smarkm case EWOULDBLOCK: 281109998Smarkm# endif 282109998Smarkm# else 283109998Smarkm case EWOULDBLOCK: 284109998Smarkm# endif 285109998Smarkm#endif 286109998Smarkm 287109998Smarkm#if defined(ENOTCONN) 288109998Smarkm case ENOTCONN: 289109998Smarkm#endif 290109998Smarkm 291109998Smarkm#ifdef EINTR 292109998Smarkm case EINTR: 293109998Smarkm#endif 294109998Smarkm 295109998Smarkm#ifdef EAGAIN 296109998Smarkm#if EWOULDBLOCK != EAGAIN 297109998Smarkm case EAGAIN: 298109998Smarkm# endif 299109998Smarkm#endif 300109998Smarkm 301109998Smarkm#ifdef EPROTO 302109998Smarkm case EPROTO: 303109998Smarkm#endif 304109998Smarkm 305109998Smarkm#ifdef EINPROGRESS 306109998Smarkm case EINPROGRESS: 307109998Smarkm#endif 308109998Smarkm 309109998Smarkm#ifdef EALREADY 310109998Smarkm case EALREADY: 311109998Smarkm#endif 312109998Smarkm return(1); 313109998Smarkm /* break; */ 314109998Smarkm default: 315109998Smarkm break; 316109998Smarkm } 317109998Smarkm return(0); 318109998Smarkm } 319238405Sjkim#endif 320