commit ed8861c

shrub  ·  2026-07-12 20:56:21 +0000 UTC
parent 550ba19
new build system, add randomart, use djb interfaces over libc where possible
93 files changed,  +4993, -657
M README
M README
+13, -3
 1@@ -6,8 +6,12 @@ and i am sharing them in the hope they will be useful to you too. some of them a
 2 and some are in C. some are really useful, and some are only sometimes useful, or probably more 
 3 useful too me than to you. but you can pick the ones you like.
 4 
 5-the ones in C have their own subdirectories with ninja to build and install. for the scripts, just 
 6-copy them to your path.
 7+you can build and install all programs and scripts with the top level ninja file:
 8+	
 9+    ninja
10+    ninja install
11+
12+if you want to only install certain tools, run ninja and copy only the ones you want manually.
13 
14 tools
15 -----
16@@ -38,6 +42,12 @@ tools
17 
18 - peek : simple command tracer.
19 
20+- randomart : render drunken bishop randomart for openssh-format public keys.
21+
22 license
23 -------
24-public domain, except nviz which is ISC licensed, as it uses code from samurai. 
25+public domain, with the exceptions of nviz which is ISC licensed, as it uses code from samurai, 
26+and randomart which is BSD-licensed, as it uses code from openssh.
27+
28+thank you to Daniel J Bernstein for all of the code in shared/
29+thank you to Michael Forney for almost all of the code in nviz/
+87, -0
 1@@ -0,0 +1,87 @@
 2+# i know this is a ninja file, but you're allowed to edit it.
 3+# you can also pass things on the command line if you like, eg
 4+#
 5+#     CC=clang ninja
 6+
 7+cc = $${CC:-cc}
 8+ar = $${AR:-ar}
 9+ranlib = $${RANLIB:-ranlib}
10+base_cflags = $${CFLAGS:--O2 -std=c99}
11+ldflags = $${LDFLAGS:-}
12+default_libs = $${LIBS:-}
13+proto_libs = $${PROTO_LIBS:--lexpat}
14+prefix = $${PREFIX:-/usr/local}
15+destdir = $${DESTDIR:-}
16+bindir = $${BINDIR:-$${DESTDIR:-}$${PREFIX:-/usr/local}/bin}
17+mandir = $${MANDIR:-$${DESTDIR:-}$${PREFIX:-/usr/local}/man/man1}
18+
19+rule cc
20+  command = $cc $cflags -MMD -MF $out.d -c -o $out $in
21+  deps = gcc
22+  depfile = $out.d
23+  description = cc $out
24+
25+rule link
26+  command = $cc $ldflags -o $out $in $libs
27+  description = link $out
28+
29+rule ar
30+  command = rm -f $out && $ar rcs $out $in && $ranlib $out
31+  description = ar $out
32+
33+rule install_bin
34+  command = mkdir -p $bindir && cp $in $bindir/$name
35+  description = install $name
36+
37+rule install_man
38+  command = mkdir -p $mandir && cp $in $mandir/$name
39+  description = man $name
40+
41+subninja shared/top.ninja
42+subninja peek/top.ninja
43+subninja proto/top.ninja
44+subninja shar/top.ninja
45+subninja randomart/top.ninja
46+subninja nviz/top.ninja
47+
48+build _always_build_: phony
49+
50+build all: phony shared-all peek-all proto-all shar-all randomart-all nviz-all
51+
52+build install-deps: install_bin deps | _always_build_
53+  name = deps
54+build install-drudge: install_bin drudge | _always_build_
55+  name = drudge
56+build install-fine: install_bin fine | _always_build_
57+  name = fine
58+build install-flick: install_bin flick | _always_build_
59+  name = flick
60+build install-gen: install_bin gen | _always_build_
61+  name = gen
62+build install-life: install_bin life | _always_build_
63+  name = life
64+build install-lint: install_bin lint | _always_build_
65+  name = lint
66+build install-pinkie: install_bin pinkie | _always_build_
67+  name = pinkie
68+build install-tlsver: install_bin tlsver | _always_build_
69+  name = tlsver
70+
71+build install-peek: install_bin peek/peek | _always_build_ peek-all
72+  name = peek
73+build install-proto: install_bin proto/proto | _always_build_ proto-all
74+  name = proto
75+build install-shar: install_bin shar/shar | _always_build_ shar-all
76+  name = shar
77+build install-randomart: install_bin randomart/randomart | _always_build_ randomart-all
78+  name = randomart
79+build install-nviz: install_bin nviz/nviz | _always_build_ nviz-all
80+  name = nviz
81+build install-shar.1: install_man shar/shar.1 | _always_build_ shar-all
82+  name = shar.1
83+
84+build install-scripts: phony install-deps install-drudge install-fine install-flick install-gen install-life install-lint install-pinkie install-tlsver
85+build install-bins: phony install-peek install-proto install-shar install-randomart install-nviz install-shar.1
86+build install: phony install-scripts install-bins
87+
88+default all
+0, -43
 1@@ -1,43 +0,0 @@
 2-# i know this is a ninja file, but you're allowed to edit it.
 3-# you can also pass things on the command line if you like, eg
 4-#
 5-#     CC=clang ninja
 6-
 7-cc = $${CC:-cc}
 8-cflags = $${CFLAGS:--O2 -std=c99}
 9-ldflags = $${LDFLAGS:-}
10-libs = $${LIBS:-}
11-prefix = $${PREFIX:-/usr/local}
12-destdir = $${DESTDIR:-}
13-bindir = $${BINDIR:-$${DESTDIR:-}$${PREFIX:-/usr/local}/bin}
14-
15-rule cc
16-  command = $cc $cflags -MMD -MF $out.d -c -o $out $in
17-  deps = gcc
18-  depfile = $out.d
19-  description = cc $out
20-
21-rule link
22-  command = $cc $ldflags -o $out $in $libs
23-  description = link $out
24-
25-rule install
26-  command = mkdir -p $bindir && cp nviz $bindir/
27-  description = install nviz
28-
29-build env.o: cc env.c
30-build graph.o: cc graph.c
31-build htab.o: cc htab.c
32-build log.o: cc log.c
33-build nviz.o: cc nviz.c
34-build os-posix.o: cc os-posix.c
35-build parse.o: cc parse.c
36-build scan.o: cc scan.c
37-build tree.o: cc tree.c
38-build util.o: cc util.c
39-
40-build nviz: link env.o graph.o htab.o log.o nviz.o os-posix.o parse.o scan.o tree.o util.o
41-build all: phony nviz
42-build install: install nviz
43-
44-default all
+0, -4
 1@@ -9,10 +9,6 @@ just for fun. i think the graphs it emits are ever so slightly prettier.
 2 the vast majority of nviz's code is stolen directly from samurai, so it's under the same
 3 ISC license that samurai is.
 4 
 5-build:
 6-    ninja
 7-    ninja install
 8-
 9 examples:
10     nviz
11     nviz -g | dot -Tpng -o build.png
+25, -0
 1@@ -0,0 +1,25 @@
 2+build nviz/env.o: cc nviz/env.c
 3+  cflags = $base_cflags
 4+build nviz/graph.o: cc nviz/graph.c
 5+  cflags = $base_cflags
 6+build nviz/htab.o: cc nviz/htab.c
 7+  cflags = $base_cflags
 8+build nviz/log.o: cc nviz/log.c
 9+  cflags = $base_cflags
10+build nviz/nviz.o: cc nviz/nviz.c
11+  cflags = $base_cflags
12+build nviz/os-posix.o: cc nviz/os-posix.c
13+  cflags = $base_cflags
14+build nviz/parse.o: cc nviz/parse.c
15+  cflags = $base_cflags
16+build nviz/scan.o: cc nviz/scan.c
17+  cflags = $base_cflags
18+build nviz/tree.o: cc nviz/tree.c
19+  cflags = $base_cflags
20+build nviz/util.o: cc nviz/util.c
21+  cflags = $base_cflags
22+
23+build nviz/nviz: link nviz/env.o nviz/graph.o nviz/htab.o nviz/log.o nviz/nviz.o nviz/os-posix.o nviz/parse.o nviz/scan.o nviz/tree.o nviz/util.o
24+  libs = $default_libs
25+
26+build nviz-all: phony nviz/nviz
+0, -34
 1@@ -1,34 +0,0 @@
 2-# i know this is a ninja file, but you're allowed to edit it.
 3-# you can also pass things on the command line if you like, eg
 4-#
 5-#     CC=clang ninja
 6-
 7-cc = $${CC:-cc}
 8-cflags = $${CFLAGS:--O2 -std=c99}
 9-ldflags = $${LDFLAGS:-}
10-libs = $${LIBS:-}
11-prefix = $${PREFIX:-/usr/local}
12-destdir = $${DESTDIR:-}
13-bindir = $${BINDIR:-$${DESTDIR:-}$${PREFIX:-/usr/local}/bin}
14-
15-rule cc
16-  command = $cc $cflags -MMD -MF $out.d -c -o $out $in
17-  deps = gcc
18-  depfile = $out.d
19-  description = cc $out
20-
21-rule link
22-  command = $cc $ldflags -o $out $in $libs
23-  description = link $out
24-
25-rule install
26-  command = mkdir -p $bindir && cp peek $bindir/
27-  description = install peek
28-
29-build peek.o: cc peek.c
30-
31-build peek: link peek.o
32-build all: phony peek
33-build install: install peek
34-
35-default all
+126, -36
  1@@ -1,12 +1,14 @@
  2 #define _POSIX_C_SOURCE 200809L
  3 #include <arpa/inet.h>
  4+#include <alloc.h>
  5+#include <buffer.h>
  6+#include <byte.h>
  7 #include <errno.h>
  8+#include <fmt.h>
  9 #include <netinet/in.h>
 10 #include <signal.h>
 11 #include <stdbool.h>
 12-#include <stdio.h>
 13-#include <stdlib.h>
 14-#include <string.h>
 15+#include <strerr.h>
 16 #include <sys/ptrace.h>
 17 #include <sys/socket.h>
 18 #include <sys/syscall.h>
 19@@ -24,11 +26,45 @@ struct proc {
 20 static struct proc *procs;
 21 static size_t nprocs;
 22 
 23+static void
 24+out(const char *s)
 25+{
 26+	buffer_puts(buffer_1, s);
 27+}
 28+
 29+static void
 30+outc(char c)
 31+{
 32+	buffer_put(buffer_1, &c, 1);
 33+}
 34+
 35+static void
 36+out_ulong(unsigned long u)
 37+{
 38+	char buf[FMT_ULONG];
 39+	unsigned int n;
 40+
 41+	n = fmt_ulong(buf, u);
 42+	buffer_put(buffer_1, buf, n);
 43+}
 44+
 45 static void
 46 die(const char *msg)
 47 {
 48-	perror(msg);
 49-	exit(1);
 50+	strerr_die2sys(111, "peek: ", msg);
 51+}
 52+
 53+static char *
 54+unknown_string(void)
 55+{
 56+	char *s;
 57+
 58+	s = alloc(2);
 59+	if (!s)
 60+		die("alloc");
 61+	s[0] = '?';
 62+	s[1] = '\0';
 63+	return s;
 64 }
 65 
 66 static struct proc *
 67@@ -40,9 +76,9 @@ procget(pid_t pid)
 68 		if (procs[i].pid == pid)
 69 			return &procs[i];
 70 	}
 71-	procs = realloc(procs, (nprocs + 1) * sizeof(procs[0]));
 72-	if (!procs)
 73-		die("realloc");
 74+	if (!alloc_re((char **)&procs, nprocs * sizeof(procs[0]),
 75+	    (nprocs + 1) * sizeof(procs[0])))
 76+		die("alloc_re");
 77 	procs[nprocs] = (struct proc){.pid = pid};
 78 	return &procs[nprocs++];
 79 }
 80@@ -79,9 +115,9 @@ readmem(pid_t pid, unsigned long addr, void *buf, size_t n)
 81 	for (i = 0; i < n; i += sizeof(long)) {
 82 		long v = ptrace(PTRACE_PEEKDATA, pid, addr + i, 0);
 83 		if (v == -1 && errno)
 84-			memset(p + i, 0, n - i);
 85+			byte_zero(p + i, n - i);
 86 		else
 87-			memcpy(p + i, &v, n - i < sizeof(v) ? n - i : sizeof(v));
 88+			byte_copy(p + i, n - i < sizeof(v) ? n - i : sizeof(v), (char *)&v);
 89 	}
 90 }
 91 
 92@@ -92,27 +128,29 @@ readstr(pid_t pid, unsigned long addr)
 93 	size_t cap, len;
 94 
 95 	if (!addr)
 96-		return strdup("?");
 97+		return unknown_string();
 98 	cap = 64;
 99 	len = 0;
100-	s = malloc(cap);
101+	s = alloc(cap);
102 	if (!s)
103-		die("malloc");
104+		die("alloc");
105 	for (;;) {
106 		long v = ptrace(PTRACE_PEEKDATA, pid, addr + len, 0);
107 		size_t i;
108 		char *b = (char *)&v;
109 
110 		if (v == -1 && errno) {
111-			free(s);
112-			return strdup("?");
113+			alloc_free(s);
114+			return unknown_string();
115 		}
116 		for (i = 0; i < sizeof(v); i++) {
117 			if (len + 1 >= cap) {
118+				size_t oldcap = cap;
119 				cap *= 2;
120-				s = realloc(s, cap);
121+				if (!alloc_re(&s, oldcap, cap))
122+					s = NULL;
123 				if (!s)
124-					die("realloc");
125+					die("alloc_re");
126 			}
127 			s[len++] = b[i];
128 			if (!b[i])
129@@ -129,21 +167,37 @@ printnet(pid_t pid, unsigned long addr, unsigned long len)
130 
131 	if (!addr || len < sizeof(sa_family_t))
132 		return;
133-	memset(&ss, 0, sizeof(ss));
134+	byte_zero(&ss, sizeof(ss));
135 	readmem(pid, addr, &ss, len < sizeof(ss) ? len : sizeof(ss));
136 	if (ss.ss_family == AF_UNIX) {
137 		struct sockaddr_un *un = (struct sockaddr_un *)&ss;
138-		printf("net  %d unix:%s\n", pid, un->sun_path[0] ? un->sun_path : "(anon)");
139+		out("net  ");
140+		out_ulong((unsigned long)pid);
141+		out(" unix:");
142+		out(un->sun_path[0] ? un->sun_path : "(anon)");
143+		out("\n");
144 	} else if (ss.ss_family == AF_INET) {
145 		struct sockaddr_in *in = (struct sockaddr_in *)&ss;
146 		if (!inet_ntop(AF_INET, &in->sin_addr, host, sizeof(host)))
147 			return;
148-		printf("net  %d %s:%u\n", pid, host, ntohs(in->sin_port));
149+		out("net  ");
150+		out_ulong((unsigned long)pid);
151+		out(" ");
152+		out(host);
153+		out(":");
154+		out_ulong((unsigned long)ntohs(in->sin_port));
155+		out("\n");
156 	} else if (ss.ss_family == AF_INET6) {
157 		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&ss;
158 		if (!inet_ntop(AF_INET6, &in6->sin6_addr, host, sizeof(host)))
159 			return;
160-		printf("net  %d [%s]:%u\n", pid, host, ntohs(in6->sin6_port));
161+		out("net  ");
162+		out_ulong((unsigned long)pid);
163+		out(" [");
164+		out(host);
165+		out("]:");
166+		out_ulong((unsigned long)ntohs(in6->sin6_port));
167+		out("\n");
168 	}
169 }
170 
171@@ -155,28 +209,48 @@ tracecall(pid_t pid, struct user_regs_struct *r)
172 	switch ((long)r->orig_rax) {
173 	case SYS_execve:
174 		s = readstr(pid, r->rdi);
175-		printf("exec %d %s\n", pid, s);
176-		free(s);
177+		out("exec ");
178+		out_ulong((unsigned long)pid);
179+		out(" ");
180+		out(s);
181+		out("\n");
182+		alloc_free(s);
183 		break;
184 	case SYS_execveat:
185 		s = readstr(pid, r->rsi);
186-		printf("exec %d %s\n", pid, s);
187-		free(s);
188+		out("exec ");
189+		out_ulong((unsigned long)pid);
190+		out(" ");
191+		out(s);
192+		out("\n");
193+		alloc_free(s);
194 		break;
195 	case SYS_open:
196 		s = readstr(pid, r->rdi);
197-		printf("file %d %s\n", pid, s);
198-		free(s);
199+		out("file ");
200+		out_ulong((unsigned long)pid);
201+		out(" ");
202+		out(s);
203+		out("\n");
204+		alloc_free(s);
205 		break;
206 	case SYS_openat:
207 		s = readstr(pid, r->rsi);
208-		printf("file %d %s\n", pid, s);
209-		free(s);
210+		out("file ");
211+		out_ulong((unsigned long)pid);
212+		out(" ");
213+		out(s);
214+		out("\n");
215+		alloc_free(s);
216 		break;
217 	case SYS_openat2:
218 		s = readstr(pid, r->rsi);
219-		printf("file %d %s\n", pid, s);
220-		free(s);
221+		out("file ");
222+		out_ulong((unsigned long)pid);
223+		out(" ");
224+		out(s);
225+		out("\n");
226+		alloc_free(s);
227 		break;
228 	case SYS_connect:
229 		printnet(pid, r->rsi, r->rdx);
230@@ -191,7 +265,10 @@ main(int argc, char *argv[])
231 	pid_t pid;
232 
233 	if (argc < 2) {
234-		fprintf(stderr, "usage: %s cmd [args...]\n", argv[0]);
235+		buffer_puts(buffer_2, "usage: ");
236+		buffer_puts(buffer_2, argv[0]);
237+		buffer_puts(buffer_2, " cmd [args...]\n");
238+		buffer_flush(buffer_2);
239 		return 2;
240 	}
241 	pid = fork();
242@@ -222,12 +299,20 @@ main(int argc, char *argv[])
243 		}
244 		p = procget(pid);
245 		if (WIFEXITED(status)) {
246-			printf("exit %d %d\n", pid, WEXITSTATUS(status));
247+			out("exit ");
248+			out_ulong((unsigned long)pid);
249+			out(" ");
250+			out_ulong((unsigned long)WEXITSTATUS(status));
251+			out("\n");
252 			procdel(pid);
253 			continue;
254 		}
255 		if (WIFSIGNALED(status)) {
256-			printf("exit %d sig%d\n", pid, WTERMSIG(status));
257+			out("exit ");
258+			out_ulong((unsigned long)pid);
259+			out(" sig");
260+			out_ulong((unsigned long)WTERMSIG(status));
261+			out("\n");
262 			procdel(pid);
263 			continue;
264 		}
265@@ -249,7 +334,11 @@ main(int argc, char *argv[])
266 			if ((event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK ||
267 			     event == PTRACE_EVENT_CLONE) &&
268 			    ptrace(PTRACE_GETEVENTMSG, pid, 0, &msg) == 0) {
269-				printf("fork %d -> %lu\n", pid, msg);
270+				out("fork ");
271+				out_ulong((unsigned long)pid);
272+				out(" -> ");
273+				out_ulong(msg);
274+				out("\n");
275 				procget((pid_t)msg);
276 			}
277 			ptrace(PTRACE_SYSCALL, pid, 0, 0);
278@@ -258,6 +347,7 @@ main(int argc, char *argv[])
279 		setopts(pid);
280 		ptrace(PTRACE_SYSCALL, pid, 0, WSTOPSIG(status) == SIGSTOP ? 0 : WSTOPSIG(status));
281 	}
282-	free(procs);
283+	buffer_flush(buffer_1);
284+	alloc_free((char *)procs);
285 	return 0;
286 }
+0, -4
 1@@ -5,10 +5,6 @@ peek is a small linux-only command tracer. it is simpler and has more human-read
 2 although it's not as in-depth. it runs some given command and prints a short stream of file opens, execs, 
 3 forks, simple network stuff, and exits.
 4 
 5-build:
 6-    ninja
 7-    ninja install
 8-
 9 example:
10     peek [any command here]
11 
+7, -0
1@@ -0,0 +1,7 @@
2+build peek/peek.o: cc peek/peek.c
3+  cflags = $base_cflags -Ishared
4+
5+build peek/peek: link peek/peek.o shared/libdjb.a
6+  libs = $default_libs
7+
8+build peek-all: phony peek/peek
+0, -38
 1@@ -1,38 +0,0 @@
 2-# i know this is a ninja file, but you're allowed to edit it.
 3-# you can also pass things on the command line if you like, eg
 4-#
 5-#     CC=clang ninja
 6-
 7-cc = $${CC:-cc}
 8-cflags = $${CFLAGS:--O2 -std=c99}
 9-ldflags = $${LDFLAGS:-}
