Use build.info, not ifdef for crypto modules
[openssl.git] / crypto / rand / rand_egd.c
1 /*
2  * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <openssl/opensslconf.h>
11
12 #include <openssl/crypto.h>
13 #include <openssl/e_os2.h>
14 #include <openssl/rand.h>
15
16 /*
17  * Query an EGD
18  */
19
20 #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_UEFI)
21 int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
22 {
23     return -1;
24 }
25
26 int RAND_egd(const char *path)
27 {
28     return -1;
29 }
30
31 int RAND_egd_bytes(const char *path, int bytes)
32 {
33     return -1;
34 }
35
36 #else
37
38 # include <unistd.h>
39 # include <stddef.h>
40 # include <sys/types.h>
41 # include <sys/socket.h>
42 # ifndef NO_SYS_UN_H
43 #  ifdef OPENSSL_SYS_VXWORKS
44 #   include <streams/un.h>
45 #  else
46 #   include <sys/un.h>
47 #  endif
48 # else
49 struct sockaddr_un {
50     short sun_family;           /* AF_UNIX */
51     char sun_path[108];         /* path name (gag) */
52 };
53 # endif                         /* NO_SYS_UN_H */
54 # include <string.h>
55 # include <errno.h>
56
57 int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
58 {
59     FILE *fp = NULL;
60     struct sockaddr_un addr;
61     int mybuffer, ret = -1, i, numbytes, fd;
62     unsigned char tempbuf[255];
63
64     if (bytes > (int)sizeof(tempbuf))
65         return -1;
66
67     /* Make socket. */
68     memset(&addr, 0, sizeof(addr));
69     addr.sun_family = AF_UNIX;
70     if (strlen(path) >= sizeof(addr.sun_path))
71         return -1;
72     strcpy(addr.sun_path, path);
73     i = offsetof(struct sockaddr_un, sun_path) + strlen(path);
74     fd = socket(AF_UNIX, SOCK_STREAM, 0);
75     if (fd == -1 || (fp = fdopen(fd, "r+")) == NULL)
76         return -1;
77     setbuf(fp, NULL);
78
79     /* Try to connect */
80     for ( ; ; ) {
81         if (connect(fd, (struct sockaddr *)&addr, i) == 0)
82             break;
83 # ifdef EISCONN
84         if (errno == EISCONN)
85             break;
86 # endif
87         switch (errno) {
88 # ifdef EINTR
89         case EINTR:
90 # endif
91 # ifdef EAGAIN
92         case EAGAIN:
93 # endif
94 # ifdef EINPROGRESS
95         case EINPROGRESS:
96 # endif
97 # ifdef EALREADY
98         case EALREADY:
99 # endif
100             /* No error, try again */
101             break;
102         default:
103             ret = -1;
104             goto err;
105         }
106     }
107
108     /* Make request, see how many bytes we can get back. */
109     tempbuf[0] = 1;
110     tempbuf[1] = bytes;
111     if (fwrite(tempbuf, sizeof(char), 2, fp) != 2 || fflush(fp) == EOF)
112         goto err;
113     if (fread(tempbuf, sizeof(char), 1, fp) != 1 || tempbuf[0] == 0)
114         goto err;
115     numbytes = tempbuf[0];
116
117     /* Which buffer are we using? */
118     mybuffer = buf == NULL;
119     if (mybuffer)
120         buf = tempbuf;
121
122     /* Read bytes. */
123     i = fread(buf, sizeof(char), numbytes, fp);
124     if (i < numbytes)
125         goto err;
126     ret = numbytes;
127     if (mybuffer)
128         RAND_add(tempbuf, i, i);
129
130  err:
131     if (fp != NULL)
132         fclose(fp);
133     return ret;
134 }
135
136 int RAND_egd_bytes(const char *path, int bytes)
137 {
138     int num;
139
140     num = RAND_query_egd_bytes(path, NULL, bytes);
141     if (num < 0)
142         return -1;
143     if (RAND_status() != 1)
144         return -1;
145     return num;
146 }
147
148 int RAND_egd(const char *path)
149 {
150     return RAND_egd_bytes(path, 255);
151 }
152
153 #endif