summary refs log tree commit diff
path: root/bin/pbd.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2018-08-08 12:07:44 -0400
committerJune McEnroe <june@causal.agency>2018-08-08 12:07:44 -0400
commit93235430573634473bccad119631e63979b6f053 (patch)
tree416f588d0f9a42efb1234d4876ce4804633ac3e0 /bin/pbd.c
parentFix colorscheme manUnderline disable (diff)
downloadsrc-93235430573634473bccad119631e63979b6f053.tar.gz
src-93235430573634473bccad119631e63979b6f053.zip
Add open(1) forwarding to pbd
Diffstat (limited to 'bin/pbd.c')
-rw-r--r--bin/pbd.c44
1 files changed, 28 insertions, 16 deletions
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;
 	}
 }