diff options
Diffstat (limited to 'propagate/src/util.c')
-rw-r--r-- | propagate/src/util.c | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/propagate/src/util.c b/propagate/src/util.c new file mode 100644 index 0000000..646492a --- /dev/null +++ b/propagate/src/util.c @@ -0,0 +1,233 @@ +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> + +#include <string.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <errno.h> + +#include "pg.h" +#include "atomicio.h" + +int +send_cmd(char dest, int type, uint8_t arg, uint8_t *data, int data_len) { + struct conn *c; + struct route *r; + int fd = -1, len; + + r = route_find(dest); + if (r) + fd = r->proc.fd[1]; + else { + c = listener_conn_find_orig(dest); + if (c) + fd = c->fd; + else { + log_warn("send_cmd %d: no route to go to dest %c", type, dest); + return -1; + } + } + len = msg_send(fd, type, dest, arg, data_len, data); + + return len; +} + +int +intab(int *tab, int val, int len) { + int n; + + for (n=0; n<len; n++) { + if (tab[n] == val) + return n; + } + return -1; +} + +char ** +explode(char *str, int len_str, char *delim, int *n_tokens) { + char *token, *saveptr; + char *to_explode; + char **exploded; + int idx_str, idx_delim; + int len_delim; + int c_tokens; + + if (!str || len_str <= 0 || !delim || !n_tokens) + return NULL; + + to_explode = xcalloc(len_str, sizeof(*to_explode)); + if (!to_explode) + return NULL; + memcpy(to_explode, str, len_str); + + /* count n_tokens */ + len_delim = strlen(delim); + c_tokens = 1; + for (idx_str = 0; idx_str < len_str; idx_str++) { + for (idx_delim = 0; idx_delim < len_delim; idx_delim++) { + if (str[idx_str] == delim[idx_delim]) + c_tokens++; + } + } + c_tokens++; + + /* copy str (strdup() does not seem to be reliable) */ + exploded = xcalloc(c_tokens, sizeof(*exploded)); + if (!exploded) { + free(to_explode); + return NULL; + } + + /* sep tokens */ + *n_tokens = 0; + token = strtok_r(to_explode, delim, &saveptr); + while (token) { + exploded[*n_tokens] = token; + (*n_tokens)++; + token = strtok_r(NULL, delim, &saveptr); + } + exploded[*n_tokens] = NULL; + + return exploded; +} + +void +*xmalloc(size_t size) { + void *p; + + if (size == 0) { + log_warn("attempted to malloc(0)"); + return NULL; + } + p = malloc(size); + if (!p) + log_warn("malloc(%d) failed", size); + + return p; +} + +void * +xcalloc(size_t nmemb, size_t size) { + void *p; + + if (nmemb == 0 || size == 0) { + log_warn("attempted to calloc(%d,%d)", nmemb, size); + return NULL; + } + p = calloc(nmemb, size); + if (!p) + log_warn("calloc(%d,%d) failed", nmemb, size); + + return p; +} + +int +setnonblock(int fd) { + int flags; + int ret; + + log_debug("nonblock %d", fd); + if ((flags = fcntl(fd, F_GETFL, 0)) == -1) + flags = 0; + ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if (ret < 0 ) + log_warn("fcntl setnonblock err : %s", strerror(errno)); + + return ret; +} + +int +execpipe(char *cmd, char **argv, int *pipes) { + int pipe_in[2], pipe_out[2]; + pid_t pid; + + pipe(pipe_in); + pipe(pipe_out); + + pid = fork(); + if (pid == -1) { + log_warn("failed to fork !"); + return -1; + } + + if (pid == 0) { + close(pipe_in[0]); + dup2(pipe_in[1], fileno(stdout)); + close(pipe_in[1]); // XXX correct ? + close(pipe_out[1]); + dup2(pipe_out[0], fileno(stdin)); + close(pipe_out[0]); // XXX correct ? + if (execvp(cmd, argv) == -1) { + log_warn("execpipe child: failed to execute %s %s : %d", cmd, argv, errno); + exit(1); + } + + /* NOT REACHED */ + } + + pipes[0] = pipe_in[0]; + pipes[1] = pipe_out[1]; + + return pid; +} + +int +readbuf(int fd, uint8_t **out, int len) { + uint8_t buf[BUFMAX]; + int outlen; + + if (len > sizeof(buf)) { + log_warn("readbuf: len too big %d", len); + return -1; + } + if ((outlen = atomicio(read, fd, buf, len)) < 0) { + log_warn("readbuf: atomicio read error"); + return -1; + } + if (outlen != len) + log_warn("readbuf: invalid atomicio read size %d, should be %d", + outlen, len); + + *out = buf; + return outlen; +} + +int +writebuf(uint8_t *buf, int fd, int len) { + int writelen; + + if ((writelen = atomicio(vwrite, fd, buf, len)) < 0) { + log_warn("writebuf: atomicio write error"); + return -1; + } + if (writelen < len) + log_warn("writebuf: incomplete write, %d on %d", + writelen, len); + + return writelen; +} + +int +readwrite(int ifd, int ofd, int len) { + char buf[BUFMAX]; + int red, wrote; + + red = atomicio(read, ifd, buf, len); + if (red < 0) { + log_warn("readwrite: atomicio read error"); + return -1; + } + if (red != len) + log_warn("readbuf: invalid atomicio read size %d, should be %d", + red, len); + + if ((wrote = atomicio(vwrite, ofd, buf, red)) < red) { + log_warn("readwrite: atomicio write error"); + return -1; + } + + return wrote; +} |