10-libs = $${LIBS:--lexpat}
11-prefix = $${PREFIX:-/usr/local}
12-destdir = $${DESTDIR:-}
13-bindir = $${BINDIR:-$${DESTDIR:-}$${PREFIX:-/usr/local}/bin}
14-
15-rule cc
16-  command = $cc $cflags -MMD -MF $out.d -c -o $out $in
17-  deps = gcc
18-  depfile = $out.d
19-  description = cc $out
20-
21-rule link
22-  command = $cc $ldflags -o $out $in $libs
23-  description = link $out
24-
25-rule install
26-  command = mkdir -p $bindir && cp proto $bindir/
27-  description = install proto
28-
29-build parse.o: cc parse.c
30-build mdoc.o: cc mdoc.c
31-build proto.o: cc proto.c
32-build protocol.o: cc protocol.c
33-build util.o: cc util.c
34-
35-build proto: link parse.o mdoc.o proto.o protocol.o util.o
36-build all: phony proto
37-build install: install proto
38-
39-default all
+53, -47
  1@@ -1,8 +1,8 @@
  2 #include <stdbool.h>
  3+#include <alloc.h>
  4+#include <buffer.h>
  5 #include <ctype.h>
  6-#include <stdio.h>
  7-#include <stdlib.h>
  8-#include <string.h>
  9+#include <str.h>
 10 
 11 #include "mdoc.h"
 12 #include "util.h"
 13@@ -29,7 +29,8 @@ has_description(const struct description *desc)
 14 static void
 15 mdoc_macro(const char *s)
 16 {
 17-	printf("%s\n", s);
 18+	buffer_puts(buffer_1, s);
 19+	buffer_puts(buffer_1, "\n");
 20 }
 21 
 22 static void
 23@@ -37,9 +38,9 @@ mdoc_text(const char *s)
 24 {
 25 	for (; *s; ++s) {
 26 		if (*s == '\\')
 27-			fputs("\\e", stdout);
 28+			buffer_puts(buffer_1, "\\e");
 29 		else
 30-			putchar(*s);
 31+			buffer_put(buffer_1, s, 1);
 32 	}
 33 }
 34 
 35@@ -49,18 +50,18 @@ mdoc_textline(const char *s, size_t len)
 36 	size_t i;
 37 
 38 	if (!s || len == 0) {
 39-		putchar('\n');
 40+		buffer_puts(buffer_1, "\n");
 41 		return;
 42 	}
 43 	if (s[0] == '.' || s[0] == '\'')
 44-		fputs("\\&", stdout);
 45+		buffer_puts(buffer_1, "\\&");
 46 	for (i = 0; i < len; ++i) {
 47 		if (s[i] == '\\')
 48-			fputs("\\e", stdout);
 49+			buffer_puts(buffer_1, "\\e");
 50 		else
 51-			putchar(s[i]);
 52+			buffer_put(buffer_1, s + i, 1);
 53 	}
 54-	putchar('\n');
 55+	buffer_puts(buffer_1, "\n");
 56 }
 57 
 58 static void
 59@@ -76,18 +77,18 @@ mdoc_paragraphs(const struct description *desc, bool leadpp)
 60 	} else {
 61 		if (leadpp)
 62 			mdoc_macro(".Pp");
 63-		fputs(".D1 ", stdout);
 64+		buffer_puts(buffer_1, ".D1 ");
 65 		mdoc_text(desc->summary);
 66-		putchar('\n');
 67+		buffer_puts(buffer_1, "\n");
 68 		if (!desc->text || !desc->text[0])
 69 			return;
 70 		mdoc_macro(".Pp");
 71 	}
 72 	line = desc->text;
 73 	while (*line) {
 74-		next = strchr(line, '\n');
 75-		if (!next)
 76-			next = line + strlen(line);
 77+		next = line + str_chr(line, '\n');
 78+		if (*next == '\0')
 79+			next = line + str_len(line);
 80 		mdoc_textline(line, (size_t)(next - line));
 81 		line = *next ? next + 1 : next;
 82 	}
 83@@ -98,35 +99,37 @@ mdoc_message_signature(const struct message *msg)
 84 {
 85 	size_t i;
 86 
 87-	printf(".Fo %s\n", msg->name);
 88+	buffer_puts(buffer_1, ".Fo ");
 89+	buffer_puts(buffer_1, msg->name);
 90+	buffer_puts(buffer_1, "\n");
 91 	for (i = 0; i < msg->nargs; ++i) {
 92 		const struct argument *arg = &msg->args[i];
 93 
 94-		fputs(".Fa \"", stdout);
 95+		buffer_puts(buffer_1, ".Fa \"");
 96 		if (arg->nullable)
 97-			fputc('?', stdout);
 98+			buffer_puts(buffer_1, "?");
 99 		if (arg->iface && arg->iface[0] &&
100-		    (strcmp(arg->type, "object") == 0 || strcmp(arg->type, "new_id") == 0))
101+		    (str_equal(arg->type, "object") || str_equal(arg->type, "new_id")))
102 			mdoc_text(arg->iface);
103 		else
104 			mdoc_text(arg->type);
105-		fputc(' ', stdout);
106+		buffer_puts(buffer_1, " ");
107 		mdoc_text(arg->name);
108-		fputs("\"\n", stdout);
109+		buffer_puts(buffer_1, "\"\n");
110 	}
111-	fputs(".Fc", stdout);
112+	buffer_puts(buffer_1, ".Fc");
113 	{
114 		const struct argument *creator = message_creator_arg(msg);
115 
116 		if (creator) {
117-			fputs(" \"creates ", stdout);
118+			buffer_puts(buffer_1, " \"creates ");
119 			mdoc_text(creator->iface);
120-			fputc('"', stdout);
121+			buffer_puts(buffer_1, "\"");
122 		}
123 	}
124 	if (msg->destructor)
125-		fputs(" \"destructor\"", stdout);
126-	putchar('\n');
127+		buffer_puts(buffer_1, " \"destructor\"");
128+	buffer_puts(buffer_1, "\n");
129 }
130 
131 static void
132@@ -150,10 +153,10 @@ mdoc_message_args(const struct message *msg)
133 
134 		if (!arg->summary || !arg->summary[0])
135 			continue;
136-		fputs(".It Va ", stdout);
137+		buffer_puts(buffer_1, ".It Va ");
138 		mdoc_text(arg->name);
139-		putchar('\n');
140-		mdoc_textline(arg->summary, strlen(arg->summary));
141+		buffer_puts(buffer_1, "\n");
142+		mdoc_textline(arg->summary, str_len(arg->summary));
143 	}
144 	mdoc_macro(".El");
145 }
146@@ -173,9 +176,9 @@ mdoc_enum_detail(const struct enumdef *en)
147 	size_t i;
148 
149 	mdoc_macro(".It");
150-	fputs(".Sy ", stdout);
151+	buffer_puts(buffer_1, ".Sy ");
152 	mdoc_text(en->name);
153-	putchar('\n');
154+	buffer_puts(buffer_1, "\n");
155 	mdoc_paragraphs(&en->desc, true);
156 	if (en->nentries == 0)
157 		return;
158@@ -183,13 +186,13 @@ mdoc_enum_detail(const struct enumdef *en)
159 	for (i = 0; i < en->nentries; ++i) {
160 		const struct enumentry *entry = &en->entries[i];
161 
162-		fputs(".It Dv ", stdout);
163+		buffer_puts(buffer_1, ".It Dv ");
164 		mdoc_text(entry->name);
165-		fputs(" = ", stdout);
166+		buffer_puts(buffer_1, " = ");
167 		mdoc_text(entry->value);
168-		putchar('\n');
169+		buffer_puts(buffer_1, "\n");
170 		if (entry->summary && entry->summary[0])
171-			mdoc_textline(entry->summary, strlen(entry->summary));
172+			mdoc_textline(entry->summary, str_len(entry->summary));
173 		mdoc_paragraphs(&entry->desc, true);
174 	}
175 	mdoc_macro(".El");
176@@ -200,11 +203,12 @@ mdoc_interface_detail(const struct interface *iface)
177 {
178 	size_t i;
179 
180-	fputs(".Ss ", stdout);
181+	buffer_puts(buffer_1, ".Ss ");
182 	mdoc_text(iface->name);
183-	putchar('\n');
184-	fputs(".Sy Version:\\ ", stdout);
185-	printf("%d\n", iface->version);
186+	buffer_puts(buffer_1, "\n");
187+	buffer_puts(buffer_1, ".Sy Version:\\ ");
188+	put_ulong(buffer_1, (unsigned long)iface->version);
189+	buffer_puts(buffer_1, "\n");
190 	mdoc_paragraphs(&iface->desc, true);
191 
192 	if (iface->nrequests > 0) {
193@@ -239,11 +243,10 @@ mdoc_title(const char *name)
194 	size_t i, len;
195 	char *title;
196 
197-	len = strlen(name);
198-	title = xmalloc(len + 1);
199+	len = str_len(name);
200+	title = copystr(name);
201 	for (i = 0; i < len; ++i)
202 		title[i] = (char)toupper((unsigned char)name[i]);
203-	title[len] = '\0';
204 	return title;
205 }
206 
207@@ -257,12 +260,14 @@ print_protocol_mdoc(const struct protocol *proto)
208 	mdoc_macro(".\\\" generated by proto from shrubtools!!!!.");
209 	mdoc_macro(".\\\" srcdump.net/shrub/shrubtools");
210 	mdoc_macro(".Dd $Mdocdate$");
211-	printf(".Dt %s 7\n", title);
212+	buffer_puts(buffer_1, ".Dt ");
213+	buffer_puts(buffer_1, title);
214+	buffer_puts(buffer_1, " 7\n");
215 	mdoc_macro(".Os");
216 	mdoc_macro(".Sh NAME");
217-	fputs(".Nm ", stdout);
218+	buffer_puts(buffer_1, ".Nm ");
219 	mdoc_text(proto->name);
220-	putchar('\n');
221+	buffer_puts(buffer_1, "\n");
222 	mdoc_macro(".Nd protocol specification");
223 	if (has_description(&proto->desc)) {
224 		mdoc_macro(".Sh DESCRIPTION");
225@@ -271,5 +276,6 @@ print_protocol_mdoc(const struct protocol *proto)
226 	mdoc_macro(".Sh INTERFACES");
227 	for (i = 0; i < proto->nifaces; ++i)
228 		mdoc_interface_detail(&proto->ifaces[i]);
229-	free(title);
230+	alloc_free(title);
231+	buffer_flush(buffer_1);
232 }
+128, -88
  1@@ -1,8 +1,14 @@
  2 #include <expat.h>
  3+#include <alloc.h>
  4+#include <byte.h>
  5+#include <scan.h>
  6+#include <str.h>
  7+#include <stralloc.h>
  8+#include <buffer.h>
  9+#include <strerr.h>
 10 #include <stdbool.h>
 11 #include <stdio.h>
 12-#include <stdlib.h>
 13-#include <string.h>
 14+#include <unistd.h>
 15 
 16 #include "parse.h"
 17 #include "util.h"
 18@@ -27,9 +33,7 @@ struct parser {
 19 	enum parse_scope stack[32];
 20 	size_t depth;
 21 	struct description *desc;
 22-	char *text;
 23-	size_t textlen;
 24-	size_t textcap;
 25+	stralloc text;
 26 };
 27 
 28 static const char *attr(const char **, const char *);
 29@@ -43,6 +47,40 @@ static char *normalizedtext(const char *);
 30 static void onstart(void *, const char *, const char **);
 31 static void onend(void *, const char *);
 32 static void ontext(void *, const XML_Char *, int);
 33+extern const char *argv0;
 34+
 35+static void
 36+die_path_line(const char *path, unsigned long line, const char *msg)
 37+{
 38+	buffer_puts(buffer_2, argv0);
 39+	buffer_puts(buffer_2, ": ");
 40+	buffer_puts(buffer_2, path);
 41+	buffer_puts(buffer_2, ":");
 42+	put_ulong(buffer_2, line);
 43+	buffer_puts(buffer_2, ": ");
 44+	buffer_puts(buffer_2, msg);
 45+	buffer_puts(buffer_2, "\n");
 46+	buffer_flush(buffer_2);
 47+	_exit(1);
 48+}
 49+
 50+static void
 51+die_path_line_col(const char *path, unsigned long line, unsigned long col,
 52+    const char *msg)
 53+{
 54+	buffer_puts(buffer_2, argv0);
 55+	buffer_puts(buffer_2, ": ");
 56+	buffer_puts(buffer_2, path);
 57+	buffer_puts(buffer_2, ":");
 58+	put_ulong(buffer_2, line);
 59+	buffer_puts(buffer_2, ":");
 60+	put_ulong(buffer_2, col);
 61+	buffer_puts(buffer_2, ": ");
 62+	buffer_puts(buffer_2, msg);
 63+	buffer_puts(buffer_2, "\n");
 64+	buffer_flush(buffer_2);
 65+	_exit(1);
 66+}
 67 
 68 static const char *
 69 attr(const char **attrs, const char *name)
 70@@ -50,7 +88,7 @@ attr(const char **attrs, const char *name)
 71 	size_t i;
 72 
 73 	for (i = 0; attrs && attrs[i]; i += 2) {
 74-		if (strcmp(attrs[i], name) == 0)
 75+		if (str_equal(attrs[i], name))
 76 			return attrs[i + 1];
 77 	}
 78 	return NULL;
 79@@ -59,14 +97,17 @@ attr(const char **attrs, const char *name)
 80 static int
 81 parseint(const char *what, const char *s)
 82 {
 83-	char *end;
 84-	long v;
 85+	char *msg;
 86+	unsigned long v;
 87+	unsigned int n;
 88 
 89 	if (!s)
 90-		die("missing %s attribute", what);
 91-	v = strtol(s, &end, 10);
 92-	if (*s == '\0' || *end != '\0' || v < 0)
 93-		die("invalid %s: %s", what, s);
 94+		strerr_die4x(111, argv0, ": missing ", what, " attribute");
 95+	n = scan_ulong(s, &v);
 96+	if (*s == '\0' || s[n] != '\0' || v > 2147483647UL) {
 97+		msg = copystr(s);
 98+		strerr_die6x(111, argv0, ": invalid ", what, ": ", msg, "");
 99+	}
100 	return (int)v;
101 }
102 
103@@ -74,7 +115,7 @@ static void
104 pushscope(struct parser *p, enum parse_scope scope)
105 {
106 	if (p->depth == countof(p->stack))
107-		die("%s: XML nesting too deep", p->path);
108+		strerr_die4x(111, argv0, ": ", p->path, ": XML nesting too deep");
109 	p->stack[p->depth++] = scope;
110 }
111 
112@@ -94,10 +135,10 @@ inscope(const struct parser *p, enum parse_scope scope)
113 static void
114 cleartext(struct parser *p)
115 {
116-	free(p->text);
117-	p->text = NULL;
118-	p->textlen = 0;
119-	p->textcap = 0;
120+	alloc_free(p->text.s);
121+	p->text.s = NULL;
122+	p->text.len = 0;
123+	p->text.a = 0;
124 }
125 
126 static void
127@@ -107,39 +148,32 @@ appendtext(struct parser *p, const char *s, int n)
128 
129 	if (n <= 0)
130 		return;
131-	need = p->textlen + (size_t)n + 1;
132-	if (need > p->textcap) {
133-		p->textcap = p->textcap ? p->textcap * 2 : 128;
134-		while (p->textcap < need)
135-			p->textcap *= 2;
136-		p->text = xreallocarray(p->text, p->textcap, sizeof(p->text[0]));
137-	}
138-	memcpy(p->text + p->textlen, s, (size_t)n);
139-	p->textlen += (size_t)n;
140-	p->text[p->textlen] = '\0';
141+	need = p->text.len + (size_t)n + 1;
142+	if (!stralloc_ready(&p->text, need))
143+		die_nomem();
144+	byte_copy(p->text.s + p->text.len, (unsigned int)n, (char *)s);
145+	p->text.len += (size_t)n;
146+	p->text.s[p->text.len] = '\0';
147 }
148 
149 static char *
150 normalizedtext(const char *s)
151 {
152 	const char *start, *end, *lineend;
153-	char *out;
154-	size_t cap, len, n;
155+	stralloc out = {0};
156+	size_t n;
157 
158 	if (!s)
159 		return NULL;
160 	start = s;
161 	while (*start == '\n' || *start == '\r' || *start == '\t' || *start == ' ')
162 		++start;
163-	end = s + strlen(s);
164+	end = s + str_len(s);
165 	while (end > start && (end[-1] == '\n' || end[-1] == '\r' || end[-1] == '\t' || end[-1] == ' '))
166 		--end;
167 	if (start == end)
168 		return NULL;
169 
170-	cap = (size_t)(end - start) + 1;
171-	out = xmalloc(cap);
172-	len = 0;
173 	while (start < end) {
174 		while (start < end && (*start == '\n' || *start == '\r'))
175 			++start;
176@@ -152,21 +186,27 @@ normalizedtext(const char *s)
177 			--lineend;
178 		n = (size_t)(lineend - start);
179 		if (n > 0) {
180-			if (len > 0)
181-				out[len++] = '\n';
182-			memcpy(out + len, start, n);
183-			len += n;
184+			if (out.len > 0 && !stralloc_catb(&out, "\n", 1))
185+				goto nomem;
186+			if (!stralloc_catb(&out, start, (unsigned int)n))
187+				goto nomem;
188 		}
189 		start = lineend;
190 		while (start < end && *start != '\n' && *start != '\r')
191 			++start;
192 	}
193-	if (len == 0) {
194-		free(out);
195+	if (out.len == 0) {
196+		alloc_free(out.s);
197 		return NULL;
198 	}
199-	out[len] = '\0';
200-	return out;
201+	if (!stralloc_0(&out))
202+		goto nomem;
203+	return out.s;
204+
205+nomem:
206+	alloc_free(out.s);
207+	die_nomem();
208+	return NULL;
209 }
210 
211 static void
212@@ -175,88 +215,88 @@ onstart(void *data, const char *name, const char **attrs)
213 	struct parser *p = data;
214 	const char *aname, *atype, *iface, *allow_null, *version, *type, *summary;
215 
216-	if (strcmp(name, "protocol") == 0) {
217+	if (str_equal(name, "protocol")) {
218 		if (p->proto->name)
219-			die("%s:%lu: duplicate protocol element",
220-				p->path, XML_GetCurrentLineNumber(p->xml));
221+			die_path_line(p->path, XML_GetCurrentLineNumber(p->xml),
222+			    "duplicate protocol element");
223 		aname = attr(attrs, "name");
224 		if (!aname)
225-			die("%s:%lu: protocol missing name",
226-				p->path, XML_GetCurrentLineNumber(p->xml));
227-		p->proto->name = xstrdup(aname);
228+			die_path_line(p->path, XML_GetCurrentLineNumber(p->xml),
229+			    "protocol missing name");
230+		p->proto->name = copystr(aname);
231 		pushscope(p, SCOPE_PROTOCOL);
232 		return;
233 	}
234 
235-	if (strcmp(name, "interface") == 0 && inscope(p, SCOPE_PROTOCOL)) {
236+	if (str_equal(name, "interface") && inscope(p, SCOPE_PROTOCOL)) {
237 		aname = attr(attrs, "name");
238 		version = attr(attrs, "version");
239 		if (!aname || !version)
240-			die("%s:%lu: interface missing name/version",
241-				p->path, XML_GetCurrentLineNumber(p->xml));
242+			die_path_line(p->path, XML_GetCurrentLineNumber(p->xml),
243+			    "interface missing name/version");
244 		p->iface = proto_add_interface(p->proto, aname, parseint("version", version));
245 		pushscope(p, SCOPE_INTERFACE);
246 		return;
247 	}
248 
249-	if ((strcmp(name, "request") == 0 || strcmp(name, "event") == 0) && inscope(p, SCOPE_INTERFACE)) {
250+	if ((str_equal(name, "request") || str_equal(name, "event")) && inscope(p, SCOPE_INTERFACE)) {
251 		aname = attr(attrs, "name");
252 		type = attr(attrs, "type");
253 		if (!aname)
254-			die("%s:%lu: message missing name",
255-				p->path, XML_GetCurrentLineNumber(p->xml));
256+			die_path_line(p->path, XML_GetCurrentLineNumber(p->xml),
257+			    "message missing name");
258 		p->msg = iface_add_message(p->iface,
259-			strcmp(name, "request") == 0 ? MSG_REQUEST : MSG_EVENT, aname);
260-		p->msg->destructor = type && strcmp(type, "destructor") == 0;
261+			str_equal(name, "request") ? MSG_REQUEST : MSG_EVENT, aname);
262+		p->msg->destructor = type && str_equal(type, "destructor");
263 		pushscope(p, SCOPE_MESSAGE);
264 		return;
265 	}
266 
267-	if (strcmp(name, "arg") == 0 && inscope(p, SCOPE_MESSAGE)) {
268+	if (str_equal(name, "arg") && inscope(p, SCOPE_MESSAGE)) {
269 		aname = attr(attrs, "name");
270 		atype = attr(attrs, "type");
271 		iface = attr(attrs, "interface");
272 		allow_null = attr(attrs, "allow-null");
273 		summary = attr(attrs, "summary");
274 		if (!aname || !atype)
275-			die("%s:%lu: arg missing name/type",
276-				p->path, XML_GetCurrentLineNumber(p->xml));
277+			die_path_line(p->path, XML_GetCurrentLineNumber(p->xml),
278+			    "arg missing name/type");
279 		message_add_arg(p->msg, aname, atype, iface,
280-			allow_null && strcmp(allow_null, "true") == 0);
281+			allow_null && str_equal(allow_null, "true"));
282 		if (summary)
283-			p->msg->args[p->msg->nargs - 1].summary = xstrdup(summary);
284+			p->msg->args[p->msg->nargs - 1].summary = copystr(summary);
285 		return;
286 	}
287 
288-	if (strcmp(name, "enum") == 0 && inscope(p, SCOPE_INTERFACE)) {
289+	if (str_equal(name, "enum") && inscope(p, SCOPE_INTERFACE)) {
290 		aname = attr(attrs, "name");
291 		if (!aname)
292-			die("%s:%lu: enum missing name",
293-				p->path, XML_GetCurrentLineNumber(p->xml));
294+			die_path_line(p->path, XML_GetCurrentLineNumber(p->xml),
295+			    "enum missing name");
296 		iface_add_enum(p->iface, aname);
297 		p->en = iface_last_enum(p->iface);
298 		pushscope(p, SCOPE_ENUM);
299 		return;
300 	}
301 
302-	if (strcmp(name, "entry") == 0 && inscope(p, SCOPE_ENUM)) {
303+	if (str_equal(name, "entry") && inscope(p, SCOPE_ENUM)) {
304 		const char *value;
305 
306 		aname = attr(attrs, "name");
307 		value = attr(attrs, "value");
308 		summary = attr(attrs, "summary");
309 		if (!aname || !value)
310-			die("%s:%lu: entry missing name/value",
311-				p->path, XML_GetCurrentLineNumber(p->xml));
312+			die_path_line(p->path, XML_GetCurrentLineNumber(p->xml),
313+			    "entry missing name/value");
314 		enum_add_entry(p->en, aname, value);
315 		p->entry = enum_last_entry(p->en);
316 		if (summary)
317-			p->entry->summary = xstrdup(summary);
318+			p->entry->summary = copystr(summary);
319 		pushscope(p, SCOPE_ENTRY);
320 		return;
321 	}
322 
323-	if (strcmp(name, "description") == 0) {
324+	if (str_equal(name, "description")) {
325 		if (inscope(p, SCOPE_MESSAGE))
326 			p->desc = &p->msg->desc;
327 		else if (inscope(p, SCOPE_ENTRY))
328@@ -270,8 +310,8 @@ onstart(void *data, const char *name, const char **attrs)
329 		else
330 			return;
331 		summary = attr(attrs, "summary");
332-		free(p->desc->summary);
333-		p->desc->summary = summary ? xstrdup(summary) : NULL;
334+		alloc_free(p->desc->summary);
335+		p->desc->summary = summary ? copystr(summary) : NULL;
336 		cleartext(p);
337 		pushscope(p, SCOPE_DESCRIPTION);
338 		return;
339@@ -283,14 +323,14 @@ onend(void *data, const char *name)
340 {
341 	struct parser *p = data;
342 
343-	if (strcmp(name, "request") == 0 || strcmp(name, "event") == 0) {
344+	if (str_equal(name, "request") || str_equal(name, "event")) {
345 		if (inscope(p, SCOPE_MESSAGE)) {
346 			p->msg = NULL;
347 			popscope(p);
348 		}
349 		return;
350 	}
351-	if (strcmp(name, "enum") == 0) {
352+	if (str_equal(name, "enum")) {
353 		if (inscope(p, SCOPE_ENUM))
354 		{
355 			p->en = NULL;
356@@ -298,31 +338,31 @@ onend(void *data, const char *name)
357 		}
358 		return;
359 	}
360-	if (strcmp(name, "entry") == 0) {
361+	if (str_equal(name, "entry")) {
362 		if (inscope(p, SCOPE_ENTRY)) {
363 			p->entry = NULL;
364 			popscope(p);
365 		}
366 		return;
367 	}
368-	if (strcmp(name, "description") == 0) {
369+	if (str_equal(name, "description")) {
370 		if (inscope(p, SCOPE_DESCRIPTION)) {
371-			free(p->desc->text);
372-			p->desc->text = normalizedtext(p->text);
373+			alloc_free(p->desc->text);
374+			p->desc->text = normalizedtext(p->text.s);
375 			p->desc = NULL;
376 			cleartext(p);
377 			popscope(p);
378 		}
379 		return;
380 	}
381-	if (strcmp(name, "interface") == 0) {
382+	if (str_equal(name, "interface")) {
383 		if (inscope(p, SCOPE_INTERFACE)) {
384 			p->iface = NULL;
385 			popscope(p);
386 		}
387 		return;
388 	}
389-	if (strcmp(name, "protocol") == 0) {
390+	if (str_equal(name, "protocol")) {
391 		if (inscope(p, SCOPE_PROTOCOL))
392 			popscope(p);
393 		return;
394@@ -346,12 +386,12 @@ parsefile(const char *path, struct protocol *proto)
395 	void *buf;
396 	int done;
397 
398-	memset(&p, 0, sizeof(p));
399+	byte_zero(&p, sizeof(p));
400 	p.path = path;
401 	p.proto = proto;
402 	p.xml = XML_ParserCreate(NULL);
403 	if (!p.xml)
404-		die("XML_ParserCreate:");
405+		strerr_die2sys(111, argv0, ": XML_ParserCreate");
406 	XML_SetUserData(p.xml, &p);
407 	XML_SetElementHandler(p.xml, onstart, onend);
408 	XML_SetCharacterDataHandler(p.xml, ontext);
409@@ -359,7 +399,7 @@ parsefile(const char *path, struct protocol *proto)
410 	fp = fopen(path, "rb");
411 	if (!fp) {
412 		XML_ParserFree(p.xml);
413-		die("open %s:", path);
414+		strerr_die4sys(111, argv0, ": open ", path, "");
415 	}
416 
417 	done = 0;
418@@ -368,16 +408,16 @@ parsefile(const char *path, struct protocol *proto)
419 
420 		buf = XML_GetBuffer(p.xml, 4096);
421 		if (!buf)
422-			die("%s: XML_GetBuffer failed", path);
423+			strerr_die4x(111, argv0, ": ", path, ": XML_GetBuffer failed");
424 		nread = fread(buf, 1, 4096, fp);
425 		done = nread < 4096;
426 		if (ferror(fp))
427-			die("read %s:", path);
428+			strerr_die4sys(111, argv0, ": read ", path, "");
429 		if (XML_ParseBuffer(p.xml, (int)nread, done) == XML_STATUS_ERROR) {
430-			die("%s:%lu:%lu: %s", path,
431-				XML_GetCurrentLineNumber(p.xml),
432-				XML_GetCurrentColumnNumber(p.xml),
433-				XML_ErrorString(XML_GetErrorCode(p.xml)));
434+			die_path_line_col(path,
435+			    XML_GetCurrentLineNumber(p.xml),
436+			    XML_GetCurrentColumnNumber(p.xml),
437+			    XML_ErrorString(XML_GetErrorCode(p.xml)));
438 		}
439 	}
440 
441@@ -386,6 +426,6 @@ parsefile(const char *path, struct protocol *proto)
442 	cleartext(&p);
443 
444 	if (!proto->name)
445-		die("%s: missing protocol element", path);
446+		strerr_die4x(111, argv0, ": ", path, ": missing protocol element");
447 	proto_resolve(proto);
448 }
+126, -79
  1@@ -1,8 +1,11 @@
  2 #include <stdbool.h>
  3+#include <alloc.h>
  4+#include <byte.h>
  5+#include <buffer.h>
  6+#include <str.h>
  7+#include <strerr.h>
  8 #include <glob.h>
  9 #include <sys/stat.h>
 10-#include <stdio.h>
 11-#include <stdlib.h>
 12 #include <string.h>
 13 
 14 #include "parse.h"
 15@@ -12,13 +15,7 @@
 16 
 17 const char *argv0;
 18 
 19-struct nameset {
 20-	const char **items;
 21-	size_t len;
 22-	size_t cap;
 23-};
 24-
 25-static void usage(FILE *);
 26+static void usage(buffer *);
 27 static const char *progname(const char *, const char *);
 28 static bool fileexists(const char *);
 29 static bool haspathsep(const char *);
 30@@ -31,11 +28,22 @@ static void print_message(const struct message *);
 31 static void print_args(const struct message *);
 32 static void print_arg(const struct argument *);
 33 static void print_description(const struct description *, const char *);
 34+static void put_line(buffer *, const char *);
 35+
 36+static void
 37+put_line(buffer *b, const char *s)
 38+{
 39+	buffer_puts(b, s);
 40+	buffer_puts(b, "\n");
 41+}
 42 
 43 static void
 44-usage(FILE *fp)
 45+usage(buffer *b)
 46 {
 47-	fprintf(fp, "usage: %s [-h] [-m] FILE [INTERFACE]\n", argv0);
 48+	buffer_puts(b, "usage: ");
 49+	buffer_puts(b, argv0);
 50+	buffer_puts(b, " [-h] [-m] FILE [INTERFACE]\n");
 51+	buffer_flush(b);
 52 }
 53 
 54 static const char *
 55@@ -60,7 +68,7 @@ fileexists(const char *path)
 56 static bool
 57 haspathsep(const char *path)
 58 {
 59-	return strchr(path, '/') != NULL;
 60+	return path[str_chr(path, '/')];
 61 }
 62 
 63 static char *
 64@@ -69,41 +77,60 @@ joinpath(const char *dir, const char *name)
 65 	size_t ndir, nname;
 66 	char *path;
 67 
 68-	ndir = strlen(dir);
 69-	nname = strlen(name);
 70-	path = xmalloc(ndir + 1 + nname + 1);
 71-	memcpy(path, dir, ndir);
 72+	ndir = str_len(dir);
 73+	nname = str_len(name);
 74+	path = alloc((unsigned int)(ndir + 1 + nname + 1));
 75+	if (!path)
 76+		strerr_die2sys(111, argv0, ": alloc");
 77+	byte_copy(path, ndir, (char *)dir);
 78 	path[ndir] = '/';
 79-	memcpy(path + ndir + 1, name, nname + 1);
 80+	byte_copy(path + ndir + 1, nname + 1, (char *)name);
 81 	return path;
 82 }
 83 
 84 static char *
 85 searchsystem(const char *name)
 86 {
 87-	static const char *patterns[] = {
 88-		"/usr/share/wayland/%s",
 89-		"/usr/share/wayland/%s.xml",
 90-		"/usr/share/wayland-protocols/*/*/%s",
 91-		"/usr/share/wayland-protocols/*/*/%s.xml",
 92-		"/use/share/wayland-protocols/*/*/%s",
 93-		"/use/share/wayland-protocols/*/*/%s.xml",
 94+	static const char *prefixes[] = {
 95+		"/usr/share/wayland/",
 96+		"/usr/share/wayland/",
 97+		"/usr/share/wayland-protocols/*/*/",
 98+		"/usr/share/wayland-protocols/*/*/",
 99+		"/usr/share/wayland-protocols/*/*/",
100+		"/usr/share/wayland-protocols/*/*/",
101+	};
102+	static const char *suffixes[] = {
103+		"",
104+		".xml",
105+		"",
106+		".xml",
107+		"",
108+		".xml",
109 	};
110 	glob_t g;
111-	char *pattern, *found;
112-	size_t i;
113-
114-	for (i = 0; i < countof(patterns); ++i) {
115-		xasprintf(&pattern, patterns[i], name);
116-		memset(&g, 0, sizeof(g));
117+	char *pattern;
118+	char *found;
119+	size_t i, nprefix, nname, nsuffix;
120+
121+	for (i = 0; i < countof(prefixes); ++i) {
122+		nprefix = str_len(prefixes[i]);
123+		nname = str_len(name);
124+		nsuffix = str_len(suffixes[i]);
125+		pattern = alloc((unsigned int)(nprefix + nname + nsuffix + 1));
126+		if (!pattern)
127+			die_nomem();
128+		byte_copy(pattern, nprefix, (char *)prefixes[i]);
129+		byte_copy(pattern + nprefix, nname, (char *)name);
130+		byte_copy(pattern + nprefix + nname, nsuffix + 1, (char *)suffixes[i]);
131+		byte_zero(&g, sizeof(g));
132 		if (glob(pattern, 0, NULL, &g) == 0 && g.gl_pathc > 0 && fileexists(g.gl_pathv[0])) {
133-			found = xstrdup(g.gl_pathv[0]);
134+			found = copystr(g.gl_pathv[0]);
135 			globfree(&g);
136-			free(pattern);
137+			alloc_free(pattern);
138 			return found;
139 		}
140 		globfree(&g);
141-		free(pattern);
142+		alloc_free(pattern);
143 	}
144 	return NULL;
145 }
146@@ -114,17 +141,17 @@ resolvepath(const char *arg)
147 	char *path, *found;
148 
149 	if (fileexists(arg))
150-		return xstrdup(arg);
151+		return copystr(arg);
152 	if (!haspathsep(arg)) {
153 		path = joinpath(".", arg);
154 		if (fileexists(path))
155 			return path;
156-		free(path);
157+		alloc_free(path);
158 		found = searchsystem(arg);
159 		if (found)
160 			return found;
161 	}
162-	return xstrdup(arg);
163+	return copystr(arg);
164 }
165 
166 static void
167@@ -133,15 +160,17 @@ print_description(const struct description *desc, const char *prefix)
168 	const char *line, *next;
169 
170 	if (desc->summary && desc->summary[0])
171-		printf("%s%s\n", prefix, desc->summary);
172+		buffer_puts(buffer_1, prefix), put_line(buffer_1, desc->summary);
173 	if (!desc->text || !desc->text[0])
174 		return;
175 	line = desc->text;
176 	while (*line) {
177-		next = strchr(line, '\n');
178-		if (!next)
179-			next = line + strlen(line);
180-		printf("%s%.*s\n", prefix, (int)(next - line), line);
181+		next = line + str_chr(line, '\n');
182+		if (*next == '\0')
183+			next = line + str_len(line);
184+		buffer_puts(buffer_1, prefix);
185+		buffer_put(buffer_1, line, (unsigned int)(next - line));
186+		buffer_puts(buffer_1, "\n");
187 		line = *next ? next + 1 : next;
188 	}
189 }
190@@ -151,23 +180,31 @@ print_protocol_summary(const struct protocol *proto)
191 {
192 	size_t i;
193 
194-	printf("%s\n\n", proto->name);
195+	put_line(buffer_1, proto->name);
196+	buffer_puts(buffer_1, "\n");
197 	print_description(&proto->desc, "");
198 	if ((proto->desc.summary && proto->desc.summary[0]) || (proto->desc.text && proto->desc.text[0]))
199-		printf("\n");
200-	printf("interfaces: %zu\n", proto->nifaces);
201-	printf("requests:   %zu\n", proto->total_requests);
202-	printf("events:     %zu\n", proto->total_events);
203-	printf("enums:      %zu\n\n", proto->total_enums);
204+		buffer_puts(buffer_1, "\n");
205+	buffer_puts(buffer_1, "interfaces: "); put_ulong(buffer_1, proto->nifaces); buffer_puts(buffer_1, "\n");
206+	buffer_puts(buffer_1, "requests:   "); put_ulong(buffer_1, proto->total_requests); buffer_puts(buffer_1, "\n");
207+	buffer_puts(buffer_1, "events:     "); put_ulong(buffer_1, proto->total_events); buffer_puts(buffer_1, "\n");
208+	buffer_puts(buffer_1, "enums:      "); put_ulong(buffer_1, proto->total_enums); buffer_puts(buffer_1, "\n\n");
209 
210 	for (i = 0; i < proto->nifaces; ++i) {
211 		const struct interface *iface = &proto->ifaces[i];
212 
213-		printf("%-18s v%-2d requests=%-3zu events=%-2zu creates=%-2zu",
214-			iface->name, iface->version, iface->nrequests, iface->nevents, iface->ncreates);
215+		buffer_puts(buffer_1, iface->name);
216+		buffer_puts(buffer_1, " v");
217+		put_ulong(buffer_1, (unsigned long)iface->version);
218+		buffer_puts(buffer_1, " requests=");
219+		put_ulong(buffer_1, iface->nrequests);
220+		buffer_puts(buffer_1, " events=");
221+		put_ulong(buffer_1, iface->nevents);
222+		buffer_puts(buffer_1, " creates=");
223+		put_ulong(buffer_1, iface->ncreates);
224 		if (!iface->created_by_local)
225-			printf("  root");
226-		putchar('\n');
227+			buffer_puts(buffer_1, " root");
228+		buffer_puts(buffer_1, "\n");
229 	}
230 }
231 
232@@ -175,11 +212,11 @@ static void
233 print_arg(const struct argument *arg)
234 {
235 	if (arg->nullable)
236-		putchar('?');
237-	if (arg->iface && arg->iface[0] && (strcmp(arg->type, "object") == 0 || strcmp(arg->type, "new_id") == 0))
238-		printf("%s", arg->iface);
239+		buffer_puts(buffer_1, "?");
240+	if (arg->iface && arg->iface[0] && (str_equal(arg->type, "object") || str_equal(arg->type, "new_id")))
241+		buffer_puts(buffer_1, arg->iface);
242 	else
243-		printf("%s", arg->type);
244+		buffer_puts(buffer_1, arg->type);
245 }
246 
247 static void
248@@ -195,7 +232,7 @@ print_args(const struct message *msg)
249 		if (arg->new_id && arg->iface && arg->iface[0])
250 			continue;
251 		if (!first)
252-			printf(", ");
253+			buffer_puts(buffer_1, ", ");
254 		print_arg(arg);
255 		first = false;
256 	}
257@@ -206,15 +243,19 @@ print_message(const struct message *msg)
258 {
259 	const struct argument *creator;
260 
261-	printf("  %d  %s(", msg->opcode, msg->name);
262+	buffer_puts(buffer_1, "  ");
263+	put_ulong(buffer_1, (unsigned long)msg->opcode);
264+	buffer_puts(buffer_1, "  ");
265+	buffer_puts(buffer_1, msg->name);
266+	buffer_puts(buffer_1, "(");
267 	print_args(msg);
268-	printf(")");
269+	buffer_puts(buffer_1, ")");
270 	creator = message_creator_arg(msg);
271 	if (creator)
272-		printf(" => %s", creator->iface);
273+		buffer_puts(buffer_1, " => "), buffer_puts(buffer_1, creator->iface);
274 	if (msg->destructor)
275-		printf(" [destructor]");
276-	putchar('\n');
277+		buffer_puts(buffer_1, " [destructor]");
278+	buffer_puts(buffer_1, "\n");
279 	print_description(&msg->desc, "     ");
280 }
281 
282@@ -224,25 +265,30 @@ print_interface_summary(const struct protocol *proto, const struct interface *if
283 	size_t i;
284 
285 	(void)proto;
286-	printf("interface %s@%d\n\n", iface->name, iface->version);
287+	buffer_puts(buffer_1, "interface ");
288+	buffer_puts(buffer_1, iface->name);
289+	buffer_puts(buffer_1, "@");
290+	put_ulong(buffer_1, (unsigned long)iface->version);
291+	buffer_puts(buffer_1, "\n\n");
292 	print_description(&iface->desc, "");
293 	if ((iface->desc.summary && iface->desc.summary[0]) || (iface->desc.text && iface->desc.text[0]))
294-		printf("\n");
295+		buffer_puts(buffer_1, "\n");
296 
297-	printf("requests\n");
298+	put_line(buffer_1, "requests");
299 	for (i = 0; i < iface->nrequests; ++i)
300 		print_message(&iface->requests[i]);
301 
302-	printf("\n");
303-	printf("events\n");
304+	buffer_puts(buffer_1, "\n");
305+	put_line(buffer_1, "events");
306 	for (i = 0; i < iface->nevents; ++i)
307 		print_message(&iface->events[i]);
308 
309-	printf("\n");
310-	printf("enums\n");
311+	buffer_puts(buffer_1, "\n");
312+	put_line(buffer_1, "enums");
313 	for (i = 0; i < iface->nenums; ++i)
314 	{
315-		printf("  %s\n", iface->enums[i].name);
316+		buffer_puts(buffer_1, "  ");
317+		put_line(buffer_1, iface->enums[i].name);
318 		print_description(&iface->enums[i].desc, "     ");
319 	}
320 }
321@@ -257,23 +303,23 @@ main(int argc, char *argv[])
322 	bool mflag;
323 	int i;
324 
325-	memset(&proto, 0, sizeof(proto));
326+	byte_zero(&proto, sizeof(proto));
327 	argv0 = progname(argv[0], "proto");
328 	path = NULL;
329 	ifname = NULL;
330 	mflag = false;
331 
332 	for (i = 1; i < argc; ++i) {
333-		if (strcmp(argv[i], "-h") == 0) {
334-			usage(stdout);
335+		if (str_equal(argv[i], "-h")) {
336+			usage(buffer_1);
337 			return 0;
338 		}
339-		if (strcmp(argv[i], "-m") == 0) {
340+		if (str_equal(argv[i], "-m")) {
341 			mflag = true;
342 			continue;
343 		}
344 		if (argv[i][0] == '-' && argv[i][1] != '\0') {
345-			usage(stderr);
346+			usage(buffer_2);
347 			return 2;
348 		}
349 		if (!path) {
350@@ -284,12 +330,12 @@ main(int argc, char *argv[])
351 			ifname = argv[i];
352 			continue;
353 		}
354-		usage(stderr);
355+		usage(buffer_2);
356 		return 2;
357 	}
358 
359 	if (!path) {
360-		usage(stderr);
361+		usage(buffer_2);
362 		return 2;
363 	}
364 
365@@ -297,13 +343,13 @@ main(int argc, char *argv[])
366 	parsefile(path, &proto);
367 
368 	if (mflag && ifname)
369-		die("-m cannot be used with an interface name");
370+		strerr_die2x(111, argv0, ": -m cannot be used with an interface name");
371 
372 	iface = NULL;
373 	if (ifname) {
374 		iface = proto_find_interface(&proto, ifname);
375 		if (!iface)
376-			die("unknown interface: %s", ifname);
377+			strerr_die4x(111, argv0, ": unknown interface: ", ifname, "");
378 	}
379 
380 	if (mflag)
381@@ -313,7 +359,8 @@ main(int argc, char *argv[])
382 	else
383 		print_protocol_summary(&proto);
384 
385-	free(path);
386+	buffer_flush(buffer_1);
387+	alloc_free(path);
388 	proto_free(&proto);
389 	return 0;
390 }
+74, -42
  1@@ -1,11 +1,13 @@
  2-#include <stdlib.h>
  3-#include <string.h>
  4+#include <alloc.h>
  5+#include <byte.h>
  6+#include <str.h>
  7 
  8 #include "protocol.h"
  9 #include "util.h"
 10 
 11 static void free_message(struct message *);
 12 static void free_description(struct description *);
 13+extern const char *argv0;
 14 
 15 struct interface *
 16 proto_add_interface(struct protocol *proto, const char *name, int version)
 17@@ -13,12 +15,18 @@ proto_add_interface(struct protocol *proto, const char *name, int version)
 18 	struct interface *iface;
 19 
 20 	if (proto->nifaces == proto->ifacecap) {
 21+		size_t oldcap;
 22+
 23+		oldcap = proto->ifacecap;
 24 		proto->ifacecap = proto->ifacecap ? proto->ifacecap * 2 : 8;
 25-		proto->ifaces = xreallocarray(proto->ifaces, proto->ifacecap, sizeof(proto->ifaces[0]));
 26+		if (!alloc_re((char **)&proto->ifaces,
 27+		    oldcap * sizeof(proto->ifaces[0]),
 28+		    proto->ifacecap * sizeof(proto->ifaces[0])))
 29+			die_nomem();
 30 	}
 31 	iface = &proto->ifaces[proto->nifaces++];
 32-	memset(iface, 0, sizeof(*iface));
 33-	iface->name = xstrdup(name);
 34+	byte_zero(iface, sizeof(*iface));
 35+	iface->name = copystr(name);
 36 	iface->version = version;
 37 	return iface;
 38 }
 39@@ -29,7 +37,7 @@ proto_find_interface(const struct protocol *proto, const char *name)
 40 	size_t i;
 41 
 42 	for (i = 0; i < proto->nifaces; ++i) {
 43-		if (strcmp(proto->ifaces[i].name, name) == 0)
 44+		if (str_equal(proto->ifaces[i].name, name))
 45 			return &proto->ifaces[i];
 46 	}
 47 	return NULL;
 48@@ -52,12 +60,18 @@ iface_add_message(struct interface *iface, enum message_dir dir, const char *nam
 49 		cap = &iface->eventcap;
 50 	}
 51 	if (*nlist == *cap) {
 52+		size_t oldcap;
 53+
 54+		oldcap = *cap;
 55 		*cap = *cap ? *cap * 2 : 8;
 56-		*list = xreallocarray(*list, *cap, sizeof((*list)[0]));
 57+		if (!alloc_re((char **)list,
 58+		    oldcap * sizeof((*list)[0]),
 59+		    *cap * sizeof((*list)[0])))
 60+			die_nomem();
 61 	}
 62 	msg = &(*list)[(*nlist)++];
 63-	memset(msg, 0, sizeof(*msg));
 64-	msg->name = xstrdup(name);
 65+	byte_zero(msg, sizeof(*msg));
 66+	msg->name = copystr(name);
 67 	msg->dir = dir;
 68 	msg->opcode = (int)(*nlist - 1);
 69 	return msg;
 70@@ -69,28 +83,40 @@ message_add_arg(struct message *msg, const char *name, const char *type, const c
 71 	struct argument *arg;
 72 
 73 	if (msg->nargs == msg->argcap) {
 74+		size_t oldcap;
 75+
 76+		oldcap = msg->argcap;
 77 		msg->argcap = msg->argcap ? msg->argcap * 2 : 8;
 78-		msg->args = xreallocarray(msg->args, msg->argcap, sizeof(msg->args[0]));
 79+		if (!alloc_re((char **)&msg->args,
 80+		    oldcap * sizeof(msg->args[0]),
 81+		    msg->argcap * sizeof(msg->args[0])))
 82+			die_nomem();
 83 	}
 84 	arg = &msg->args[msg->nargs++];
 85-	memset(arg, 0, sizeof(*arg));
 86-	arg->name = xstrdup(name);
 87-	arg->type = xstrdup(type);
 88-	arg->iface = iface ? xstrdup(iface) : NULL;
 89+	byte_zero(arg, sizeof(*arg));
 90+	arg->name = copystr(name);
 91+	arg->type = copystr(type);
 92+	arg->iface = iface ? copystr(iface) : NULL;
 93 	arg->summary = NULL;
 94 	arg->nullable = nullable;
 95-	arg->new_id = strcmp(type, "new_id") == 0;
 96+	arg->new_id = str_equal(type, "new_id");
 97 }
 98 
 99 void
100 iface_add_enum(struct interface *iface, const char *name)
101 {
102 	if (iface->nenums == iface->enumcap) {
103+		size_t oldcap;
104+
105+		oldcap = iface->enumcap;
106 		iface->enumcap = iface->enumcap ? iface->enumcap * 2 : 4;
107-		iface->enums = xreallocarray(iface->enums, iface->enumcap, sizeof(iface->enums[0]));
108+		if (!alloc_re((char **)&iface->enums,
109+		    oldcap * sizeof(iface->enums[0]),
110+		    iface->enumcap * sizeof(iface->enums[0])))
111+			die_nomem();
112 	}
113-	memset(&iface->enums[iface->nenums], 0, sizeof(iface->enums[0]));
114-	iface->enums[iface->nenums++].name = xstrdup(name);
115+	byte_zero(&iface->enums[iface->nenums], sizeof(iface->enums[0]));
116+	iface->enums[iface->nenums++].name = copystr(name);
117 }
118 
119 struct enumdef *
120@@ -105,12 +131,18 @@ void
121 enum_add_entry(struct enumdef *en, const char *name, const char *value)
122 {
123 	if (en->nentries == en->entrycap) {
124+		size_t oldcap;
125+
126+		oldcap = en->entrycap;
127 		en->entrycap = en->entrycap ? en->entrycap * 2 : 8;
128-		en->entries = xreallocarray(en->entries, en->entrycap, sizeof(en->entries[0]));
129+		if (!alloc_re((char **)&en->entries,
130+		    oldcap * sizeof(en->entries[0]),
131+		    en->entrycap * sizeof(en->entries[0])))
132+			die_nomem();
133 	}
134-	memset(&en->entries[en->nentries], 0, sizeof(en->entries[0]));
135-	en->entries[en->nentries].name = xstrdup(name);
136-	en->entries[en->nentries].value = xstrdup(value);
137+	byte_zero(&en->entries[en->nentries], sizeof(en->entries[0]));
138+	en->entries[en->nentries].name = copystr(name);
139+	en->entries[en->nentries].value = copystr(value);
140 	++en->nentries;
141 }
142 
143@@ -170,8 +202,8 @@ proto_resolve(struct protocol *proto)
144 static void
145 free_description(struct description *desc)
146 {
147-	free(desc->summary);
148-	free(desc->text);
149+	alloc_free(desc->summary);
150+	alloc_free(desc->text);
151 }
152 
153 static void
154@@ -179,15 +211,15 @@ free_message(struct message *msg)
155 {
156 	size_t i;
157 
158-	free(msg->name);
159+	alloc_free(msg->name);
160 	free_description(&msg->desc);
161 	for (i = 0; i < msg->nargs; ++i) {
162-		free(msg->args[i].name);
163-		free(msg->args[i].type);
164-		free(msg->args[i].iface);
165-		free(msg->args[i].summary);
166+		alloc_free(msg->args[i].name);
167+		alloc_free(msg->args[i].type);
168+		alloc_free(msg->args[i].iface);
169+		alloc_free(msg->args[i].summary);
170 	}
171-	free(msg->args);
172+	alloc_free((char *)msg->args);
173 }
174 
175 void
176@@ -195,12 +227,12 @@ proto_free(struct protocol *proto)
177 {
178 	size_t i, j;
179 
180-	free(proto->name);
181+	alloc_free(proto->name);
182 	free_description(&proto->desc);
183 	for (i = 0; i < proto->nifaces; ++i) {
184 		struct interface *iface = &proto->ifaces[i];
185 
186-		free(iface->name);
187+		alloc_free(iface->name);
188 		free_description(&iface->desc);
189 		for (j = 0; j < iface->nrequests; ++j)
190 			free_message(&iface->requests[j]);
191@@ -210,20 +242,20 @@ proto_free(struct protocol *proto)
192 		{
193 			size_t k;
194 
195-			free(iface->enums[j].name);
196+			alloc_free(iface->enums[j].name);
197 			free_description(&iface->enums[j].desc);
198 			for (k = 0; k < iface->enums[j].nentries; ++k) {
199-				free(iface->enums[j].entries[k].name);
200-				free(iface->enums[j].entries[k].value);
201-				free(iface->enums[j].entries[k].summary);
202+				alloc_free(iface->enums[j].entries[k].name);
203+				alloc_free(iface->enums[j].entries[k].value);
204+				alloc_free(iface->enums[j].entries[k].summary);
205 				free_description(&iface->enums[j].entries[k].desc);
206 			}
207-			free(iface->enums[j].entries);
208+			alloc_free((char *)iface->enums[j].entries);
209 		}
210-		free(iface->requests);
211-		free(iface->events);
212-		free(iface->enums);
213+		alloc_free((char *)iface->requests);
214+		alloc_free((char *)iface->events);
215+		alloc_free((char *)iface->enums);
216 	}
217-	free(proto->ifaces);
218-	memset(proto, 0, sizeof(*proto));
219+	alloc_free((char *)proto->ifaces);
220+	byte_zero(proto, sizeof(*proto));
221 }
+0, -4
 1@@ -3,10 +3,6 @@ proto
 2 
 3 proto is a small command-line tool for inspecting wayland protocol xml files in a nice human-readable way. i was kinda sick of having a browser open just for browsing wayland.app. it searches your system paths, so you can do stuff like 'proto xdg-shell' or 'proto wayland' and it knows where to look. it can also read local files, but you need to give it the path. you can also provide an interface as an argument, and it will give you the rundown on that. with `-m`, it emits an mdoc manpage for the whole protocol.
 4 
 5-build:
 6-    ninja
 7-    ninja install
 8-
 9 examples
10     proto xdg-shell
11     proto xdg-shell xdg_wm_base
+15, -0
 1@@ -0,0 +1,15 @@
 2+build proto/parse.o: cc proto/parse.c
 3+  cflags = $base_cflags -Ishared
 4+build proto/mdoc.o: cc proto/mdoc.c
 5+  cflags = $base_cflags -Ishared
 6+build proto/proto.o: cc proto/proto.c
 7+  cflags = $base_cflags -Ishared
 8+build proto/protocol.o: cc proto/protocol.c
 9+  cflags = $base_cflags -Ishared
10+build proto/util.o: cc proto/util.c
11+  cflags = $base_cflags -Ishared
12+
13+build proto/proto: link proto/parse.o proto/mdoc.o proto/proto.o proto/protocol.o proto/util.o shared/libdjb.a
14+  libs = $proto_libs
15+
16+build proto-all: phony proto/proto
+23, -115
  1@@ -1,131 +1,39 @@
  2-#include <errno.h>
  3-#include <stdarg.h>
  4-#include <stdbool.h>
  5-#include <stdint.h>
  6-#include <stdio.h>
  7-#include <stdlib.h>
  8-#include <string.h>
  9+#include <alloc.h>
 10+#include <byte.h>
 11+#include <fmt.h>
 12+#include <str.h>
 13+#include <strerr.h>
 14 
 15 #include "util.h"
 16 
 17 extern const char *argv0;
 18 
 19-static void
 20-vwarn(const char *fmt, va_list ap)
 21-{
 22-	fprintf(stderr, "%s: ", argv0);
 23-	vfprintf(stderr, fmt, ap);
 24-	if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
 25-		putc(' ', stderr);
 26-		perror(NULL);
 27-	} else {
 28-		putc('\n', stderr);
 29-	}
 30-}
 31-
 32-void
 33-warn(const char *fmt, ...)
 34-{
 35-	va_list ap;
 36-
 37-	va_start(ap, fmt);
 38-	vwarn(fmt, ap);
 39-	va_end(ap);
 40-}
 41-
 42-void
 43-die(const char *fmt, ...)
 44-{
 45-	va_list ap;
 46-
 47-	va_start(ap, fmt);
 48-	vwarn(fmt, ap);
 49-	va_end(ap);
 50-	exit(1);
 51-}
 52-
 53-void *
 54-xmalloc(size_t n)
 55-{
 56-	void *p;
 57-
 58-	p = malloc(n ? n : 1);
 59-	if (!p)
 60-		die("malloc:");
 61-	return p;
 62-}
 63-
 64-void *
 65-xcalloc(size_t n, size_t m)
 66-{
 67-	void *p;
 68-
 69-	p = calloc(n, m);
 70-	if (!p)
 71-		die("calloc:");
 72-	return p;
 73-}
 74-
 75-static void *
 76-reallocarray_(void *p, size_t n, size_t m)
 77-{
 78-	if (m && n > SIZE_MAX / m) {
 79-		errno = ENOMEM;
 80-		return NULL;
 81-	}
 82-	return realloc(p, n * m);
 83-}
 84-
 85-void *
 86-xreallocarray(void *p, size_t n, size_t m)
 87-{
 88-	p = reallocarray_(p, n, m);
 89-	if (!p)
 90-		die("reallocarray:");
 91-	return p;
 92-}
 93-
 94 char *
 95-xstrdup(const char *s)
 96+copystr(const char *s)
 97 {
 98-	size_t n;
 99-	char *p;
100+	unsigned int n;
101+	char *out;
102 
103-	n = strlen(s) + 1;
104-	p = xmalloc(n);
105-	memcpy(p, s, n);
106-	return p;
107+	n = str_len(s) + 1;
108+	out = alloc(n);
109+	if (!out)
110+		die_nomem();
111+	byte_copy(out, n, (char *)s);
112+	return out;
113 }
114 
115-char *
116-xmemdup0(const char *s, size_t n)
117+void
118+die_nomem(void)
119 {
120-	char *p;
121-
122-	p = xmalloc(n + 1);
123-	memcpy(p, s, n);
124-	p[n] = '\0';
125-	return p;
126+	strerr_die2sys(111, argv0, ": alloc");
127 }
128 
129-int
130-xasprintf(char **s, const char *fmt, ...)
131+void
132+put_ulong(buffer *b, unsigned long u)
133 {
134-	va_list ap;
135-	int ret;
136-	size_t n;
137+	char buf[FMT_ULONG];
138+	unsigned int len;
139 
140-	va_start(ap, fmt);
141-	ret = vsnprintf(NULL, 0, fmt, ap);
142-	va_end(ap);
143-	if (ret < 0)
144-		die("vsnprintf:");
145-	n = (size_t)ret + 1;
146-	*s = xmalloc(n);
147-	va_start(ap, fmt);
148-	ret = vsnprintf(*s, n, fmt, ap);
149-	va_end(ap);
150-	if (ret < 0 || (size_t)ret >= n)
151-		die("vsnprintf:");
152-	return ret;
153+	len = fmt_ulong(buf, u);
154+	buffer_put(b, buf, len);
155 }
+5, -9
 1@@ -3,18 +3,14 @@
 2 
 3 #include <stddef.h>
 4 
 5+#include <buffer.h>
 6+
 7 #ifndef countof
 8 #define countof(a) (sizeof(a) / sizeof((a)[0]))
 9 #endif
10 
11-void warn(const char *, ...);
12-void die(const char *, ...);
13-
14-void *xmalloc(size_t);
15-void *xcalloc(size_t, size_t);
16-void *xreallocarray(void *, size_t, size_t);
17-int xasprintf(char **, const char *, ...);
18-char *xstrdup(const char *);
19-char *xmemdup0(const char *, size_t);
20+char *copystr(const char *);
21+void die_nomem(void);
22+void put_ulong(buffer *, unsigned long);
23 
24 #endif
+307, -0
  1@@ -0,0 +1,307 @@
  2+/*	$OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $	*/
  3+
  4+/*
  5+ * Copyright (c) 1996 by Internet Software Consortium.
  6+ *
  7+ * Permission to use, copy, modify, and distribute this software for any
  8+ * purpose with or without fee is hereby granted, provided that the above
  9+ * copyright notice and this permission notice appear in all copies.
 10+ *
 11+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 12+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 13+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 14+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 15+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 16+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 17+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 18+ * SOFTWARE.
 19+ */
 20+
 21+/*
 22+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
 23+ *
 24+ * International Business Machines, Inc. (hereinafter called IBM) grants
 25+ * permission under its copyrights to use, copy, modify, and distribute this
 26+ * Software with or without fee, provided that the above copyright notice and
 27+ * all paragraphs of this notice appear in all copies, and that the name of IBM
 28+ * not be used in connection with the marketing of any product incorporating
 29+ * the Software or modifications thereof, without specific, written prior
 30+ * permission.
 31+ *
 32+ * To the extent it has a right to do so, IBM grants an immunity from suit
 33+ * under its patents, if any, for the use, sale or manufacture of products to
 34+ * the extent that such products are used for performing Domain Name System
 35+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
 36+ * granted for any product per se or for any other function of any product.
 37+ *
 38+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
 39+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 40+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
 41+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
 42+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
 43+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
 44+ */
 45+
 46+/* OPENBSD ORIGINAL: lib/libc/net/base64.c */
 47+
 48+#include "defs"
 49+
 50+#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON))
 51+
 52+#include <sys/types.h>
 53+#include <ctype.h>
 54+
 55+#include <byte.h>
 56+#include "base64.h"
 57+
 58+static const char Base64[] =
 59+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 60+static const char Pad64 = '=';
 61+
 62+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
 63+   The following encoding technique is taken from RFC 1521 by Borenstein
 64+   and Freed.  It is reproduced here in a slightly edited form for
 65+   convenience.
 66+
 67+   A 65-character subset of US-ASCII is used, enabling 6 bits to be
 68+   represented per printable character. (The extra 65th character, "=",
 69+   is used to signify a special processing function.)
 70+
 71+   The encoding process represents 24-bit groups of input bits as output
 72+   strings of 4 encoded characters. Proceeding from left to right, a
 73+   24-bit input group is formed by concatenating 3 8-bit input groups.
 74+   These 24 bits are then treated as 4 concatenated 6-bit groups, each
 75+   of which is translated into a single digit in the base64 alphabet.
 76+
 77+   Each 6-bit group is used as an index into an array of 64 printable
 78+   characters. The character referenced by the index is placed in the
 79+   output string.
 80+
 81+                         Table 1: The Base64 Alphabet
 82+
 83+      Value Encoding  Value Encoding  Value Encoding  Value Encoding
 84+          0 A            17 R            34 i            51 z
 85+          1 B            18 S            35 j            52 0
 86+          2 C            19 T            36 k            53 1
 87+          3 D            20 U            37 l            54 2
 88+          4 E            21 V            38 m            55 3
 89+          5 F            22 W            39 n            56 4
 90+          6 G            23 X            40 o            57 5
 91+          7 H            24 Y            41 p            58 6
 92+          8 I            25 Z            42 q            59 7
 93+          9 J            26 a            43 r            60 8
 94+         10 K            27 b            44 s            61 9
 95+         11 L            28 c            45 t            62 +
 96+         12 M            29 d            46 u            63 /
 97+         13 N            30 e            47 v
 98+         14 O            31 f            48 w         (pad) =
 99+         15 P            32 g            49 x
100+         16 Q            33 h            50 y
101+
102+   Special processing is performed if fewer than 24 bits are available
103+   at the end of the data being encoded.  A full encoding quantum is
104+   always completed at the end of a quantity.  When fewer than 24 input
105+   bits are available in an input group, zero bits are added (on the
106+   right) to form an integral number of 6-bit groups.  Padding at the
107+   end of the data is performed using the '=' character.
108+
109+   Since all base64 input is an integral number of octets, only the
110+         -------------------------------------------------                       
111+   following cases can arise:
112+   
113+       (1) the final quantum of encoding input is an integral
114+           multiple of 24 bits; here, the final unit of encoded
115+	   output will be an integral multiple of 4 characters
116+	   with no "=" padding,
117+       (2) the final quantum of encoding input is exactly 8 bits;
118+           here, the final unit of encoded output will be two
119+	   characters followed by two "=" padding characters, or
120+       (3) the final quantum of encoding input is exactly 16 bits;
121+           here, the final unit of encoded output will be three
122+	   characters followed by one "=" padding character.
123+   */
124+
125+#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) 
126+int
127+b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize)
128+{
129+	size_t datalength = 0;
130+	u_char input[3];
131+	u_char output[4];
132+	u_int i;
133+
134+	while (2 < srclength) {
135+		input[0] = *src++;
136+		input[1] = *src++;
137+		input[2] = *src++;
138+		srclength -= 3;
139+
140+		output[0] = input[0] >> 2;
141+		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
142+		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
143+		output[3] = input[2] & 0x3f;
144+
145+		if (datalength + 4 > targsize)
146+			return (-1);
147+		target[datalength++] = Base64[output[0]];
148+		target[datalength++] = Base64[output[1]];
149+		target[datalength++] = Base64[output[2]];
150+		target[datalength++] = Base64[output[3]];
151+	}
152+    
153+	/* Now we worry about padding. */
154+	if (0 != srclength) {
155+		/* Get what's left. */
156+		input[0] = input[1] = input[2] = '\0';
157+		for (i = 0; i < srclength; i++)
158+			input[i] = *src++;
159+	
160+		output[0] = input[0] >> 2;
161+		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
162+		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
163+
164+		if (datalength + 4 > targsize)
165+			return (-1);
166+		target[datalength++] = Base64[output[0]];
167+		target[datalength++] = Base64[output[1]];
168+		if (srclength == 1)
169+			target[datalength++] = Pad64;
170+		else
171+			target[datalength++] = Base64[output[2]];
172+		target[datalength++] = Pad64;
173+	}
174+	if (datalength >= targsize)
175+		return (-1);
176+	target[datalength] = '\0';	/* Returned value doesn't count \0. */
177+	return (datalength);
178+}
179+#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */
180+
181+#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)
182+
183+/* skips all whitespace anywhere.
184+   converts characters, four at a time, starting at (or after)
185+   src from base - 64 numbers into three 8 bit bytes in the target area.
186+   it returns the number of data bytes stored at the target, or -1 on error.
187+ */
188+
189+int
190+b64_pton(char const *src, u_char *target, size_t targsize)
191+{
192+	u_int tarindex, state;
193+	int ch;
194+	size_t pos;
195+
196+	state = 0;
197+	tarindex = 0;
198+
199+	while ((ch = *src++) != '\0') {
200+		if (isspace(ch))	/* Skip whitespace anywhere. */
201+			continue;
202+
203+		if (ch == Pad64)
204+			break;
205+
206+		pos = byte_chr(Base64, 64, ch);
207+		if (pos >= 64)		/* A non-base64 character. */
208+			return (-1);
209+
210+		switch (state) {
211+		case 0:
212+			if (target) {
213+				if (tarindex >= targsize)
214+					return (-1);
215+				target[tarindex] = pos << 2;
216+			}
217+			state = 1;
218+			break;
219+		case 1:
220+			if (target) {
221+				if (tarindex + 1 >= targsize)
222+					return (-1);
223+				target[tarindex]   |=  pos >> 4;
224+				target[tarindex+1]  = (pos & 0x0f)
225+							<< 4 ;
226+			}
227+			tarindex++;
228+			state = 2;
229+			break;
230+		case 2:
231+			if (target) {
232+				if (tarindex + 1 >= targsize)
233+					return (-1);
234+				target[tarindex]   |=  pos >> 2;
235+				target[tarindex+1]  = (pos & 0x03)
236+							<< 6;
237+			}
238+			tarindex++;
239+			state = 3;
240+			break;
241+		case 3:
242+			if (target) {
243+				if (tarindex >= targsize)
244+					return (-1);
245+				target[tarindex] |= pos;
246+			}
247+			tarindex++;
248+			state = 0;
249+			break;
250+		}
251+	}
252+
253+	/*
254+	 * We are done decoding Base-64 chars.  Let's see if we ended
255+	 * on a byte boundary, and/or with erroneous trailing characters.
256+	 */
257+
258+	if (ch == Pad64) {		/* We got a pad char. */
259+		ch = *src++;		/* Skip it, get next. */
260+		switch (state) {
261+		case 0:		/* Invalid = in first position */
262+		case 1:		/* Invalid = in second position */
263+			return (-1);
264+
265+		case 2:		/* Valid, means one byte of info */
266+			/* Skip any number of spaces. */
267+			for (; ch != '\0'; ch = *src++)
268+				if (!isspace(ch))
269+					break;
270+			/* Make sure there is another trailing = sign. */
271+			if (ch != Pad64)
272+				return (-1);
273+			ch = *src++;		/* Skip the = */
274+			/* Fall through to "single trailing =" case. */
275+			/* FALLTHROUGH */
276+
277+		case 3:		/* Valid, means two bytes of info */
278+			/*
279+			 * We know this char is an =.  Is there anything but
280+			 * whitespace after it?
281+			 */
282+			for (; ch != '\0'; ch = *src++)
283+				if (!isspace(ch))
284+					return (-1);
285+
286+			/*
287+			 * Now make sure for cases 2 and 3 that the "extra"
288+			 * bits that slopped past the last full byte were
289+			 * zeros.  If we don't check them, they become a
290+			 * subliminal channel.
291+			 */
292+			if (target && target[tarindex] != 0)
293+				return (-1);
294+		}
295+	} else {
296+		/*
297+		 * We ended by seeing the end of the string.  Make sure we
298+		 * have no partial bytes lying around.
299+		 */
300+		if (state != 0)
301+			return (-1);
302+	}
303+
304+	return (tarindex);
305+}
306+
307+#endif /* !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) */
308+#endif 
+63, -0
 1@@ -0,0 +1,63 @@
 2+/*
 3+ * Copyright (c) 1996 by Internet Software Consortium.
 4+ *
 5+ * Permission to use, copy, modify, and distribute this software for any
 6+ * purpose with or without fee is hereby granted, provided that the above
 7+ * copyright notice and this permission notice appear in all copies.
 8+ *
 9+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
10+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
12+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16+ * SOFTWARE.
17+ */
18+
19+/*
20+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
21+ *
22+ * International Business Machines, Inc. (hereinafter called IBM) grants
23+ * permission under its copyrights to use, copy, modify, and distribute this
24+ * Software with or without fee, provided that the above copyright notice and
25+ * all paragraphs of this notice appear in all copies, and that the name of IBM
26+ * not be used in connection with the marketing of any product incorporating
27+ * the Software or modifications thereof, without specific, written prior
28+ * permission.
29+ *
30+ * To the extent it has a right to do so, IBM grants an immunity from suit
31+ * under its patents, if any, for the use, sale or manufacture of products to
32+ * the extent that such products are used for performing Domain Name System
33+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
34+ * granted for any product per se or for any other function of any product.
35+ *
36+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
37+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
38+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
39+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
40+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
41+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
42+ */
43+
44+#ifndef _BSD_BASE64_H
45+#define _BSD_BASE64_H
46+
47+#include "defs"
48+
49+#ifndef HAVE___B64_NTOP
50+# ifndef HAVE_B64_NTOP
51+int b64_ntop(u_char const *src, size_t srclength, char *target,
52+    size_t targsize);
53+# endif /* !HAVE_B64_NTOP */
54+# define __b64_ntop(a,b,c,d) b64_ntop(a,b,c,d)
55+#endif /* HAVE___B64_NTOP */
56+
57+#ifndef HAVE___B64_PTON
58+# ifndef HAVE_B64_PTON
59+int b64_pton(char const *src, u_char *target, size_t targsize);
60+# endif /* !HAVE_B64_PTON */
61+# define __b64_pton(a,b,c) b64_pton(a,b,c)
62+#endif /* HAVE___B64_PTON */
63+
64+#endif /* _BSD_BASE64_H */
+174, -0
  1@@ -0,0 +1,174 @@
  2+/*	$OpenBSD: sha2.h,v 1.10 2016/09/03 17:00:29 tedu Exp $	*/
  3+
  4+/*
  5+ * FILE:	sha2.h
  6+ * AUTHOR:	Aaron D. Gifford <me@aarongifford.com>
  7+ * 
  8+ * Copyright (c) 2000-2001, Aaron D. Gifford
  9+ * All rights reserved.
 10+ *
 11+ * Redistribution and use in source and binary forms, with or without
 12+ * modification, are permitted provided that the following conditions
 13+ * are met:
 14+ * 1. Redistributions of source code must retain the above copyright
 15+ *    notice, this list of conditions and the following disclaimer.
 16+ * 2. Redistributions in binary form must reproduce the above copyright
 17+ *    notice, this list of conditions and the following disclaimer in the
 18+ *    documentation and/or other materials provided with the distribution.
 19+ * 3. Neither the name of the copyright holder nor the names of contributors
 20+ *    may be used to endorse or promote products derived from this software
 21+ *    without specific prior written permission.
 22+ * 
 23+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
 24+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 25+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 26+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
 27+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 28+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 29+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 30+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 31+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 32+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 33+ * SUCH DAMAGE.
 34+ *
 35+ * $From: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
 36+ */
 37+
 38+/* OPENBSD ORIGINAL: include/sha2.h */
 39+
 40+#ifndef _SSHSHA2_H
 41+#define _SSHSHA2_H
 42+
 43+#include "defs"
 44+
 45+#if !defined(HAVE_SHA256UPDATE) || !defined(HAVE_SHA384UPDATE) || \
 46+    !defined(HAVE_SHA512UPDATE)
 47+
 48+/*** SHA-256/384/512 Various Length Definitions ***********************/
 49+#define SHA224_BLOCK_LENGTH		64
 50+#define SHA224_DIGEST_LENGTH		28
 51+#define SHA224_DIGEST_STRING_LENGTH	(SHA224_DIGEST_LENGTH * 2 + 1)
 52+#define SHA256_BLOCK_LENGTH		64
 53+#define SHA256_DIGEST_LENGTH		32
 54+#define SHA256_DIGEST_STRING_LENGTH	(SHA256_DIGEST_LENGTH * 2 + 1)
 55+#define SHA384_BLOCK_LENGTH		128
 56+#define SHA384_DIGEST_LENGTH		48
 57+#define SHA384_DIGEST_STRING_LENGTH	(SHA384_DIGEST_LENGTH * 2 + 1)
 58+#define SHA512_BLOCK_LENGTH		128
 59+#define SHA512_DIGEST_LENGTH		64
 60+#define SHA512_DIGEST_STRING_LENGTH	(SHA512_DIGEST_LENGTH * 2 + 1)
 61+#define SHA512_256_BLOCK_LENGTH		128
 62+#define SHA512_256_DIGEST_LENGTH	32
 63+#define SHA512_256_DIGEST_STRING_LENGTH	(SHA512_256_DIGEST_LENGTH * 2 + 1)
 64+
 65+
 66+/*** SHA-224/256/384/512 Context Structure *******************************/
 67+typedef struct _SHA2_CTX {
 68+	union {
 69+		u_int32_t	st32[8];
 70+		u_int64_t	st64[8];
 71+	} state;
 72+	u_int64_t	bitcount[2];
 73+	u_int8_t	buffer[SHA512_BLOCK_LENGTH];
 74+} SHA2_CTX;
 75+
 76+#if 0
 77+__BEGIN_DECLS
 78+void SHA224Init(SHA2_CTX *);
 79+void SHA224Transform(u_int32_t state[8], const u_int8_t [SHA224_BLOCK_LENGTH]);
 80+void SHA224Update(SHA2_CTX *, const u_int8_t *, size_t)
 81+	__attribute__((__bounded__(__string__,2,3)));
 82+void SHA224Pad(SHA2_CTX *);
 83+void SHA224Final(u_int8_t [SHA224_DIGEST_LENGTH], SHA2_CTX *)
 84+	__attribute__((__bounded__(__minbytes__,1,SHA224_DIGEST_LENGTH)));
 85+char *SHA224End(SHA2_CTX *, char *)
 86+	__attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH)));
 87+char *SHA224File(const char *, char *)
 88+	__attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH)));
 89+char *SHA224FileChunk(const char *, char *, off_t, off_t)
 90+	__attribute__((__bounded__(__minbytes__,2,SHA224_DIGEST_STRING_LENGTH)));
 91+char *SHA224Data(const u_int8_t *, size_t, char *)
 92+	__attribute__((__bounded__(__string__,1,2)))
 93+	__attribute__((__bounded__(__minbytes__,3,SHA224_DIGEST_STRING_LENGTH)));
 94+#endif /* 0 */
 95+
 96+#ifndef HAVE_SHA256UPDATE
 97+void SHA256Init(SHA2_CTX *);
 98+void SHA256Transform(u_int32_t state[8], const u_int8_t [SHA256_BLOCK_LENGTH]);
 99+void SHA256Update(SHA2_CTX *, const u_int8_t *, size_t)
100+	__attribute__((__bounded__(__string__,2,3)));
101+void SHA256Pad(SHA2_CTX *);
102+void SHA256Final(u_int8_t [SHA256_DIGEST_LENGTH], SHA2_CTX *)
103+	__attribute__((__bounded__(__minbytes__,1,SHA256_DIGEST_LENGTH)));
104+char *SHA256End(SHA2_CTX *, char *)
105+	__attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH)));
106+char *SHA256File(const char *, char *)
107+	__attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH)));
108+char *SHA256FileChunk(const char *, char *, off_t, off_t)
109+	__attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH)));
110+char *SHA256Data(const u_int8_t *, size_t, char *)
111+	__attribute__((__bounded__(__string__,1,2)))
112+	__attribute__((__bounded__(__minbytes__,3,SHA256_DIGEST_STRING_LENGTH)));
113+#endif /* HAVE_SHA256UPDATE */
114+
115+#ifndef HAVE_SHA384UPDATE
116+void SHA384Init(SHA2_CTX *);
117+void SHA384Transform(u_int64_t state[8], const u_int8_t [SHA384_BLOCK_LENGTH]);
118+void SHA384Update(SHA2_CTX *, const u_int8_t *, size_t)
119+	__attribute__((__bounded__(__string__,2,3)));
120+void SHA384Pad(SHA2_CTX *);
121+void SHA384Final(u_int8_t [SHA384_DIGEST_LENGTH], SHA2_CTX *)
122+	__attribute__((__bounded__(__minbytes__,1,SHA384_DIGEST_LENGTH)));
123+char *SHA384End(SHA2_CTX *, char *)
124+	__attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH)));
125+char *SHA384File(const char *, char *)
126+	__attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH)));
127+char *SHA384FileChunk(const char *, char *, off_t, off_t)
128+	__attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH)));
129+char *SHA384Data(const u_int8_t *, size_t, char *)
130+	__attribute__((__bounded__(__string__,1,2)))
131+	__attribute__((__bounded__(__minbytes__,3,SHA384_DIGEST_STRING_LENGTH)));
132+#endif /* HAVE_SHA384UPDATE */
133+
134+#ifndef HAVE_SHA512UPDATE
135+void SHA512Init(SHA2_CTX *);
136+void SHA512Transform(u_int64_t state[8], const u_int8_t [SHA512_BLOCK_LENGTH]);
137+void SHA512Update(SHA2_CTX *, const u_int8_t *, size_t)
138+	__attribute__((__bounded__(__string__,2,3)));
139+void SHA512Pad(SHA2_CTX *);
140+void SHA512Final(u_int8_t [SHA512_DIGEST_LENGTH], SHA2_CTX *)
141+	__attribute__((__bounded__(__minbytes__,1,SHA512_DIGEST_LENGTH)));
142+char *SHA512End(SHA2_CTX *, char *)
143+	__attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH)));
144+char *SHA512File(const char *, char *)
145+	__attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH)));
146+char *SHA512FileChunk(const char *, char *, off_t, off_t)
147+	__attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH)));
148+char *SHA512Data(const u_int8_t *, size_t, char *)
149+	__attribute__((__bounded__(__string__,1,2)))
150+	__attribute__((__bounded__(__minbytes__,3,SHA512_DIGEST_STRING_LENGTH)));
151+#endif /* HAVE_SHA512UPDATE */
152+
153+#if 0
154+void SHA512_256Init(SHA2_CTX *);
155+void SHA512_256Transform(u_int64_t state[8], const u_int8_t [SHA512_256_BLOCK_LENGTH]);
156+void SHA512_256Update(SHA2_CTX *, const u_int8_t *, size_t)
157+	__attribute__((__bounded__(__string__,2,3)));
158+void SHA512_256Pad(SHA2_CTX *);
159+void SHA512_256Final(u_int8_t [SHA512_256_DIGEST_LENGTH], SHA2_CTX *)
160+	__attribute__((__bounded__(__minbytes__,1,SHA512_256_DIGEST_LENGTH)));
161+char *SHA512_256End(SHA2_CTX *, char *)
162+	__attribute__((__bounded__(__minbytes__,2,SHA512_256_DIGEST_STRING_LENGTH)));
163+char *SHA512_256File(const char *, char *)
164+	__attribute__((__bounded__(__minbytes__,2,SHA512_256_DIGEST_STRING_LENGTH)));
165+char *SHA512_256FileChunk(const char *, char *, off_t, off_t)
166+	__attribute__((__bounded__(__minbytes__,2,SHA512_256_DIGEST_STRING_LENGTH)));
167+char *SHA512_256Data(const u_int8_t *, size_t, char *)
168+	__attribute__((__bounded__(__string__,1,2)))
169+	__attribute__((__bounded__(__minbytes__,3,SHA512_256_DIGEST_STRING_LENGTH)));
170+__END_DECLS
171+#endif /* 0 */
172+
173+#endif /* HAVE_SHA{256,384,512}UPDATE */
174+
175+#endif /* _SSHSHA2_H */
+58, -0
 1@@ -0,0 +1,58 @@
 2+#ifndef RANDOMART_DEFS
 3+#define RANDOMART_DEFS
 4+
 5+#ifndef _DEFAULT_SOURCE
 6+#define _DEFAULT_SOURCE
 7+#endif
 8+
 9+#include <sys/types.h>
