bss_fd.c revision 290207
123693Speter/* crypto/bio/bss_fd.c */
21590Srgrimes/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
31590Srgrimes * All rights reserved.
41590Srgrimes *
51590Srgrimes * This package is an SSL implementation written
61590Srgrimes * by Eric Young (eay@cryptsoft.com).
71590Srgrimes * The implementation was written so as to conform with Netscapes SSL.
81590Srgrimes *
91590Srgrimes * This library is free for commercial and non-commercial use as long as
101590Srgrimes * the following conditions are aheared to.  The following conditions
111590Srgrimes * apply to all code found in this distribution, be it the RC4, RSA,
121590Srgrimes * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
131590Srgrimes * included with this distribution is covered by the same copyright terms
141590Srgrimes * except that the holder is Tim Hudson (tjh@cryptsoft.com).
151590Srgrimes *
161590Srgrimes * Copyright remains Eric Young's, and as such any Copyright notices in
171590Srgrimes * the code are not to be removed.
181590Srgrimes * If this package is used in a product, Eric Young should be given attribution
191590Srgrimes * as the author of the parts of the library used.
201590Srgrimes * This can be in the form of a textual message at program startup or
211590Srgrimes * in documentation (online or textual) provided with the package.
221590Srgrimes *
231590Srgrimes * Redistribution and use in source and binary forms, with or without
241590Srgrimes * modification, are permitted provided that the following conditions
251590Srgrimes * are met:
261590Srgrimes * 1. Redistributions of source code must retain the copyright
271590Srgrimes *    notice, this list of conditions and the following disclaimer.
2823693Speter * 2. Redistributions in binary form must reproduce the above copyright
2950477Speter *    notice, this list of conditions and the following disclaimer in the
301590Srgrimes *    documentation and/or other materials provided with the distribution.
31240506Seadler * 3. All advertising materials mentioning features or use of this software
321590Srgrimes *    must display the following acknowledgement:
3379535Sru *    "This product includes cryptographic software written by
341590Srgrimes *     Eric Young (eay@cryptsoft.com)"
351590Srgrimes *    The word 'cryptographic' can be left out if the rouines from the library
361590Srgrimes *    being used are not cryptographic related :-).
371590Srgrimes * 4. If you include any Windows specific code (or a derivative thereof) from
3868963Sru *    the apps directory (application code) you must include an acknowledgement:
39168632Sdes *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4070197Sru *
4170197Sru * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
421590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
431590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4468963Sru * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4595083Scharnier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
461590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
471590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48107262Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49100521Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50100521Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51100521Sume * SUCH DAMAGE.
52100521Sume *
53100521Sume * The licence and distribution terms for any publically available version or
54100521Sume * derivative of this code cannot be changed.  i.e. this code cannot simply be
55100521Sume * copied and put under another distribution licence
56100521Sume * [including the GNU Public Licence.]
571590Srgrimes */
5895083Scharnier
591590Srgrimes#include <stdio.h>
602537Spst#include <errno.h>
6157670Ssheldonh#define USE_SOCKETS
6257670Ssheldonh#include "cryptlib.h"
632537Spst
642537Spst#if defined(OPENSSL_NO_POSIX_IO)
6567483Sru/*
6667483Sru * Dummy placeholder for BIO_s_fd...
6767483Sru */
6867483SruBIO *BIO_new_fd(int fd, int close_flag)
691590Srgrimes{
701590Srgrimes    return NULL;
711590Srgrimes}
7269909Sru
7369909Sruint BIO_fd_non_fatal_error(int err)
7469909Sru{
7572109Scharnier    return 0;
762537Spst}
772537Spst
781590Srgrimesint BIO_fd_should_retry(int i)
791590Srgrimes{
801590Srgrimes    return 0;
812537Spst}
822537Spst
832537SpstBIO_METHOD *BIO_s_fd(void)
842537Spst{
852537Spst    return NULL;
862537Spst}
872537Spst#else
882537Spst/*
892537Spst * As for unconditional usage of "UPLINK" interface in this module.
902537Spst * Trouble is that unlike Unix file descriptors [which are indexes
9199249Smini * in kernel-side per-process table], corresponding descriptors on
9299249Smini * platforms which require "UPLINK" interface seem to be indexes
93131491Sru * in a user-land, non-global table. Well, in fact they are indexes
94131491Sru * in stdio _iob[], and recall that _iob[] was the very reason why
9599249Smini * "UPLINK" interface was introduced in first place. But one way on
9699249Smini * another. Neither libcrypto or libssl use this BIO meaning that
9799249Smini * file descriptors can only be provided by application. Therefore
98117010Sjmallett * "UPLINK" calls are due...
99202756Sed */
1001590Srgrimes# include "bio_lcl.h"
10195083Scharnier
1021590Srgrimesstatic int fd_write(BIO *h, const char *buf, int num);
1031590Srgrimesstatic int fd_read(BIO *h, char *buf, int size);
1041590Srgrimesstatic int fd_puts(BIO *h, const char *str);
1052537Spststatic int fd_gets(BIO *h, char *buf, int size);
106107262Srustatic long fd_ctrl(BIO *h, int cmd, long arg1, void *arg2);
107107262Srustatic int fd_new(BIO *h);
108107262Srustatic int fd_free(BIO *data);
1091590Srgrimesint BIO_fd_should_retry(int s);
110107262Sru
1111590Srgrimesstatic BIO_METHOD methods_fdp = {
1121590Srgrimes    BIO_TYPE_FD, "file descriptor",
1131590Srgrimes    fd_write,
1141590Srgrimes    fd_read,
1151590Srgrimes    fd_puts,
1161590Srgrimes    fd_gets,
1171590Srgrimes    fd_ctrl,
1181590Srgrimes    fd_new,
1191590Srgrimes    fd_free,
1201590Srgrimes    NULL,
1212537Spst};
1221590Srgrimes
1231590SrgrimesBIO_METHOD *BIO_s_fd(void)
1241590Srgrimes{
1251590Srgrimes    return (&methods_fdp);
1261590Srgrimes}
1271590Srgrimes
1281590SrgrimesBIO *BIO_new_fd(int fd, int close_flag)
1291590Srgrimes{
1302537Spst    BIO *ret;
1312537Spst    ret = BIO_new(BIO_s_fd());
1322537Spst    if (ret == NULL)
1332537Spst        return (NULL);
1341590Srgrimes    BIO_set_fd(ret, fd, close_flag);
13595083Scharnier    return (ret);
1361590Srgrimes}
1371590Srgrimes
1381590Srgrimesstatic int fd_new(BIO *bi)
13968963Sru{
1401590Srgrimes    bi->init = 0;
141107262Sru    bi->num = -1;
142107262Sru    bi->ptr = NULL;
143107262Sru    bi->flags = BIO_FLAGS_UPLINK; /* essentially redundant */
1441590Srgrimes    return (1);
145107262Sru}
1461590Srgrimes
1471590Srgrimesstatic int fd_free(BIO *a)
1481590Srgrimes{
1491590Srgrimes    if (a == NULL)
1501590Srgrimes        return (0);
1511590Srgrimes    if (a->shutdown) {
1521590Srgrimes        if (a->init) {
1531590Srgrimes            UP_close(a->num);
1541590Srgrimes        }
1551590Srgrimes        a->init = 0;
1561590Srgrimes        a->flags = BIO_FLAGS_UPLINK;
15768963Sru    }
1581590Srgrimes    return (1);
1591590Srgrimes}
1601590Srgrimes
1611590Srgrimesstatic int fd_read(BIO *b, char *out, int outl)
16268963Sru{
1631590Srgrimes    int ret = 0;
1641590Srgrimes
1651590Srgrimes    if (out != NULL) {
1661590Srgrimes        clear_sys_error();
1671590Srgrimes        ret = UP_read(b->num, out, outl);
1681590Srgrimes        BIO_clear_retry_flags(b);
1691590Srgrimes        if (ret <= 0) {
1701590Srgrimes            if (BIO_fd_should_retry(ret))
1711590Srgrimes                BIO_set_retry_read(b);
17268963Sru        }
1731590Srgrimes    }
1741590Srgrimes    return (ret);
17595083Scharnier}
17695083Scharnier
17795083Scharnierstatic int fd_write(BIO *b, const char *in, int inl)
1781590Srgrimes{
1791590Srgrimes    int ret;
1801590Srgrimes    clear_sys_error();
1811590Srgrimes    ret = UP_write(b->num, in, inl);
1821590Srgrimes    BIO_clear_retry_flags(b);
1831590Srgrimes    if (ret <= 0) {
1841590Srgrimes        if (BIO_fd_should_retry(ret))
1851590Srgrimes            BIO_set_retry_write(b);
1861590Srgrimes    }
1871590Srgrimes    return (ret);
1881590Srgrimes}
1891590Srgrimes
1901590Srgrimesstatic long fd_ctrl(BIO *b, int cmd, long num, void *ptr)
1911590Srgrimes{
1921590Srgrimes    long ret = 1;
1935369Sjkh    int *ip;
1945369Sjkh
195107262Sru    switch (cmd) {
1965369Sjkh    case BIO_CTRL_RESET:
197150316Sdds        num = 0;
19868963Sru    case BIO_C_FILE_SEEK:
1995369Sjkh        ret = (long)UP_lseek(b->num, num, 0);
20064775Sbrian        break;
20164775Sbrian    case BIO_C_FILE_TELL:
20264775Sbrian    case BIO_CTRL_INFO:
20364775Sbrian        ret = (long)UP_lseek(b->num, 0, 1);
20464775Sbrian        break;
205108257Sru    case BIO_C_SET_FD:
20664775Sbrian        fd_free(b);
20765069Ssheldonh        b->num = *((int *)ptr);
20865064Sbrian        b->shutdown = (int)num;
2092589Spst        b->init = 1;
21095083Scharnier        break;
21195083Scharnier    case BIO_C_GET_FD:
21295083Scharnier        if (b->init) {
2132589Spst            ip = (int *)ptr;
2142589Spst            if (ip != NULL)
2152589Spst                *ip = b->num;
21668963Sru            ret = b->num;
2172589Spst        } else
21823693Speter            ret = -1;
219202756Sed        break;
22064775Sbrian    case BIO_CTRL_GET_CLOSE:
22164775Sbrian        ret = b->shutdown;
222202756Sed        break;
22323693Speter    case BIO_CTRL_SET_CLOSE:
22423693Speter        b->shutdown = (int)num;
2251590Srgrimes        break;
2261590Srgrimes    case BIO_CTRL_PENDING:
2271590Srgrimes    case BIO_CTRL_WPENDING:
2281590Srgrimes        ret = 0;
22964775Sbrian        break;
23079366Sru    case BIO_CTRL_DUP:
23127836Swollman    case BIO_CTRL_FLUSH:
23227836Swollman        ret = 1;
23327836Swollman        break;
23427836Swollman    default:
23527836Swollman        ret = 0;
23627836Swollman        break;
2371590Srgrimes    }
2381590Srgrimes    return (ret);
23968963Sru}
2401590Srgrimes
2411590Srgrimesstatic int fd_puts(BIO *bp, const char *str)
242168657Sru{
243132277Stjr    int n, ret;
244132277Stjr
245132277Stjr    n = strlen(str);
246    ret = fd_write(bp, str, n);
247    return (ret);
248}
249
250static int fd_gets(BIO *bp, char *buf, int size)
251{
252    int ret = 0;
253    char *ptr = buf;
254    char *end = buf + size - 1;
255
256    while ((ptr < end) && (fd_read(bp, ptr, 1) > 0) && (ptr[0] != '\n'))
257        ptr++;
258
259    ptr[0] = '\0';
260
261    if (buf[0] != '\0')
262        ret = strlen(buf);
263    return (ret);
264}
265
266int BIO_fd_should_retry(int i)
267{
268    int err;
269
270    if ((i == 0) || (i == -1)) {
271        err = get_last_sys_error();
272
273# if defined(OPENSSL_SYS_WINDOWS) && 0/* more microsoft stupidity? perhaps
274                                       * not? Ben 4/1/99 */
275        if ((i == -1) && (err == 0))
276            return (1);
277# endif
278
279        return (BIO_fd_non_fatal_error(err));
280    }
281    return (0);
282}
283
284int BIO_fd_non_fatal_error(int err)
285{
286    switch (err) {
287
288# ifdef EWOULDBLOCK
289#  ifdef WSAEWOULDBLOCK
290#   if WSAEWOULDBLOCK != EWOULDBLOCK
291    case EWOULDBLOCK:
292#   endif
293#  else
294    case EWOULDBLOCK:
295#  endif
296# endif
297
298# if defined(ENOTCONN)
299    case ENOTCONN:
300# endif
301
302# ifdef EINTR
303    case EINTR:
304# endif
305
306# ifdef EAGAIN
307#  if EWOULDBLOCK != EAGAIN
308    case EAGAIN:
309#  endif
310# endif
311
312# ifdef EPROTO
313    case EPROTO:
314# endif
315
316# ifdef EINPROGRESS
317    case EINPROGRESS:
318# endif
319
320# ifdef EALREADY
321    case EALREADY:
322# endif
323        return (1);
324        /* break; */
325    default:
326        break;
327    }
328    return (0);
329}
330#endif
331