-
Notifications
You must be signed in to change notification settings - Fork 0
/
restart.c
232 lines (202 loc) · 5.57 KB
/
restart.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/wait.h>
#include "restart.h"
#define BLKSIZE PIPE_BUF
#define MILLION 1000000L
#define D_MILLION 1000000.0
/* Private functions */
static int gettimeout(struct timeval end,
struct timeval *timeoutp) {
gettimeofday(timeoutp, NULL);
timeoutp->tv_sec = end.tv_sec - timeoutp->tv_sec;
timeoutp->tv_usec = end.tv_usec - timeoutp->tv_usec;
if (timeoutp->tv_usec >= MILLION) {
timeoutp->tv_sec++;
timeoutp->tv_usec -= MILLION;
}
if (timeoutp->tv_usec < 0) {
timeoutp->tv_sec--;
timeoutp->tv_usec += MILLION;
}
if ((timeoutp->tv_sec < 0) ||
((timeoutp->tv_sec == 0) && (timeoutp->tv_usec == 0))) {
errno = ETIME;
return -1;
}
return 0;
}
/* Restart versions of traditional functions */
int r_close(int fildes) {
int retval;
while (retval = close(fildes), retval == -1 && errno == EINTR) ;
return retval;
}
int r_dup2(int fildes, int fildes2) {
int retval;
while (retval = dup2(fildes, fildes2), retval == -1 && errno == EINTR) ;
return retval;
}
int r_open2(const char *path, int oflag) {
int retval;
while (retval = open(path, oflag), retval == -1 && errno == EINTR) ;
return retval;
}
int r_open3(const char *path, int oflag, mode_t mode) {
int retval;
while (retval = open(path, oflag, mode), retval == -1 && errno == EINTR) ;
return retval;
}
ssize_t r_read(int fd, void *buf, size_t size) {
ssize_t retval;
while (retval = read(fd, buf, size), retval == -1 && errno == EINTR) ;
return retval;
}
pid_t r_wait(int *stat_loc) {
pid_t retval;
while (((retval = wait(stat_loc)) == -1) && (errno == EINTR)) ;
return retval;
}
pid_t r_waitpid(pid_t pid, int *stat_loc, int options) {
pid_t retval;
while (((retval = waitpid(pid, stat_loc, options)) == -1) &&
(errno == EINTR)) ;
return retval;
}
ssize_t r_write(int fd, void *buf, size_t size) {
char *bufp;
size_t bytestowrite;
ssize_t byteswritten;
size_t totalbytes;
for (bufp = buf, bytestowrite = size, totalbytes = 0;
bytestowrite > 0;
bufp += byteswritten, bytestowrite -= byteswritten) {
byteswritten = write(fd, bufp, bytestowrite);
if ((byteswritten) == -1 && (errno != EINTR))
return -1;
if (byteswritten == -1)
byteswritten = 0;
totalbytes += byteswritten;
}
return totalbytes;
}
/* Utility functions */
struct timeval add2currenttime(double seconds) {
struct timeval newtime;
gettimeofday(&newtime, NULL);
newtime.tv_sec += (int)seconds;
newtime.tv_usec += (int)((seconds - (int)seconds)*D_MILLION + 0.5);
if (newtime.tv_usec >= MILLION) {
newtime.tv_sec++;
newtime.tv_usec -= MILLION;
}
return newtime;
}
int copyfile(int fromfd, int tofd) {
int bytesread;
int totalbytes = 0;
while ((bytesread = readwrite(fromfd, tofd)) > 0)
totalbytes += bytesread;
return totalbytes;
}
ssize_t readblock(int fd, void *buf, size_t size) {
char *bufp;
ssize_t bytesread;
size_t bytestoread;
size_t totalbytes;
for (bufp = buf, bytestoread = size, totalbytes = 0;
bytestoread > 0;
bufp += bytesread, bytestoread -= bytesread) {
bytesread = read(fd, bufp, bytestoread);
if ((bytesread == 0) && (totalbytes == 0))
return 0;
if (bytesread == 0) {
errno = EINVAL;
return -1;
}
if ((bytesread) == -1 && (errno != EINTR))
return -1;
if (bytesread == -1)
bytesread = 0;
totalbytes += bytesread;
}
return totalbytes;
}
int readline(int fd, char *buf, int nbytes) {
int numread = 0;
int returnval;
while (numread < nbytes - 1) {
returnval = read(fd, buf + numread, 1);
if ((returnval == -1) && (errno == EINTR))
continue;
if ((returnval == 0) && (numread == 0))
return 0;
if (returnval == 0)
break;
if (returnval == -1)
return -1;
numread++;
if (buf[numread-1] == '\n') {
buf[numread] = '\0';
return numread;
}
}
errno = EINVAL;
return -1;
}
ssize_t readtimed(int fd, void *buf, size_t nbyte, double seconds) {
struct timeval timedone;
timedone = add2currenttime(seconds);
if (waitfdtimed(fd, timedone) == -1)
return (ssize_t)(-1);
return r_read(fd, buf, nbyte);
}
int readwrite(int fromfd, int tofd) {
char buf[BLKSIZE];
int bytesread;
if ((bytesread = r_read(fromfd, buf, BLKSIZE)) < 0)
return -1;
if (bytesread == 0)
return 0;
if (r_write(tofd, buf, bytesread) < 0)
return -1;
return bytesread;
}
int readwriteblock(int fromfd, int tofd, char *buf, int size) {
int bytesread;
bytesread = readblock(fromfd, buf, size);
if (bytesread != size) /* can only be 0 or -1 */
return bytesread;
return r_write(tofd, buf, size);
}
int waitfdtimed(int fd, struct timeval end) {
fd_set readset;
int retval;
struct timeval timeout;
if ((fd < 0) || (fd >= FD_SETSIZE)) {
errno = EINVAL;
return -1;
}
FD_ZERO(&readset);
FD_SET(fd, &readset);
if (gettimeout(end, &timeout) == -1)
return -1;
while (((retval = select(fd+1, &readset, NULL, NULL, &timeout)) == -1)
&& (errno == EINTR)) {
if (gettimeout(end, &timeout) == -1)
return -1;
FD_ZERO(&readset);
FD_SET(fd, &readset);
}
if (retval == 0) {
errno = ETIME;
return -1;
}
if (retval == -1)
return -1;
return 0;
}