10+
11+#include <stdint.h>
12+#include <string.h>
13+
14+#if defined(__linux__)
15+#include <endian.h>
16+#endif
17+
18+#ifndef LITTLE_ENDIAN
19+#define LITTLE_ENDIAN 1234
20+#endif
21+
22+#ifndef BIG_ENDIAN
23+#define BIG_ENDIAN 4321
24+#endif
25+
26+#ifndef BYTE_ORDER
27+#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)
28+#define BYTE_ORDER __BYTE_ORDER
29+#undef LITTLE_ENDIAN
30+#undef BIG_ENDIAN
31+#define LITTLE_ENDIAN __LITTLE_ENDIAN
32+#define BIG_ENDIAN __BIG_ENDIAN
33+#elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
34+    defined(__ORDER_BIG_ENDIAN__)
35+#define BYTE_ORDER __BYTE_ORDER__
36+#undef LITTLE_ENDIAN
37+#undef BIG_ENDIAN
38+#define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
39+#define BIG_ENDIAN __ORDER_BIG_ENDIAN__
40+#endif
41+#endif
42+
43+#ifndef BYTE_ORDER
44+#error "unable to determine BYTE_ORDER"
45+#endif
46+
47+#ifndef __bounded__
48+#define __bounded__(x, y, z)
49+#endif
50+
51+#ifndef DEF_WEAK
52+#define DEF_WEAK(x)
53+#endif
54+
55+#ifndef HAVE_EXPLICIT_BZERO
56+#define explicit_bzero(p, n) memset((p), 0, (n))
57+#endif
58+
59+#endif
+251, -0
  1@@ -0,0 +1,251 @@
  2+/*	$OpenBSD: md5.c,v 1.9 2014/01/08 06:14:57 tedu Exp $	*/
  3+
  4+/*
  5+ * This code implements the MD5 message-digest algorithm.
  6+ * The algorithm is due to Ron Rivest.	This code was
  7+ * written by Colin Plumb in 1993, no copyright is claimed.
  8+ * This code is in the public domain; do with it what you wish.
  9+ *
 10+ * Equivalent code is available from RSA Data Security, Inc.
 11+ * This code has been tested against that, and is equivalent,
 12+ * except that you don't need to include two pages of legalese
 13+ * with every copy.
 14+ *
 15+ * To compute the message digest of a chunk of bytes, declare an
 16+ * MD5Context structure, pass it to MD5Init, call MD5Update as
 17+ * needed on buffers full of bytes, and then call MD5Final, which
 18+ * will fill a supplied 16-byte array with the digest.
 19+ */
 20+
 21+#include "defs"
 22+
 23+#ifndef WITH_OPENSSL
 24+
 25+#include <sys/types.h>
 26+#include <byte.h>
 27+#include "md5.h"
 28+
 29+#define PUT_64BIT_LE(cp, value) do {					\
 30+	(cp)[7] = (value) >> 56;					\
 31+	(cp)[6] = (value) >> 48;					\
 32+	(cp)[5] = (value) >> 40;					\
 33+	(cp)[4] = (value) >> 32;					\
 34+	(cp)[3] = (value) >> 24;					\
 35+	(cp)[2] = (value) >> 16;					\
 36+	(cp)[1] = (value) >> 8;						\
 37+	(cp)[0] = (value); } while (0)
 38+
 39+#define PUT_32BIT_LE(cp, value) do {					\
 40+	(cp)[3] = (value) >> 24;					\
 41+	(cp)[2] = (value) >> 16;					\
 42+	(cp)[1] = (value) >> 8;						\
 43+	(cp)[0] = (value); } while (0)
 44+
 45+static u_int8_t PADDING[MD5_BLOCK_LENGTH] = {
 46+	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 47+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 48+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 49+};
 50+
 51+/*
 52+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
 53+ * initialization constants.
 54+ */
 55+void
 56+MD5Init(MD5_CTX *ctx)
 57+{
 58+	ctx->count = 0;
 59+	ctx->state[0] = 0x67452301;
 60+	ctx->state[1] = 0xefcdab89;
 61+	ctx->state[2] = 0x98badcfe;
 62+	ctx->state[3] = 0x10325476;
 63+}
 64+
 65+/*
 66+ * Update context to reflect the concatenation of another buffer full
 67+ * of bytes.
 68+ */
 69+void
 70+MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
 71+{
 72+	size_t have, need;
 73+
 74+	/* Check how many bytes we already have and how many more we need. */
 75+	have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
 76+	need = MD5_BLOCK_LENGTH - have;
 77+
 78+	/* Update bitcount */
 79+	ctx->count += (u_int64_t)len << 3;
 80+
 81+	if (len >= need) {
 82+		if (have != 0) {
 83+			byte_copy(ctx->buffer + have, need, input);
 84+			MD5Transform(ctx->state, ctx->buffer);
 85+			input += need;
 86+			len -= need;
 87+			have = 0;
 88+		}
 89+
 90+		/* Process data in MD5_BLOCK_LENGTH-byte chunks. */
 91+		while (len >= MD5_BLOCK_LENGTH) {
 92+			MD5Transform(ctx->state, input);
 93+			input += MD5_BLOCK_LENGTH;
 94+			len -= MD5_BLOCK_LENGTH;
 95+		}
 96+	}
 97+
 98+	/* Handle any remaining bytes of data. */
 99+	if (len != 0)
100+		byte_copy(ctx->buffer + have, len, input);
101+}
102+
103+/*
104+ * Pad pad to 64-byte boundary with the bit pattern
105+ * 1 0* (64-bit count of bits processed, MSB-first)
106+ */
107+void
108+MD5Pad(MD5_CTX *ctx)
109+{
110+	u_int8_t count[8];
111+	size_t padlen;
112+
113+	/* Convert count to 8 bytes in little endian order. */
114+	PUT_64BIT_LE(count, ctx->count);
115+
116+	/* Pad out to 56 mod 64. */
117+	padlen = MD5_BLOCK_LENGTH -
118+	    ((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
119+	if (padlen < 1 + 8)
120+		padlen += MD5_BLOCK_LENGTH;
121+	MD5Update(ctx, PADDING, padlen - 8);		/* padlen - 8 <= 64 */
122+	MD5Update(ctx, count, 8);
123+}
124+
125+/*
126+ * Final wrapup--call MD5Pad, fill in digest and zero out ctx.
127+ */
128+void
129+MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
130+{
131+	int i;
132+
133+	MD5Pad(ctx);
134+	for (i = 0; i < 4; i++)
135+		PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
136+	byte_zero(ctx, sizeof(*ctx));
137+}
138+
139+
140+/* The four core functions - F1 is optimized somewhat */
141+
142+/* #define F1(x, y, z) (x & y | ~x & z) */
143+#define F1(x, y, z) (z ^ (x & (y ^ z)))
144+#define F2(x, y, z) F1(z, x, y)
145+#define F3(x, y, z) (x ^ y ^ z)
146+#define F4(x, y, z) (y ^ (x | ~z))
147+
148+/* This is the central step in the MD5 algorithm. */
149+#define MD5STEP(f, w, x, y, z, data, s) \
150+	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
151+
152+/*
153+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
154+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
155+ * the data and converts bytes into longwords for this routine.
156+ */
157+void
158+MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
159+{
160+	u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
161+
162+#if BYTE_ORDER == LITTLE_ENDIAN
163+	byte_copy(in, sizeof(in), block);
164+#else
165+	for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
166+		in[a] = (u_int32_t)(
167+		    (u_int32_t)(block[a * 4 + 0]) |
168+		    (u_int32_t)(block[a * 4 + 1]) <<  8 |
169+		    (u_int32_t)(block[a * 4 + 2]) << 16 |
170+		    (u_int32_t)(block[a * 4 + 3]) << 24);
171+	}
172+#endif
173+
174+	a = state[0];
175+	b = state[1];
176+	c = state[2];
177+	d = state[3];
178+
179+	MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);
180+	MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
181+	MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
182+	MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
183+	MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);
184+	MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
185+	MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
186+	MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
187+	MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);
188+	MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
189+	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
190+	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
191+	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);
192+	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
193+	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
194+	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
195+
196+	MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);
197+	MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);
198+	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
199+	MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
200+	MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);
201+	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);
202+	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
203+	MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
204+	MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);
205+	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);
206+	MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
207+	MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
208+	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
209+	MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);
210+	MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
211+	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
212+
213+	MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);
214+	MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
215+	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
216+	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
217+	MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);
218+	MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
219+	MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
220+	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
221+	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
222+	MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
223+	MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
224+	MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
225+	MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);
226+	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
227+	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
228+	MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23);
229+
230+	MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);
231+	MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10);
232+	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
233+	MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21);
234+	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);
235+	MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10);
236+	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
237+	MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21);
238+	MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f,  6);
239+	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
240+	MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15);
241+	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
242+	MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82,  6);
243+	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
244+	MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15);
245+	MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21);
246+
247+	state[0] += a;
248+	state[1] += b;
249+	state[2] += c;
250+	state[3] += d;
251+}
252+#endif /* !WITH_OPENSSL */
+51, -0
 1@@ -0,0 +1,51 @@
 2+/*	$OpenBSD: md5.h,v 1.17 2012/12/05 23:19:57 deraadt Exp $	*/
 3+
 4+/*
 5+ * This code implements the MD5 message-digest algorithm.
 6+ * The algorithm is due to Ron Rivest.  This code was
 7+ * written by Colin Plumb in 1993, no copyright is claimed.
 8+ * This code is in the public domain; do with it what you wish.
 9+ *
10+ * Equivalent code is available from RSA Data Security, Inc.
11+ * This code has been tested against that, and is equivalent,
12+ * except that you don't need to include two pages of legalese
13+ * with every copy.
14+ */
15+
16+#ifndef _MD5_H_
17+#define _MD5_H_
18+
19+#ifndef WITH_OPENSSL
20+
21+#define	MD5_BLOCK_LENGTH		64
22+#define	MD5_DIGEST_LENGTH		16
23+#define	MD5_DIGEST_STRING_LENGTH	(MD5_DIGEST_LENGTH * 2 + 1)
24+
25+typedef struct MD5Context {
26+	u_int32_t state[4];			/* state */
27+	u_int64_t count;			/* number of bits, mod 2^64 */
28+	u_int8_t buffer[MD5_BLOCK_LENGTH];	/* input buffer */
29+} MD5_CTX;
30+
31+void	 MD5Init(MD5_CTX *);
32+void	 MD5Update(MD5_CTX *, const u_int8_t *, size_t)
33+		__attribute__((__bounded__(__string__,2,3)));
34+void	 MD5Pad(MD5_CTX *);
35+void	 MD5Final(u_int8_t [MD5_DIGEST_LENGTH], MD5_CTX *)
36+		__attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH)));
37+void	 MD5Transform(u_int32_t [4], const u_int8_t [MD5_BLOCK_LENGTH])
38+		__attribute__((__bounded__(__minbytes__,1,4)))
39+		__attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH)));
40+char	*MD5End(MD5_CTX *, char *)
41+		__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
42+char	*MD5File(const char *, char *)
43+		__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
44+char	*MD5FileChunk(const char *, char *, off_t, off_t)
45+		__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
46+char	*MD5Data(const u_int8_t *, size_t, char *)
47+		__attribute__((__bounded__(__string__,1,2)))
48+		__attribute__((__bounded__(__minbytes__,3,MD5_DIGEST_STRING_LENGTH)));
49+
50+#endif /* !WITH_OPENSSL */
51+
52+#endif /* _MD5_H_ */
+451, -0
  1@@ -0,0 +1,451 @@
  2+/* somewhat derived from OpenSSH */
  3+#include "defs"
  4+
  5+#include <ctype.h>
  6+#include <stdio.h>
  7+#include <stdlib.h>
  8+#include <string.h>
  9+
 10+#include <alloc.h>
 11+#include <byte.h>
 12+#include <str.h>
 13+#include <stralloc.h>
 14+#include <subgetopt.h>
 15+#include <buffer.h>
 16+#include <strerr.h>
 17+#include <openreadclose.h>
 18+
 19+#include "base64.h"
 20+#include "bsd-sha2.h"
 21+#include "md5.h"
 22+
 23+#define FLDBASE 8
 24+#define FLDSIZE_Y (FLDBASE + 1)
 25+#define FLDSIZE_X (FLDBASE * 2 + 1)
 26+
 27+struct options {
 28+	int hashalg;
 29+};
 30+
 31+static void
 32+usage(void)
 33+{
 34+	buffer_puts(buffer_2, "usage: randomart [-E md5|sha256] [file ...]\n");
 35+	buffer_puts(buffer_2,
 36+	    "       randomart [-E md5|sha256] -k public_key_line\n");
 37+	buffer_flush(buffer_2);
 38+	exit(1);
 39+}
 40+
 41+static void
 42+warnx1(const char *a, const char *b)
 43+{
 44+	strerr_warn3(a, b, "", 0);
 45+}
 46+
 47+static void
 48+warnx2(const char *a, const char *b, const char *c)
 49+{
 50+	strerr_warn4(a, b, c, "", 0);
 51+}
 52+
 53+static void
 54+warnsys1(const char *a, const char *b)
 55+{
 56+	strerr_warn3(a, b, "", &strerr_sys);
 57+}
 58+
 59+static char *
 60+alloc_nz(unsigned int size)
 61+{
 62+	char *ret;
 63+
 64+	ret = alloc(size ? size : 1);
 65+	if (ret == NULL) {
 66+		strerr_die2sys(111, "randomart: ", "alloc");
 67+		exit(1);
 68+	}
 69+	return ret;
 70+}
 71+
 72+static char *
 73+dup_string(const char *s)
 74+{
 75+	char *ret;
 76+	unsigned int len;
 77+
 78+	len = str_len(s) + 1;
 79+	ret = alloc_nz(len);
 80+	byte_copy(ret, len, (char *)s);
 81+	return ret;
 82+}
 83+
 84+static char *
 85+trim(char *s)
 86+{
 87+	char *end;
 88+
 89+	while (*s != '\0' && isspace((unsigned char)*s))
 90+		s++;
 91+	if (*s == '\0')
 92+		return s;
 93+	end = s + str_len(s) - 1;
 94+	while (end > s && isspace((unsigned char)*end))
 95+		*end-- = '\0';
 96+	return s;
 97+}
 98+
 99+static unsigned int
