aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs6/s6-ftrigrd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs6/s6-ftrigrd.c')
-rw-r--r--src/libs6/s6-ftrigrd.c312
1 files changed, 113 insertions, 199 deletions
diff --git a/src/libs6/s6-ftrigrd.c b/src/libs6/s6-ftrigrd.c
index 5b5ffd9..a037e31 100644
--- a/src/libs6/s6-ftrigrd.c
+++ b/src/libs6/s6-ftrigrd.c
@@ -1,293 +1,207 @@
/* ISC license. */
-#include <sys/uio.h>
#include <string.h>
#include <stdint.h>
+#include <unistd.h>
#include <errno.h>
+#include <fcntl.h>
#include <signal.h>
#include <regex.h>
+#include <stdio.h>
#include <skalibs/posixplz.h>
-#include <skalibs/types.h>
#include <skalibs/allreadwrite.h>
-#include <skalibs/error.h>
-#include <skalibs/strerr.h>
#include <skalibs/buffer.h>
-#include <skalibs/alloc.h>
+#include <skalibs/strerr.h>
#include <skalibs/stralloc.h>
-#include <skalibs/genalloc.h>
#include <skalibs/sig.h>
#include <skalibs/tai.h>
#include <skalibs/djbunix.h>
#include <skalibs/iopause.h>
-#include <skalibs/textmessage.h>
-#include <skalibs/textclient.h>
+#include <skalibs/sassserver.h>
-#include "ftrig1.h"
-#include <s6/ftrigr.h>
+#include "ftrigr-internal.h"
#include <skalibs/posixishard.h>
#define FTRIGRD_MAXREADS 32
-#define FTRIGRD_BUFSIZE 16
+#define FTRIGRD_BUFSIZE 32
#define dienomem() strerr_diefu1sys(111, "stralloc_catb")
typedef struct ftrigio_s ftrigio, *ftrigio_ref ;
struct ftrigio_s
{
+ ftrigio_ref prev ;
+ ftrigio_ref next ;
unsigned int xindex ;
- ftrig1_t trig ;
+ uint32_t id ;
+ uint32_t flags ;
buffer b ;
- regex_t re ;
+ char buf[FTRIGRD_BUFSIZE] ;
+ int fdw ;
+ size_t start ;
stralloc sa ;
- uint32_t options ;
- uint16_t id ; /* given by client */
+ regex_t re ;
} ;
-#define FTRIGIO_ZERO { .xindex = 0, .trig = FTRIG1_ZERO, .b = BUFFER_INIT(0, -1, 0, 0), .buf = "", .sa = STRALLOC_ZERO, .options = 0, .id = 0 }
+#define FTRIGIO_ZERO { .prev = 0, .next = 0, .xindex = 0, .id = 0, .flags = 0, .b = BUFFER_INIT(0, -1, 0, 0), .buf = "", .fdw = -1, .start = 0, .sa = STRALLOC_ZERO }
-static genalloc g = GENALLOC_ZERO ; /* ftrigio */
+static ftrigio ftrigio_head = { .prev = &ftrigio_head, .next = &ftrigio_head, .start = 0, .sa = STRALLOC_ZERO } ;
+#define numio (ftrigio_head.start)
-static void ftrigio_free (ftrigio *p)
+static void cleanup (void *x)
{
- alloc_free(p->b.c.x) ;
- ftrig1_free(&p->trig) ;
- stralloc_free(&p->sa) ;
- regfree(&p->re) ;
+ (void)x ;
+ for (ftrigio *p = ftrigio_head.next ; p != &ftrigio_head ; p = p->next)
+ unlink_void(p->sa.s) ;
}
-static void cleanup (void)
+static void ftrigio_remove (void *x)
{
- size_t n = genalloc_len(ftrigio, &g) ;
- ftrigio *a = genalloc_s(ftrigio, &g) ;
- for (size_t i = 0 ; i < n ; i++) ftrigio_free(a + i) ;
- genalloc_setlen(ftrigio, &g, 0) ;
+ ftrigio *p = x ;
+ p->next->prev = p->prev ;
+ p->prev->next = p->next ;
+ numio-- ;
+ p->prev = p->next = 0 ;
+ unlink_void(p->sa.s) ;
+ fd_close(p->fdw) ;
+ fd_close(buffer_fd(&p->b)) ;
+ p->sa.len = 0 ;
+ regfree(&p->re) ;
}
-static void trig (uint16_t id, char what, char info)
+static int ftrigio_add (void *x, uint32_t id, uint32_t flags, uint32_t opcode, char const *s, size_t len)
{
- char pack[4] ;
- uint16_pack_big(pack, id) ;
- pack[2] = what ; pack[3] = info ;
- if (!textmessage_put(textmessage_sender_x, pack, 4))
- {
- cleanup() ;
- strerr_diefu1sys(111, "build answer") ;
- }
-}
+ ftrigio *p = x ;
+ size_t pathlen ;
+ if (len < 3 || s[len - 1]) return EPROTO ;
+ pathlen = strlen(s) ;
+ if (pathlen + 1 >= len) return EPROTO ;
+ p->start = pathlen + 41 ;
+ if (!stralloc_ready(&p->sa, p->start)) { cleanup(0) ; dienomem() ; }
-static void answer (unsigned char c)
-{
- if (!textmessage_put(textmessage_sender_1, (char *)&c, 1))
{
- cleanup() ;
- strerr_diefu1sys(111, "textmessage_put") ;
+ char tmp[p->start + 1] ;
+ int r = skalibs_regcomp(&p->re, s + pathlen + 1, REG_EXTENDED) ;
+ if (r) return r == REG_ESPACE ? ENOMEM : EINVAL ;
+ memcpy(tmp, s, pathlen) ;
+ memcpy(tmp + pathlen, "/.ftrig1:", 9) ;
+ if (!timestamp(tmp + pathlen + 9)) goto err0 ;
+ memcpy(tmp + pathlen + 34, ":XXXXXX", 8) ;
+ r = mkptemp3(tmp, 0622, O_NONBLOCK | O_CLOEXEC) ;
+ if (r == -1) goto err0 ;
+ buffer_init(&p->b, &buffer_read, r, p->buf, FTRIGRD_BUFSIZE) ;
+ p->fdw = open_write(tmp) ;
+ if (p->fdw == -1) { unlink_void(tmp) ; goto err1 ; }
+ stralloc_copyb(&p->sa, tmp, pathlen + 1) ;
+ stralloc_catb(&p->sa, tmp + pathlen + 2, 40) ;
+ if (rename(tmp, p->sa.s) == -1) { unlink_void(tmp) ; goto err2 ; }
}
-}
+
+ p->id = id ;
+ p->flags = flags ;
+ p->prev = &ftrigio_head ;
+ p->next = ftrigio_head.next ;
+ ftrigio_head.next = p ;
+ numio++ ;
+ (void)opcode ;
+ return 0 ;
-static void ftrigio_remove (size_t i)
-{
- size_t n = genalloc_len(ftrigio, &g) ;
- ftrigio *a = genalloc_s(ftrigio, &g) ;
- ftrigio_free(a + i) ;
- a[i] = a[--n] ;
- genalloc_setlen(ftrigio, &g, n) ;
+ err2:
+ fd_close(p->fdw) ;
+ err1:
+ fd_close(buffer_fd(&p->b)) ;
+ err0:
+ regfree(&p->re) ;
+ return errno ;
}
-static inline int ftrigio_read (ftrigio *p)
+static inline int ftrigio_read (sassserver *a, ftrigio *p)
{
unsigned int i = FTRIGRD_MAXREADS ;
while (i--)
{
- regmatch_t pmatch ;
size_t blen ;
ssize_t r = sanitize_read(buffer_fill(&p->b)) ;
if (!r) break ;
- if (r < 0) return (trig(p->id, 'd', errno), 0) ;
- blen = buffer_len(&p->b) ;
- if (!stralloc_readyplus(&p->sa, blen+1))
+ if (r == -1)
{
- cleanup() ;
- dienomem() ;
+ sassserver_async_failure(a, p->id, errno) ;
+ return 0 ;
}
+ blen = buffer_len(&p->b) ;
+ if (!stralloc_readyplus(&p->sa, blen+1)) { cleanup(0) ; dienomem() ; }
buffer_getnofill(&p->b, p->sa.s + p->sa.len, blen) ;
p->sa.len += blen ;
p->sa.s[p->sa.len] = 0 ;
- while (!regexec(&p->re, p->sa.s, 1, &pmatch, REG_NOTBOL | REG_NOTEOL))
- {
- trig(p->id, '!', p->sa.s[pmatch.rm_eo - 1]) ;
- if (!(p->options & FTRIGR_REPEAT)) return 0 ;
- memmove(p->sa.s, p->sa.s + pmatch.rm_eo, p->sa.len + 1 - pmatch.rm_eo) ;
- p->sa.len -= pmatch.rm_eo ;
- }
- }
- return 1 ;
-}
-
-static int parse_protocol (struct iovec const *v, void *context)
-{
- char const *s = v->iov_base ;
- uint16_t id ;
- if (v->iov_len < 3)
- {
- cleanup() ;
- strerr_dief1x(100, "invalid client request") ;
- }
- uint16_unpack_big(s, &id) ;
- switch (s[2])
- {
- case 'U' : /* unsubscribe */
- {
- size_t n = genalloc_len(ftrigio, &g) ;
- size_t i = 0 ;
- for (; i < n ; i++) if (genalloc_s(ftrigio, &g)[i].id == id) break ;
- if (i < n)
- {
- ftrigio_remove(i) ;
- answer(0) ;
- }
- else answer(EINVAL) ;
- break ;
- }
- case 'L' : /* subscribe to path and match re */
+ if (!regexec(&p->re, p->sa.s + p->start, 0, 0, 0))
{
- size_t n = genalloc_len(ftrigio, &g) ;
- ftrigio *p ;
- char *x ;
- uint32_t options, pathlen, relen ;
- int r ;
- if (v->iov_len < 19)
- {
- answer(EPROTO) ;
- break ;
- }
- uint32_unpack_big(s + 3, &options) ;
- uint32_unpack_big(s + 7, &pathlen) ;
- uint32_unpack_big(s + 11, &relen) ;
- if (((pathlen + relen + 17) != v->iov_len) || s[15 + pathlen] || s[v->iov_len - 1])
- {
- answer(EPROTO) ;
- break ;
- }
- if (!genalloc_readyplus(ftrigio, &g, 1))
- {
- answer(ENOMEM) ;
- break ;
- }
- x = alloc(FTRIGRD_BUFSIZE) ;
- if (!x)
- {
- answer(ENOMEM) ;
- break ;
- }
- p = genalloc_s(ftrigio, &g) + n ;
- r = skalibs_regcomp(&p->re, s + 16 + pathlen, REG_EXTENDED) ;
- if (r)
- {
- alloc_free(x) ;
- answer(r == REG_ESPACE ? ENOMEM : EINVAL) ;
- break ;
- }
- if (!ftrig1_make(&p->trig, s + 15))
- {
- regfree(&p->re) ;
- alloc_free(x) ;
- answer(errno) ;
- break ;
- }
- buffer_init(&p->b, &buffer_read, p->trig.fd, x, FTRIGRD_BUFSIZE) ;
- p->options = options ;
- p->id = id ;
- p->sa = stralloc_zero ;
- genalloc_setlen(ftrigio, &g, n+1) ;
- answer(0) ;
- break ;
+ sassserver_async_success(a, p->id, p->flags, p->sa.s + p->start, p->sa.len - p->start) ;
+ p->sa.len = p->start ;
}
- default :
- cleanup() ;
- strerr_dief1x(100, "invalid client request") ;
}
- (void)context ;
return 1 ;
}
int main (void)
{
+ sassserver a = SASSSERVER_ZERO ;
+ int r = 0 ;
PROG = "s6-ftrigrd" ;
if (ndelay_on(0) == -1 || ndelay_on(1) == -1)
strerr_diefu1sys(111, "make fds nonblocking") ;
if (!sig_altignore(SIGPIPE))
strerr_diefu1sys(111, "ignore SIGPIPE") ;
+ if (!tain_now_set_stopwatch_g())
+ strerr_diefu1sys(111, "tain_now_set_stopwatch") ;
{
tain deadline ;
- tain_now_set_stopwatch_g() ;
- tain_addsec_g(&deadline, 2) ;
- if (!textclient_server_01x_init_g(FTRIGR_BANNER1, FTRIGR_BANNER1_LEN, FTRIGR_BANNER2, FTRIGR_BANNER2_LEN, &deadline))
- strerr_diefu1sys(111, "sync with client") ;
+ tain_addsec_g(&deadline, 5) ;
+ sassserver_init_g(&a, FTRIGR_BANNER1, FTRIGR_BANNER2, &ftrigio_add, &ftrigio_remove, sizeof(ftrigio), &cleanup, 0, &deadline) ;
}
- for (;;)
+ while (!r)
{
- size_t n = genalloc_len(ftrigio, &g) ;
- size_t i = 0 ;
- iopause_fd x[3 + n] ;
+ tain deadline = TAIN_INFINITE ;
+ iopause_fd x[3 + numio] ;
+
+ sassserver_prepare_iopause(&a, x, &deadline) ;
- x[0].fd = 0 ; x[0].events = IOPAUSE_EXCEPT | IOPAUSE_READ ;
- x[1].fd = 1 ; x[1].events = IOPAUSE_EXCEPT | (textmessage_sender_isempty(textmessage_sender_1) ? 0 : IOPAUSE_WRITE) ;
- x[2].fd = textmessage_sender_fd(textmessage_sender_x) ;
- x[2].events = IOPAUSE_EXCEPT | (textmessage_sender_isempty(textmessage_sender_x) ? 0 : IOPAUSE_WRITE) ;
- for (; i < n ; i++)
+ for (ftrigio *p = ftrigio_head.next ; p != &ftrigio_head ; p = p->next, r++)
{
- ftrigio *p = genalloc_s(ftrigio, &g) + i ;
- p->xindex = 3+i ;
- x[3+i].fd = p->trig.fd ;
- x[3+i].events = IOPAUSE_READ ;
+ p->xindex = 3+r ;
+ x[3+r].fd = buffer_fd(&p->b) ;
+ x[3+r].events = IOPAUSE_READ ;
}
- if (iopause(x, 3 + n, 0, 0) < 0)
+ r = iopause_g(x, 3 + numio, &deadline) ;
+ if (r == -1)
{
- cleanup() ;
+ cleanup(0) ;
strerr_diefu1sys(111, "iopause") ;
}
-
- /* client closed */
- if ((x[0].revents | x[1].revents) & IOPAUSE_EXCEPT) break ;
-
- /* client is reading */
- if (x[1].revents & IOPAUSE_WRITE)
- if (!textmessage_sender_flush(textmessage_sender_1) && !error_isagain(errno))
- {
- cleanup() ;
- strerr_diefu1sys(111, "flush stdout") ;
- }
- if (x[2].revents & IOPAUSE_WRITE)
- if (!textmessage_sender_flush(textmessage_sender_x) && !error_isagain(errno))
- {
- cleanup() ;
- return 1 ;
- }
-
- /* scan listening ftrigs */
- for (i = 0 ; i < genalloc_len(ftrigio, &g) ; i++)
+ if (!r)
{
- ftrigio *p = genalloc_s(ftrigio, &g) + i ;
- if (x[p->xindex].revents & IOPAUSE_READ)
- if (!ftrigio_read(p)) ftrigio_remove(i--) ;
+ sassserver_timeout(&a) ;
+ continue ;
}
- /* client is writing */
- if (!textmessage_receiver_isempty(textmessage_receiver_0) || x[0].revents & IOPAUSE_READ)
+ sassserver_write_event(&a, x) ;
+
+ for (ftrigio *p = ftrigio_head.next ; p != &ftrigio_head ; p = p->next) if (x[p->xindex].revents & IOPAUSE_READ)
{
- if (textmessage_handle(textmessage_receiver_0, &parse_protocol, 0) < 0)
+ if (!ftrigio_read(&a, p))
{
- if (errno == EPIPE) break ; /* normal exit */
- cleanup() ;
- strerr_diefu1sys(111, "handle messages from client") ;
+ p = p->prev ;
+ ftrigio_remove(p->next) ;
}
}
+
+ r = sassserver_read_event(&a, x) ;
}
- cleanup() ;
- return 0 ;
+
+ cleanup(0) ;
+ _exit(0) ;
}