spiped 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/spiped/extconf.rb +3 -0
- data/ext/spiped/spiped-source/BUILDING +46 -0
- data/ext/spiped/spiped-source/CHANGELOG +44 -0
- data/ext/spiped/spiped-source/COPYRIGHT +33 -0
- data/ext/spiped/spiped-source/Makefile +47 -0
- data/ext/spiped/spiped-source/Makefile.POSIX +27 -0
- data/ext/spiped/spiped-source/Makefile.inc +20 -0
- data/ext/spiped/spiped-source/Makefile.prog +23 -0
- data/ext/spiped/spiped-source/POSIX/README +10 -0
- data/ext/spiped/spiped-source/POSIX/posix-cflags.sh +10 -0
- data/ext/spiped/spiped-source/POSIX/posix-clock_realtime.c +3 -0
- data/ext/spiped/spiped-source/POSIX/posix-l.c +1 -0
- data/ext/spiped/spiped-source/POSIX/posix-l.sh +14 -0
- data/ext/spiped/spiped-source/POSIX/posix-msg_nosignal.c +3 -0
- data/ext/spiped/spiped-source/README +198 -0
- data/ext/spiped/spiped-source/STYLE +151 -0
- data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.c +464 -0
- data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.h +45 -0
- data/ext/spiped/spiped-source/libcperciva/alg/sha256.c +442 -0
- data/ext/spiped/spiped-source/libcperciva/alg/sha256.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c +13 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c +8 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport.sh +37 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport.h +63 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport_x86_aesni.c +30 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.c +166 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.h +31 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.c +229 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.h +31 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.c +124 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.h +41 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.c +293 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.h +43 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.c +46 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.h +9 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.c +215 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.c +21 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.c +276 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.h +167 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/mpool.h +85 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.c +334 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.h +89 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.c +241 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.h +60 -0
- data/ext/spiped/spiped-source/libcperciva/events/events.c +203 -0
- data/ext/spiped/spiped-source/libcperciva/events/events.h +106 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_immediate.c +149 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_internal.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_network.c +347 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_network_selectstats.c +106 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_timer.c +273 -0
- data/ext/spiped/spiped-source/libcperciva/network/network.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_accept.c +103 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_connect.c +258 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_read.c +155 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_write.c +188 -0
- data/ext/spiped/spiped-source/libcperciva/util/asprintf.c +49 -0
- data/ext/spiped/spiped-source/libcperciva/util/asprintf.h +16 -0
- data/ext/spiped/spiped-source/libcperciva/util/daemonize.c +134 -0
- data/ext/spiped/spiped-source/libcperciva/util/daemonize.h +10 -0
- data/ext/spiped/spiped-source/libcperciva/util/entropy.c +76 -0
- data/ext/spiped/spiped-source/libcperciva/util/entropy.h +13 -0
- data/ext/spiped/spiped-source/libcperciva/util/imalloc.h +33 -0
- data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.c +19 -0
- data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.h +33 -0
- data/ext/spiped/spiped-source/libcperciva/util/monoclock.c +52 -0
- data/ext/spiped/spiped-source/libcperciva/util/monoclock.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/noeintr.c +54 -0
- data/ext/spiped/spiped-source/libcperciva/util/noeintr.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock.c +472 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock.h +56 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_internal.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_util.c +271 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_util.h +51 -0
- data/ext/spiped/spiped-source/libcperciva/util/sysendian.h +146 -0
- data/ext/spiped/spiped-source/libcperciva/util/warnp.c +76 -0
- data/ext/spiped/spiped-source/libcperciva/util/warnp.h +59 -0
- data/ext/spiped/spiped-source/proto/proto_conn.c +362 -0
- data/ext/spiped/spiped-source/proto/proto_conn.h +25 -0
- data/ext/spiped/spiped-source/proto/proto_crypt.c +396 -0
- data/ext/spiped/spiped-source/proto/proto_crypt.h +102 -0
- data/ext/spiped/spiped-source/proto/proto_handshake.c +330 -0
- data/ext/spiped/spiped-source/proto/proto_handshake.h +30 -0
- data/ext/spiped/spiped-source/proto/proto_pipe.c +202 -0
- data/ext/spiped/spiped-source/proto/proto_pipe.h +23 -0
- data/ext/spiped/spiped-source/spipe/Makefile +90 -0
- data/ext/spiped/spiped-source/spipe/README +24 -0
- data/ext/spiped/spiped-source/spipe/main.c +178 -0
- data/ext/spiped/spiped-source/spipe/pushbits.c +101 -0
- data/ext/spiped/spiped-source/spipe/pushbits.h +10 -0
- data/ext/spiped/spiped-source/spipe/spipe.1 +60 -0
- data/ext/spiped/spiped-source/spiped/Makefile +98 -0
- data/ext/spiped/spiped-source/spiped/README +62 -0
- data/ext/spiped/spiped-source/spiped/dispatch.c +214 -0
- data/ext/spiped/spiped-source/spiped/dispatch.h +27 -0
- data/ext/spiped/spiped-source/spiped/main.c +267 -0
- data/ext/spiped/spiped-source/spiped/spiped.1 +112 -0
- data/lib/spiped.rb +3 -0
- metadata +143 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
#include <sys/socket.h>
|
|
2
|
+
|
|
3
|
+
#include <assert.h>
|
|
4
|
+
#include <errno.h>
|
|
5
|
+
#include <limits.h>
|
|
6
|
+
#include <signal.h>
|
|
7
|
+
#include <stdint.h>
|
|
8
|
+
#include <stdlib.h>
|
|
9
|
+
#include <unistd.h>
|
|
10
|
+
|
|
11
|
+
#include "events.h"
|
|
12
|
+
#include "warnp.h"
|
|
13
|
+
|
|
14
|
+
#include "network.h"
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* POSIX.1-2008 requires that MSG_NOSIGNAL be defined as a flag for send(2)
|
|
18
|
+
* which has the effect of preventing SIGPIPE from being raised when writing
|
|
19
|
+
* to a descriptor which has been shut down. Unfortunately there are some
|
|
20
|
+
* platforms which are not POSIX.1-2008 compliant; we provide a workaround
|
|
21
|
+
* (-DPOSIXFAIL_MSG_NOSIGNAL) which instead blocks the SIGPIPE signal on such
|
|
22
|
+
* platforms.
|
|
23
|
+
*
|
|
24
|
+
* (This workaround could be used automatically, but requiring that it be
|
|
25
|
+
* explicitly enabled helps to get platforms fixed.)
|
|
26
|
+
*/
|
|
27
|
+
#ifdef POSIXFAIL_MSG_NOSIGNAL
|
|
28
|
+
#ifndef MSG_NOSIGNAL
|
|
29
|
+
#define MSG_NOSIGNAL 0
|
|
30
|
+
#endif
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
struct network_write_cookie {
|
|
34
|
+
int (*callback)(void *, ssize_t);
|
|
35
|
+
void * cookie;
|
|
36
|
+
int fd;
|
|
37
|
+
const uint8_t * buf;
|
|
38
|
+
size_t buflen;
|
|
39
|
+
size_t minlen;
|
|
40
|
+
size_t bufpos;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/* Invoke the callback, clean up, and return the callback's status. */
|
|
44
|
+
static int
|
|
45
|
+
docallback(struct network_write_cookie * C, ssize_t nbytes)
|
|
46
|
+
{
|
|
47
|
+
int rc;
|
|
48
|
+
|
|
49
|
+
/* Invoke the callback. */
|
|
50
|
+
rc = (C->callback)(C->cookie, nbytes);
|
|
51
|
+
|
|
52
|
+
/* Clean up. */
|
|
53
|
+
free(C);
|
|
54
|
+
|
|
55
|
+
/* Return the callback's status. */
|
|
56
|
+
return (rc);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* The socket is ready for reading/writing. */
|
|
60
|
+
static int
|
|
61
|
+
callback_buf(void * cookie)
|
|
62
|
+
{
|
|
63
|
+
struct network_write_cookie * C = cookie;
|
|
64
|
+
size_t oplen;
|
|
65
|
+
ssize_t len;
|
|
66
|
+
#ifdef POSIXFAIL_MSG_NOSIGNAL
|
|
67
|
+
void (*oldsig)(int);
|
|
68
|
+
#endif
|
|
69
|
+
|
|
70
|
+
/* If we don't have MSG_NOSIGNAL, catch SIGPIPE. */
|
|
71
|
+
#ifdef POSIXFAIL_MSG_NOSIGNAL
|
|
72
|
+
if ((oldsig = signal(SIGPIPE, SIG_IGN)) == SIG_ERR) {
|
|
73
|
+
warnp("signal(SIGPIPE)");
|
|
74
|
+
goto failed;
|
|
75
|
+
}
|
|
76
|
+
#endif
|
|
77
|
+
|
|
78
|
+
/* Attempt to read/write data to/from the buffer. */
|
|
79
|
+
oplen = C->buflen - C->bufpos;
|
|
80
|
+
len = send(C->fd, C->buf + C->bufpos, oplen, MSG_NOSIGNAL);
|
|
81
|
+
|
|
82
|
+
/* We should never see a send length of zero. */
|
|
83
|
+
assert(len != 0);
|
|
84
|
+
|
|
85
|
+
/* If we set a SIGPIPE handler, restore the old one. */
|
|
86
|
+
#ifdef POSIXFAIL_MSG_NOSIGNAL
|
|
87
|
+
if (signal(SIGPIPE, oldsig) == SIG_ERR) {
|
|
88
|
+
warnp("signal(SIGPIPE)");
|
|
89
|
+
goto failed;
|
|
90
|
+
}
|
|
91
|
+
#endif
|
|
92
|
+
|
|
93
|
+
/* Failure? */
|
|
94
|
+
if (len == -1) {
|
|
95
|
+
/* Was it really an error, or just a try-again? */
|
|
96
|
+
if ((errno == EAGAIN) ||
|
|
97
|
+
(errno == EWOULDBLOCK) ||
|
|
98
|
+
(errno == EINTR))
|
|
99
|
+
goto tryagain;
|
|
100
|
+
|
|
101
|
+
/* Something went wrong. */
|
|
102
|
+
goto failed;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* We processed some data. Do we need to keep going? */
|
|
106
|
+
if ((C->bufpos += len) < C->minlen)
|
|
107
|
+
goto tryagain;
|
|
108
|
+
|
|
109
|
+
/* Invoke the callback and return. */
|
|
110
|
+
return (docallback(C, C->bufpos));
|
|
111
|
+
|
|
112
|
+
tryagain:
|
|
113
|
+
/* Reset the event. */
|
|
114
|
+
if (events_network_register(callback_buf, C, C->fd,
|
|
115
|
+
EVENTS_NETWORK_OP_WRITE))
|
|
116
|
+
goto failed;
|
|
117
|
+
|
|
118
|
+
/* Callback was reset. */
|
|
119
|
+
return (0);
|
|
120
|
+
|
|
121
|
+
failed:
|
|
122
|
+
/* Invoke the callback with a failure status and return. */
|
|
123
|
+
return (docallback(C, -1));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* network_write(fd, buf, buflen, minwrite, callback, cookie):
|
|
128
|
+
* Asynchronously write up to ${buflen} bytes of data from ${buf} to ${fd}.
|
|
129
|
+
* When at least ${minwrite} bytes have been written or on error, invoke
|
|
130
|
+
* ${callback}(${cookie}, lenwrit), where lenwrit is -1 on error and the
|
|
131
|
+
* number of bytes written (between ${minwrite} and ${buflen} inclusive)
|
|
132
|
+
* otherwise. Return a cookie which can be passed to network_write_cancel in
|
|
133
|
+
* order to cancel the write.
|
|
134
|
+
*/
|
|
135
|
+
void *
|
|
136
|
+
network_write(int fd, const uint8_t * buf, size_t buflen, size_t minwrite,
|
|
137
|
+
int (* callback)(void *, ssize_t), void * cookie)
|
|
138
|
+
{
|
|
139
|
+
struct network_write_cookie * C;
|
|
140
|
+
|
|
141
|
+
/* Make sure buflen is non-zero. */
|
|
142
|
+
assert(buflen != 0);
|
|
143
|
+
|
|
144
|
+
/* Sanity-check: # bytes must fit into a ssize_t. */
|
|
145
|
+
assert(buflen <= SSIZE_MAX);
|
|
146
|
+
|
|
147
|
+
/* Bake a cookie. */
|
|
148
|
+
if ((C = malloc(sizeof(struct network_write_cookie))) == NULL)
|
|
149
|
+
goto err0;
|
|
150
|
+
C->callback = callback;
|
|
151
|
+
C->cookie = cookie;
|
|
152
|
+
C->fd = fd;
|
|
153
|
+
C->buf = buf;
|
|
154
|
+
C->buflen = buflen;
|
|
155
|
+
C->minlen = minwrite;
|
|
156
|
+
C->bufpos = 0;
|
|
157
|
+
|
|
158
|
+
/* Register a callback for network readiness. */
|
|
159
|
+
if (events_network_register(callback_buf, C, C->fd,
|
|
160
|
+
EVENTS_NETWORK_OP_WRITE))
|
|
161
|
+
goto err1;
|
|
162
|
+
|
|
163
|
+
/* Success! */
|
|
164
|
+
return (C);
|
|
165
|
+
|
|
166
|
+
err1:
|
|
167
|
+
free(C);
|
|
168
|
+
err0:
|
|
169
|
+
/* Failure! */
|
|
170
|
+
return (NULL);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* network_write_cancel(cookie):
|
|
175
|
+
* Cancel the buffer write for which the cookie ${cookie} was returned by
|
|
176
|
+
* network_write. Do not invoke the callback associated with the write.
|
|
177
|
+
*/
|
|
178
|
+
void
|
|
179
|
+
network_write_cancel(void * cookie)
|
|
180
|
+
{
|
|
181
|
+
struct network_write_cookie * C = cookie;
|
|
182
|
+
|
|
183
|
+
/* Kill the network event. */
|
|
184
|
+
events_network_cancel(C->fd, EVENTS_NETWORK_OP_WRITE);
|
|
185
|
+
|
|
186
|
+
/* Free the cookie. */
|
|
187
|
+
free(C);
|
|
188
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#include <stdarg.h>
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
#include <stdlib.h>
|
|
4
|
+
|
|
5
|
+
#include "asprintf.h"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* asprintf(ret, format, ...):
|
|
9
|
+
* Do asprintf(3) like GNU and BSD do.
|
|
10
|
+
*/
|
|
11
|
+
int
|
|
12
|
+
asprintf(char ** ret, const char * format, ...)
|
|
13
|
+
{
|
|
14
|
+
va_list ap;
|
|
15
|
+
int len;
|
|
16
|
+
size_t buflen;
|
|
17
|
+
|
|
18
|
+
/* Figure out how long the string needs to be. */
|
|
19
|
+
va_start(ap, format);
|
|
20
|
+
len = vsnprintf(NULL, 0, format, ap);
|
|
21
|
+
va_end(ap);
|
|
22
|
+
|
|
23
|
+
/* Did we fail? */
|
|
24
|
+
if (len < 0)
|
|
25
|
+
goto err0;
|
|
26
|
+
buflen = (size_t)(len) + 1;
|
|
27
|
+
|
|
28
|
+
/* Allocate memory. */
|
|
29
|
+
if ((*ret = malloc(buflen)) == NULL)
|
|
30
|
+
goto err0;
|
|
31
|
+
|
|
32
|
+
/* Actually generate the string. */
|
|
33
|
+
va_start(ap, format);
|
|
34
|
+
len = vsnprintf(*ret, buflen, format, ap);
|
|
35
|
+
va_end(ap);
|
|
36
|
+
|
|
37
|
+
/* Did we fail? */
|
|
38
|
+
if (len < 0)
|
|
39
|
+
goto err1;
|
|
40
|
+
|
|
41
|
+
/* Success! */
|
|
42
|
+
return (len);
|
|
43
|
+
|
|
44
|
+
err1:
|
|
45
|
+
free(*ret);
|
|
46
|
+
err0:
|
|
47
|
+
/* Failure! */
|
|
48
|
+
return (-1);
|
|
49
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#ifndef _ASPRINTF_H_
|
|
2
|
+
#define _ASPRINTF_H_
|
|
3
|
+
|
|
4
|
+
/* Avoid namespace collisions with BSD/GNU asprintf. */
|
|
5
|
+
#ifdef asprintf
|
|
6
|
+
#undef asprintf
|
|
7
|
+
#endif
|
|
8
|
+
#define asprintf libcperciva_asprintf
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* asprintf(ret, format, ...):
|
|
12
|
+
* Do asprintf(3) like GNU and BSD do.
|
|
13
|
+
*/
|
|
14
|
+
int asprintf(char **, const char *, ...);
|
|
15
|
+
|
|
16
|
+
#endif /* !_ASPRINTF_H_ */
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#include <errno.h>
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
#include <unistd.h>
|
|
4
|
+
|
|
5
|
+
#include "noeintr.h"
|
|
6
|
+
#include "warnp.h"
|
|
7
|
+
|
|
8
|
+
#include "daemonize.h"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* daemonize(spid):
|
|
12
|
+
* Daemonize and write the process ID in decimal to a file named ${spid}.
|
|
13
|
+
* The parent process will exit only after the child has written its pid.
|
|
14
|
+
* On success, the child will return 0; on failure, the parent will return
|
|
15
|
+
* -1.
|
|
16
|
+
*/
|
|
17
|
+
int
|
|
18
|
+
daemonize(const char * spid)
|
|
19
|
+
{
|
|
20
|
+
FILE * f;
|
|
21
|
+
int fd[2];
|
|
22
|
+
char dummy = 0;
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Create a pipe for the child to notify the parent when it has
|
|
26
|
+
* finished daemonizing.
|
|
27
|
+
*/
|
|
28
|
+
if (pipe(fd)) {
|
|
29
|
+
warnp("pipe");
|
|
30
|
+
goto err0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/*
|
|
34
|
+
* Fork into the parent process (which waits for a poke and exits)
|
|
35
|
+
* and the child process (which keeps going).
|
|
36
|
+
*/
|
|
37
|
+
switch (fork()) {
|
|
38
|
+
case -1:
|
|
39
|
+
/* Fork failed. */
|
|
40
|
+
warnp("fork");
|
|
41
|
+
goto err2;
|
|
42
|
+
case 0:
|
|
43
|
+
/* In child process. */
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
/*
|
|
47
|
+
* In parent process. Close write end of pipe so that if the
|
|
48
|
+
* client dies we will notice the pipe being reset.
|
|
49
|
+
*/
|
|
50
|
+
while (close(fd[1])) {
|
|
51
|
+
if (errno == EINTR)
|
|
52
|
+
continue;
|
|
53
|
+
warnp("close");
|
|
54
|
+
goto err1;
|
|
55
|
+
}
|
|
56
|
+
do {
|
|
57
|
+
switch (read(fd[0], &dummy, 1)) {
|
|
58
|
+
case -1:
|
|
59
|
+
/* Error in read. */
|
|
60
|
+
break;
|
|
61
|
+
case 0:
|
|
62
|
+
/* EOF -- the child died without poking us. */
|
|
63
|
+
goto err1;
|
|
64
|
+
case 1:
|
|
65
|
+
/* We have been poked by the child. Exit. */
|
|
66
|
+
_exit(0);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* Anything other than EINTR is bad. */
|
|
70
|
+
if (errno != EINTR) {
|
|
71
|
+
warnp("read");
|
|
72
|
+
goto err1;
|
|
73
|
+
}
|
|
74
|
+
} while (1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Set ourselves to be a session leader. */
|
|
78
|
+
if (setsid() == -1) {
|
|
79
|
+
warnp("setsid");
|
|
80
|
+
goto die;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Write out our pid file. */
|
|
84
|
+
if ((f = fopen(spid, "w")) == NULL) {
|
|
85
|
+
warnp("fopen(%s)", spid);
|
|
86
|
+
goto die;
|
|
87
|
+
}
|
|
88
|
+
if (fprintf(f, "%d", getpid()) < 0) {
|
|
89
|
+
warnp("fprintf");
|
|
90
|
+
goto die;
|
|
91
|
+
}
|
|
92
|
+
if (fclose(f)) {
|
|
93
|
+
warnp("fclose");
|
|
94
|
+
goto die;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Tell the parent to suicide. */
|
|
98
|
+
if (noeintr_write(fd[1], &dummy, 1) == -1) {
|
|
99
|
+
warnp("write");
|
|
100
|
+
goto die;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* Close the pipe. */
|
|
104
|
+
while (close(fd[0])) {
|
|
105
|
+
if (errno == EINTR)
|
|
106
|
+
continue;
|
|
107
|
+
warnp("close");
|
|
108
|
+
goto die;
|
|
109
|
+
}
|
|
110
|
+
while (close(fd[1])) {
|
|
111
|
+
if (errno == EINTR)
|
|
112
|
+
continue;
|
|
113
|
+
warnp("close");
|
|
114
|
+
goto die;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* Success! */
|
|
118
|
+
return (0);
|
|
119
|
+
|
|
120
|
+
err2:
|
|
121
|
+
close(fd[1]);
|
|
122
|
+
err1:
|
|
123
|
+
close(fd[0]);
|
|
124
|
+
err0:
|
|
125
|
+
/* Failure! */
|
|
126
|
+
return (-1);
|
|
127
|
+
|
|
128
|
+
die:
|
|
129
|
+
/*
|
|
130
|
+
* We're in the child and something bad happened; the parent will be
|
|
131
|
+
* notified when we die thanks to the pipe being closed.
|
|
132
|
+
*/
|
|
133
|
+
_exit(0);
|
|
134
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#include <fcntl.h>
|
|
2
|
+
#include <limits.h>
|
|
3
|
+
#include <stdint.h>
|
|
4
|
+
#include <unistd.h>
|
|
5
|
+
|
|
6
|
+
#include "warnp.h"
|
|
7
|
+
|
|
8
|
+
#include "entropy.h"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* XXX Portability
|
|
12
|
+
* XXX We obtain random bytes from the operating system by opening
|
|
13
|
+
* XXX /dev/urandom and reading them from that device; this works on
|
|
14
|
+
* XXX modern UNIX-like operating systems but not on systems like
|
|
15
|
+
* XXX win32 where there is no concept of /dev/urandom.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* entropy_read(buf, buflen):
|
|
20
|
+
* Fill the given buffer with random bytes provided by the operating system.
|
|
21
|
+
*/
|
|
22
|
+
int
|
|
23
|
+
entropy_read(uint8_t * buf, size_t buflen)
|
|
24
|
+
{
|
|
25
|
+
int fd;
|
|
26
|
+
ssize_t lenread;
|
|
27
|
+
|
|
28
|
+
/* Sanity-check the buffer size. */
|
|
29
|
+
if (buflen > SSIZE_MAX) {
|
|
30
|
+
warn0("Programmer error: "
|
|
31
|
+
"Trying to read insane amount of random data: %zu",
|
|
32
|
+
buflen);
|
|
33
|
+
goto err0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Open /dev/urandom. */
|
|
37
|
+
if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
|
|
38
|
+
warnp("open(/dev/urandom)");
|
|
39
|
+
goto err0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Read bytes until we have filled the buffer. */
|
|
43
|
+
while (buflen > 0) {
|
|
44
|
+
if ((lenread = read(fd, buf, buflen)) == -1) {
|
|
45
|
+
warnp("read(/dev/urandom)");
|
|
46
|
+
goto err1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* The random device should never EOF. */
|
|
50
|
+
if (lenread == 0) {
|
|
51
|
+
warn0("EOF on /dev/urandom?");
|
|
52
|
+
goto err1;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* We've filled a portion of the buffer. */
|
|
56
|
+
buf += lenread;
|
|
57
|
+
buflen -= lenread;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Close the device. */
|
|
61
|
+
while (close(fd) == -1) {
|
|
62
|
+
if (errno != EINTR) {
|
|
63
|
+
warnp("close(/dev/urandom)");
|
|
64
|
+
goto err0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Success! */
|
|
69
|
+
return (0);
|
|
70
|
+
|
|
71
|
+
err1:
|
|
72
|
+
close(fd);
|
|
73
|
+
err0:
|
|
74
|
+
/* Failure! */
|
|
75
|
+
return (-1);
|
|
76
|
+
}
|