100+format_box_label(char *buf, unsigned int buf_len, const char *text,
101+    const char *fallback)
102+{
103+	int r;
104+
105+	r = snprintf(buf, buf_len, "[%s]", text);
106+	if (r < 0 || (unsigned int)r >= buf_len)
107+		r = snprintf(buf, buf_len, "[%s]", fallback);
108+	return (r <= 0) ? 0 : str_len(buf);
109+}
110+
111+static int
112+compute_digest(const u_char *data, size_t len, int hashalg,
113+    u_char *digest, size_t *digest_len, const char **label)
114+{
115+	MD5_CTX md5;
116+	SHA2_CTX sha256;
117+
118+	switch (hashalg) {
119+	case 0:
120+		MD5Init(&md5);
121+		MD5Update(&md5, data, len);
122+		MD5Final(digest, &md5);
123+		*digest_len = MD5_DIGEST_LENGTH;
124+		*label = "MD5";
125+		return 0;
126+	case 1:
127+		SHA256Init(&sha256);
128+		SHA256Update(&sha256, data, len);
129+		SHA256Final(digest, &sha256);
130+		*digest_len = SHA256_DIGEST_LENGTH;
131+		*label = "SHA256";
132+		return 0;
133+	default:
134+		return -1;
135+	}
136+}
137+
138+static int
139+sa_catc(stralloc *sa, char c)
140+{
141+	return stralloc_catb(sa, &c, 1);
142+}
143+
144+static int
145+sa_catn(stralloc *sa, char c, unsigned int n)
146+{
147+	while (n-- > 0) {
148+		if (!sa_catc(sa, c))
149+			return 0;
150+	}
151+	return 1;
152+}
153+
154+static char *
155+render_randomart(const char *title, const char *subtitle,
156+    const u_char *dgst_raw, size_t dgst_raw_len)
157+{
158+	static const char augmentation_string[] = " .o+=*BOX@%&#/^SE";
159+	char title_buf[FLDSIZE_X];
160+	char subtitle_buf[FLDSIZE_X];
161+	u_char field[FLDSIZE_X][FLDSIZE_Y];
162+	stralloc out = { 0 };
163+	unsigned int i, title_len, subtitle_len;
164+	u_int b;
165+	int x, y;
166+	unsigned int len = str_len(augmentation_string) - 1;
167+
168+	byte_zero(field, sizeof(field));
169+	x = FLDSIZE_X / 2;
170+	y = FLDSIZE_Y / 2;
171+
172+	for (i = 0; i < dgst_raw_len; i++) {
173+		int input = dgst_raw[i];
174+
175+		for (b = 0; b < 4; b++) {
176+			x += (input & 0x1) ? 1 : -1;
177+			y += (input & 0x2) ? 1 : -1;
178+			if (x < 0)
179+				x = 0;
180+			if (y < 0)
181+				y = 0;
182+			if (x >= FLDSIZE_X)
183+				x = FLDSIZE_X - 1;
184+			if (y >= FLDSIZE_Y)
185+				y = FLDSIZE_Y - 1;
186+			if (field[x][y] < len - 2)
187+				field[x][y]++;
188+			input >>= 2;
189+		}
190+	}
191+
192+	field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
193+	field[x][y] = len;
194+
195+	title_len = format_box_label(title_buf, sizeof(title_buf), title, "key");
196+	subtitle_len = format_box_label(subtitle_buf, sizeof(subtitle_buf),
197+	    subtitle, "hash");
198+
199+	if (!sa_catc(&out, '+') ||
200+	    !sa_catn(&out, '-', (FLDSIZE_X - title_len) / 2) ||
201+	    !stralloc_catb(&out, title_buf, title_len) ||
202+	    !sa_catn(&out, '-', FLDSIZE_X - ((FLDSIZE_X - title_len) / 2 + title_len)) ||
203+	    !stralloc_catb(&out, "+\n", 2))
204+		goto fail;
205+
206+	for (y = 0; y < FLDSIZE_Y; y++) {
207+		if (!sa_catc(&out, '|'))
208+			goto fail;
209+		for (x = 0; x < FLDSIZE_X; x++) {
210+			char ch = augmentation_string[field[x][y] > len ?
211+			    len : field[x][y]];
212+			if (!sa_catc(&out, ch))
213+				goto fail;
214+		}
215+		if (!stralloc_catb(&out, "|\n", 2))
216+			goto fail;
217+	}
218+
219+	if (!sa_catc(&out, '+') ||
220+	    !sa_catn(&out, '-', (FLDSIZE_X - subtitle_len) / 2) ||
221+	    !stralloc_catb(&out, subtitle_buf, subtitle_len) ||
222+	    !sa_catn(&out, '-', FLDSIZE_X - ((FLDSIZE_X - subtitle_len) / 2 + subtitle_len)) ||
223+	    !sa_catc(&out, '+') ||
224+	    !stralloc_0(&out))
225+		goto fail;
226+
227+	return out.s;
228+
229+fail:
230+	alloc_free(out.s);
231+	return NULL;
232+}
233+
234+static int
235+parse_public_key_line(char *line, char **typep, u_char **blobp,
236+    size_t *blob_lenp)
237+{
238+	char *type, *blob_text, *rest;
239+	int decoded_len;
240+	unsigned int blob_cap;
241+	u_char *blob;
242+
243+	line = trim(line);
244+	if (*line == '\0' || *line == '#')
245+		return 1;
246+
247+	type = strtok(line, " \t");
248+	blob_text = strtok(NULL, " \t");
249+	rest = strtok(NULL, "");
250+	(void)rest;
251+	if (type == NULL || blob_text == NULL)
252+		return -1;
253+
254+	blob_cap = (str_len(blob_text) / 4) * 3 + 4;
255+	blob = (u_char *)alloc_nz(blob_cap);
256+	decoded_len = b64_pton(blob_text, blob, blob_cap);
257+	if (decoded_len < 0) {
258+		alloc_free(blob);
259+		return -1;
260+	}
261+
262+	*typep = dup_string(type);
263+	*blobp = blob;
264+	*blob_lenp = (size_t)decoded_len;
265+	return 0;
266+}
267+
268+static int
269+print_art(const char *label, const char *art)
270+{
271+	if (buffer_puts(buffer_1, label) == -1 ||
272+	    buffer_puts(buffer_1, "\n") == -1 ||
273+	    buffer_puts(buffer_1, art) == -1 ||
274+	    buffer_puts(buffer_1, "\n") == -1 ||
275+	    buffer_flush(buffer_1) == -1)
276+		return -1;
277+	return 0;
278+}
279+
280+static int
281+process_key_line(char *line, const char *label, const struct options *opts)
282+{
283+	char *type = NULL, *art = NULL;
284+	u_char *blob = NULL;
285+	u_char digest[SHA256_DIGEST_LENGTH];
286+	size_t blob_len = 0, digest_len = 0;
287+	const char *hash_label = NULL;
288+	int ret = 1;
289+
290+	ret = parse_public_key_line(line, &type, &blob, &blob_len);
291+	if (ret == 1) {
292+		ret = 2;
293+		goto out;
294+	}
295+	if (ret != 0) {
296+		warnx2(label, ": ", "unable to parse OpenSSH public key line");
297+		goto out;
298+	}
299+	if (compute_digest(blob, blob_len, opts->hashalg, digest,
300+	    &digest_len, &hash_label) != 0) {
301+		warnx1(label, ": unsupported digest");
302+		goto out;
303+	}
304+	art = render_randomart(type, hash_label, digest, digest_len);
305+	if (art == NULL) {
306+		warnx1(label, ": unable to render randomart");
307+		goto out;
308+	}
309+	ret = print_art(label, art);
310+out:
311+	alloc_free(type);
312+	alloc_free(blob);
313+	alloc_free(art);
314+	return ret;
315+}
316+
317+static int
318+process_blob(char *blob, const char *label, const struct options *opts)
319+{
320+	char *line = blob;
321+	char *next;
322+	int ret = 1;
323+	int line_ret;
324+
325+	while (*line) {
326+		next = strchr(line, '\n');
327+		if (next != NULL)
328+			*next = '\0';
329+		line_ret = process_key_line(line, label, opts);
330+		if (line_ret == 0) {
331+			ret = 0;
332+			break;
333+		}
334+		if (next == NULL)
335+			break;
336+		line = next + 1;
337+	}
338+	if (ret != 0)
339+		warnx1(label, ": no usable public key line found");
340+	return ret;
341+}
342+
343+static int
344+process_path(const char *path, const struct options *opts)
345+{
346+	stralloc sa = { 0 };
347+	int ret;
348+
349+	ret = openreadclose(path, &sa, 8192);
350+	if (ret == 0) {
351+		warnsys1(path, ": ");
352+		alloc_free(sa.s);
353+		return 1;
354+	}
355+	if (ret == -1) {
356+		warnsys1(path, ": ");
357+		alloc_free(sa.s);
358+		return 1;
359+	}
360+	if (!stralloc_0(&sa))
361+		strerr_die2sys(111, "randomart: ", "stralloc_0");
362+	ret = process_blob(sa.s, path, opts);
363+	alloc_free(sa.s);
364+	return ret;
365+}
366+
367+static int
368+process_stdin(const struct options *opts)
369+{
370+	stralloc sa = { 0 };
371+	char ch;
372+	int r;
373+	int ret = 1;
374+
375+	for (;;) {
376+		r = buffer_get(buffer_0, &ch, 1);
377+		if (r < 0) {
378+			warnsys1("<stdin>", ": ");
379+			break;
380+		}
381+		if (r == 0) {
382+			if (sa.len != 0) {
383+				if (!stralloc_0(&sa))
384+					strerr_die2sys(111, "randomart: ",
385+					    "stralloc_0");
386+				ret = process_key_line(sa.s, "<stdin>", opts);
387+			}
388+			break;
389+		}
390+		if (ch == '\n') {
391+			if (!stralloc_0(&sa))
392+				strerr_die2sys(111, "randomart: ", "stralloc_0");
393+			ret = process_key_line(sa.s, "<stdin>", opts);
394+			if (ret == 0)
395+				break;
396+			sa.len = 0;
397+		} else if (!stralloc_append(&sa, &ch)) {
398+			strerr_die2sys(111, "randomart: ", "stralloc_append");
399+		}
400+	}
401+	if (ret != 0)
402+		warnx1("<stdin>", ": no usable public key line found");
403+	alloc_free(sa.s);
404+	return ret;
405+}
406+
407+int
408+main(int argc, char **argv)
409+{
410+	struct options opts;
411+	char *inline_key = NULL;
412+	int ch;
413+	int ret = 0;
414+
415+	opts.hashalg = 1;
416+
417+	while ((ch = subgetopt(argc, (const char * const *)argv, "E:k:h")) !=
418+	    SUBGETOPTDONE) {
419+		switch (ch) {
420+		case 'E':
421+			if (str_equal(subgetoptarg, "md5"))
422+				opts.hashalg = 0;
423+			else if (str_equal(subgetoptarg, "sha256"))
424+				opts.hashalg = 1;
425+			else
426+				usage();
427+			break;
428+		case 'k':
429+			inline_key = (char *)subgetoptarg;
430+			break;
431+		case 'h':
432+		default:
433+			usage();
434+		}
435+	}
436+
437+	argc -= subgetoptind;
438+	argv += subgetoptind;
439+
440+	if (inline_key != NULL) {
441+		char *buf = dup_string(inline_key);
442+
443+		ret = process_key_line(buf, "<inline>", &opts);
444+		alloc_free(buf);
445+		return ret;
446+	}
447+	if (argc == 0)
448+		return process_stdin(&opts);
449+	for (; *argv != NULL; argv++)
450+		ret |= process_path(*argv, &opts);
451+	return ret;
452+}
+5, -0
1@@ -0,0 +1,5 @@
2+randomart
3+---------
4+generate drunken bishop randomart based on openssh-format public keys. openssh has this, but i don't have openssh. this is for people who use dropbear or other alternative ssh implementations without this fun feature.
5+
6+code under BSD-style license due to being derived from OpenSSH.
+1010, -0
   1@@ -0,0 +1,1010 @@
   2+/*	$OpenBSD: sha2.c,v 1.28 2019/07/23 12:35:22 dtucker Exp $	*/
   3+
   4+/*
   5+ * FILE:	sha2.c
   6+ * AUTHOR:	Aaron D. Gifford <me@aarongifford.com>
   7+ * 
   8+ * Copyright (c) 2000-2001, Aaron D. Gifford
   9+ * All rights reserved.
  10+ *
  11+ * Redistribution and use in source and binary forms, with or without
  12+ * modification, are permitted provided that the following conditions
  13+ * are met:
  14+ * 1. Redistributions of source code must retain the above copyright
  15+ *    notice, this list of conditions and the following disclaimer.
  16+ * 2. Redistributions in binary form must reproduce the above copyright
  17+ *    notice, this list of conditions and the following disclaimer in the
  18+ *    documentation and/or other materials provided with the distribution.
  19+ * 3. Neither the name of the copyright holder nor the names of contributors
  20+ *    may be used to endorse or promote products derived from this software
  21+ *    without specific prior written permission.
  22+ * 
  23+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
  24+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
  27+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33+ * SUCH DAMAGE.
  34+ *
  35+ * $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
  36+ */
  37+
  38+/* OPENBSD ORIGINAL: lib/libc/hash/sha2.c */
  39+
  40+#include "defs"
  41+
  42+#if !defined(HAVE_SHA256UPDATE) || !defined(HAVE_SHA384UPDATE) || \
  43+    !defined(HAVE_SHA512UPDATE)
  44+
  45+/* no-op out, similar to DEF_WEAK but only needed here */
  46+#define MAKE_CLONE(x, y)	void __ssh_compat_make_clone_##x_##y(void)
  47+
  48+#include <byte.h>
  49+#include "bsd-sha2.h"
  50+
  51+/*
  52+ * UNROLLED TRANSFORM LOOP NOTE:
  53+ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
  54+ * loop version for the hash transform rounds (defined using macros
  55+ * later in this file).  Either define on the command line, for example:
  56+ *
  57+ *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
  58+ *
  59+ * or define below:
  60+ *
  61+ *   #define SHA2_UNROLL_TRANSFORM
  62+ *
  63+ */
  64+#ifndef SHA2_SMALL
  65+#if defined(__amd64__) || defined(__i386__)
  66+#define SHA2_UNROLL_TRANSFORM
  67+#endif
  68+#endif
  69+
  70+/*** SHA-224/256/384/512 Machine Architecture Definitions *****************/
  71+/*
  72+ * BYTE_ORDER NOTE:
  73+ *
  74+ * Please make sure that your system defines BYTE_ORDER.  If your
  75+ * architecture is little-endian, make sure it also defines
  76+ * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
  77+ * equivalent.
  78+ *
  79+ * If your system does not define the above, then you can do so by
  80+ * hand like this:
  81+ *
  82+ *   #define LITTLE_ENDIAN 1234
  83+ *   #define BIG_ENDIAN    4321
  84+ *
  85+ * And for little-endian machines, add:
  86+ *
  87+ *   #define BYTE_ORDER LITTLE_ENDIAN 
  88+ *
  89+ * Or for big-endian machines:
  90+ *
  91+ *   #define BYTE_ORDER BIG_ENDIAN
  92+ *
  93+ * The FreeBSD machine this was written on defines BYTE_ORDER
  94+ * appropriately by including <sys/types.h> (which in turn includes
  95+ * <machine/endian.h> where the appropriate definitions are actually
  96+ * made).
  97+ */
  98+#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
  99+#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
 100+#endif
 101+
 102+
 103+/*** SHA-224/256/384/512 Various Length Definitions ***********************/
 104+/* NOTE: Most of these are in sha2.h */
 105+#define SHA224_SHORT_BLOCK_LENGTH	(SHA224_BLOCK_LENGTH - 8)
 106+#define SHA256_SHORT_BLOCK_LENGTH	(SHA256_BLOCK_LENGTH - 8)
 107+#define SHA384_SHORT_BLOCK_LENGTH	(SHA384_BLOCK_LENGTH - 16)
 108+#define SHA512_SHORT_BLOCK_LENGTH	(SHA512_BLOCK_LENGTH - 16)
 109+
 110+/*** ENDIAN SPECIFIC COPY MACROS **************************************/
 111+#define BE_8_TO_32(dst, cp) do {					\
 112+	(dst) = (u_int32_t)(cp)[3] | ((u_int32_t)(cp)[2] << 8) |	\
 113+	    ((u_int32_t)(cp)[1] << 16) | ((u_int32_t)(cp)[0] << 24);	\
 114+} while(0)
 115+
 116+#define BE_8_TO_64(dst, cp) do {					\
 117+	(dst) = (u_int64_t)(cp)[7] | ((u_int64_t)(cp)[6] << 8) |	\
 118+	    ((u_int64_t)(cp)[5] << 16) | ((u_int64_t)(cp)[4] << 24) |	\
 119+	    ((u_int64_t)(cp)[3] << 32) | ((u_int64_t)(cp)[2] << 40) |	\
 120+	    ((u_int64_t)(cp)[1] << 48) | ((u_int64_t)(cp)[0] << 56);	\
 121+} while (0)
 122+
 123+#define BE_64_TO_8(cp, src) do {					\
 124+	(cp)[0] = (src) >> 56;						\
 125+        (cp)[1] = (src) >> 48;						\
 126+	(cp)[2] = (src) >> 40;						\
 127+	(cp)[3] = (src) >> 32;						\
 128+	(cp)[4] = (src) >> 24;						\
 129+	(cp)[5] = (src) >> 16;						\
 130+	(cp)[6] = (src) >> 8;						\
 131+	(cp)[7] = (src);						\
 132+} while (0)
 133+
 134+#define BE_32_TO_8(cp, src) do {					\
 135+	(cp)[0] = (src) >> 24;						\
 136+	(cp)[1] = (src) >> 16;						\
 137+	(cp)[2] = (src) >> 8;						\
 138+	(cp)[3] = (src);						\
 139+} while (0)
 140+
 141+/*
 142+ * Macro for incrementally adding the unsigned 64-bit integer n to the
 143+ * unsigned 128-bit integer (represented using a two-element array of
 144+ * 64-bit words):
 145+ */
 146+#define ADDINC128(w,n) do {						\
 147+	(w)[0] += (u_int64_t)(n);					\
 148+	if ((w)[0] < (n)) {						\
 149+		(w)[1]++;						\
 150+	}								\
 151+} while (0)
 152+
 153+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
 154+/*
 155+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
 156+ *
 157+ *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
 158+ *   S is a ROTATION) because the SHA-224/256/384/512 description document
 159+ *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
 160+ *   same "backwards" definition.
 161+ */
 162+/* Shift-right (used in SHA-224, SHA-256, SHA-384, and SHA-512): */
 163+#define R(b,x)		((x) >> (b))
 164+/* 32-bit Rotate-right (used in SHA-224 and SHA-256): */
 165+#define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
 166+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
 167+#define S64(b,x)	(((x) >> (b)) | ((x) << (64 - (b))))
 168+
 169+/* Two of six logical functions used in SHA-224, SHA-256, SHA-384, and SHA-512: */
 170+#define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
 171+#define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
 172+
 173+/* Four of six logical functions used in SHA-224 and SHA-256: */
 174+#define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
 175+#define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
 176+#define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
 177+#define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
 178+
 179+/* Four of six logical functions used in SHA-384 and SHA-512: */
 180+#define Sigma0_512(x)	(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
 181+#define Sigma1_512(x)	(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
 182+#define sigma0_512(x)	(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
 183+#define sigma1_512(x)	(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
 184+
 185+
 186+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
 187+/* Hash constant words K for SHA-224 and SHA-256: */
 188+static const u_int32_t K256[64] = {
 189+	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
 190+	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
 191+	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
 192+	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
 193+	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
 194+	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
 195+	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
 196+	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
 197+	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
 198+	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
 199+	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
 200+	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
 201+	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
 202+	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
 203+	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
 204+	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
 205+};
 206+
 207+/* Initial hash value H for SHA-256: */
 208+static const u_int32_t sha256_initial_hash_value[8] = {
 209+	0x6a09e667UL,
 210+	0xbb67ae85UL,
 211+	0x3c6ef372UL,
 212+	0xa54ff53aUL,
 213+	0x510e527fUL,
 214+	0x9b05688cUL,
 215+	0x1f83d9abUL,
 216+	0x5be0cd19UL
 217+};
 218+
 219+/* Hash constant words K for SHA-384 and SHA-512: */
 220+static const u_int64_t K512[80] = {
 221+	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
 222+	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
 223+	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
 224+	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
 225+	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
 226+	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
 227+	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
 228+	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
 229+	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
 230+	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
 231+	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
 232+	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
 233+	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
 234+	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
 235+	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
 236+	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
 237+	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
 238+	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
 239+	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
 240+	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
 241+	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
 242+	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
 243+	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
 244+	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
 245+	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
 246+	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
 247+	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
 248+	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
 249+	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
 250+	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
 251+	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
 252+	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
 253+	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
 254+	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
 255+	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
 256+	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
 257+	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
 258+	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
 259+	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
 260+	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
 261+};
 262+
 263+/* Initial hash value H for SHA-512 */
 264+static const u_int64_t sha512_initial_hash_value[8] = {
 265+	0x6a09e667f3bcc908ULL,
 266+	0xbb67ae8584caa73bULL,
 267+	0x3c6ef372fe94f82bULL,
 268+	0xa54ff53a5f1d36f1ULL,
 269+	0x510e527fade682d1ULL,
 270+	0x9b05688c2b3e6c1fULL,
 271+	0x1f83d9abfb41bd6bULL,
 272+	0x5be0cd19137e2179ULL
 273+};
 274+
 275+#if !defined(SHA2_SMALL)
 276+#if 0
 277+/* Initial hash value H for SHA-224: */
 278+static const u_int32_t sha224_initial_hash_value[8] = {
 279+	0xc1059ed8UL,
 280+	0x367cd507UL,
 281+	0x3070dd17UL,
 282+	0xf70e5939UL,
 283+	0xffc00b31UL,
 284+	0x68581511UL,
 285+	0x64f98fa7UL,
 286+	0xbefa4fa4UL
 287+};
 288+#endif /* 0 */
 289+
 290+/* Initial hash value H for SHA-384 */
 291+static const u_int64_t sha384_initial_hash_value[8] = {
 292+	0xcbbb9d5dc1059ed8ULL,
 293+	0x629a292a367cd507ULL,
 294+	0x9159015a3070dd17ULL,
 295+	0x152fecd8f70e5939ULL,
 296+	0x67332667ffc00b31ULL,
 297+	0x8eb44a8768581511ULL,
 298+	0xdb0c2e0d64f98fa7ULL,
 299+	0x47b5481dbefa4fa4ULL
 300+};
 301+
 302+#if 0
 303+/* Initial hash value H for SHA-512-256 */
 304+static const u_int64_t sha512_256_initial_hash_value[8] = {
 305+	0x22312194fc2bf72cULL,
 306+	0x9f555fa3c84c64c2ULL,
 307+	0x2393b86b6f53b151ULL,
 308+	0x963877195940eabdULL,
 309+	0x96283ee2a88effe3ULL,
 310+	0xbe5e1e2553863992ULL,
 311+	0x2b0199fc2c85b8aaULL,
 312+	0x0eb72ddc81c52ca2ULL
 313+};
 314+
 315+/*** SHA-224: *********************************************************/
 316+void
 317+SHA224Init(SHA2_CTX *context)
 318+{
 319+	byte_copy(context->state.st32, sizeof(sha224_initial_hash_value),
 320+	    sha224_initial_hash_value);
 321+	byte_zero(context->buffer, sizeof(context->buffer));
 322+	context->bitcount[0] = 0;
 323+}
 324+DEF_WEAK(SHA224Init);
 325+
 326+MAKE_CLONE(SHA224Transform, SHA256Transform);
 327+MAKE_CLONE(SHA224Update, SHA256Update);
 328+MAKE_CLONE(SHA224Pad, SHA256Pad);
 329+DEF_WEAK(SHA224Transform);
 330+DEF_WEAK(SHA224Update);
 331+DEF_WEAK(SHA224Pad);
 332+
 333+void
 334+SHA224Final(u_int8_t digest[SHA224_DIGEST_LENGTH], SHA2_CTX *context)
 335+{
 336+	SHA224Pad(context);
 337+
 338+#if BYTE_ORDER == LITTLE_ENDIAN
 339+	int	i;
 340+
 341+	/* Convert TO host byte order */
 342+	for (i = 0; i < 7; i++)
 343+		BE_32_TO_8(digest + i * 4, context->state.st32[i]);
 344+#else
 345+	byte_copy(digest, SHA224_DIGEST_LENGTH, context->state.st32);
 346+#endif
 347+	explicit_bzero(context, sizeof(*context));
 348+}
 349+DEF_WEAK(SHA224Final);
 350+#endif /* !defined(SHA2_SMALL) */
 351+#endif /* 0 */
 352+
 353+/*** SHA-256: *********************************************************/
 354+void
 355+SHA256Init(SHA2_CTX *context)
 356+{
 357+	byte_copy(context->state.st32, sizeof(sha256_initial_hash_value),
 358+	    sha256_initial_hash_value);
 359+	byte_zero(context->buffer, sizeof(context->buffer));
 360+	context->bitcount[0] = 0;
 361+}
 362+DEF_WEAK(SHA256Init);
 363+
 364+#ifdef SHA2_UNROLL_TRANSFORM
 365+
 366+/* Unrolled SHA-256 round macros: */
 367+
 368+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) do {				    \
 369+	BE_8_TO_32(W256[j], data);					    \
 370+	data += 4;							    \
 371+	T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + W256[j]; \
 372+	(d) += T1;							    \
 373+	(h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c));		    \
 374+	j++;								    \
 375+} while(0)
 376+
 377+#define ROUND256(a,b,c,d,e,f,g,h) do {					    \
 378+	s0 = W256[(j+1)&0x0f];						    \
 379+	s0 = sigma0_256(s0);						    \
 380+	s1 = W256[(j+14)&0x0f];						    \
 381+	s1 = sigma1_256(s1);						    \
 382+	T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] +	    \
 383+	     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);		    \
 384+	(d) += T1;							    \
 385+	(h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c));		    \
 386+	j++;								    \
 387+} while(0)
 388+
 389+void
 390+SHA256Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH])
 391+{
 392+	u_int32_t	a, b, c, d, e, f, g, h, s0, s1;
 393+	u_int32_t	T1, W256[16];
 394+	int		j;
 395+
 396+	/* Initialize registers with the prev. intermediate value */
 397+	a = state[0];
 398+	b = state[1];
 399+	c = state[2];
 400+	d = state[3];
 401+	e = state[4];
 402+	f = state[5];
 403+	g = state[6];
 404+	h = state[7];
 405+
 406+	j = 0;
 407+	do {
 408+		/* Rounds 0 to 15 (unrolled): */
 409+		ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
 410+		ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
 411+		ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
 412+		ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
 413+		ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
 414+		ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
 415+		ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
 416+		ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
 417+	} while (j < 16);
 418+
 419+	/* Now for the remaining rounds up to 63: */
 420+	do {
 421+		ROUND256(a,b,c,d,e,f,g,h);
 422+		ROUND256(h,a,b,c,d,e,f,g);
 423+		ROUND256(g,h,a,b,c,d,e,f);
 424+		ROUND256(f,g,h,a,b,c,d,e);
 425+		ROUND256(e,f,g,h,a,b,c,d);
 426+		ROUND256(d,e,f,g,h,a,b,c);
 427+		ROUND256(c,d,e,f,g,h,a,b);
 428+		ROUND256(b,c,d,e,f,g,h,a);
 429+	} while (j < 64);
 430+
 431+	/* Compute the current intermediate hash value */
 432+	state[0] += a;
 433+	state[1] += b;
 434+	state[2] += c;
 435+	state[3] += d;
 436+	state[4] += e;
 437+	state[5] += f;
 438+	state[6] += g;
 439+	state[7] += h;
 440+
 441+	/* Clean up */
 442+	a = b = c = d = e = f = g = h = T1 = 0;
 443+}
 444+
 445+#else /* SHA2_UNROLL_TRANSFORM */
 446+
 447+void
 448+SHA256Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH])
 449+{
 450+	u_int32_t	a, b, c, d, e, f, g, h, s0, s1;
 451+	u_int32_t	T1, T2, W256[16];
 452+	int		j;
 453+
 454+	/* Initialize registers with the prev. intermediate value */
 455+	a = state[0];
 456+	b = state[1];
 457+	c = state[2];
 458+	d = state[3];
 459+	e = state[4];
 460+	f = state[5];
 461+	g = state[6];
 462+	h = state[7];
 463+
 464+	j = 0;
 465+	do {
 466+		BE_8_TO_32(W256[j], data);
 467+		data += 4;
 468+		/* Apply the SHA-256 compression function to update a..h */
 469+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
 470+		T2 = Sigma0_256(a) + Maj(a, b, c);
 471+		h = g;
 472+		g = f;
 473+		f = e;
 474+		e = d + T1;
 475+		d = c;
 476+		c = b;
 477+		b = a;
 478+		a = T1 + T2;
 479+
 480+		j++;
 481+	} while (j < 16);
 482+
 483+	do {
 484+		/* Part of the message block expansion: */
 485+		s0 = W256[(j+1)&0x0f];
 486+		s0 = sigma0_256(s0);
 487+		s1 = W256[(j+14)&0x0f];	
 488+		s1 = sigma1_256(s1);
 489+
 490+		/* Apply the SHA-256 compression function to update a..h */
 491+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 
 492+		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
 493+		T2 = Sigma0_256(a) + Maj(a, b, c);
 494+		h = g;
 495+		g = f;
 496+		f = e;
 497+		e = d + T1;
 498+		d = c;
 499+		c = b;
 500+		b = a;
 501+		a = T1 + T2;
 502+
 503+		j++;
 504+	} while (j < 64);
 505+
 506+	/* Compute the current intermediate hash value */
 507+	state[0] += a;
 508+	state[1] += b;
 509+	state[2] += c;
 510+	state[3] += d;
 511+	state[4] += e;
 512+	state[5] += f;
 513+	state[6] += g;
 514+	state[7] += h;
 515+
 516+	/* Clean up */
 517+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
 518+}
 519+
 520+#endif /* SHA2_UNROLL_TRANSFORM */
 521+DEF_WEAK(SHA256Transform);
 522+
 523+void
 524+SHA256Update(SHA2_CTX *context, const u_int8_t *data, size_t len)
 525+{
 526+	u_int64_t	freespace, usedspace;
 527+
 528+	/* Calling with no data is valid (we do nothing) */
 529+	if (len == 0)
 530+		return;
 531+
 532+	usedspace = (context->bitcount[0] >> 3) % SHA256_BLOCK_LENGTH;
 533+	if (usedspace > 0) {
 534+		/* Calculate how much free space is available in the buffer */
 535+		freespace = SHA256_BLOCK_LENGTH - usedspace;
 536+
 537+		if (len >= freespace) {
 538+			/* Fill the buffer completely and process it */
 539+			byte_copy(&context->buffer[usedspace], freespace, data);
 540+			context->bitcount[0] += freespace << 3;
 541+			len -= freespace;
 542+			data += freespace;
 543+			SHA256Transform(context->state.st32, context->buffer);
 544+		} else {
 545+			/* The buffer is not yet full */
 546+			byte_copy(&context->buffer[usedspace], len, data);
 547+			context->bitcount[0] += (u_int64_t)len << 3;
 548+			/* Clean up: */
 549+			usedspace = freespace = 0;
 550+			return;
 551+		}
 552+	}
 553+	while (len >= SHA256_BLOCK_LENGTH) {
 554+		/* Process as many complete blocks as we can */
 555+		SHA256Transform(context->state.st32, data);
 556+		context->bitcount[0] += SHA256_BLOCK_LENGTH << 3;
 557+		len -= SHA256_BLOCK_LENGTH;
 558+		data += SHA256_BLOCK_LENGTH;
 559+	}
 560+	if (len > 0) {
 561+		/* There's left-overs, so save 'em */
 562+		byte_copy(context->buffer, len, data);
 563+		context->bitcount[0] += len << 3;
 564+	}
 565+	/* Clean up: */
 566+	usedspace = freespace = 0;
 567+}
 568+DEF_WEAK(SHA256Update);
 569+
 570+void
 571+SHA256Pad(SHA2_CTX *context)
 572+{
 573+	unsigned int	usedspace;
 574+
 575+	usedspace = (context->bitcount[0] >> 3) % SHA256_BLOCK_LENGTH;
 576+	if (usedspace > 0) {
 577+		/* Begin padding with a 1 bit: */
 578+		context->buffer[usedspace++] = 0x80;
 579+
 580+		if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
 581+			/* Set-up for the last transform: */
 582+			byte_zero(&context->buffer[usedspace],
 583+			    SHA256_SHORT_BLOCK_LENGTH - usedspace);
 584+		} else {
 585+			if (usedspace < SHA256_BLOCK_LENGTH) {
 586+				byte_zero(&context->buffer[usedspace],
 587+				    SHA256_BLOCK_LENGTH - usedspace);
 588+			}
 589+			/* Do second-to-last transform: */
 590+			SHA256Transform(context->state.st32, context->buffer);
 591+
 592+			/* Prepare for last transform: */
 593+			byte_zero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
 594+		}
 595+	} else {
 596+		/* Set-up for the last transform: */
 597+		byte_zero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
 598+
 599+		/* Begin padding with a 1 bit: */
 600+		*context->buffer = 0x80;
 601+	}
 602+	/* Store the length of input data (in bits) in big endian format: */
 603+	BE_64_TO_8(&context->buffer[SHA256_SHORT_BLOCK_LENGTH],
 604+	    context->bitcount[0]);
 605+
 606+	/* Final transform: */
 607+	SHA256Transform(context->state.st32, context->buffer);
 608+
 609+	/* Clean up: */
 610+	usedspace = 0;
 611+}
 612+DEF_WEAK(SHA256Pad);
 613+
 614+void
 615+SHA256Final(u_int8_t digest[SHA256_DIGEST_LENGTH], SHA2_CTX *context)
 616+{
 617+	SHA256Pad(context);
 618+
 619+#if BYTE_ORDER == LITTLE_ENDIAN
 620+	int	i;
 621+
 622+	/* Convert TO host byte order */
 623+	for (i = 0; i < 8; i++)
 624+		BE_32_TO_8(digest + i * 4, context->state.st32[i]);
 625+#else
 626+	byte_copy(digest, SHA256_DIGEST_LENGTH, context->state.st32);
 627+#endif
 628+	explicit_bzero(context, sizeof(*context));
 629+}
 630+DEF_WEAK(SHA256Final);
 631+
 632+
 633+/*** SHA-512: *********************************************************/
 634+void
 635+SHA512Init(SHA2_CTX *context)
 636+{
 637+	byte_copy(context->state.st64, sizeof(sha512_initial_hash_value),
 638+	    sha512_initial_hash_value);
 639+	byte_zero(context->buffer, sizeof(context->buffer));
 640+	context->bitcount[0] = context->bitcount[1] =  0;
 641+}
 642+DEF_WEAK(SHA512Init);
 643+
 644+#ifdef SHA2_UNROLL_TRANSFORM
 645+
 646+/* Unrolled SHA-512 round macros: */
 647+
 648+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) do {				    \
 649+	BE_8_TO_64(W512[j], data);					    \
 650+	data += 8;							    \
 651+	T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + W512[j]; \
 652+	(d) += T1;							    \
 653+	(h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c));		    \
 654+	j++;								    \
 655+} while(0)
 656+
 657+
 658+#define ROUND512(a,b,c,d,e,f,g,h) do {					    \
 659+	s0 = W512[(j+1)&0x0f];						    \
 660+	s0 = sigma0_512(s0);						    \
 661+	s1 = W512[(j+14)&0x0f];						    \
 662+	s1 = sigma1_512(s1);						    \
 663+	T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] +	    \
 664+             (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);		    \
 665+	(d) += T1;							    \
 666+	(h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c));		    \
 667+	j++;								    \
 668+} while(0)
 669+
 670+void
 671+SHA512Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
 672+{
 673+	u_int64_t	a, b, c, d, e, f, g, h, s0, s1;
 674+	u_int64_t	T1, W512[16];
 675+	int		j;
 676+
 677+	/* Initialize registers with the prev. intermediate value */
 678+	a = state[0];
 679+	b = state[1];
 680+	c = state[2];
 681+	d = state[3];
 682+	e = state[4];
 683+	f = state[5];
 684+	g = state[6];
 685+	h = state[7];
 686+
 687+	j = 0;
 688+	do {
 689+		/* Rounds 0 to 15 (unrolled): */
 690+		ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
 691+		ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
 692+		ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
 693+		ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
 694+		ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
 695+		ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
 696+		ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
 697+		ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
 698+	} while (j < 16);
 699+
 700+	/* Now for the remaining rounds up to 79: */
 701+	do {
 702+		ROUND512(a,b,c,d,e,f,g,h);
 703+		ROUND512(h,a,b,c,d,e,f,g);
 704+		ROUND512(g,h,a,b,c,d,e,f);
 705+		ROUND512(f,g,h,a,b,c,d,e);
 706+		ROUND512(e,f,g,h,a,b,c,d);
 707+		ROUND512(d,e,f,g,h,a,b,c);
 708+		ROUND512(c,d,e,f,g,h,a,b);
 709+		ROUND512(b,c,d,e,f,g,h,a);
 710+	} while (j < 80);
 711+
 712+	/* Compute the current intermediate hash value */
 713+	state[0] += a;
 714+	state[1] += b;
 715+	state[2] += c;
 716+	state[3] += d;
 717+	state[4] += e;
 718+	state[5] += f;
 719+	state[6] += g;
 720+	state[7] += h;
 721+
 722+	/* Clean up */
 723+	a = b = c = d = e = f = g = h = T1 = 0;
 724+}
 725+
 726+#else /* SHA2_UNROLL_TRANSFORM */
 727+
 728+void
 729+SHA512Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
 730+{
 731+	u_int64_t	a, b, c, d, e, f, g, h, s0, s1;
 732+	u_int64_t	T1, T2, W512[16];
 733+	int		j;
 734+
 735+	/* Initialize registers with the prev. intermediate value */
 736+	a = state[0];
 737+	b = state[1];
 738+	c = state[2];
 739+	d = state[3];
 740+	e = state[4];
 741+	f = state[5];
 742+	g = state[6];
 743+	h = state[7];
 744+
 745+	j = 0;
 746+	do {
 747+		BE_8_TO_64(W512[j], data);
 748+		data += 8;
 749+		/* Apply the SHA-512 compression function to update a..h */
 750+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
 751+		T2 = Sigma0_512(a) + Maj(a, b, c);
 752+		h = g;
 753+		g = f;
 754+		f = e;
 755+		e = d + T1;
 756+		d = c;
 757+		c = b;
 758+		b = a;
 759+		a = T1 + T2;
 760+
 761+		j++;
 762+	} while (j < 16);
 763+
 764+	do {
 765+		/* Part of the message block expansion: */
 766+		s0 = W512[(j+1)&0x0f];
 767+		s0 = sigma0_512(s0);
 768+		s1 = W512[(j+14)&0x0f];
 769+		s1 =  sigma1_512(s1);
 770+
 771+		/* Apply the SHA-512 compression function to update a..h */
 772+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
 773+		     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
 774+		T2 = Sigma0_512(a) + Maj(a, b, c);
 775+		h = g;
 776+		g = f;
 777+		f = e;
 778+		e = d + T1;
 779+		d = c;
 780+		c = b;
 781+		b = a;
 782+		a = T1 + T2;
 783+
 784+		j++;
 785+	} while (j < 80);
 786+
 787+	/* Compute the current intermediate hash value */
 788+	state[0] += a;
 789+	state[1] += b;
 790+	state[2] += c;
 791+	state[3] += d;
 792+	state[4] += e;
 793+	state[5] += f;
 794+	state[6] += g;
 795+	state[7] += h;
 796+
 797+	/* Clean up */
 798+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
 799+}
 800+
 801+#endif /* SHA2_UNROLL_TRANSFORM */
 802+DEF_WEAK(SHA512Transform);
 803+
 804+void
 805+SHA512Update(SHA2_CTX *context, const u_int8_t *data, size_t len)
 806+{
 807+	size_t	freespace, usedspace;
 808+
 809+	/* Calling with no data is valid (we do nothing) */
 810+	if (len == 0)
 811+		return;
 812+
 813+	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
 814+	if (usedspace > 0) {
 815+		/* Calculate how much free space is available in the buffer */
 816+		freespace = SHA512_BLOCK_LENGTH - usedspace;
 817+
 818+		if (len >= freespace) {
 819+			/* Fill the buffer completely and process it */
 820+			byte_copy(&context->buffer[usedspace], freespace, data);
 821+			ADDINC128(context->bitcount, freespace << 3);
 822+			len -= freespace;
 823+			data += freespace;
 824+			SHA512Transform(context->state.st64, context->buffer);
 825+		} else {
 826+			/* The buffer is not yet full */
 827+			byte_copy(&context->buffer[usedspace], len, data);
 828+			ADDINC128(context->bitcount, len << 3);
 829+			/* Clean up: */
 830+			usedspace = freespace = 0;
 831+			return;
 832+		}
 833+	}
 834+	while (len >= SHA512_BLOCK_LENGTH) {
 835+		/* Process as many complete blocks as we can */
 836+		SHA512Transform(context->state.st64, data);
 837+		ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
 838+		len -= SHA512_BLOCK_LENGTH;
 839+		data += SHA512_BLOCK_LENGTH;
 840+	}
 841+	if (len > 0) {
 842+		/* There's left-overs, so save 'em */
 843+		byte_copy(context->buffer, len, data);
 844+		ADDINC128(context->bitcount, len << 3);
 845+	}
 846+	/* Clean up: */
 847+	usedspace = freespace = 0;
 848+}
 849+DEF_WEAK(SHA512Update);
 850+
 851+void
 852+SHA512Pad(SHA2_CTX *context)
 853+{
 854+	unsigned int	usedspace;
 855+
 856+	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
 857+	if (usedspace > 0) {
 858+		/* Begin padding with a 1 bit: */
 859+		context->buffer[usedspace++] = 0x80;
 860+
 861+		if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
 862+			/* Set-up for the last transform: */
 863+			byte_zero(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
 864+		} else {
 865+			if (usedspace < SHA512_BLOCK_LENGTH) {
 866+				byte_zero(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
 867+			}
 868+			/* Do second-to-last transform: */
 869+			SHA512Transform(context->state.st64, context->buffer);
 870+
 871+			/* And set-up for the last transform: */
 872+			byte_zero(context->buffer, SHA512_BLOCK_LENGTH - 2);
 873+		}
 874+	} else {
 875+		/* Prepare for final transform: */
 876+		byte_zero(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
 877+
 878+		/* Begin padding with a 1 bit: */
 879+		*context->buffer = 0x80;
 880+	}
 881+	/* Store the length of input data (in bits) in big endian format: */
 882+	BE_64_TO_8(&context->buffer[SHA512_SHORT_BLOCK_LENGTH],
 883+	    context->bitcount[1]);
 884+	BE_64_TO_8(&context->buffer[SHA512_SHORT_BLOCK_LENGTH + 8],
 885+	    context->bitcount[0]);
 886+
 887+	/* Final transform: */
 888+	SHA512Transform(context->state.st64, context->buffer);
 889+
 890+	/* Clean up: */
 891+	usedspace = 0;
 892+}
 893+DEF_WEAK(SHA512Pad);
 894+
 895+void
 896+SHA512Final(u_int8_t digest[SHA512_DIGEST_LENGTH], SHA2_CTX *context)
 897+{
 898+	SHA512Pad(context);
 899+
 900+#if BYTE_ORDER == LITTLE_ENDIAN
 901+	int	i;
 902+
 903+	/* Convert TO host byte order */
 904+	for (i = 0; i < 8; i++)
 905+		BE_64_TO_8(digest + i * 8, context->state.st64[i]);
 906+#else
 907+	byte_copy(digest, SHA512_DIGEST_LENGTH, context->state.st64);
 908+#endif
 909+	explicit_bzero(context, sizeof(*context));
 910+}
 911+DEF_WEAK(SHA512Final);
 912+
 913+#if !defined(SHA2_SMALL)
 914+
 915+/*** SHA-384: *********************************************************/
 916+void
 917+SHA384Init(SHA2_CTX *context)
 918+{
 919+	byte_copy(context->state.st64, sizeof(sha384_initial_hash_value),
 920+	    sha384_initial_hash_value);
 921+	byte_zero(context->buffer, sizeof(context->buffer));
 922+	context->bitcount[0] = context->bitcount[1] = 0;
 923+}
 924+DEF_WEAK(SHA384Init);
 925+
 926+MAKE_CLONE(SHA384Transform, SHA512Transform);
 927+MAKE_CLONE(SHA384Update, SHA512Update);
 928+MAKE_CLONE(SHA384Pad, SHA512Pad);
 929+DEF_WEAK(SHA384Transform);
 930+DEF_WEAK(SHA384Update);
 931+DEF_WEAK(SHA384Pad);
 932+
 933+/* Equivalent of MAKE_CLONE (which is a no-op) for SHA384 funcs */
 934+void
 935+SHA384Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
 936+{
 937+	SHA512Transform(state, data);
 938+}
 939+
 940+void
 941+SHA384Update(SHA2_CTX *context, const u_int8_t *data, size_t len)
 942+{
 943+	SHA512Update(context, data, len);
 944+}
 945+
 946+void
 947+SHA384Pad(SHA2_CTX *context)
 948+{
 949+	SHA512Pad(context);
 950+}
 951+
 952+void
 953+SHA384Final(u_int8_t digest[SHA384_DIGEST_LENGTH], SHA2_CTX *context)
 954+{
 955+	SHA384Pad(context);
 956+
 957+#if BYTE_ORDER == LITTLE_ENDIAN
 958+	int	i;
 959+
 960+	/* Convert TO host byte order */
 961+	for (i = 0; i < 6; i++)
 962+		BE_64_TO_8(digest + i * 8, context->state.st64[i]);
 963+#else
 964+	byte_copy(digest, SHA384_DIGEST_LENGTH, context->state.st64);
 965+#endif
 966+	/* Zero out state data */
 967+	explicit_bzero(context, sizeof(*context));
 968+}
 969+DEF_WEAK(SHA384Final);
 970+
 971+#if 0
 972+/*** SHA-512/256: *********************************************************/
 973+void
 974+SHA512_256Init(SHA2_CTX *context)
 975+{
 976+	byte_copy(context->state.st64, sizeof(sha512_256_initial_hash_value),
 977+	    sha512_256_initial_hash_value);
 978+	byte_zero(context->buffer, sizeof(context->buffer));
 979+	context->bitcount[0] = context->bitcount[1] = 0;
 980+}
 981+DEF_WEAK(SHA512_256Init);
 982+
 983+MAKE_CLONE(SHA512_256Transform, SHA512Transform);
 984+MAKE_CLONE(SHA512_256Update, SHA512Update);
 985+MAKE_CLONE(SHA512_256Pad, SHA512Pad);
 986+DEF_WEAK(SHA512_256Transform);
 987+DEF_WEAK(SHA512_256Update);
 988+DEF_WEAK(SHA512_256Pad);
 989+
 990+void
 991+SHA512_256Final(u_int8_t digest[SHA512_256_DIGEST_LENGTH], SHA2_CTX *context)
 992+{
 993+	SHA512_256Pad(context);
 994+
 995+#if BYTE_ORDER == LITTLE_ENDIAN
 996+	int	i;
 997+
 998+	/* Convert TO host byte order */
 999+	for (i = 0; i < 4; i++)
1000+		BE_64_TO_8(digest + i * 8, context->state.st64[i]);
1001+#else
1002+	byte_copy(digest, SHA512_256_DIGEST_LENGTH, context->state.st64);
1003+#endif
1004+	/* Zero out state data */
1005+	explicit_bzero(context, sizeof(*context));
1006+}
1007+DEF_WEAK(SHA512_256Final);
1008+#endif /* !defined(SHA2_SMALL) */
1009+#endif /* 0 */
1010+
1011+#endif /* HAVE_SHA{256,384,512}UPDATE */
+13, -0
 1@@ -0,0 +1,13 @@
 2+build randomart/randomart.o: cc randomart/randomart.c
 3+  cflags = $base_cflags -Ishared -Irandomart
 4+build randomart/base64.o: cc randomart/base64.c
 5+  cflags = $base_cflags -Ishared -Irandomart
 6+build randomart/md5.o: cc randomart/md5.c
 7+  cflags = $base_cflags -Ishared -Irandomart
 8+build randomart/sha2.o: cc randomart/sha2.c
 9+  cflags = $base_cflags -Ishared -Irandomart
10+
11+build randomart/randomart: link randomart/randomart.o randomart/base64.o randomart/md5.o randomart/sha2.o shared/libdjb.a
12+  libs = $default_libs
13+
14+build randomart-all: phony randomart/randomart
+0, -42
 1@@ -1,42 +0,0 @@
 2-# i know this is a ninja file, but you're allowed to edit it.
 3-# you can also pass things on the command line if you like, eg
 4-#
 5-#     CC=clang ninja
 6-
 7-cc = $${CC:-cc}
 8-cflags = $${CFLAGS:--O2 -std=c99}
 9-ldflags = $${LDFLAGS:-}
10-libs = $${LIBS:-}
11-prefix = $${PREFIX:-/usr/local}
12-destdir = $${DESTDIR:-}
13-bindir = $${BINDIR:-$${DESTDIR:-}$${PREFIX:-/usr/local}/bin}
14-mandir = $${MANDIR:-$${DESTDIR:-}$${PREFIX:-/usr/local}/man/man1}
15-
16-rule cc
17-  command = $cc $cflags -MMD -MF $out.d -c -o $out $in
18-  deps = gcc
19-  depfile = $out.d
20-  description = cc $out
21-
22-rule link
23-  command = $cc $ldflags -o $out $in $libs
24-  description = link $out
25-
26-rule install
27-  command = mkdir -p $bindir && cp shar $bindir/
28-  description = install shar
29-
30-rule install-man
31-  command = mkdir -p $mandir && cp shar.1 $mandir/
32-  description = man shar.1
33-
34-build shar.o: cc shar.c
35-
36-build shar: link shar.o
37-build all: phony shar
38-build man: install-man shar.1
39-build install: phony install-bin install-man
40-build install-bin: install shar
41-build install-man: install-man shar.1
42-
43-default all
+0, -5
1@@ -2,8 +2,3 @@ shar
2 ----
3 a small public domain shar implementation.
4 
5-build:
6-    ninja
7-    ninja install
8-
9-
+143, -64
  1@@ -1,33 +1,97 @@
  2-/*small shar in C inspired by netbsd shar script but with some 
  3+/*small shar in C inspired by netbsd shar script but with some
  4  * improvements, public domain :] */
  5 
  6 #include <sys/stat.h>
  7 #include <sys/types.h>
  8 
  9-#include <errno.h>
 10-#include <stdio.h>
 11-#include <stdlib.h>
 12+#include <alloc.h>
 13+#include <buffer.h>
 14+#include <byte.h>
 15+#include <fmt.h>
 16+#include <open.h>
 17+#include <str.h>
 18+#include <strerr.h>
 19+
 20 #include <string.h>
 21+#include <unistd.h>
 22+
 23+static void
 24+die_usage(void)
 25+{
 26+	buffer_puts(buffer_2, "usage: shar [file ...]\n");
 27+	buffer_flush(buffer_2);
 28+	_exit(1);
 29+}
 30+
 31+static void
 32+die_nomem(void)
 33+{
 34+	strerr_die2sys(111, "shar: ", "alloc");
 35+}
 36+
 37+static void
 38+warn_path(const char *path)
 39+{
 40+	strerr_warn4("shar: ", path, ": ", "", &strerr_sys);
 41+}
 42+
 43+static void
 44+out(const char *s)
 45+{
 46+	buffer_puts(buffer_1, s);
 47+}
 48+
 49+static void
 50+outn(const char *s, unsigned int n)
 51+{
 52+	buffer_put(buffer_1, s, n);
 53+}
 54 
 55+static void
 56+outc(char c)
 57+{
 58+	buffer_put(buffer_1, &c, 1);
 59+}
 60+
 61+static void
 62+out_ulong(unsigned long u)
 63+{
 64+	char buf[FMT_ULONG];
 65+	unsigned int n;
 66+
 67+	n = fmt_ulong(buf, u);
 68+	outn(buf, n);
 69+}
 70+
 71+static void
 72+out_mode(unsigned int mode)
 73+{
 74+	char buf[3];
 75+
 76+	buf[0] = '0' + ((mode >> 6) & 7);
 77+	buf[1] = '0' + ((mode >> 3) & 7);
 78+	buf[2] = '0' + (mode & 7);
 79+	outn(buf, sizeof(buf));
 80+}
 81 
 82 /* single quote path name */
 83 static void
 84 q(char *s)
 85 {
 86-	putchar('\'');
 87+	outc('\'');
 88 	for (; *s; s++)
 89 		if (*s == '\'')
 90-			fputs("'\\''", stdout);
 91+			out("'\\''");
 92 		else
 93-			putchar(*s);
 94-	putchar('\'');
 95+			outc(*s);
 96+	outc('\'');
 97 }
 98 
 99 static void
100 qt(char *s, char *t)
101 {
102 	q(s);
103-	fputs(t, stdout);
104+	out(t);
105 }
106 
107 static void
108@@ -36,88 +100,101 @@ mkpar(char *s)
109 	char *p, *e;
110 	size_t n;
111 
112-	if ((e = strrchr(s, '/')) == NULL || e == s)
113+	e = strrchr(s, '/');
114+	if (e == NULL || e == s)
115 		return;
116-	n = e - s;
117-	if ((p = malloc(n + 1)) == NULL) {
118-		fprintf(stderr, "shar: %s\n", strerror(errno));
119-		exit(1);
120-	}
121-	memcpy(p, s, n);
122+	n = (size_t)(e - s);
123+	p = alloc((unsigned int)n + 1);
124+	if (!p)
125+		die_nomem();
126+	byte_copy(p, n, s);
127 	p[n] = 0;
128-	fputs("mkdir -p ", stdout);
129+	out("mkdir -p ");
130 	q(p);
131-	fputs(" > /dev/null 2>&1\n", stdout);
132-	free(p);
133+	out(" > /dev/null 2>&1\n");
134+	alloc_free(p);
135 }
136 
137 static int
138 readfile(char *s)
139 {
140-	FILE *f;
141+	int fd, r, bol;
142+	char buf[4096];
143 	struct stat st;
144-	int c, bol = 1;
145+	unsigned int i;
146 
147-	if ((f = fopen(s, "r")) == NULL) {
148-		fprintf(stderr, "shar: %s: %s\n", s, strerror(errno));
149+	fd = open_read(s);
150+	if (fd == -1) {
151+		warn_path(s);
152 		return 1;
153 	}
154 	if (stat(s, &st) == -1) {
155-		fprintf(stderr, "shar: %s: %s\n", s, strerror(errno));
156-		fclose(f);
157+		warn_path(s);
158+		close(fd);
159 		return 1;
160 	}
161 	mkpar(s);
162-	fputs("echo x - ", stdout);
163+	out("echo x - ");
164 	q(s);
165-	fputs("\nsed 's/^X//' >", stdout);
166+	out("\nsed 's/^X//' >");
167 	q(s);
168-	fputs(" << 'SHAR_EOF'\n", stdout);
169-	while ((c = getc(f)) != EOF) {
170-		if (bol)
171-			putchar('X');
172-		putchar(c);
173-		bol = c == '\n';
174-	}
175-	if (ferror(f)) {
176-		fprintf(stderr, "shar: %s: %s\n", s, strerror(errno));
177-		fclose(f);
178-		return 1;
179+	out(" << 'SHAR_EOF'\n");
180+	bol = 1;
181+	for (;;) {
182+		r = read(fd, buf, sizeof(buf));
183+		if (r == 0)
184+			break;
185+		if (r < 0) {
186+			warn_path(s);
187+			close(fd);
188+			return 1;
189+		}
190+		for (i = 0; i < (unsigned int)r; ++i) {
191+			if (bol)
192+				outc('X');
193+			outc(buf[i]);
194+			bol = buf[i] == '\n';
195+		}
196 	}
197-	fclose(f);
198+	close(fd);
199 	/* netbsd shar glues the marker to non newline files but we fix and trim */
200 	if (!bol)
201-		putchar('\n');
202-	fputs("SHAR_EOF\n", stdout);
203+		outc('\n');
204+	out("SHAR_EOF\n");
205 	if (!bol) {
206-		fputs("dd if=", stdout);
207+		out("dd if=");
208 		q(s);
209-		fputs(" of=", stdout);
210+		out(" of=");
211 		qt(s, ".$$");
212-		printf(" bs=1 count=%lld > /dev/null 2>&1 && mv ",
213-		    (long long)st.st_size);
214+		out(" bs=1 count=");
215+		out_ulong((unsigned long)st.st_size);
216+		out(" > /dev/null 2>&1 && mv ");
217 		qt(s, ".$$");
218-		putchar(' ');
219+		outc(' ');
220 		q(s);
221-		putchar('\n');
222+		outc('\n');
223 	}
224-	printf("chmod %03o ", (unsigned)st.st_mode & 0777);
225+	out("chmod ");
226+	out_mode((unsigned int)st.st_mode & 0777);
227+	outc(' ');
228 	q(s);
229-	putchar('\n');
230+	outc('\n');
231 	return 0;
232 }
233 
234 static void
235 makedir(char *s, mode_t m)
236 {
237-	fputs("echo c - ", stdout);
238+	out("echo c - ");
239 	q(s);
240-	fputs("\nmkdir -p ", stdout);
241+	out("\nmkdir -p ");
242 	q(s);
243-	fputs(" > /dev/null 2>&1\n", stdout);
244-	printf("chmod %03o ", (unsigned)m & 0777);
245+	out(" > /dev/null 2>&1\n");
246+	out("chmod ");
247+	out_mode((unsigned int)m & 0777);
248+	outc(' ');
249 	q(s);
250-	putchar('\n');
251+	outc('\n');
252 }
253 
254 static void
255@@ -125,16 +202,19 @@ head(int n, char **v)
256 {
257 	int i;
258 
259-	fputs("# This is a shell archive.  Save it in a file, remove anything before\n"
260+	out("# This is a shell archive.  Save it in a file, remove anything before\n"
261 	    "# this line, and then unpack it by entering \"sh file\".  Note, it may\n"
262 	    "# create directories; files and directories will be owned by you and\n"
263 	    "# have their original permissions.\n"
264 	    "#\n"
265 	    "# This archive contains:\n"
266-	    "#\n", stdout);
267-	for (i = 1; i < n; i++)
268-		printf("#\t%s\n", v[i]);
269-	printf("#\n");
270+	    "#\n");
271+	for (i = 1; i < n; i++) {
272+		out("#\t");
273+		out(v[i]);
274+		outc('\n');
275+	}
276+	out("#\n");
277 }
278 
279 int
280@@ -143,16 +223,15 @@ main(int n, char **v)
281 	struct stat st;
282 	int i;
283 
284-	if (n == 1) {
285-		fprintf(stderr, "usage: shar [file ...]\n");
286-		return 1;
287-	}
288+	if (n == 1)
289+		die_usage();
290 	head(n, v);
291 	for (i = 1; i < n; i++)
292 		if (stat(v[i], &st) == 0 && S_ISDIR(st.st_mode))
293 			makedir(v[i], st.st_mode);
294 		else if (readfile(v[i]))
295 			return 1;
296-	printf("exit\n\n");
297+	out("exit\n\n");
298+	buffer_flush(buffer_1);
299 	return 0;
300 }
+7, -0
1@@ -0,0 +1,7 @@
2+build shar/shar.o: cc shar/shar.c
3+  cflags = $base_cflags -Ishared
4+
5+build shar/shar: link shar/shar.o shared/libdjb.a
6+  libs = $default_libs
7+
8+build shar-all: phony shar/shar
+34, -0
 1@@ -0,0 +1,34 @@
 2+/* Public domain. */
 3+
 4+#include <errno.h>
 5+#include <stdlib.h>
 6+#include "alloc.h"
 7+#include "error.h"
 8+
 9+#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */
10+#define SPACE 2048 /* must be multiple of ALIGNMENT */
11+
12+typedef union { char irrelevant[ALIGNMENT]; double d; } aligned;
13+static aligned realspace[SPACE / ALIGNMENT];
14+#define space ((char *) realspace)
15+static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */
16+
17+/*@null@*//*@out@*/char *alloc(n)
18+unsigned int n;
19+{
20+  char *x;
21+  n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */
22+  if (n <= avail) { avail -= n; return space + avail; }
23+  x = malloc(n);
24+  if (!x) errno = error_nomem;
25+  return x;
26+}
27+
28+void alloc_free(x)
29+char *x;
30+{
31+  if (x >= space)
32+    if (x < space + SPACE)
33+      return; /* XXX: assuming that pointers are flat */
34+  free(x);
35+}
+10, -0
 1@@ -0,0 +1,10 @@
 2+/* Public domain. */
 3+
 4+#ifndef ALLOC_H
 5+#define ALLOC_H
 6+
 7+extern /*@null@*//*@out@*/char *alloc();
 8+extern void alloc_free();
 9+extern int alloc_re();
10+
11+#endif
+19, -0
 1@@ -0,0 +1,19 @@
 2+/* Public domain. */
 3+
 4+#include "alloc.h"
 5+#include "byte.h"
 6+
 7+int alloc_re(x,m,n)
 8+char **x;
 9+unsigned int m;
10+unsigned int n;
11+{
12+  char *y;
13+ 
14+  y = alloc(n);
15+  if (!y) return 0;
16+  byte_copy(y,m,*x);
17+  alloc_free(*x);
18+  *x = y;
19+  return 1;
20+}
+12, -0
 1@@ -0,0 +1,12 @@
 2+/* Public domain. */
 3+
 4+#include "buffer.h"
 5+
 6+void buffer_init(buffer *s,int (*op)(),int fd,char *buf,unsigned int len)
 7+{
 8+  s->x = buf;
 9+  s->fd = fd;
10+  s->op = op;
11+  s->p = 0;
12+  s->n = len;
13+}
+61, -0
 1@@ -0,0 +1,61 @@
 2+/* Public domain. */
 3+
 4+#ifndef BUFFER_H
 5+#define BUFFER_H
 6+
 7+typedef struct buffer {
 8+  char *x;
 9+  unsigned int p;
10+  unsigned int n;
11+  int fd;
12+  int (*op)();
13+} buffer;
14+
15+#define BUFFER_INIT(op,fd,buf,len) { (buf), 0, (len), (fd), (op) }
16+#define BUFFER_INSIZE 8192
17+#define BUFFER_OUTSIZE 8192
18+
19+extern void buffer_init(buffer *,int (*)(),int,char *,unsigned int);
20+
21+extern int buffer_flush(buffer *);
22+extern int buffer_put(buffer *,const char *,unsigned int);
23+extern int buffer_putalign(buffer *,const char *,unsigned int);
24+extern int buffer_putflush(buffer *,const char *,unsigned int);
25+extern int buffer_puts(buffer *,const char *);
26+extern int buffer_putsalign(buffer *,const char *);
27+extern int buffer_putsflush(buffer *,const char *);
28+
29+#define buffer_PUTC(s,c) \
30+  ( ((s)->n != (s)->p) \
31+    ? ( (s)->x[(s)->p++] = (c), 0 ) \
32+    : buffer_put((s),&(c),1) \
33+  )
34+
35+extern int buffer_get(buffer *,char *,unsigned int);
36+extern int buffer_bget(buffer *,char *,unsigned int);
37+extern int buffer_feed(buffer *);
38+
39+extern char *buffer_peek(buffer *);
40+extern void buffer_seek(buffer *,unsigned int);
41+
42+#define buffer_PEEK(s) ( (s)->x + (s)->n )
43+#define buffer_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) )
44+
45+#define buffer_GETC(s,c) \
46+  ( ((s)->p > 0) \
47+    ? ( *(c) = (s)->x[(s)->n], buffer_SEEK((s),1), 1 ) \
48+    : buffer_get((s),(c),1) \
49+  )
50+
51+extern int buffer_copy(buffer *,buffer *);
52+
53+extern int buffer_unixread(int,char *,unsigned int);
54+extern int buffer_unixwrite(int,const char *,unsigned int);
55+
56+extern buffer *buffer_0;
57+extern buffer *buffer_0small;
58+extern buffer *buffer_1;
59+extern buffer *buffer_1small;
60+extern buffer *buffer_2;
61+
62+#endif
+13, -0
 1@@ -0,0 +1,13 @@
 2+/* Public domain. */
 3+
 4+#include "buffer.h"
 5+
 6+int buffer_0_read(fd,buf,len) int fd; char *buf; int len;
 7+{
 8+  if (buffer_flush(buffer_1) == -1) return -1;
 9+  return buffer_unixread(fd,buf,len);
10+}
11+
12+char buffer_0_space[BUFFER_INSIZE];
13+static buffer it = BUFFER_INIT(buffer_0_read,0,buffer_0_space,sizeof buffer_0_space);
14+buffer *buffer_0 = &it;
+7, -0
1@@ -0,0 +1,7 @@
2+/* Public domain. */
3+
4+#include "buffer.h"
5+
6+char buffer_1_space[BUFFER_OUTSIZE];
7+static buffer it = BUFFER_INIT(buffer_unixwrite,1,buffer_1_space,sizeof buffer_1_space);
8+buffer *buffer_1 = &it;
+7, -0
1@@ -0,0 +1,7 @@
2+/* Public domain. */
3+
4+#include "buffer.h"
5+
6+char buffer_2_space[256];
7+static buffer it = BUFFER_INIT(buffer_unixwrite,2,buffer_2_space,sizeof buffer_2_space);
8+buffer *buffer_2 = &it;
+69, -0
 1@@ -0,0 +1,69 @@
 2+/* Public domain. */
 3+
 4+#include "buffer.h"
 5+#include "byte.h"
 6+#include "error.h"
 7+
 8+static int oneread(int (*op)(),int fd,char *buf,unsigned int len)
 9+{
10+  int r;
11+
12+  for (;;) {
13+    r = op(fd,buf,len);
14+    if (r == -1) if (errno == error_intr) continue;
15+    return r;
16+  }
17+}
18+
19+static int getthis(buffer *s,char *buf,unsigned int len)
20+{
21+  if (len > s->p) len = s->p;
22+  s->p -= len;
23+  byte_copy(buf,len,s->x + s->n);
24+  s->n += len;
25+  return len;
26+}
27+
28+int buffer_feed(buffer *s)
29+{
30+  int r;
31+
32+  if (s->p) return s->p;
33+  r = oneread(s->op,s->fd,s->x,s->n);
34+  if (r <= 0) return r;
35+  s->p = r;
36+  s->n -= r;
37+  if (s->n > 0) byte_copyr(s->x + s->n,r,s->x);
38+  return r;
39+}
40+
41+int buffer_bget(buffer *s,char *buf,unsigned int len)
42+{
43+  int r;
44+ 
45+  if (s->p > 0) return getthis(s,buf,len);
46+  if (s->n <= len) return oneread(s->op,s->fd,buf,s->n);
47+  r = buffer_feed(s); if (r <= 0) return r;
48+  return getthis(s,buf,len);
49+}
50+
51+int buffer_get(buffer *s,char *buf,unsigned int len)
52+{
53+  int r;
54+ 
55+  if (s->p > 0) return getthis(s,buf,len);
56+  if (s->n <= len) return oneread(s->op,s->fd,buf,len);
57+  r = buffer_feed(s); if (r <= 0) return r;
58+  return getthis(s,buf,len);
59+}
60+
61+char *buffer_peek(buffer *s)
62+{
63+  return s->x + s->n;
64+}
65+
66+void buffer_seek(buffer *s,unsigned int len)
67+{
68+  s->n += len;
69+  s->p -= len;
70+}
+90, -0
 1@@ -0,0 +1,90 @@
 2+/* Public domain. */
 3+
 4+#include "buffer.h"
 5+#include "str.h"
 6+#include "byte.h"
 7+#include "error.h"
 8+
 9+static int allwrite(int (*op)(),int fd,const char *buf,unsigned int len)
10+{
11+  int w;
12+
13+  while (len) {
14+    w = op(fd,buf,len);
15+    if (w == -1) {
16+      if (errno == error_intr) continue;
17+      return -1; /* note that some data may have been written */
18+    }
19+    if (w == 0) ; /* luser's fault */
20+    buf += w;
21+    len -= w;
22+  }
23+  return 0;
24+}
25+
26+int buffer_flush(buffer *s)
27+{
28+  int p;
29+ 
30+  p = s->p;
31+  if (!p) return 0;
32+  s->p = 0;
33+  return allwrite(s->op,s->fd,s->x,p);
34+}
35+
36+int buffer_putalign(buffer *s,const char *buf,unsigned int len)
37+{
38+  unsigned int n;
39+ 
40+  while (len > (n = s->n - s->p)) {
41+    byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n;
42+    if (buffer_flush(s) == -1) return -1;
43+  }
44+  /* now len <= s->n - s->p */
45+  byte_copy(s->x + s->p,len,buf);
46+  s->p += len;
47+  return 0;
48+}
49+
50+int buffer_put(buffer *s,const char *buf,unsigned int len)
51+{
52+  unsigned int n;
53+ 
54+  n = s->n;
55+  if (len > n - s->p) {
56+    if (buffer_flush(s) == -1) return -1;
57+    /* now s->p == 0 */
58+    if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE;
59+    while (len > s->n) {
60+      if (n > len) n = len;
61+      if (allwrite(s->op,s->fd,buf,n) == -1) return -1;
62+      buf += n;
63+      len -= n;
64+    }
65+  }
66+  /* now len <= s->n - s->p */
67+  byte_copy(s->x + s->p,len,buf);
68+  s->p += len;
69+  return 0;
70+}
71+
72+int buffer_putflush(buffer *s,const char *buf,unsigned int len)
73+{
74+  if (buffer_flush(s) == -1) return -1;
75+  return allwrite(s->op,s->fd,buf,len);
76+}
77+
78+int buffer_putsalign(buffer *s,const char *buf)
79+{
80+  return buffer_putalign(s,buf,str_len(buf));
81+}
82+
83+int buffer_puts(buffer *s,const char *buf)
84+{
85+  return buffer_put(s,buf,str_len(buf));
86+}
87+
88+int buffer_putsflush(buffer *s,const char *buf)
89+{
90+  return buffer_putflush(s,buf,str_len(buf));
91+}
+9, -0
 1@@ -0,0 +1,9 @@
 2+/* Public domain. */
 3+
 4+#include <unistd.h>
 5+#include "buffer.h"
 6+
 7+int buffer_unixread(int fd,char *buf,unsigned int len)
 8+{
 9+  return read(fd,buf,len);
10+}
+9, -0
 1@@ -0,0 +1,9 @@
 2+/* Public domain. */
 3+
 4+#include <unistd.h>
 5+#include "buffer.h"
 6+
 7+int buffer_unixwrite(int fd,const char *buf,unsigned int len)
 8+{
 9+  return write(fd,buf,len);
10+}
+15, -0
 1@@ -0,0 +1,15 @@
 2+/* Public domain. */
 3+
 4+#ifndef BYTE_H
 5+#define BYTE_H
 6+
 7+extern unsigned int byte_chr();
 8+extern unsigned int byte_rchr();
 9+extern void byte_copy();
10+extern void byte_copyr();
11+extern int byte_diff();
12+extern void byte_zero();
13+
14+#define byte_equal(s,n,t) (!byte_diff((s),(n),(t)))
15+
16+#endif
+22, -0
 1@@ -0,0 +1,22 @@
 2+/* Public domain. */
 3+
 4+#include "byte.h"
 5+
 6+unsigned int byte_chr(s,n,c)
 7+char *s;
 8+register unsigned int n;
 9+int c;
10+{
11+  register char ch;
12+  register char *t;
13+
14+  ch = c;
15+  t = s;
16+  for (;;) {
17+    if (!n) break; if (*t == ch) break; ++t; --n;
18+    if (!n) break; if (*t == ch) break; ++t; --n;
19+    if (!n) break; if (*t == ch) break; ++t; --n;
20+    if (!n) break; if (*t == ch) break; ++t; --n;
21+  }
22+  return t - s;
23+}
+16, -0
 1@@ -0,0 +1,16 @@
 2+/* Public domain. */
 3+
 4+#include "byte.h"
 5+
 6+void byte_copy(to,n,from)
 7+register char *to;
 8+register unsigned int n;
 9+register char *from;
10+{
11+  for (;;) {
12+    if (!n) return; *to++ = *from++; --n;
13+    if (!n) return; *to++ = *from++; --n;
14+    if (!n) return; *to++ = *from++; --n;
15+    if (!n) return; *to++ = *from++; --n;
16+  }
17+}
+18, -0
 1@@ -0,0 +1,18 @@
 2+/* Public domain. */
 3+
 4+#include "byte.h"
 5+
 6+void byte_copyr(to,n,from)
 7+register char *to;
 8+register unsigned int n;
 9+register char *from;
10+{
11+  to += n;
12+  from += n;
13+  for (;;) {
14+    if (!n) return; *--to = *--from; --n;
15+    if (!n) return; *--to = *--from; --n;
16+    if (!n) return; *--to = *--from; --n;
17+    if (!n) return; *--to = *--from; --n;
18+  }
19+}
+18, -0
 1@@ -0,0 +1,18 @@
 2+/* Public domain. */
 3+
 4+#include "byte.h"
 5+
 6+int byte_diff(s,n,t)
 7+register char *s;
 8+register unsigned int n;
 9+register char *t;
10+{
11+  for (;;) {
12+    if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
13+    if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
14+    if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
15+    if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
16+  }
17+  return ((int)(unsigned int)(unsigned char) *s)
18+       - ((int)(unsigned int)(unsigned char) *t);
19+}
+25, -0
 1@@ -0,0 +1,25 @@
 2+/* Public domain. */
 3+
 4+#include "byte.h"
 5+
 6+unsigned int byte_rchr(s,n,c)
 7+char *s;
 8+register unsigned int n;
 9+int c;
10+{
11+  register char ch;
12+  register char *t;
13+  register char *u;
14+
15+  ch = c;
16+  t = s;
17+  u = 0;
18+  for (;;) {
19+    if (!n) break; if (*t == ch) u = t; ++t; --n;
20+    if (!n) break; if (*t == ch) u = t; ++t; --n;
21+    if (!n) break; if (*t == ch) u = t; ++t; --n;
22+    if (!n) break; if (*t == ch) u = t; ++t; --n;
23+  }
24+  if (!u) u = t;
25+  return u - s;
26+}
+15, -0
 1@@ -0,0 +1,15 @@
 2+/* Public domain. */
 3+
 4+#include "byte.h"
 5+
 6+void byte_zero(s,n)
 7+register char *s;
 8+register unsigned int n;
 9+{
10+  for (;;) {
11+    if (!n) return; *s++ = 0; --n;
12+    if (!n) return; *s++ = 0; --n;
13+    if (!n) return; *s++ = 0; --n;
14+    if (!n) return; *s++ = 0; --n;
15+  }
16+}
+132, -0
  1@@ -0,0 +1,132 @@
  2+/* Public domain. */
  3+
  4+#include <errno.h>
  5+#include "error.h"
  6+
  7+/* warning: as coverage improves here, should update error_{str,temp} */
  8+
  9+int error_intr =
 10+#ifdef EINTR
 11+EINTR;
 12+#else
 13+-1;
 14+#endif
 15+
 16+int error_nomem =
 17+#ifdef ENOMEM
 18+ENOMEM;
 19+#else
 20+-2;
 21+#endif
 22+
 23+int error_noent = 
 24+#ifdef ENOENT
 25+ENOENT;
 26+#else
 27+-3;
 28+#endif
 29+
 30+int error_txtbsy =
 31+#ifdef ETXTBSY
 32+ETXTBSY;
 33+#else
 34+-4;
 35+#endif
 36+
 37+int error_io =
 38+#ifdef EIO
 39+EIO;
 40+#else
 41+-5;
 42+#endif
 43+
 44+int error_exist =
 45+#ifdef EEXIST
 46+EEXIST;
 47+#else
 48+-6;
 49+#endif
 50+
 51+int error_timeout =
 52+#ifdef ETIMEDOUT
 53+ETIMEDOUT;
 54+#else
 55+-7;
 56+#endif
 57+
 58+int error_inprogress =
 59+#ifdef EINPROGRESS
 60+EINPROGRESS;
 61+#else
 62+-8;
 63+#endif
 64+
 65+int error_wouldblock =
 66+#ifdef EWOULDBLOCK
 67+EWOULDBLOCK;
 68+#else
 69+-9;
 70+#endif
 71+
 72+int error_again =
 73+#ifdef EAGAIN
 74+EAGAIN;
 75+#else
 76+-10;
 77+#endif
 78+
 79+int error_pipe =
 80+#ifdef EPIPE
 81+EPIPE;
 82+#else
 83+-11;
 84+#endif
 85+
 86+int error_perm =
 87+#ifdef EPERM
 88+EPERM;
 89+#else
 90+-12;
 91+#endif
 92+
 93+int error_acces =
 94+#ifdef EACCES
 95+EACCES;
 96+#else
 97+-13;
 98+#endif
 99+
100+int error_nodevice =
101+#ifdef ENXIO
102+ENXIO;
103+#else
104+-14;
105+#endif
106+
107+int error_proto =
108+#ifdef EPROTO
109+EPROTO;
110+#else
111+-15;
112+#endif
113+
114+int error_isdir =
115+#ifdef EISDIR
116+EISDIR;
117+#else
118+-16;
119+#endif
120+
121+int error_connrefused =
122+#ifdef ECONNREFUSED
123+ECONNREFUSED;
124+#else
125+-17;
126+#endif
127+
128+int error_notdir =
129+#ifdef ENOTDIR
130+ENOTDIR;
131+#else
132+-18;
133+#endif
+30, -0
 1@@ -0,0 +1,30 @@
 2+/* Public domain. */
 3+
 4+#ifndef ERROR_H
 5+#define ERROR_H
 6+
 7+#include <errno.h>
 8+
 9+extern int error_intr;
10+extern int error_nomem;
11+extern int error_noent;
12+extern int error_txtbsy;
13+extern int error_io;
14+extern int error_exist;
15+extern int error_timeout;
16+extern int error_inprogress;
17+extern int error_wouldblock;
18+extern int error_again;
19+extern int error_pipe;
20+extern int error_perm;
21+extern int error_acces;
22+extern int error_nodevice;
23+extern int error_proto;
24+extern int error_isdir;
25+extern int error_connrefused;
26+extern int error_notdir;
27+
28+extern const char *error_str(int);
29+extern int error_temp(int);
30+
31+#endif
+267, -0
  1@@ -0,0 +1,267 @@
  2+/* Public domain. */
  3+
  4+#include <errno.h>
  5+#include "error.h"
  6+
  7+#define X(e,s) if (i == e) return s;
  8+
  9+const char *error_str(int i)
 10+{
 11+  X(0,"no error")
 12+  X(error_intr,"interrupted system call")
 13+  X(error_nomem,"out of memory")
 14+  X(error_noent,"file does not exist")
 15+  X(error_txtbsy,"text busy")
 16+  X(error_io,"input/output error")
 17+  X(error_exist,"file already exists")
 18+  X(error_timeout,"timed out")
 19+  X(error_inprogress,"operation in progress")
 20+  X(error_again,"temporary failure")
 21+  X(error_wouldblock,"input/output would block")
 22+  X(error_pipe,"broken pipe")
 23+  X(error_perm,"permission denied")
 24+  X(error_acces,"access denied")
 25+  X(error_nodevice,"device not configured")
 26+  X(error_proto,"protocol error")
 27+  X(error_isdir,"is a directory")
 28+  X(error_connrefused,"connection refused")
 29+  X(error_notdir,"not a directory")
 30+#ifdef ESRCH
 31+  X(ESRCH,"no such process")
 32+#endif
 33+#ifdef E2BIG
 34+  X(E2BIG,"argument list too long")
 35+#endif
 36+#ifdef ENOEXEC
 37+  X(ENOEXEC,"exec format error")
 38+#endif
 39+#ifdef EBADF
 40+  X(EBADF,"file descriptor not open")
 41+#endif
 42+#ifdef ECHILD
 43+  X(ECHILD,"no child processes")
 44+#endif
 45+#ifdef EDEADLK
 46+  X(EDEADLK,"operation would cause deadlock")
 47+#endif
 48+#ifdef EFAULT
 49+  X(EFAULT,"bad address")
 50+#endif
 51+#ifdef ENOTBLK
 52+  X(ENOTBLK,"not a block device")
 53+#endif
 54+#ifdef EBUSY
 55+  X(EBUSY,"device busy")
 56+#endif
 57+#ifdef EXDEV
 58+  X(EXDEV,"cross-device link")
 59+#endif
 60+#ifdef ENODEV
 61+  X(ENODEV,"device does not support operation")
 62+#endif
 63+#ifdef EINVAL
 64+  X(EINVAL,"invalid argument")
 65+#endif
 66+#ifdef ENFILE
 67+  X(ENFILE,"system cannot open more files")
 68+#endif
 69+#ifdef EMFILE
 70+  X(EMFILE,"process cannot open more files")
 71+#endif
 72+#ifdef ENOTTY
 73+  X(ENOTTY,"not a tty")
 74+#endif
 75+#ifdef EFBIG
 76+  X(EFBIG,"file too big")
 77+#endif
 78+#ifdef ENOSPC
 79+  X(ENOSPC,"out of disk space")
 80+#endif
 81+#ifdef ESPIPE
 82+  X(ESPIPE,"unseekable descriptor")
 83+#endif
 84+#ifdef EROFS
 85+  X(EROFS,"read-only file system")
 86+#endif
 87+#ifdef EMLINK
 88+  X(EMLINK,"too many links")
 89+#endif
 90+#ifdef EDOM
 91+  X(EDOM,"input out of range")
 92+#endif
 93+#ifdef ERANGE
 94+  X(ERANGE,"output out of range")
 95+#endif
 96+#ifdef EALREADY
 97+  X(EALREADY,"operation already in progress")
 98+#endif
 99+#ifdef ENOTSOCK
100+  X(ENOTSOCK,"not a socket")
101+#endif
102+#ifdef EDESTADDRREQ
103+  X(EDESTADDRREQ,"destination address required")
104+#endif
105+#ifdef EMSGSIZE
106+  X(EMSGSIZE,"message too long")
107+#endif
108+#ifdef EPROTOTYPE
109+  X(EPROTOTYPE,"incorrect protocol type")
110+#endif
111+#ifdef ENOPROTOOPT
112+  X(ENOPROTOOPT,"protocol not available")
113+#endif
114+#ifdef EPROTONOSUPPORT
115+  X(EPROTONOSUPPORT,"protocol not supported")
116+#endif
117+#ifdef ESOCKTNOSUPPORT
118+  X(ESOCKTNOSUPPORT,"socket type not supported")
119+#endif
120+#ifdef EOPNOTSUPP
121+  X(EOPNOTSUPP,"operation not supported")
122+#endif
123+#ifdef EPFNOSUPPORT
124+  X(EPFNOSUPPORT,"protocol family not supported")
125+#endif
126+#ifdef EAFNOSUPPORT
127+  X(EAFNOSUPPORT,"address family not supported")
128+#endif
129+#ifdef EADDRINUSE
130+  X(EADDRINUSE,"address already used")
131+#endif
132+#ifdef EADDRNOTAVAIL
133+  X(EADDRNOTAVAIL,"address not available")
134+#endif
135+#ifdef ENETDOWN
136+  X(ENETDOWN,"network down")
137+#endif
138+#ifdef ENETUNREACH
139+  X(ENETUNREACH,"network unreachable")
140+#endif
141+#ifdef ENETRESET
142+  X(ENETRESET,"network reset")
143+#endif
144+#ifdef ECONNABORTED
145+  X(ECONNABORTED,"connection aborted")
146+#endif
147+#ifdef ECONNRESET
148+  X(ECONNRESET,"connection reset")
149+#endif
150+#ifdef ENOBUFS
151+  X(ENOBUFS,"out of buffer space")
152+#endif
153+#ifdef EISCONN
154+  X(EISCONN,"already connected")
155+#endif
156+#ifdef ENOTCONN
157+  X(ENOTCONN,"not connected")
158+#endif
159+#ifdef ESHUTDOWN
160+  X(ESHUTDOWN,"socket shut down")
161+#endif
162+#ifdef ETOOMANYREFS
163+  X(ETOOMANYREFS,"too many references")
164+#endif
165+#ifdef ELOOP
166+  X(ELOOP,"symbolic link loop")
167+#endif
168+#ifdef ENAMETOOLONG
169+  X(ENAMETOOLONG,"file name too long")
170+#endif
171+#ifdef EHOSTDOWN
172+  X(EHOSTDOWN,"host down")
173+#endif
174+#ifdef EHOSTUNREACH
175+  X(EHOSTUNREACH,"host unreachable")
176+#endif
177+#ifdef ENOTEMPTY
178+  X(ENOTEMPTY,"directory not empty")
179+#endif
180+#ifdef EPROCLIM
181+  X(EPROCLIM,"too many processes")
182+#endif
183+#ifdef EUSERS
184+  X(EUSERS,"too many users")
185+#endif
186+#ifdef EDQUOT
187+  X(EDQUOT,"disk quota exceeded")
188+#endif
189+#ifdef ESTALE
190+  X(ESTALE,"stale NFS file handle")
191+#endif
192+#ifdef EREMOTE
193+  X(EREMOTE,"too many levels of remote in path")
194+#endif
195+#ifdef EBADRPC
196+  X(EBADRPC,"RPC structure is bad")
197+#endif
198+#ifdef ERPCMISMATCH
199+  X(ERPCMISMATCH,"RPC version mismatch")
200+#endif
201+#ifdef EPROGUNAVAIL
202+  X(EPROGUNAVAIL,"RPC program unavailable")
203+#endif
204+#ifdef EPROGMISMATCH
205+  X(EPROGMISMATCH,"program version mismatch")
206+#endif
207+#ifdef EPROCUNAVAIL
208+  X(EPROCUNAVAIL,"bad procedure for program")
209+#endif
210+#ifdef ENOLCK
211+  X(ENOLCK,"no locks available")
212+#endif
213+#ifdef ENOSYS
214+  X(ENOSYS,"system call not available")
215+#endif
216+#ifdef EFTYPE
217+  X(EFTYPE,"bad file type")
218+#endif
219+#ifdef EAUTH
220+  X(EAUTH,"authentication error")
221+#endif
222+#ifdef ENEEDAUTH
223+  X(ENEEDAUTH,"not authenticated")
224+#endif
225+#ifdef ENOSTR
226+  X(ENOSTR,"not a stream device")
227+#endif
228+#ifdef ETIME
229+  X(ETIME,"timer expired")
230+#endif
231+#ifdef ENOSR
232+  X(ENOSR,"out of stream resources")
233+#endif
234+#ifdef ENOMSG
235+  X(ENOMSG,"no message of desired type")
236+#endif
237+#ifdef EBADMSG
238+  X(EBADMSG,"bad message type")
239+#endif
240+#ifdef EIDRM
241+  X(EIDRM,"identifier removed")
242+#endif
243+#ifdef ENONET
244+  X(ENONET,"machine not on network")
245+#endif
246+#ifdef ERREMOTE
247+  X(ERREMOTE,"object not local")
248+#endif
249+#ifdef ENOLINK
250+  X(ENOLINK,"link severed")
251+#endif
252+#ifdef EADV
253+  X(EADV,"advertise error")
254+#endif
255+#ifdef ESRMNT
256+  X(ESRMNT,"srmount error")
257+#endif
258+#ifdef ECOMM
259+  X(ECOMM,"communication error")
260+#endif
261+#ifdef EMULTIHOP
262+  X(EMULTIHOP,"multihop attempted")
263+#endif
264+#ifdef EREMCHG
265+  X(EREMCHG,"remote address changed")
266+#endif
267+  return "unknown error";
268+}
+27, -0
 1@@ -0,0 +1,27 @@
 2+/* Public domain. */
 3+
 4+#ifndef FMT_H
 5+#define FMT_H
 6+
 7+#define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */
 8+#define FMT_LEN ((char *) 0) /* convenient abbreviation */
 9+
10+extern unsigned int fmt_uint(char *,unsigned int);
11+extern unsigned int fmt_uint0(char *,unsigned int,unsigned int);
12+extern unsigned int fmt_xint(char *,unsigned int);
13+extern unsigned int fmt_nbbint(char *,unsigned int,unsigned int,unsigned int,unsigned int);
14+extern unsigned int fmt_ushort(char *,unsigned short);
15+extern unsigned int fmt_xshort(char *,unsigned short);
16+extern unsigned int fmt_nbbshort(char *,unsigned int,unsigned int,unsigned int,unsigned short);
17+extern unsigned int fmt_ulong(char *,unsigned long);
18+extern unsigned int fmt_xlong(char *,unsigned long);
19+extern unsigned int fmt_nbblong(char *,unsigned int,unsigned int,unsigned int,unsigned long);
20+
21+extern unsigned int fmt_plusminus(char *,int);
22+extern unsigned int fmt_minus(char *,int);
23+extern unsigned int fmt_0x(char *,int);
24+
25+extern unsigned int fmt_str(char *,const char *);
26+extern unsigned int fmt_strn(char *,const char *,unsigned int);
27+
28+#endif
+8, -0
1@@ -0,0 +1,8 @@
2+/* Public domain. */
3+
4+#include "fmt.h"
5+
6+unsigned int fmt_uint(register char *s,register unsigned int u)
7+{
8+  return fmt_ulong(s,u);
9+}
+12, -0
 1@@ -0,0 +1,12 @@
 2+/* Public domain. */
 3+
 4+#include "fmt.h"
 5+
 6+unsigned int fmt_uint0(char *s,unsigned int u,unsigned int n)
 7+{
 8+  unsigned int len;
 9+  len = fmt_uint(FMT_LEN,u);
10+  while (len < n) { if (s) *s++ = '0'; ++len; }
11+  if (s) fmt_uint(s,u);
12+  return len;
13+}
+15, -0
 1@@ -0,0 +1,15 @@
 2+/* Public domain. */
 3+
 4+#include "fmt.h"
 5+
 6+unsigned int fmt_ulong(register char *s,register unsigned long u)
 7+{
 8+  register unsigned int len; register unsigned long q;
 9+  len = 1; q = u;
10+  while (q > 9) { ++len; q /= 10; }
11+  if (s) {
12+    s += len;
13+    do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */
14+  }
15+  return len;
16+}
+9, -0
 1@@ -0,0 +1,9 @@
 2+/* Public domain. */
 3+
 4+#ifndef GEN_ALLOC_H
 5+#define GEN_ALLOC_H
 6+
 7+#define GEN_ALLOC_typedef(ta,type,field,len,a) \
 8+  typedef struct ta { type *field; unsigned int len; unsigned int a; } ta;
 9+
10+#endif
+36, -0
 1@@ -0,0 +1,36 @@
 2+/* Public domain. */
 3+
 4+#ifndef GEN_ALLOC_DEFS_H
 5+#define GEN_ALLOC_DEFS_H
 6+
 7+#define GEN_ALLOC_ready(ta,type,field,len,a,i,n,x,base,ta_ready) \
 8+int ta_ready(register ta *x,register unsigned int n) \
 9+{ register unsigned int i; \
10+  if (x->field) { \
11+    i = x->a; \
12+    if (n > i) { \
13+      x->a = base + n + (n >> 3); \
14+      if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \
15+      x->a = i; return 0; } \
16+    return 1; } \
17+  x->len = 0; \
18+  return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); }
19+
20+#define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \
21+int ta_rplus(register ta *x,register unsigned int n) \
22+{ register unsigned int i; \
23+  if (x->field) { \
24+    i = x->a; n += x->len; \
25+    if (n > i) { \
26+      x->a = base + n + (n >> 3); \
27+      if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \
28+      x->a = i; return 0; } \
29+    return 1; } \
30+  x->len = 0; \
31+  return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); }
32+
33+#define GEN_ALLOC_append(ta,type,field,len,a,i,n,x,base,ta_rplus,ta_append) \
34+int ta_append(register ta *x,register const type *i) \
35+{ if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; }
36+
37+#endif
+6, -0
1@@ -0,0 +1,6 @@
2+#ifndef HASWAITP_H
3+#define HASWAITP_H
4+
5+#define HASWAITPID 1
6+
7+#endif
+12, -0
 1@@ -0,0 +1,12 @@
 2+/* Public domain. */
 3+
 4+#ifndef OPEN_H
 5+#define OPEN_H
 6+
 7+extern int open_read(const char *);
 8+extern int open_excl(const char *);
 9+extern int open_append(const char *);
