summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bin/.gitignore1
-rw-r--r--bin/Makefile4
-rw-r--r--bin/pbd.c44
3 files changed, 31 insertions, 18 deletions
diff --git a/bin/.gitignore b/bin/.gitignore
index 6dfe7457..5ff66354 100644
--- a/bin/.gitignore
+++ b/bin/.gitignore
@@ -4,6 +4,7 @@ dtch
 glitch
 hnel
 modem
+open
 pbcopy
 pbd
 pbpaste
diff --git a/bin/Makefile b/bin/Makefile
index ae667eef..677b5673 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -1,4 +1,4 @@
-ANY_BINS = atch dtch glitch hnel modem pbcopy pbd pbpaste pngo scheme wake xx
+ANY_BINS = atch dtch glitch hnel modem open pbcopy pbd pbpaste pngo scheme wake xx
 BSD_BINS = klon watch
 LIN_BINS = bri fbatt fbclock
 ALL_BINS = $(ANY_BINS) $(BSD_BINS) $(LIN_BINS)
@@ -21,7 +21,7 @@ tags: *.c
 atch: dtch
 	ln -f dtch atch
 
-pbcopy pbpaste: pbd
+open pbcopy pbpaste: pbd
 	ln -f pbd $@
 
 scheme.png: scheme
diff --git a/bin/pbd.c b/bin/pbd.c
index 77832433..4ee11fe6 100644
--- a/bin/pbd.c
+++ b/bin/pbd.c
@@ -21,14 +21,13 @@
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <sysexits.h>
 #include <unistd.h>
 
-#define UNUSED __attribute__((unused))
-
-static void spawn(const char *cmd, int dest, int src) {
+static void spawn(const char *cmd, const char *arg, int dest, int src) {
 	pid_t pid = fork();
 	if (pid < 0) err(EX_OSERR, "fork");
 
@@ -42,7 +41,7 @@ static void spawn(const char *cmd, int dest, int src) {
 		int fd = dup2(src, dest);
 		if (fd < 0) err(EX_OSERR, "dup2");
 
-		execlp(cmd, cmd, NULL);
+		execlp(cmd, cmd, arg, NULL);
 		err(EX_UNAVAILABLE, "%s", cmd);
 	}
 }
@@ -74,19 +73,21 @@ static int pbd(void) {
 		error = fcntl(client, F_SETFD, FD_CLOEXEC);
 		if (error) err(EX_IOERR, "fcntl");
 
-		spawn("pbpaste", STDOUT_FILENO, client);
-
-		char p;
-		ssize_t peek = recv(client, &p, 1, MSG_PEEK);
-		if (peek < 0) err(EX_IOERR, "recv");
+		char c = 0;
+		ssize_t size = read(client, &c, 1);
+		if (size < 0) warn("read");
 
-		if (peek) spawn("pbcopy", STDIN_FILENO, client);
+		switch (c) {
+			break; case 'p': spawn("pbpaste", NULL, STDOUT_FILENO, client);
+			break; case 'c': spawn("pbcopy", NULL, STDIN_FILENO, client);
+			break; case 'o': spawn("xargs", "open", STDIN_FILENO, client);
+		}
 
 		close(client);
 	}
 }
 
-static int pbdClient(void) {
+static int pbdClient(char c) {
 	int client = socket(PF_INET, SOCK_STREAM, 0);
 	if (client < 0) err(EX_OSERR, "socket");
 
@@ -98,6 +99,9 @@ static int pbdClient(void) {
 	int error = connect(client, (struct sockaddr *)&addr, sizeof(addr));
 	if (error) err(EX_UNAVAILABLE, "connect");
 
+	ssize_t size = write(client, &c, 1);
+	if (size < 0) err(EX_IOERR, "write");
+
 	return client;
 }
 
@@ -107,30 +111,38 @@ static void copy(int out, int in) {
 	while (0 < (readSize = read(in, buf, sizeof(buf)))) {
 		ssize_t writeSize = write(out, buf, readSize);
 		if (writeSize < 0) err(EX_IOERR, "write(%d)", out);
-		if (writeSize < readSize) errx(EX_IOERR, "short write(%d)", out);
 	}
 	if (readSize < 0) err(EX_IOERR, "read(%d)", in);
 }
 
 static int pbcopy(void) {
-	int client = pbdClient();
+	int client = pbdClient('c');
 	copy(client, STDIN_FILENO);
 	return EX_OK;
 }
 
 static int pbpaste(void) {
-	int client = pbdClient();
-	shutdown(client, SHUT_WR);
+	int client = pbdClient('p');
 	copy(STDOUT_FILENO, client);
 	return EX_OK;
 }
 
-int main(int argc UNUSED, char *argv[]) {
+static int open1(char *url) {
+	if (!url) return EX_USAGE;
+	int client = pbdClient('o');
+	ssize_t size = write(client, url, strlen(url));
+	if (size < 0) err(EX_IOERR, "write");
+	return EX_OK;
+}
+
+int main(int argc, char *argv[]) {
+	(void)argc;
 	if (!argv[0][0] || !argv[0][1]) return EX_USAGE;
 	switch (argv[0][2]) {
 		case 'd': return pbd();
 		case 'c': return pbcopy();
 		case 'p': return pbpaste();
+		case 'e': return open1(argv[1]);
 		default:  return EX_USAGE;
 	}
 }