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