10+extern int open_trunc(const char *);
11+extern int open_write(const char *);
12+
13+#endif
+8, -0
1@@ -0,0 +1,8 @@
2+/* Public domain. */
3+
4+#include <sys/types.h>
5+#include <fcntl.h>
6+#include "open.h"
7+
8+int open_read(const char *fn)
9+{ return open(fn,O_RDONLY | O_NDELAY); }
+18, -0
 1@@ -0,0 +1,18 @@
 2+/* Public domain. */
 3+
 4+#include "error.h"
 5+#include "open.h"
 6+#include "readclose.h"
 7+#include "openreadclose.h"
 8+
 9+int openreadclose(const char *fn,stralloc *sa,unsigned int bufsize)
10+{
11+  int fd;
12+  fd = open_read(fn);
13+  if (fd == -1) {
14+    if (errno == error_noent) return 0;
15+    return -1;
16+  }
17+  if (readclose(fd,sa,bufsize) == -1) return -1;
18+  return 1;
19+}
+10, -0
 1@@ -0,0 +1,10 @@
 2+/* Public domain. */
 3+
 4+#ifndef OPENREADCLOSE_H
 5+#define OPENREADCLOSE_H
 6+
 7+#include "stralloc.h"
 8+
 9+extern int openreadclose(const char *,stralloc *,unsigned int);
