aboutsummaryrefslogtreecommitdiffstats
path: root/propagate/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'propagate/src/util.c')
-rw-r--r--propagate/src/util.c233
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;
+}