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
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+}
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
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+}
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+}
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
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 = ⁢
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 = ⁢
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 = ⁢
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+}
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+}
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+}
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+}
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
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+}
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+}
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+}
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+}
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+}
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+}
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
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
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+}
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
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+}
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+}
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+}
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
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
1@@ -0,0 +1,6 @@
2+#ifndef HASWAITP_H
3+#define HASWAITP_H
4+
5+#define HASWAITPID 1
6+
7+#endif
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
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); }
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+}
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
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+}
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
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
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+}
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+}
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
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
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+}
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+}
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+}
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+}
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
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+}
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+}
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+}
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)
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+}
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+}
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)
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
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+}
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+}
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+}
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
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
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
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+}
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