10+
11+#endif
+23, -0
 1@@ -0,0 +1,23 @@
 2+/* Public domain. */
 3+
 4+#include <unistd.h>
 5+#include "error.h"
 6+#include "readclose.h"
 7+
 8+int readclose_append(int fd,stralloc *sa,unsigned int bufsize)
 9+{
10+  int r;
11+  for (;;) {
12+    if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; }
13+    r = read(fd,sa->s + sa->len,bufsize);
14+    if (r == -1) if (errno == error_intr) continue;
15+    if (r <= 0) { close(fd); return r; }
16+    sa->len += r;
17+  }
18+}
19+
20+int readclose(int fd,stralloc *sa,unsigned int bufsize)
21+{
22+  if (!stralloc_copys(sa,"")) { close(fd); return -1; }
23+  return readclose_append(fd,sa,bufsize);
24+}
+11, -0
 1@@ -0,0 +1,11 @@
 2+/* Public domain. */
 3+
 4+#ifndef READCLOSE_H
 5+#define READCLOSE_H
 6+
 7+#include "stralloc.h"
 8+
 9+extern int readclose_append(int,stralloc *,unsigned int);
10+extern int readclose(int,stralloc *,unsigned int);
11+
12+#endif
+30, -0
 1@@ -0,0 +1,30 @@
 2+/* Public domain. */
 3+
 4+#ifndef SCAN_H
 5+#define SCAN_H
 6+
 7+extern unsigned int scan_uint(const char *,unsigned int *);
 8+extern unsigned int scan_xint(const char *,unsigned int *);
 9+extern unsigned int scan_nbbint(const char *,unsigned int,unsigned int,unsigned int,unsigned int *);
