1 // This file is basically utility functions from various places mashed together, including
2 // from my helper library libjh.
9 #include <sys/select.h>
12 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <netinet/tcp.h>
22 #define JH_TCP_HINTS (&libjh_tcp_hints)
23 const struct addrinfo libjh_tcp_hints = {
24 .ai_flags = AI_ADDRCONFIG,
25 .ai_family = AF_UNSPEC,
26 .ai_socktype = SOCK_STREAM,
30 int netopen_server(const char *node /*NULL for ANY*/, const char *service, const struct addrinfo *hints) {
31 struct addrinfo hints_;
32 if (hints == &libjh_tcp_hints) {
34 hints_.ai_flags |= AI_PASSIVE;
35 hints_.ai_flags &= ~AI_ADDRCONFIG;
39 struct addrinfo *addrs;
40 int gai_res = getaddrinfo(node, service, hints, &addrs);
41 if (gai_res) return gai_res;
43 int s = socket(addrs[0].ai_family, addrs[0].ai_socktype, addrs[0].ai_protocol);
44 if (s == -1) goto err_socket;
46 if (bind(s, addrs[0].ai_addr, addrs[0].ai_addrlen)) goto err_bind_n_listen;
47 if (listen(s, 16)) goto err_bind_n_listen;
61 ssize_t read_nointr(int fd, void *buf, size_t count, int *last_res) {
64 while (done < count) {
65 ssize_t part_res = read(fd, buf+done, count-done);
66 if (part_res == -1 && errno == EINTR) continue;
68 if (last_res) *last_res = part_res;
69 if (done) return done;
74 if (last_res) *last_res = 1;
78 void *slurp_fd(int fd, size_t *len_out) {
84 if (fstat(fd, &st) == 0) {
86 size_guess = st.st_size;
94 buf = realloc(buf, size_guess);
95 if (buf == NULL) return NULL;
97 ssize_t read_res = read_nointr(fd, buf+done, size_guess-done, &last_res);
98 if (last_res == -1) { errno_=errno; free(buf); errno=errno_; return NULL; }
100 if (len_out) *len_out = done;
105 void *slurp_file(char *path, size_t *len_out) {
106 int fd = open(path, O_RDONLY|O_CLOEXEC);
107 if (fd == -1) return NULL;
108 char *res = slurp_fd(fd, len_out);
115 time_t real_seconds(void) {
117 int s = clock_gettime(CLOCK_REALTIME, &t);
122 /* Subtract the `struct timeval' values X and Y,
123 storing the result in RESULT.
124 Return 1 if the difference is negative, otherwise 0. */
125 int timespec_subtract(struct timespec *result, struct timespec *x, struct timespec *y) {
126 /* Perform the carry for the later subtraction by updating y. */
127 if (x->tv_nsec < y->tv_nsec) {
128 int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
129 y->tv_nsec -= 1000000000 * nsec;
132 if (x->tv_nsec - y->tv_nsec > 1000000000) {
133 int nsec = (x->tv_nsec - y->tv_nsec) / 1000000000;
134 y->tv_nsec += 1000000000 * nsec;
138 /* Compute the time remaining to wait.
139 tv_usec is certainly positive. */
140 result->tv_sec = x->tv_sec - y->tv_sec;
141 result->tv_nsec = x->tv_nsec - y->tv_nsec;
143 /* Return 1 if result is negative. */
144 return x->tv_sec < y->tv_sec;
147 void sleep_until(time_t dst_sec) {
149 dst.tv_sec = dst_sec;
151 while (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &dst, NULL)) /* nothing */;
154 time_t round_up(time_t t, int align) {
155 t = t - 1; /* counter bad +t for aligned things in last step */
156 t = t - t%align; /* round down to align */
157 t = t + align; /* add alignment to make it a round up */