ratox

FIFO based tox client
git clone git://git.2f30.org/ratox
Log | Files | Refs | README | LICENSE

commit 99b652c0c07c6acf81b6a8cf36a107be76fbe98d
parent 9ec6ecb6fc5ef2551b705aa01c01dbe880696881
Author: FRIGN <dev@frign.de>
Date:   Thu, 18 Sep 2014 11:22:29 +0200

Add fifos for incoming requests and remove cmd-parser

Diffstat:
Mratox.c | 206++++++++++++++++++++-----------------------------------------------------------
1 file changed, 51 insertions(+), 155 deletions(-)

diff --git a/ratox.c b/ratox.c @@ -4,6 +4,7 @@ #include <sys/types.h> #include <ctype.h> +#include <dirent.h> #include <errno.h> #include <fcntl.h> #include <limits.h> @@ -129,6 +130,7 @@ struct request { char idstr[2 * TOX_CLIENT_ID_SIZE + 1]; /* null terminated friend request message */ char *msgstr; + int fd; TAILQ_ENTRY(request) entry; }; @@ -158,70 +160,9 @@ static void id2str(uint8_t *, char *); static void str2id(char *, uint8_t *); static struct friend *friendcreate(int32_t); static void friendload(void); -static int cmdrun(void); -static int cmdaccept(char *, size_t); -static int cmdhelp(char *, size_t); static void writeline(const char *, const char *, const char *, ...); static void loop(void); -static char qsep[] = " \t\r\n"; - -/* tokenization routines taken from Plan9 */ -static char * -qtoken(char *s, char *sep) -{ - int quoting; - char *t; - - quoting = 0; - t = s; /* s is output string, t is input string */ - while(*t!='\0' && (quoting || strchr(sep, *t)==NULL)) { - if(*t != '\'') { - *s++ = *t++; - continue; - } - /* *t is a quote */ - if(!quoting) { - quoting = 1; - t++; - continue; - } - /* quoting and we're on a quote */ - if(t[1] != '\'') { - /* end of quoted section; absorb closing quote */ - t++; - quoting = 0; - continue; - } - /* doubled quote; fold one quote into two */ - t++; - *s++ = *t++; - } - if(*s != '\0') { - *s = '\0'; - if(t == s) - t++; - } - return t; -} - -static int -tokenize(char *s, char **args, int maxargs) -{ - int nargs; - - for(nargs=0; nargs<maxargs; nargs++) { - while(*s!='\0' && strchr(qsep, *s)!=NULL) - s++; - if(*s == '\0') - break; - args[nargs] = s; - s = qtoken(s, qsep); - } - - return nargs; -} - static void printrat(void) { @@ -309,6 +250,7 @@ static void cbfriendrequest(Tox *m, const uint8_t *id, const uint8_t *data, uint16_t len, void *udata) { struct request *req; + int r; req = calloc(1, sizeof(*req)); if (!req) { @@ -328,6 +270,18 @@ cbfriendrequest(Tox *m, const uint8_t *id, const uint8_t *data, uint16_t len, vo req->msgstr[len] = '\0'; } + r = mkfifoat(gslots[REQUEST].fd[OUT], req->idstr, 0644); + if (r < 0 && errno != EEXIST) { + perror("mkfifoat"); + exit(EXIT_FAILURE); + } + r = openat(gslots[REQUEST].fd[OUT], req->idstr, O_RDWR | O_NONBLOCK); + if (r < 0) { + perror("open"); + exit(EXIT_FAILURE); + } + req->fd = r; + TAILQ_INSERT_TAIL(&reqhead, req, entry); printout("Pending request from %s with message: %s\n", @@ -586,6 +540,7 @@ localinit(void) uint8_t address[TOX_FRIEND_ADDRESS_SIZE]; uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH + 1]; FILE *fp; + DIR *d; int r; size_t i, m; @@ -627,7 +582,17 @@ localinit(void) perror("mkdir"); exit(EXIT_FAILURE); } - gslots[i].fd[m] = 0; + d = opendir(gfiles[m].name); + if (!d) { + perror("opendir"); + exit(EXIT_FAILURE); + } + r = dirfd(d); + if (r < 0) { + perror("dirfd"); + exit(EXIT_FAILURE); + } + gslots[i].fd[m] = r; } } } @@ -807,94 +772,6 @@ friendload(void) free(fids); } -struct cmd { - const char *cmd; - int (*cb)(char *, size_t); - const char *usage; -} cmds[] = { - { .cmd = "a", .cb = cmdaccept, .usage = "usage: a [id]\tAccept or list pending requests\n" }, - { .cmd = "h", .cb = cmdhelp, .usage = NULL }, -}; - -static int -cmdaccept(char *cmd, size_t sz) -{ - struct request *req, *tmp; - char *args[2]; - int r; - int found = 0; - - r = tokenize(cmd, args, 2); - - if (r == 1) { - TAILQ_FOREACH(req, &reqhead, entry) { - printout("Pending request from %s with message: %s\n", - req->idstr, req->msgstr); - found = 1; - } - if (found == 0) - printf("No pending requests\n"); - } else { - for (req = TAILQ_FIRST(&reqhead); req; req = tmp) { - tmp = TAILQ_NEXT(req, entry); - if (strcmp(req->idstr, args[1]) == 0) { - tox_add_friend_norequest(tox, req->id); - printout("Accepted friend request for %s\n", req->idstr); - datasave(); - TAILQ_REMOVE(&reqhead, req, entry); - free(req->msgstr); - free(req); - break; - } - } - } - - return 0; -} - -static int -cmdhelp(char *cmd, size_t sz) -{ - size_t i; - - for (i = 0; i < LEN(cmds); i++) - if (cmds[i].usage) - fprintf(stderr, "%s", cmds[i].usage); - return 0; -} - -static int -cmdrun(void) -{ - char cmd[BUFSIZ]; - ssize_t n; - size_t i; - -again: - n = read(STDIN_FILENO, cmd, sizeof(cmd) - 1); - if (n < 0) { - if (errno == EINTR) - goto again; - perror("read"); - exit(EXIT_FAILURE); - } - if (n == 0) - return 0; - cmd[n] = '\0'; - if (cmd[strlen(cmd) - 1] == '\n') - cmd[strlen(cmd) - 1] = '\0'; - if (cmd[0] == '\0') - return 0; - - for (i = 0; i < LEN(cmds); i++) - if (cmd[0] == cmds[i].cmd[0]) - if (cmd[1] == '\0' || isspace((int)cmd[1])) - return (*cmds[i].cb)(cmd, strlen(cmd)); - - fprintf(stderr, "Unknown command '%s', type h for help\n", cmd); - return -1; -} - static void writeline(const char *path, const char *mode, const char *fmt, ...) @@ -1034,10 +911,12 @@ static void loop(void) { struct friend *f; + struct request *r; time_t t0, t1, now; int connected = 0; int i, n; int fdmax; + char c; fd_set rfds; struct timeval tv; @@ -1062,8 +941,6 @@ loop(void) tox_do(tox); FD_ZERO(&rfds); - FD_SET(STDIN_FILENO, &rfds); - fdmax = STDIN_FILENO; for (i = 0; i < LEN(gslots); i++) { FD_SET(gslots[i].fd[IN], &rfds); @@ -1071,6 +948,12 @@ loop(void) fdmax = gslots[i].fd[IN]; } + TAILQ_FOREACH(r, &reqhead, entry) { + FD_SET(r->fd, &rfds); + if(r->fd > fdmax) + fdmax = r->fd; + } + TAILQ_FOREACH(f, &friendhead, entry) { /* Only monitor friends that are online */ if (tox_get_friend_connection_status(tox, f->fid) == 1) { @@ -1164,15 +1047,28 @@ loop(void) if (n == 0) continue; - if (FD_ISSET(STDIN_FILENO, &rfds) != 0) - cmdrun(); - for (i = 0; i < LEN(gslots); i++) { if (FD_ISSET(gslots[i].fd[IN], &rfds) == 0) continue; (*gslots[i].cb)(NULL); } + TAILQ_FOREACH(r, &reqhead, entry) { + if (FD_ISSET(r->fd, &rfds) == 0) + continue; + if (read(r->fd, &c, 1) != 1 || c != '1') { + continue; + } + tox_add_friend_norequest(tox, r->id); + printout("Accepted friend request for %s\n", r->idstr); + datasave(); + close(r->fd); + unlinkat(gslots[REQUEST].fd[OUT], r->idstr, 0); + TAILQ_REMOVE(&reqhead, r, entry); + free(r->msgstr); + free(r); + } + TAILQ_FOREACH(f, &friendhead, entry) { for (i = 0; i < NR_FFIFOS; i++) { if (FD_ISSET(f->fd[i], &rfds) == 0)