10+extern unsigned int scan_ushort(const char *,unsigned short *);
11+extern unsigned int scan_xshort(const char *,unsigned short *);
12+extern unsigned int scan_nbbshort(const char *,unsigned int,unsigned int,unsigned int,unsigned short *);
13+extern unsigned int scan_ulong(const char *,unsigned long *);
14+extern unsigned int scan_xlong(const char *,unsigned long *);
15+extern unsigned int scan_nbblong(const char *,unsigned int,unsigned int,unsigned int,unsigned long *);
16+
17+extern unsigned int scan_plusminus(const char *,int *);
18+extern unsigned int scan_0x(const char *,unsigned int *);
19+
20+extern unsigned int scan_whitenskip(const char *,unsigned int);
21+extern unsigned int scan_nonwhitenskip(const char *,unsigned int);
22+extern unsigned int scan_charsetnskip(const char *,const char *,unsigned int);
23+extern unsigned int scan_noncharsetnskip(const char *,const char *,unsigned int);
24+
25+extern unsigned int scan_strncmp(const char *,const char *,unsigned int);
26+extern unsigned int scan_memcmp(const char *,const char *,unsigned int);
27+
28+extern unsigned int scan_long(const char *,long *);
29+extern unsigned int scan_8long(const char *,unsigned long *);
30+
31+#endif
+16, -0
 1@@ -0,0 +1,16 @@
 2+/* Public domain. */
 3+
 4+#include "scan.h"
 5+
 6+unsigned int scan_ulong(register const char *s,register unsigned long *u)
 7+{
 8+  register unsigned int pos = 0;
 9+  register unsigned long result = 0;
10+  register unsigned long c;
11+  while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {
12+    result = result * 10 + c;
13+    ++pos;
14+  }
15+  *u = result;
16+  return pos;
17+}
+53, -0
 1@@ -0,0 +1,53 @@
 2+/* Public domain. */
 3+
 4+/* sgetopt.c, sgetopt.h: (yet another) improved getopt clone, outer layer
 5+D. J. Bernstein, djb@pobox.com.
 6+Depends on subgetopt.h, buffer.h.
 7+No system requirements.
 8+19991219: Switched to buffer.h.
 9+19970208: Cleanups.
10+931201: Baseline.
11+No known patent problems.
12+
13+Documentation in sgetopt.3.
14+*/
15+
16+#include "buffer.h"
17+#define SGETOPTNOSHORT
18+#include "sgetopt.h"
19+#define SUBGETOPTNOSHORT
20+#include "subgetopt.h"
21+
22+#define getopt sgetoptmine
23+#define optind subgetoptind
24+#define opterr sgetopterr
25+#define optproblem subgetoptproblem
26+#define optprogname sgetoptprogname
27+
28+int opterr = 1;
29+const char *optprogname = 0;
30+
31+int getopt(int argc,const char *const *argv,const char *opts)
32+{
33+  int c;
34+  const char *s;
35+
36+  if (!optprogname) {
37+    optprogname = *argv;
38+    if (!optprogname) optprogname = "";
39+    for (s = optprogname;*s;++s) if (*s == '/') optprogname = s + 1;
40+  }
41+  c = subgetopt(argc,argv,opts);
42+  if (opterr)
43+    if (c == '?') {
44+      char chp[2]; chp[0] = optproblem; chp[1] = '\n';
45+      buffer_puts(buffer_2,optprogname);
46+      if (argv[optind] && (optind < argc))
47+        buffer_puts(buffer_2,": illegal option -- ");
48+      else
49+        buffer_puts(buffer_2,": option requires an argument -- ");
50+      buffer_put(buffer_2,chp,2);
51+      buffer_flush(buffer_2);
52+    }
53+  return c;
54+}
+23, -0
 1@@ -0,0 +1,23 @@
 2+/* Public domain. */
 3+
 4+#ifndef SGETOPT_H
 5+#define SGETOPT_H
 6+
 7+#ifndef SGETOPTNOSHORT
 8+#define getopt sgetoptmine
 9+#define optarg subgetoptarg
