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.
8280297Sjkim *
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).
15280297Sjkim *
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.
22280297Sjkim *
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 :-).
37280297Sjkim * 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)"
40280297Sjkim *
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.
52280297Sjkim *
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/*
66290207Sjkim * Dummy placeholder for BIO_s_fd...
67238405Sjkim */
68290207SjkimBIO *BIO_new_fd(int fd, int close_flag)
69290207Sjkim{
70290207Sjkim    return NULL;
71290207Sjkim}
72290207Sjkim
73290207Sjkimint BIO_fd_non_fatal_error(int err)
74290207Sjkim{
75290207Sjkim    return 0;
76290207Sjkim}
77290207Sjkim
78290207Sjkimint BIO_fd_should_retry(int i)
79290207Sjkim{
80290207Sjkim    return 0;
81290207Sjkim}
82290207Sjkim
83290207SjkimBIO_METHOD *BIO_s_fd(void)
84290207Sjkim{
85290207Sjkim    return NULL;
86290207Sjkim}
87238405Sjkim#else
88238405Sjkim/*
89160814Ssimon * As for unconditional usage of "UPLINK" interface in this module.
90160814Ssimon * Trouble is that unlike Unix file descriptors [which are indexes
91160814Ssimon * in kernel-side per-process table], corresponding descriptors on
92160814Ssimon * platforms which require "UPLINK" interface seem to be indexes
93160814Ssimon * in a user-land, non-global table. Well, in fact they are indexes
94160814Ssimon * in stdio _iob[], and recall that _iob[] was the very reason why
95160814Ssimon * "UPLINK" interface was introduced in first place. But one way on
96160814Ssimon * another. Neither libcrypto or libssl use this BIO meaning that
97160814Ssimon * file descriptors can only be provided by application. Therefore
98160814Ssimon * "UPLINK" calls are due...
99160814Ssimon */
100280297Sjkim# include "bio_lcl.h"
10155714Skris
102109998Smarkmstatic int fd_write(BIO *h, const char *buf, int num);
103109998Smarkmstatic int fd_read(BIO *h, char *buf, int size);
104109998Smarkmstatic int fd_puts(BIO *h, const char *str);
105238405Sjkimstatic int fd_gets(BIO *h, char *buf, int size);
106109998Smarkmstatic long fd_ctrl(BIO *h, int cmd, long arg1, void *arg2);
107109998Smarkmstatic int fd_new(BIO *h);
108109998Smarkmstatic int fd_free(BIO *data);
109109998Smarkmint BIO_fd_should_retry(int s);
110109998Smarkm
111280297Sjkimstatic BIO_METHOD methods_fdp = {
112280297Sjkim    BIO_TYPE_FD, "file descriptor",
113280297Sjkim    fd_write,
114280297Sjkim    fd_read,
115280297Sjkim    fd_puts,
116280297Sjkim    fd_gets,
117280297Sjkim    fd_ctrl,
118280297Sjkim    fd_new,
119280297Sjkim    fd_free,
120280297Sjkim    NULL,
121280297Sjkim};
122109998Smarkm
123109998SmarkmBIO_METHOD *BIO_s_fd(void)
124280297Sjkim{
125280297Sjkim    return (&methods_fdp);
126280297Sjkim}
127109998Smarkm
128280297SjkimBIO *BIO_new_fd(int fd, int close_flag)
129280297Sjkim{
130280297Sjkim    BIO *ret;
131280297Sjkim    ret = BIO_new(BIO_s_fd());
132280297Sjkim    if (ret == NULL)
133280297Sjkim        return (NULL);
134280297Sjkim    BIO_set_fd(ret, fd, close_flag);
135280297Sjkim    return (ret);
136280297Sjkim}
137109998Smarkm
138109998Smarkmstatic int fd_new(BIO *bi)
139280297Sjkim{
140280297Sjkim    bi->init = 0;
141280297Sjkim    bi->num = -1;
142280297Sjkim    bi->ptr = NULL;
143280297Sjkim    bi->flags = BIO_FLAGS_UPLINK; /* essentially redundant */
144280297Sjkim    return (1);
145280297Sjkim}
146109998Smarkm
147109998Smarkmstatic int fd_free(BIO *a)
148280297Sjkim{
149280297Sjkim    if (a == NULL)
150280297Sjkim        return (0);
151280297Sjkim    if (a->shutdown) {
152280297Sjkim        if (a->init) {
153280297Sjkim            UP_close(a->num);
154280297Sjkim        }
155280297Sjkim        a->init = 0;
156280297Sjkim        a->flags = BIO_FLAGS_UPLINK;
157280297Sjkim    }
158280297Sjkim    return (1);
159280297Sjkim}
160109998Smarkm
161280297Sjkimstatic int fd_read(BIO *b, char *out, int outl)
162280297Sjkim{
163280297Sjkim    int ret = 0;
164109998Smarkm
165280297Sjkim    if (out != NULL) {
166280297Sjkim        clear_sys_error();
167280297Sjkim        ret = UP_read(b->num, out, outl);
168280297Sjkim        BIO_clear_retry_flags(b);
169280297Sjkim        if (ret <= 0) {
170280297Sjkim            if (BIO_fd_should_retry(ret))
171280297Sjkim                BIO_set_retry_read(b);
172280297Sjkim        }
173280297Sjkim    }
174280297Sjkim    return (ret);
175280297Sjkim}
176280297Sjkim
177109998Smarkmstatic int fd_write(BIO *b, const char *in, int inl)
178280297Sjkim{
179280297Sjkim    int ret;
180280297Sjkim    clear_sys_error();
181280297Sjkim    ret = UP_write(b->num, in, inl);
182280297Sjkim    BIO_clear_retry_flags(b);
183280297Sjkim    if (ret <= 0) {
184280297Sjkim        if (BIO_fd_should_retry(ret))
185280297Sjkim            BIO_set_retry_write(b);
186280297Sjkim    }
187280297Sjkim    return (ret);
188280297Sjkim}
189109998Smarkm
190109998Smarkmstatic long fd_ctrl(BIO *b, int cmd, long num, void *ptr)
191280297Sjkim{
192280297Sjkim    long ret = 1;
193280297Sjkim    int *ip;
194109998Smarkm
195280297Sjkim    switch (cmd) {
196280297Sjkim    case BIO_CTRL_RESET:
197280297Sjkim        num = 0;
198280297Sjkim    case BIO_C_FILE_SEEK:
199280297Sjkim        ret = (long)UP_lseek(b->num, num, 0);
200280297Sjkim        break;
201280297Sjkim    case BIO_C_FILE_TELL:
202280297Sjkim    case BIO_CTRL_INFO:
203280297Sjkim        ret = (long)UP_lseek(b->num, 0, 1);
204280297Sjkim        break;
205280297Sjkim    case BIO_C_SET_FD:
206280297Sjkim        fd_free(b);
207280297Sjkim        b->num = *((int *)ptr);
208280297Sjkim        b->shutdown = (int)num;
209280297Sjkim        b->init = 1;
210280297Sjkim        break;
211280297Sjkim    case BIO_C_GET_FD:
212280297Sjkim        if (b->init) {
213280297Sjkim            ip = (int *)ptr;
214280297Sjkim            if (ip != NULL)
215280297Sjkim                *ip = b->num;
216280297Sjkim            ret = b->num;
217280297Sjkim        } else
218280297Sjkim            ret = -1;
219280297Sjkim        break;
220280297Sjkim    case BIO_CTRL_GET_CLOSE:
221280297Sjkim        ret = b->shutdown;
222280297Sjkim        break;
223280297Sjkim    case BIO_CTRL_SET_CLOSE:
224280297Sjkim        b->shutdown = (int)num;
225280297Sjkim        break;
226280297Sjkim    case BIO_CTRL_PENDING:
227280297Sjkim    case BIO_CTRL_WPENDING:
228280297Sjkim        ret = 0;
229280297Sjkim        break;
230280297Sjkim    case BIO_CTRL_DUP:
231280297Sjkim    case BIO_CTRL_FLUSH:
232280297Sjkim        ret = 1;
233280297Sjkim        break;
234280297Sjkim    default:
235280297Sjkim        ret = 0;
236280297Sjkim        break;
237280297Sjkim    }
238280297Sjkim    return (ret);
239280297Sjkim}
240109998Smarkm
241109998Smarkmstatic int fd_puts(BIO *bp, const char *str)
242280297Sjkim{
243280297Sjkim    int n, ret;
244109998Smarkm
245280297Sjkim    n = strlen(str);
246280297Sjkim    ret = fd_write(bp, str, n);
247280297Sjkim    return (ret);
248280297Sjkim}
249109998Smarkm
250238405Sjkimstatic int fd_gets(BIO *bp, char *buf, int size)
251280297Sjkim{
252280297Sjkim    int ret = 0;
253280297Sjkim    char *ptr = buf;
254280297Sjkim    char *end = buf + size - 1;
255238405Sjkim
256280297Sjkim    while ((ptr < end) && (fd_read(bp, ptr, 1) > 0) && (ptr[0] != '\n'))
257280297Sjkim        ptr++;
258238405Sjkim
259280297Sjkim    ptr[0] = '\0';
260238405Sjkim
261280297Sjkim    if (buf[0] != '\0')
262280297Sjkim        ret = strlen(buf);
263280297Sjkim    return (ret);
264280297Sjkim}
265238405Sjkim
266109998Smarkmint BIO_fd_should_retry(int i)
267280297Sjkim{
268280297Sjkim    int err;
269109998Smarkm
270280297Sjkim    if ((i == 0) || (i == -1)) {
271280297Sjkim        err = get_last_sys_error();
272109998Smarkm
273280297Sjkim# if defined(OPENSSL_SYS_WINDOWS) && 0/* more microsoft stupidity? perhaps
274280297Sjkim                                       * not? Ben 4/1/99 */
275280297Sjkim        if ((i == -1) && (err == 0))
276280297Sjkim            return (1);
277280297Sjkim# endif
278109998Smarkm
279280297Sjkim        return (BIO_fd_non_fatal_error(err));
280280297Sjkim    }
281280297Sjkim    return (0);
282280297Sjkim}
283109998Smarkm
284109998Smarkmint BIO_fd_non_fatal_error(int err)
285280297Sjkim{
286280297Sjkim    switch (err) {
287109998Smarkm
288280297Sjkim# ifdef EWOULDBLOCK
289280297Sjkim#  ifdef WSAEWOULDBLOCK
290280297Sjkim#   if WSAEWOULDBLOCK != EWOULDBLOCK
291280297Sjkim    case EWOULDBLOCK:
292280297Sjkim#   endif
293280297Sjkim#  else
294280297Sjkim    case EWOULDBLOCK:
295109998Smarkm#  endif
296109998Smarkm# endif
297109998Smarkm
298280297Sjkim# if defined(ENOTCONN)
299280297Sjkim    case ENOTCONN:
300280297Sjkim# endif
301109998Smarkm
302280297Sjkim# ifdef EINTR
303280297Sjkim    case EINTR:
304280297Sjkim# endif
305109998Smarkm
306280297Sjkim# ifdef EAGAIN
307280297Sjkim#  if EWOULDBLOCK != EAGAIN
308280297Sjkim    case EAGAIN:
309280297Sjkim#  endif
310109998Smarkm# endif
311109998Smarkm
312280297Sjkim# ifdef EPROTO
313280297Sjkim    case EPROTO:
314280297Sjkim# endif
315109998Smarkm
316280297Sjkim# ifdef EINPROGRESS
317280297Sjkim    case EINPROGRESS:
318280297Sjkim# endif
319109998Smarkm
320280297Sjkim# ifdef EALREADY
321280297Sjkim    case EALREADY:
322280297Sjkim# endif
323280297Sjkim        return (1);
324280297Sjkim        /* break; */
325280297Sjkim    default:
326280297Sjkim        break;
327280297Sjkim    }
328280297Sjkim    return (0);
329280297Sjkim}
330109998Smarkm#endif
331