#include <stdio.h>
#include <signal.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include "shbuf.h"
#include "shbuferr.h"
#define BUFSIZE 1024
static volatile int quit = 0;
static void _sigint(int s) {
#ifdef DEBUG
char *t = "SIGINT\n";
int _errno;
_errno = errno;
write(2, t, strlen(t));
errno = _errno;
#endif
quit = 1;
}
static int _provider() {
shbuf *sb;
if (!(sb = shbuf_create(0, BUFSIZE))) {
shbuf_perror("Could not create shbuf");
return -1;
}
if (shbuf_notify_enable(sb, 1) != 0) {
shbuf_perror("Could not enable notification system");
return -2;
}
if (shbuf_access(sb, 0700) != 0) {
shbuf_perror("Could not set access mode");
return -3;
}
fprintf(stderr, "Listening on shbuf key %i.\n", shbuf_get_key(sb));
while(!quit) {
const unsigned char *p;
unsigned long l;
ssize_t r;
if (!(p = shbuf_get_read_pointer(sb, &l))) {
if (shbuf_wait(sb) < 0)
break;
continue;
}
if (p == (unsigned char*) -1)
break;
r = write(1, p, l);
if (r == -1 && errno == EINTR)
continue;
if (r <= 0)
break;
if (shbuf_inc_read_pointer(sb, r) < 0)
break;
if (shbuf_notify(sb) < 0)
break;
}
shbuf_access(sb, 0);
shbuf_notify_enable(sb, 0);
shbuf_free(sb);
fprintf(stderr, "Exiting cleanly.\n");
return 0;
}
static int _client(key_t key) {
shbuf *sb;
if (!(sb = shbuf_open(key))) {
shbuf_perror("Could not open shbuf");
return -1;
}
if (shbuf_notify_enable(sb, 1) != 0) {
shbuf_perror("Could not enable notification.");
return -2;
}
fprintf(stderr, "Opened shbuf key %i.\n", shbuf_get_key(sb));
while(!quit && shbuf_connected(sb) == 1) {
unsigned char *p;
unsigned long l;
ssize_t r;
if (!(p = shbuf_get_write_pointer(sb, &l))) {
if (shbuf_wait(sb) < 0)
break;
continue;
}
if (p == (unsigned char*) -1)
break;
if ((r = read(0, p, l)) == -1 && errno == EINTR)
continue;
if (r <= 0)
break;
if (shbuf_inc_write_pointer(sb, r) < 0)
break;
if (shbuf_notify(sb) < 0)
break;
}
shbuf_notify_enable(sb, 0);
shbuf_free(sb);
fprintf(stderr, "Exiting cleanly.\n");
return 0;
}
int main(int argc, char *argv[]) {
signal(SIGPIPE, _sigint);
signal(SIGINT, _sigint);
signal(SIGTERM, _sigint);
signal(SIGHUP, _sigint);
siginterrupt(SIGPIPE, 1);
siginterrupt(SIGINT, 1);
siginterrupt(SIGTERM, 1);
siginterrupt(SIGHUP, 1);
if (argc <= 1)
return _provider();
return _client((key_t) atoi(argv[1]));
}