blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

blind-from-named.c (2249B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include "common.h"
      3 
      4 USAGE("[-t decisecs] [-a] ([-f fd] path [command ...] | path)")
      5 
      6 static int
      7 erecv_fd(int sock)
      8 {
      9 	int fd;
     10 	char buf[1];
     11 	struct iovec iov;
     12 	struct msghdr msg;
     13 	struct cmsghdr *cmsg;
     14 	char cms[CMSG_SPACE(sizeof(fd))];
     15 
     16 	iov.iov_base = buf;
     17 	iov.iov_len = 1;
     18 
     19 	memset(&msg, 0, sizeof(msg));
     20 	msg.msg_name = 0;
     21 	msg.msg_namelen = 0;
     22 	msg.msg_iov = &iov;
     23 	msg.msg_iovlen = 1;
     24 
     25 	msg.msg_control = (caddr_t)cms;
     26 	msg.msg_controllen = sizeof(cms);
     27 
     28 	switch (recvmsg(sock, &msg, 0)) {
     29 	case -1:
     30 		eprintf("recvmsg:");
     31 	case 0:
     32 		eprintf("recvmsg: connection closed by peer");
     33 	default:
     34 		break;
     35 	}
     36 
     37 	cmsg = CMSG_FIRSTHDR(&msg);
     38 	memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
     39 	return fd;
     40 }
     41 
     42 int
     43 main(int argc, char *argv[])
     44 {
     45 	char buf[BUFSIZ];
     46 	struct sockaddr_un addr;
     47 	int abstract = 0;
     48 	int filedes = -1;
     49 	int tries = 11;
     50 	int sockfd, fd;
     51 	size_t n;
     52 
     53 	ARGBEGIN {
     54 	case 'a':
     55 		abstract = 1;
     56 		break;
     57 	case 'f':
     58 		filedes = etoi_flag('f', UARGF(), 0, INT_MAX);
     59 		break;
     60 	case 't':
     61 		tries = etoi_flag('t', UARGF(), 0, INT_MAX - 1) + 1;
     62 		break;
     63 	default:
     64 		usage();
     65 	} ARGEND;
     66 	if (argc < 1 || (filedes >= 0 && argc == 1))
     67 		usage();
     68 	if (filedes < 0)
     69 		filedes = STDIN_FILENO;
     70 
     71 	memset(&addr, 0, sizeof(addr));
     72 	addr.sun_family = AF_UNIX;
     73 	if (strlen(argv[0]) + (size_t)(1 + abstract) > sizeof(addr.sun_path)) {
     74 		errno = ENAMETOOLONG;
     75 		eprintf("%s:", argv[0]);
     76 	}
     77 	strcpy(addr.sun_path + abstract, argv[0]);
     78 	argv++, argc--;
     79 
     80 	sockfd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
     81 	if (sockfd < 0)
     82 		eprintf("socket PF_UNIX SOCK_SEQPACKET:");
     83 
     84 retry:
     85 	if ((connect(sockfd, (const struct sockaddr *)&addr, (size_t)sizeof(addr))) < 0) {
     86 		if (--tries) {
     87 			usleep((useconds_t)100000L);
     88 			goto retry;
     89 		} else {
     90 			eprintf("bind %s%s%s:",
     91 				abstract ? "<abstract:" : "",
     92 				addr.sun_path + abstract,
     93 				abstract ? ">" : "");
     94 		}
     95 	}
     96 
     97 	fd = erecv_fd(sockfd);
     98 	close(sockfd);
     99 
    100 	if (argc) {
    101 		if (fd != filedes) {
    102 			if (dup2(fd, filedes) < 0)
    103 				eprintf("dup2 %i %i:", fd, filedes);
    104 			close(fd);
    105 		}
    106 		execvp(argv[0], argv);
    107 		eprintf("execvp %s:", argv[0]);
    108 	}
    109 
    110 	while ((n = eread(fd, buf, sizeof(buf), "<received file>")))
    111 		ewriteall(STDOUT_FILENO, buf, n, "<stdout>");
    112 	return 0;
    113 }