Introduction
Introduction Statistics Contact Development Disclaimer Help
blind-peek-head.c - blind - suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log
Files
Refs
README
LICENSE
---
blind-peek-head.c (3073B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include "common.h"
3
4 USAGE("")
5
6 static ssize_t
7 peek_socket(char *buf, size_t n)
8 {
9 ssize_t r = recv(STDIN_FILENO, buf, n, MSG_PEEK);
10 if (r < 0 && errno != ENOTSOCK)
11 eprintf("recv <stdin>:");
12 return r;
13 }
14
15 static ssize_t
16 peek_regular(char *buf, size_t n)
17 {
18 ssize_t r;
19 off_t pos = lseek(STDIN_FILENO, 0, SEEK_CUR);
20 if (pos < 0) {
21 if (errno != ESPIPE)
22 eprintf("lseek <stdin>:");
23 return -1;
24 }
25 r = pread(STDIN_FILENO, buf, n, pos);
26 if (r < 0 && errno != ESPIPE)
27 eprintf("pread <stdin>:");
28 return r;
29 }
30
31 #if defined(HAVE_TEE)
32 static ssize_t
33 peek_pipe(char *buf, size_t n)
34 {
35 int rw[2];
36 ssize_t m;
37 size_t p;
38 if (pipe(rw))
39 eprintf("pipe");
40 m = tee(STDIN_FILENO, rw[1], n, 0);
41 if (m < 0) {
42 if (errno != EINVAL)
43 eprintf("tee <stdin>:");
44 return -1;
45 }
46 close(rw[1]);
47 p = ereadall(rw[0], buf, (size_t)m, "<pipe>");
48 close(rw[0]);
49 return (ssize_t)p;
50 }
51 #endif
52
53 static size_t
54 peek(char *buf, size_t n)
55 {
56 static int method = 0;
57 ssize_t r;
58 switch (method) {
59 case 0:
60 if ((r = peek_socket(buf, n)) >= 0)
61 return (size_t)r;
62 method++;
63 /* fall-through */
64 case 1:
65 if ((r = peek_regular(buf, n)) >= 0)
66 return (size_t)r;
67 method++;
68 #if defined(HAVE_TEE)
69 /* fall-through */
70 default:
71 if ((r = peek_pipe(buf, n)) >= 0)
72 return (size_t)r;
73 eprintf("can only peek pipes, sockets, and regular files…
74 #else
75 eprintf("can only peek sockets and regular files\n");
76 #endif
77 }
78 }
79
80 int
81 main(int argc, char *argv[])
82 {
83 char buf[STREAM_HEAD_MAX], *p;
84 char magic[] = {'\0', 'u', 'i', 'v', 'f'};
85 size_t i, len = 0, last_len;
86 #if defined(HAVE_EPOLL)
87 struct epoll_event ev;
88 int epfd, epr = 0;
89 #endif
90
91 UNOFLAGS(argc);
92
93 #if defined(HAVE_EPOLL)
94 epfd = epoll_create1(0);
95 if (epfd < 0)
96 eprintf("epoll_create1:");
97
98 memset(&ev, 0, sizeof(ev));
99 ev.events = EPOLLIN | EPOLLRDHUP | EPOLLET;
100 if (epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev))
101 eprintf("epoll_ctl EPOLL_CTL_ADD:");
102
103 do {
104 last_len = len;
105 len = peek(buf, sizeof(buf));
106 p = memchr(buf, '\n', len);
107 if (p && len >= (size_t)(++p - buf) + ELEMENTSOF(magic))
108 goto ready;
109 } while (len > last_len && (epr = epoll_wait(epfd, &ev, 1, -1)) …
110 if (epr < 0)
111 eprintf("epoll_wait:");
112 #else
113 goto beginning;
114 do {
115 usleep(50000);
116 beginning:
117 last_len = len;
118 len = peek(buf, sizeof(buf));
119 p = memchr(buf, '\n', len);
120 if (p && len >= (size_t)(++p - buf) + ELEMENTSOF(magic))
121 goto ready;
122 } while (len > last_len);
123 #endif
124 eprintf("could not read entire head\n");
125
126 ready:
127 len = (size_t)(p - buf);
128 for (i = 0; i < ELEMENTSOF(magic); i++)
129 if (p[i] != magic[i])
130 goto bad_format;
131 p = buf;
132 for (i = 0; i < 3; i++) {
133 if (!isdigit(*p))
134 goto bad_format;
135 while (isdigit(*p)) p++;
136 if (*p++ != ' ')
137 goto bad_format;
138 }
139 while (isalnum(*p) || *p == ' ') {
140 if (p[0] == ' ' && p[-1] == ' ')
141 goto bad_format;
142 p++;
143 }
144 if (p[-1] == ' ' || p[0] != '\n')
145 goto bad_format;
146
147 ewriteall(STDOUT_FILENO, buf, len, "<stdout>");
148 return 0;
149
150 bad_format:
151 eprintf("<stdin>: file format not supported\n");
152 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.