1/* 2 * $Id: restart.c,v 1.1 2009-06-30 02:31:09 steven Exp $ 3 * Restart Library 4 * 5 * ** NOTICE ** 6 * 7 * This code is written by (and is therefore copyright) Dr Kay Robbins 8 * (krobbins@cs.utsa.edu) and Dr. Steve Robbins (srobbins@cs.utsa.edu), 9 * and was released with unspecified licensing as part of their book 10 * _UNIX_Systems_Programming_ (Prentice Hall, ISBN: 0130424110). 11 * 12 * Dr. Steve Robbins was kind enough to allow me to re-license this 13 * software as GPL. I would request that any bugs or problems with 14 * this code be brought to my attention (ron@pedde.com), and I will 15 * submit appropriate patches upstream, should the problem be with 16 * the original code. 17 * 18 * ** NOTICE ** 19 * 20 * This program is free software; you can redistribute it and/or modify 21 * it under the terms of the GNU General Public License as published by 22 * the Free Software Foundation; either version 2 of the License, or 23 * (at your option) any later version. 24 * 25 * This program is distributed in the hope that it will be useful, 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 * GNU General Public License for more details. 29 * 30 * You should have received a copy of the GNU General Public License 31 * along with this program; if not, write to the Free Software 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 33 */ 34 35#include <errno.h> 36#include <fcntl.h> 37#include <limits.h> 38#include <string.h> 39#include <sys/select.h> 40#include <sys/time.h> 41#include <sys/wait.h> 42#include "err.h" 43#include "restart.h" 44#define BLKSIZE PIPE_BUF 45#define MILLION 1000000L 46#define D_MILLION 1000000.0 47 48/* Private functions */ 49 50static int gettimeout(struct timeval end, 51 struct timeval *timeoutp) { 52 gettimeofday(timeoutp, NULL); 53 timeoutp->tv_sec = end.tv_sec - timeoutp->tv_sec; 54 timeoutp->tv_usec = end.tv_usec - timeoutp->tv_usec; 55 if (timeoutp->tv_usec >= MILLION) { 56 timeoutp->tv_sec++; 57 timeoutp->tv_usec -= MILLION; 58 } 59 if (timeoutp->tv_usec < 0) { 60 timeoutp->tv_sec--; 61 timeoutp->tv_usec += MILLION; 62 } 63 if ((timeoutp->tv_sec < 0) || 64 ((timeoutp->tv_sec == 0) && (timeoutp->tv_usec == 0))) { 65 errno = ETIME; 66 return -1; 67 } 68 return 0; 69} 70 71/* Restart versions of traditional functions */ 72 73int r_close(int fildes) { 74 int retval; 75 while (retval = close(fildes), retval == -1 && errno == EINTR) ; 76 return retval; 77} 78 79int r_dup2(int fildes, int fildes2) { 80 int retval; 81 while (retval = dup2(fildes, fildes2), retval == -1 && errno == EINTR) ; 82 return retval; 83} 84 85 86int r_open2(const char *path, int oflag) { 87 int retval; 88 while (retval = open(path, oflag), retval == -1 && errno == EINTR) ; 89 return retval; 90} 91 92int r_open3(const char *path, int oflag, mode_t mode) { 93 int retval; 94 while (retval = open(path, oflag, mode), retval == -1 && errno == EINTR) ; 95 return retval; 96} 97 98ssize_t r_read(int fd, void *buf, size_t size) { 99 ssize_t retval; 100 while (((retval = read(fd, buf, size)) == -1) && (errno==EINTR)) {}; 101 return retval; 102} 103 104pid_t r_wait(int *stat_loc) { 105 pid_t retval; 106 while (((retval = wait(stat_loc)) == -1) && (errno == EINTR)) ; 107 return retval; 108} 109 110pid_t r_waitpid(pid_t pid, int *stat_loc, int options) { 111 pid_t retval; 112 while (((retval = waitpid(pid, stat_loc, options)) == -1) && 113 (errno == EINTR)) ; 114 return retval; 115} 116 117ssize_t r_write(int fd, void *buf, size_t size) { 118 char *bufp; 119 size_t bytestowrite; 120 ssize_t byteswritten; 121 size_t totalbytes; 122 123 for (bufp = buf, bytestowrite = size, totalbytes = 0; 124 bytestowrite > 0; 125 bufp += byteswritten, bytestowrite -= byteswritten) { 126 byteswritten = write(fd, bufp, bytestowrite); 127 if ((byteswritten) == -1 && (errno != EINTR)) 128 return -1; 129 if (byteswritten == -1) 130 byteswritten = 0; 131 totalbytes += byteswritten; 132 } 133 return totalbytes; 134} 135 136/* Utility functions */ 137 138struct timeval add2currenttime(double seconds) { 139 struct timeval newtime; 140 141 gettimeofday(&newtime, NULL); 142 newtime.tv_sec += (int)seconds; 143 newtime.tv_usec += (int)((seconds - (int)seconds)*D_MILLION + 0.5); 144 if (newtime.tv_usec >= MILLION) { 145 newtime.tv_sec++; 146 newtime.tv_usec -= MILLION; 147 } 148 return newtime; 149} 150 151int copyfile(int fromfd, int tofd) { 152 int bytesread; 153 int totalbytes = 0; 154 155 while ((bytesread = readwrite(fromfd, tofd)) > 0) 156 totalbytes += bytesread; 157 return totalbytes; 158} 159 160ssize_t readblock(int fd, void *buf, size_t size) { 161 char *bufp; 162 ssize_t bytesread; 163 size_t bytestoread; 164 size_t totalbytes; 165 166 for (bufp = buf, bytestoread = size, totalbytes = 0; 167 bytestoread > 0; 168 bufp += bytesread, bytestoread -= bytesread) { 169 bytesread = read(fd, bufp, bytestoread); 170 if ((bytesread == 0) && (totalbytes == 0)) 171 return 0; 172 if (bytesread == 0) { 173 errno = EINVAL; 174 return -1; 175 } 176 if ((bytesread) == -1 && (errno != EINTR)) 177 return -1; 178 if (bytesread == -1) 179 bytesread = 0; 180 totalbytes += bytesread; 181 } 182 return totalbytes; 183} 184 185int readline(int fd, char *buf, int nbytes) { 186 int numread = 0; 187 int returnval; 188 189 while (numread < nbytes - 1) { 190 returnval = read(fd, buf + numread, 1); 191 if ((returnval == -1) && (errno == EINTR)) 192 continue; 193 if ((returnval == 0) && (numread == 0)) 194 return 0; 195 if (returnval == 0) 196 break; 197 if (returnval == -1) 198 return -1; 199 numread++; 200 if (buf[numread-1] == '\n') { 201 buf[numread] = '\0'; 202 return numread; 203 } 204 } 205 errno = EINVAL; 206 return -1; 207} 208 209int readlinetimed(int fd, char *buf, int nbytes, double seconds) { 210 int numread = 0; 211 int returnval; 212 213 while (numread < nbytes - 1) { 214 returnval = (int)readtimed(fd, buf + numread, 1, seconds); 215 if ((returnval == -1) && (errno == EINTR)) 216 continue; 217 if ((returnval == 0) && (numread == 0)) 218 return 0; 219 if (returnval == 0) 220 break; 221 if (returnval == -1) 222 return -1; 223 numread++; 224 if (buf[numread-1] == '\n') { 225 buf[numread] = '\0'; 226 return numread; 227 } 228 } 229 errno = EINVAL; 230 return -1; 231} 232 233ssize_t readtimed(int fd, void *buf, size_t nbyte, double seconds) { 234 struct timeval timedone; 235 236 timedone = add2currenttime(seconds); 237 if (waitfdtimed(fd, timedone) == -1) 238 return (ssize_t)(-1); 239 return r_read(fd, buf, nbyte); 240} 241 242int readwrite(int fromfd, int tofd) { 243 char buf[BLKSIZE]; 244 int bytesread; 245 246 if ((bytesread = r_read(fromfd, buf, BLKSIZE)) < 0) 247 return -1; 248 if (bytesread == 0) 249 return 0; 250 if (r_write(tofd, buf, bytesread) < 0) 251 return -1; 252 return bytesread; 253} 254 255int readwriteblock(int fromfd, int tofd, char *buf, int size) { 256 int bytesread; 257 258 bytesread = readblock(fromfd, buf, size); 259 if (bytesread != size) /* can only be 0 or -1 */ 260 return bytesread; 261 return r_write(tofd, buf, size); 262} 263 264int waitfdtimed(int fd, struct timeval end) { 265 fd_set readset; 266 int retval; 267 struct timeval timeout; 268 269 if ((fd < 0) || (fd >= FD_SETSIZE)) { 270 errno = EINVAL; 271 return -1; 272 } 273 FD_ZERO(&readset); 274 FD_SET(fd, &readset); 275 if (gettimeout(end, &timeout) == -1) 276 return -1; 277 while (((retval = select(fd+1, &readset, NULL, NULL, &timeout)) == -1) 278 && (errno == EINTR)) { 279 if (gettimeout(end, &timeout) == -1) 280 return -1; 281 FD_ZERO(&readset); 282 FD_SET(fd, &readset); 283 } 284 if (retval == 0) { 285 errno = ETIME; 286 return -1; 287 } 288 if (retval == -1) 289 return -1; 290 return 0; 291} 292