10+#define optind subgetoptind
11+#define optpos subgetoptpos
12+#define opterr sgetopterr
13+#define optproblem subgetoptproblem
14+#define optprogname sgetoptprogname
15+#define opteof subgetoptdone
16+#endif
17+
18+#include "subgetopt.h"
19+
20+extern int sgetoptmine(int,const char *const *,const char *);
21+extern int sgetopterr;
22+extern const char *sgetoptprogname;
23+
24+#endif
+16, -0
 1@@ -0,0 +1,16 @@
 2+/* Public domain. */
 3+
 4+#ifndef STR_H
 5+#define STR_H
 6+
 7+extern unsigned int str_copy(char *,const char *);
 8+extern int str_diff(const char *,const char *);
 9+extern int str_diffn(const char *,const char *,unsigned int);
10+extern unsigned int str_len(const char *);
11+extern unsigned int str_chr(const char *,int);
12+extern unsigned int str_rchr(const char *,int);
13+extern int str_start(const char *,const char *);
14+
15+#define str_equal(s,t) (!str_diff((s),(t)))
16+
17+#endif
+19, -0
 1@@ -0,0 +1,19 @@
 2+/* Public domain. */
 3+
 4+#include "str.h"
 5+
 6+unsigned int str_chr(register const char *s,int c)
 7+{
 8+  register char ch;
 9+  register const char *t;
10+
11+  ch = c;
12+  t = s;
13+  for (;;) {
14+    if (!*t) break; if (*t == ch) break; ++t;
15+    if (!*t) break; if (*t == ch) break; ++t;
16+    if (!*t) break; if (*t == ch) break; ++t;
17+    if (!*t) break; if (*t == ch) break; ++t;
18+  }
19+  return t - s;
20+}
+17, -0
 1@@ -0,0 +1,17 @@
 2+/* Public domain. */
 3+
 4+#include "str.h"
 5+
 6+int str_diff(register const char *s,register const char *t)
 7+{
 8+  register char x;
 9+
10+  for (;;) {
11+    x = *s; if (x != *t) break; if (!x) break; ++s; ++t;
12+    x = *s; if (x != *t) break; if (!x) break; ++s; ++t;
13+    x = *s; if (x != *t) break; if (!x) break; ++s; ++t;
14+    x = *s; if (x != *t) break; if (!x) break; ++s; ++t;
15+  }
16+  return ((int)(unsigned int)(unsigned char) x)
17+       - ((int)(unsigned int)(unsigned char) *t);
18+}
+16, -0
 1@@ -0,0 +1,16 @@
 2+/* Public domain. */
 3+
 4+#include "str.h"
 5+
 6+unsigned int str_len(const char *s)
 7+{
 8+  register const char *t;
 9+
10+  t = s;
11+  for (;;) {
12+    if (!*t) return t - s; ++t;
13+    if (!*t) return t - s; ++t;
14+    if (!*t) return t - s; ++t;
15+    if (!*t) return t - s; ++t;
16+  }
17+}
+15, -0
 1@@ -0,0 +1,15 @@
 2+/* Public domain. */
 3+
 4+#include "str.h"
 5+
 6+int str_start(register const char *s,register const char *t)
 7+{
 8+  register char x;
 9+
10+  for (;;) {
11+    x = *t++; if (!x) return 1; if (x != *s++) return 0;
12+    x = *t++; if (!x) return 1; if (x != *s++) return 0;
13+    x = *t++; if (!x) return 1; if (x != *s++) return 0;
14+    x = *t++; if (!x) return 1; if (x != *s++) return 0;
15+  }
16+}
+31, -0
 1@@ -0,0 +1,31 @@
 2+/* Public domain. */
 3+
 4+#ifndef STRALLOC_H
 5+#define STRALLOC_H
 6+
 7+#include "gen_alloc.h"
 8+
 9+GEN_ALLOC_typedef(stralloc,char,s,len,a)
10+
11+extern int stralloc_ready(stralloc *,unsigned int);
12+extern int stralloc_readyplus(stralloc *,unsigned int);
13+extern int stralloc_copy(stralloc *,const stralloc *);
14+extern int stralloc_cat(stralloc *,const stralloc *);
15+extern int stralloc_copys(stralloc *,const char *);
16+extern int stralloc_cats(stralloc *,const char *);
17+extern int stralloc_copyb(stralloc *,const char *,unsigned int);
18+extern int stralloc_catb(stralloc *,const char *,unsigned int);
19+extern int stralloc_append(stralloc *,const char *); /* beware: this takes a pointer to 1 char */
20+extern int stralloc_starts(stralloc *,const char *);
21+
22+#define stralloc_0(sa) stralloc_append(sa,"")
23+
24+extern int stralloc_catulong0(stralloc *,unsigned long,unsigned int);
25+extern int stralloc_catlong0(stralloc *,long,unsigned int);
26+
27+#define stralloc_catlong(sa,l) (stralloc_catlong0((sa),(l),0))
28+#define stralloc_catuint0(sa,i,n) (stralloc_catulong0((sa),(i),(n)))
29+#define stralloc_catint0(sa,i,n) (stralloc_catlong0((sa),(i),(n)))
30+#define stralloc_catint(sa,i) (stralloc_catlong0((sa),(i),0))
31+
32+#endif
+9, -0
 1@@ -0,0 +1,9 @@
 2+/* Public domain. */
 3+
 4+#include "byte.h"
 5+#include "stralloc.h"
 6+
 7+int stralloc_cat(stralloc *sato,const stralloc *safrom)
 8+{
 9+  return stralloc_catb(sato,safrom->s,safrom->len);
10+}
+14, -0
 1@@ -0,0 +1,14 @@
 2+/* Public domain. */
 3+
 4+#include "stralloc.h"
 5+#include "byte.h"
 6+
 7+int stralloc_catb(stralloc *sa,const char *s,unsigned int n)
 8+{
 9+  if (!sa->s) return stralloc_copyb(sa,s,n);
10+  if (!stralloc_readyplus(sa,n + 1)) return 0;
11+  byte_copy(sa->s + sa->len,n,s);
12+  sa->len += n;
13+  sa->s[sa->len] = 'Z'; /* ``offensive programming'' */
14+  return 1;
15+}
+10, -0
 1@@ -0,0 +1,10 @@
 2+/* Public domain. */
 3+
 4+#include "byte.h"
 5+#include "str.h"
 6+#include "stralloc.h"
 7+
 8+int stralloc_cats(stralloc *sa,const char *s)
 9+{
10+  return stralloc_catb(sa,s,str_len(s));
11+}
+8, -0
1@@ -0,0 +1,8 @@
2+/* Public domain. */
3+
4+#include "alloc.h"
5+#include "stralloc.h"
6+#include "gen_allocdefs.h"
7+
8+GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready)
9+GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus)
+13, -0
 1@@ -0,0 +1,13 @@
 2+/* Public domain. */
 3+
 4+#include "stralloc.h"
 5+#include "byte.h"
 6+
 7+int stralloc_copyb(stralloc *sa,const char *s,unsigned int n)
 8+{
 9+  if (!stralloc_ready(sa,n + 1)) return 0;
10+  byte_copy(sa->s,n,s);
11+  sa->len = n;
12+  sa->s[n] = 'Z'; /* ``offensive programming'' */
13+  return 1;
14+}
+10, -0
 1@@ -0,0 +1,10 @@
 2+/* Public domain. */
 3+
 4+#include "byte.h"
 5+#include "str.h"
 6+#include "stralloc.h"
 7+
 8+int stralloc_copys(stralloc *sa,const char *s)
 9+{
10+  return stralloc_copyb(sa,s,str_len(s));
11+}
+7, -0
1@@ -0,0 +1,7 @@
2+/* Public domain. */
3+
4+#include "alloc.h"
5+#include "stralloc.h"
6+#include "gen_allocdefs.h"
7+
8+GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
+80, -0
 1@@ -0,0 +1,80 @@
 2+/* Public domain. */
 3+
 4+#ifndef STRERR_H
 5+#define STRERR_H
 6+
 7+struct strerr {
 8+  struct strerr *who;
 9+  const char *x;
10+  const char *y;
11+  const char *z;
12+} ;
13+
14+extern struct strerr strerr_sys;
15+extern void strerr_sysinit(void);
16+
17+extern const char *strerr(const struct strerr *);
18+extern void strerr_warn(const char *,const char *,const char *,const char *,const char *,const char *,const struct strerr *);
19+extern void strerr_die(int,const char *,const char *,const char *,const char *,const char *,const char *,const struct strerr *);
20+
21+#define STRERR(r,se,a) \
22+{ se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; }
23+
24+#define STRERR_SYS(r,se,a) \
25+{ se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; }
26+#define STRERR_SYS3(r,se,a,b,c) \
27+{ se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; }
28+
29+#define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \
30+strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(se))
31+#define strerr_warn5(x1,x2,x3,x4,x5,se) \
32+strerr_warn((x1),(x2),(x3),(x4),(x5),0,(se))
33+#define strerr_warn4(x1,x2,x3,x4,se) \
34+strerr_warn((x1),(x2),(x3),(x4),0,0,(se))
35+#define strerr_warn3(x1,x2,x3,se) \
36+strerr_warn((x1),(x2),(x3),0,0,0,(se))
37+#define strerr_warn2(x1,x2,se) \
38+strerr_warn((x1),(x2),0,0,0,0,(se))
39+#define strerr_warn1(x1,se) \
40+strerr_warn((x1),0,0,0,0,0,(se))
41+
42+#define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \
43+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(se))
44+#define strerr_die5(e,x1,x2,x3,x4,x5,se) \
45+strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,(se))
46+#define strerr_die4(e,x1,x2,x3,x4,se) \
47+strerr_die((e),(x1),(x2),(x3),(x4),0,0,(se))
48+#define strerr_die3(e,x1,x2,x3,se) \
49+strerr_die((e),(x1),(x2),(x3),0,0,0,(se))
50+#define strerr_die2(e,x1,x2,se) \
51+strerr_die((e),(x1),(x2),0,0,0,0,(se))
52+#define strerr_die1(e,x1,se) \
53+strerr_die((e),(x1),0,0,0,0,0,(se))
54+
55+#define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \
56+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys)
57+#define strerr_die5sys(e,x1,x2,x3,x4,x5) \
58+strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,&strerr_sys)
59+#define strerr_die4sys(e,x1,x2,x3,x4) \
60+strerr_die((e),(x1),(x2),(x3),(x4),0,0,&strerr_sys)
61+#define strerr_die3sys(e,x1,x2,x3) \
62+strerr_die((e),(x1),(x2),(x3),0,0,0,&strerr_sys)
63+#define strerr_die2sys(e,x1,x2) \
64+strerr_die((e),(x1),(x2),0,0,0,0,&strerr_sys)
65+#define strerr_die1sys(e,x1) \
66+strerr_die((e),(x1),0,0,0,0,0,&strerr_sys)
67+
68+#define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \
69+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),0)
70+#define strerr_die5x(e,x1,x2,x3,x4,x5) \
71+strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,0)
72+#define strerr_die4x(e,x1,x2,x3,x4) \
73+strerr_die((e),(x1),(x2),(x3),(x4),0,0,0)
74+#define strerr_die3x(e,x1,x2,x3) \
75+strerr_die((e),(x1),(x2),(x3),0,0,0,0)
76+#define strerr_die2x(e,x1,x2) \
77+strerr_die((e),(x1),(x2),0,0,0,0,0)
78+#define strerr_die1x(e,x1) \
79+strerr_die((e),(x1),0,0,0,0,0,0)
80+
81+#endif
+33, -0
 1@@ -0,0 +1,33 @@
 2+/* Public domain. */
 3+
 4+#include <unistd.h>
 5+#include "buffer.h"
 6+#include "strerr.h"
 7+
 8+void strerr_warn(const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,const struct strerr *se)
 9+{
10+  strerr_sysinit();
11+ 
12+  if (x1) buffer_puts(buffer_2,x1);
13+  if (x2) buffer_puts(buffer_2,x2);
14+  if (x3) buffer_puts(buffer_2,x3);
15+  if (x4) buffer_puts(buffer_2,x4);
16+  if (x5) buffer_puts(buffer_2,x5);
17+  if (x6) buffer_puts(buffer_2,x6);
18+ 
19+  while(se) {
20+    if (se->x) buffer_puts(buffer_2,se->x);
21+    if (se->y) buffer_puts(buffer_2,se->y);
22+    if (se->z) buffer_puts(buffer_2,se->z);
23+    se = se->who;
24+  }
25+ 
26+  buffer_puts(buffer_2,"\n");
27+  buffer_flush(buffer_2);
28+}
29+
30+void strerr_die(int e,const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,const struct strerr *se)
31+{
32+  strerr_warn(x1,x2,x3,x4,x5,x6,se);
33+  _exit(e);
34+}
+14, -0
 1@@ -0,0 +1,14 @@
 2+/* Public domain. */
 3+
 4+#include "error.h"
 5+#include "strerr.h"
 6+
 7+struct strerr strerr_sys;
 8+
 9+void strerr_sysinit(void)
10+{
11+  strerr_sys.who = 0;
12+  strerr_sys.x = error_str(errno);
13+  strerr_sys.y = "";
14+  strerr_sys.z = "";
15+}
+67, -0
 1@@ -0,0 +1,67 @@
 2+/* Public domain. */
 3+
 4+#define SUBGETOPTNOSHORT
 5+#include "subgetopt.h"
 6+
 7+#define sgopt subgetopt
 8+#define optind subgetoptind
 9+#define optpos subgetoptpos
10+#define optarg subgetoptarg
11+#define optproblem subgetoptproblem
12+#define optdone subgetoptdone
13+
14+int optind = 1;
15+int optpos = 0;
16+const char *optarg = 0;
17+int optproblem = 0;
18+int optdone = SUBGETOPTDONE;
19+
20+int sgopt(int argc,const char *const *argv,const char *opts)
21+{
22+  int c;
23+  const char *s;
24+
25+  optarg = 0;
26+  if (!argv || (optind >= argc) || !argv[optind]) return optdone;
27+  if (optpos && !argv[optind][optpos]) {
28+    ++optind;
29+    optpos = 0;
30+    if ((optind >= argc) || !argv[optind]) return optdone;
31+  }
32+  if (!optpos) {
33+    if (argv[optind][0] != '-') return optdone;
34+    ++optpos;
35+    c = argv[optind][1];
36+    if ((c == '-') || (c == 0)) {
37+      if (c) ++optind;
38+      optpos = 0;
39+      return optdone;
40+    }
41+    /* otherwise c is reassigned below */
42+  }
43+  c = argv[optind][optpos];
44+  ++optpos;
45+  s = opts;
46+  while (*s) {
47+    if (c == *s) {
48+      if (s[1] == ':') {
49+        optarg = argv[optind] + optpos;
50+        ++optind;
51+        optpos = 0;
52+        if (!*optarg) {
53+          optarg = argv[optind];
54+          if ((optind >= argc) || !optarg) { /* argument past end */
55+            optproblem = c;
56+            return '?';
57+          }
58+	  ++optind;
59+        }
60+      }
61+      return c;
62+    }
63+    ++s;
64+    if (*s == ':') ++s;
65+  }
66+  optproblem = c;
67+  return '?';
68+}
+26, -0
 1@@ -0,0 +1,26 @@
 2+/* Public domain. */
 3+
 4+#ifndef SUBGETOPT_H
 5+#define SUBGETOPT_H
 6+
 7+#ifndef SUBGETOPTNOSHORT
 8+#define sgopt subgetopt
 9+#define sgoptarg subgetoptarg
10+#define sgoptind subgetoptind
11+#define sgoptpos subgetoptpos
12+#define sgoptproblem subgetoptproblem
13+#define sgoptprogname subgetoptprogname
14+#define sgoptdone subgetoptdone
15+#endif
16+
17+#define SUBGETOPTDONE -1
18+
19+extern int subgetopt(int,const char *const *,const char *);
20+extern const char *subgetoptarg;
21+extern int subgetoptind;
22+extern int subgetoptpos;
23+extern int subgetoptproblem;
24+extern const char *subgetoptprogname;
25+extern int subgetoptdone;
26+
27+#endif
+87, -0
 1@@ -0,0 +1,87 @@
 2+build shared/error.o: cc shared/error.c
 3+  cflags = $base_cflags -Ishared
 4+build shared/error_str.o: cc shared/error_str.c
 5+  cflags = $base_cflags -Ishared
 6+build shared/alloc.o: cc shared/alloc.c
 7+  cflags = $base_cflags -Ishared
 8+build shared/alloc_re.o: cc shared/alloc_re.c
 9+  cflags = $base_cflags -Ishared
10+build shared/buffer.o: cc shared/buffer.c
11+  cflags = $base_cflags -Ishared
12+build shared/buffer_get.o: cc shared/buffer_get.c
13+  cflags = $base_cflags -Ishared
14+build shared/buffer_put.o: cc shared/buffer_put.c
15+  cflags = $base_cflags -Ishared
16+build shared/buffer_read.o: cc shared/buffer_read.c
17+  cflags = $base_cflags -Ishared
18+build shared/buffer_write.o: cc shared/buffer_write.c
19+  cflags = $base_cflags -Ishared
20+build shared/buffer_0.o: cc shared/buffer_0.c
21+  cflags = $base_cflags -Ishared
22+build shared/buffer_1.o: cc shared/buffer_1.c
23+  cflags = $base_cflags -Ishared
24+build shared/buffer_2.o: cc shared/buffer_2.c
25+  cflags = $base_cflags -Ishared
26+build shared/byte_chr.o: cc shared/byte_chr.c
27+  cflags = $base_cflags -Ishared
28+build shared/byte_copy.o: cc shared/byte_copy.c
29+  cflags = $base_cflags -Ishared
30+build shared/byte_cr.o: cc shared/byte_cr.c
31+  cflags = $base_cflags -Ishared
32+build shared/byte_diff.o: cc shared/byte_diff.c
33+  cflags = $base_cflags -Ishared
34+build shared/byte_rchr.o: cc shared/byte_rchr.c
35+  cflags = $base_cflags -Ishared
36+build shared/byte_zero.o: cc shared/byte_zero.c
37+  cflags = $base_cflags -Ishared
38+build shared/fmt_ulong.o: cc shared/fmt_ulong.c
39+  cflags = $base_cflags -Ishared
40+build shared/fmt_uint.o: cc shared/fmt_uint.c
41+  cflags = $base_cflags -Ishared
42+build shared/fmt_uint0.o: cc shared/fmt_uint0.c
43+  cflags = $base_cflags -Ishared
44+build shared/str_len.o: cc shared/str_len.c
45+  cflags = $base_cflags -Ishared
46+build shared/str_chr.o: cc shared/str_chr.c
47+  cflags = $base_cflags -Ishared
48+build shared/str_diff.o: cc shared/str_diff.c
49+  cflags = $base_cflags -Ishared
50+build shared/str_start.o: cc shared/str_start.c
51+  cflags = $base_cflags -Ishared
52+build shared/scan_ulong.o: cc shared/scan_ulong.c
53+  cflags = $base_cflags -Ishared
54+build shared/stralloc_eady.o: cc shared/stralloc_eady.c
55+  cflags = $base_cflags -Ishared
56+build shared/stralloc_opyb.o: cc shared/stralloc_opyb.c
57+  cflags = $base_cflags -Ishared
58+build shared/stralloc_catb.o: cc shared/stralloc_catb.c
59+  cflags = $base_cflags -Ishared
60+build shared/stralloc_cats.o: cc shared/stralloc_cats.c
61+  cflags = $base_cflags -Ishared
62+build shared/stralloc_pend.o: cc shared/stralloc_pend.c
63+  cflags = $base_cflags -Ishared
64+build shared/stralloc_opys.o: cc shared/stralloc_opys.c
65+  cflags = $base_cflags -Ishared
66+build shared/stralloc_cat.o: cc shared/stralloc_cat.c
67+  cflags = $base_cflags -Ishared
68+build shared/sgetopt.o: cc shared/sgetopt.c
69+  cflags = $base_cflags -Ishared
70+build shared/subgetopt.o: cc shared/subgetopt.c
71+  cflags = $base_cflags -Ishared
72+build shared/readclose.o: cc shared/readclose.c
73+  cflags = $base_cflags -Ishared
74+build shared/open_read.o: cc shared/open_read.c
75+  cflags = $base_cflags -Ishared
76+build shared/openreadclose.o: cc shared/openreadclose.c
77+  cflags = $base_cflags -Ishared
78+build shared/strerr_die.o: cc shared/strerr_die.c
79+  cflags = $base_cflags -Ishared
80+build shared/strerr_sys.o: cc shared/strerr_sys.c
81+  cflags = $base_cflags -Ishared
82+build shared/wait_pid.o: cc shared/wait_pid.c
83+  cflags = $base_cflags -Ishared
84+build shared/wait_nohang.o: cc shared/wait_nohang.c
85+  cflags = $base_cflags -Ishared
86+
87+build shared/libdjb.a: ar shared/error.o shared/error_str.o shared/alloc.o shared/alloc_re.o shared/buffer.o shared/buffer_get.o shared/buffer_put.o shared/buffer_read.o shared/buffer_write.o shared/buffer_0.o shared/buffer_1.o shared/buffer_2.o shared/byte_chr.o shared/byte_copy.o shared/byte_cr.o shared/byte_diff.o shared/byte_rchr.o shared/byte_zero.o shared/fmt_ulong.o shared/fmt_uint.o shared/fmt_uint0.o shared/str_len.o shared/str_chr.o shared/str_diff.o shared/str_start.o shared/scan_ulong.o shared/stralloc_eady.o shared/stralloc_opyb.o shared/stralloc_catb.o shared/stralloc_cats.o shared/stralloc_pend.o shared/stralloc_opys.o shared/stralloc_cat.o shared/sgetopt.o shared/subgetopt.o shared/readclose.o shared/open_read.o shared/openreadclose.o shared/strerr_die.o shared/strerr_sys.o shared/wait_pid.o shared/wait_nohang.o
88+build shared-all: phony shared/libdjb.a
+16, -0
 1@@ -0,0 +1,16 @@
 2+/* Public domain. */
 3+
 4+#ifndef WAIT_H
 5+#define WAIT_H
 6+
 7+extern int wait_pid();
 8+extern int wait_nohang();
 9+extern int wait_stop();
10+extern int wait_stopnohang();
11+
12+#define wait_crashed(w) ((w) & 127)
13+#define wait_exitcode(w) ((w) >> 8)
14+#define wait_stopsig(w) ((w) >> 8)
15+#define wait_stopped(w) (((w) & 127) == 127)
16+
17+#endif
+14, -0
 1@@ -0,0 +1,14 @@
 2+/* Public domain. */
 3+
 4+#include <sys/types.h>
 5+#include <sys/wait.h>
 6+#include "haswaitp.h"
 7+
 8+int wait_nohang(wstat) int *wstat;
 9+{
10+#ifdef HASWAITPID
11+  return waitpid(-1,wstat,WNOHANG);
12+#else
13+  return wait3(wstat,WNOHANG,(struct rusage *) 0);
14+#endif
15+}
+41, -0
 1@@ -0,0 +1,41 @@
 2+/* Public domain. */
 3+
 4+#include <sys/types.h>
 5+#include <sys/wait.h>
 6+#include "error.h"
 7+#include "haswaitp.h"
 8+
 9+#ifdef HASWAITPID
10+
11+int wait_pid(wstat,pid) int *wstat; int pid;
12+{
13+  int r;
14+
15+  do
16+    r = waitpid(pid,wstat,0);
17+  while ((r == -1) && (errno == error_intr));
18+  return r;
19+}
20+
21+#else
22+
23+/* XXX untested */
24+/* XXX breaks down with more than two children */
25+static int oldpid = 0;
26+static int oldwstat; /* defined if(oldpid) */
27+
28+int wait_pid(wstat,pid) int *wstat; int pid;
29+{
30+  int r;
31+
32+  if (pid == oldpid) { *wstat = oldwstat; oldpid = 0; return pid; }
33+
34+  do {
35+    r = wait(wstat);
36+    if ((r != pid) && (r != -1)) { oldwstat = *wstat; oldpid = r; continue; }
37+  }
38+  while ((r == -1) && (errno == error_intr));
39+  return r;
40+}
41+
42+#endif