commit c4b4d74
xplshn
·
2026-07-01 01:09:02 +0000 UTC
parent fd3a93f
clang-format, mkpasswd, lsblk, fdisk, blkid, in-process execution, etc Signed-off-by: xplshn <anto@xplshn.com.ar>
M
Makefile
+26,
-14
1@@ -7,6 +7,7 @@ HDR =\
2 shared/compat.h\
3 shared/config.h\
4 shared/crypt.h\
5+ shared/wexec.h\
6 shared/fs.h\
7 shared/md5.h\
8 shared/queue.h\
9@@ -21,6 +22,7 @@ HDR =\
10 shared/utf.h\
11 shared/util.h\
12 shared/passwd.h\
13+ shared/paths.h\
14 shared/reboot.h\
15 shared/rtc.h\
16 shared/proc.h\
17@@ -52,6 +54,8 @@ LIBUTILOBJ =\
18 shared/libutil/cp.o\
19 shared/libutil/crypt.o\
20 shared/libutil/confirm.o\
21+ shared/libutil/diffutil.o\
22+ shared/libutil/wexec.o\
23 shared/libutil/ealloc.o\
24 shared/libutil/enmasse.o\
25 shared/libutil/eprintf.o\
26@@ -734,20 +738,28 @@ man: scripts/mkman/mkman
27 done
28
29 clean:
30- rm -f shared/libutf/*.o shared/libutil/*.o shared/libredline/*.o
31- rm -f cmd/posix/*.o cmd/posix/make/*.o cmd/posix/awk/*.o cmd/posix/sh/*.o
32- rm -f cmd/linux/*.o cmd/net/*.o cmd/xsi/*.o cmd/pseudo/*.o
33- rm -f cmd/extra/*.o cmd/dev/ar/*.o cmd/dev/ld/*.o cmd/dev/cc/*.o cmd/dev/as/*.o cmd/dev/xcutil/*.o
34- rm -f $(POSIX_BIN_ALL) $(LINUX_BIN_ALL) $(NET_BIN_ALL) $(XSI_BIN_ALL) $(PSEUDO_BIN_ALL) $(LIB)
35- rm -f cmd/posix/make/make cmd/posix/getconf.h cmd/posix/bc.c
36- rm -f
37- rm -f cmd/posix/awk/awk cmd/posix/awk/maketab cmd/posix/awk/awkgram.tab.c cmd/posix/awk/awkgram.tab.h cmd/posix/awk/proctab.c
38- rm -f cmd/posix/sh/sh cmd/posix/sh/mknodes cmd/posix/sh/mksyntax
39- rm -f cmd/posix/sh/syntax.c cmd/posix/sh/syntax.h cmd/posix/sh/nodes.c cmd/posix/sh/nodes.h cmd/posix/sh/builtins.c cmd/posix/sh/builtins.h cmd/posix/sh/token.h
40- rm -f cmd/dev/cc/cc1 cmd/dev/cc/cpp cmd/dev/as/as cmd/dev/ld/ld cmd/dev/ar/ar shared/libaruuelf.so
41- rm -f cmd/dev/config.h cmd/dev/cc/config.h cmd/dev/version.h
42- rm -rf aruu-box .box man/man1 man/man8 scripts/mkman/mkman
43-
44+ @printf " CLEAN object files\n"
45+ @find shared cmd -name "*.o" -exec rm -f {} +
46+ @printf " CLEAN static libraries\n"
47+ @rm -f $(LIB)
48+ @printf " CLEAN compiled binaries\n"
49+ @rm -f $(POSIX_BIN_ALL) $(LINUX_BIN_ALL) $(NET_BIN_ALL) $(XSI_BIN_ALL) $(PSEUDO_BIN_ALL)
50+ @printf " CLEAN generated headers\n"
51+ @rm -f cmd/posix/getconf.h cmd/posix/bc.c
52+ @rm -f cmd/posix/awk/awkgram.tab.c cmd/posix/awk/awkgram.tab.h
53+ @rm -f cmd/posix/sh/token.h cmd/posix/sh/syntax.c cmd/posix/sh/syntax.h
54+ @rm -f cmd/posix/sh/nodes.c cmd/posix/sh/nodes.h cmd/posix/sh/builtins.c cmd/posix/sh/builtins.h
55+ @printf " CLEAN generated sources\n"
56+ @rm -f cmd/posix/awk/proctab.c
57+ @printf " CLEAN build tools\n"
58+ @rm -f cmd/posix/awk/maketab cmd/posix/sh/mknodes cmd/posix/sh/mksyntax
59+ @rm -f scripts/mkman/mkman
60+ @printf " CLEAN dev artifacts\n"
61+ @rm -f cmd/dev/cc/cc1 cmd/dev/cc/cpp cmd/dev/as/as cmd/dev/ld/ld cmd/dev/ar/ar shared/libaruuelf.so
62+ @rm -f cmd/dev/config.h cmd/dev/cc/config.h cmd/dev/version.h
63+ @printf " CLEAN misc\n"
64+ @rm -rf aruu-box .box man/man1 man/man8
65+ @printf " CLEAN done\n"
66 AWKOBJ =\
67 cmd/posix/awk/b.o\
68 cmd/posix/awk/main.o\
+406,
-393
1@@ -14,15 +14,15 @@ LOAD=0
2 TARGET=all
3
4 while [ $# -gt 0 ]; do
5- case "$1" in
6- -j) shift; JOBS="${1:?-j requires a number}" ;;
7- -j*) JOBS="${1#-j}" ;;
8- -l) shift; LOAD="${1:?-l requires a number}" ;;
9- -l*) LOAD="${1#-l}" ;;
10- -*) printf 'unknown flag: %s\n' "$1" >&2; exit 1 ;;
11- *) TARGET="$1" ;;
12- esac
13- shift
14+ case "$1" in
15+ -j) shift; JOBS="${1:?-j requires a number}" ;;
16+ -j*) JOBS="${1#-j}" ;;
17+ -l) shift; LOAD="${1:?-l requires a number}" ;;
18+ -l*) LOAD="${1#-l}" ;;
19+ -*) printf 'unknown flag: %s\n' "$1" >&2; exit 1 ;;
20+ *) TARGET="$1" ;;
21+ esac
22+ shift
23 done
24
25 [ -f build.cfg ] || { printf 'build.cfg not found; see the repository README\n' >&2; exit 1; }
26@@ -32,45 +32,45 @@ done
27 # cppflags derived from build.cfg; any feature_* added there is picked up automatically
28 _feature_flags=""
29 while IFS= read -r _line; do
30- _trimmed=$(printf '%s' "$_line" | tr -d ' \t')
31- case "$_trimmed" in
32- FEATURE_*=*)
33- _key=${_trimmed%%=*}
34- eval "_val=\$$_key"
35- _feature_flags="$_feature_flags -D${_key}=${_val}"
36- ;;
37- esac
38+ _trimmed=$(printf '%s' "$_line" | tr -d ' \t')
39+ case "$_trimmed" in
40+ FEATURE_*=*)
41+ _key=${_trimmed%%=*}
42+ eval "_val=\$$_key"
43+ _feature_flags="$_feature_flags -D${_key}=${_val}"
44+ ;;
45+ esac
46 done <<EOF
47 $(tr ';' '\n' < build.cfg)
48 EOF
49 unset _line _key _val _trimmed
50 CPPFLAGS="-Ishared -DPREFIX=\"$PREFIX\" -D_DEFAULT_SOURCE -D_GNU_SOURCE -D_NETBSD_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_FILE_OFFSET_BITS=64$_feature_flags"
51 if [ "$FEATURE_USE_BEARSSL" = "1" ]; then
52- if pkg-config --exists libbearssl 2>/dev/null; then
53- CPPFLAGS="$CPPFLAGS $(pkg-config --cflags libbearssl)"
54- TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs libbearssl)"
55- elif pkg-config --exists bearssl 2>/dev/null; then
56- CPPFLAGS="$CPPFLAGS $(pkg-config --cflags bearssl)"
57- TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs bearssl)"
58- else
59- TLS_LDLIBS="$TLS_LDLIBS -LexternalRepos/BearSSL/build -lbearssl"
60- fi
61+ if pkg-config --exists libbearssl 2>/dev/null; then
62+ CPPFLAGS="$CPPFLAGS $(pkg-config --cflags libbearssl)"
63+ TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs libbearssl)"
64+ elif pkg-config --exists bearssl 2>/dev/null; then
65+ CPPFLAGS="$CPPFLAGS $(pkg-config --cflags bearssl)"
66+ TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs bearssl)"
67+ else
68+ TLS_LDLIBS="$TLS_LDLIBS -LexternalRepos/BearSSL/build -lbearssl"
69+ fi
70 fi
71 if [ "$FEATURE_USE_LIBRESSL" = "1" ]; then
72- if pkg-config --exists libtls 2>/dev/null; then
73- CPPFLAGS="$CPPFLAGS $(pkg-config --cflags libtls)"
74- TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs libtls)"
75- else
76- TLS_LDLIBS="$TLS_LDLIBS -ltls"
77- fi
78+ if pkg-config --exists libtls 2>/dev/null; then
79+ CPPFLAGS="$CPPFLAGS $(pkg-config --cflags libtls)"
80+ TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs libtls)"
81+ else
82+ TLS_LDLIBS="$TLS_LDLIBS -ltls"
83+ fi
84 fi
85 if [ "$FEATURE_USE_OPENSSL" = "1" ]; then
86- if pkg-config --exists openssl 2>/dev/null; then
87- CPPFLAGS="$CPPFLAGS $(pkg-config --cflags openssl)"
88- TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs openssl)"
89- else
90- TLS_LDLIBS="$TLS_LDLIBS -lssl -lcrypto"
91- fi
92+ if pkg-config --exists openssl 2>/dev/null; then
93+ CPPFLAGS="$CPPFLAGS $(pkg-config --cflags openssl)"
94+ TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs openssl)"
95+ else
96+ TLS_LDLIBS="$TLS_LDLIBS -lssl -lcrypto"
97+ fi
98 fi
99 unset _feature_flags
100
101@@ -91,22 +91,22 @@ EXTRA_HDR=
102 # timestamp comparison
103 #
104 mtime() {
105- stat -c '%Y' "$1" 2>/dev/null || stat -f '%m' "$1" 2>/dev/null || echo 0
106+ stat -c '%Y' "$1" 2>/dev/null || stat -f '%m' "$1" 2>/dev/null || echo 0
107 }
108
109 newer_than() {
110- local s t
111- [ -e "$2" ] || return 0
112- s=$(mtime "$1"); t=$(mtime "$2")
113- [ "$s" -gt "$t" ]
114+ local s t
115+ [ -e "$2" ] || return 0
116+ s=$(mtime "$1"); t=$(mtime "$2")
117+ [ "$s" -gt "$t" ]
118 }
119
120 any_newer_than() {
121- local target="$1"; shift
122- for src do
123- newer_than "$src" "$target" && return 0
124- done
125- return 1
126+ local target="$1"; shift
127+ for src do
128+ newer_than "$src" "$target" && return 0
129+ done
130+ return 1
131 }
132
133 # parallel job queue
134@@ -119,441 +119,454 @@ _objs=""
135
136 # wraps arg in single quotes, escaping embedded ones, for safe eval
137 shquote() {
138- printf "'"
139- printf '%s' "$1" | sed "s/'/'\\\\''/g"
140- printf "'"
141+ printf "'"
142+ printf '%s' "$1" | sed "s/'/'\\\\''/g"
143+ printf "'"
144 }
145
146 enqueue() {
147- local desc="$1" cmd="$2"
148- _qn=$((_qn + 1))
149- local s="$WORKDIR/j${_qn}.sh"
150- {
151- printf '#!/bin/sh\n'
152- printf 'printf "%%s\\n" %s\n' "$(shquote "$desc")"
153- printf 'eval %s\n' "$(shquote "$cmd")"
154- } > "$s"
155- _queue="$_queue $_qn"
156+ local desc="$1" cmd="$2"
157+ _qn=$((_qn + 1))
158+ local s="$WORKDIR/j${_qn}.sh"
159+ {
160+ printf '#!/bin/sh\n'
161+ printf 'printf "%%s\\n" %s\n' "$(shquote "$desc")"
162+ printf 'eval %s\n' "$(shquote "$cmd")"
163+ } > "$s"
164+ _queue="$_queue $_qn"
165 }
166
167 # silently skipped on systems without /proc/loadavg
168 _wait_for_load() {
169- [ "$LOAD" -eq 0 ] && return 0
170- local avg
171- while true; do
172- avg=$(awk '{printf "%d", int($1 + 0.5)}' /proc/loadavg 2>/dev/null) || return 0
173- [ "$avg" -le "$LOAD" ] && return 0
174- sleep 1
175- done
176+ [ "$LOAD" -eq 0 ] && return 0
177+ local avg
178+ while true; do
179+ avg=$(awk '{printf "%d", int($1 + 0.5)}' /proc/loadavg 2>/dev/null) || return 0
180+ [ "$avg" -le "$LOAD" ] && return 0
181+ sleep 1
182+ done
183 }
184
185 drain() {
186- [ -z "$_queue" ] && return 0
187- local n
188- _wait_for_load
189- if [ "$JOBS" -le 1 ]; then
190- for n in $_queue; do
191- sh "$WORKDIR/j${n}.sh" || { printf 'error: build step failed\n' >&2; exit 1; }
192- done
193- else
194- # xargs -P (POSIX 2024), -n 1 so each path becomes its own sh invocation
195- for n in $_queue; do
196- printf '%s\n' "$WORKDIR/j${n}.sh"
197- done | xargs -P "$JOBS" -n 1 sh || { printf 'error: build step failed\n' >&2; exit 1; }
198- fi
199- _queue=""
200+ [ -z "$_queue" ] && return 0
201+ local n
202+ _wait_for_load
203+ if [ "$JOBS" -le 1 ]; then
204+ for n in $_queue; do
205+ sh "$WORKDIR/j${n}.sh" || { printf 'error: build step failed\n' >&2; exit 1; }
206+ done
207+ else
208+ # xargs -P (POSIX 2024), -n 1 so each path becomes its own sh invocation
209+ for n in $_queue; do
210+ printf '%s\n' "$WORKDIR/j${n}.sh"
211+ done | xargs -P "$JOBS" -n 1 sh || { printf 'error: build step failed\n' >&2; exit 1; }
212+ fi
213+ _queue=""
214 }
215
216 # compile and link primitives
217 #
218 compile_c() {
219- local src="$1" obj="$2"; shift 2
220- # shellcheck disable=SC2086
221- any_newer_than "$obj" "$src" $HDR $EXTRA_HDR || return 0
222- enqueue " CC $obj" "$CC $* $CPPFLAGS $CFLAGS -o $obj -c $src"
223+ local src="$1" obj="$2"; shift 2
224+ # shellcheck disable=SC2086
225+ any_newer_than "$obj" "$src" $HDR $EXTRA_HDR || return 0
226+ enqueue " CC $obj" "$CC $* $CPPFLAGS $CFLAGS -o $obj -c $src"
227 }
228
229 link_bin() {
230- local bin="$1" objs="" libs="" sep=0; shift
231- for a do
232- if [ "$a" = "--" ]; then sep=1
233- elif [ "$sep" = 0 ]; then objs="$objs $a"
234- else libs="$libs $a"
235- fi
236- done
237- drain
238- # shellcheck disable=SC2086
239- any_newer_than "$bin" $objs || return 0
240- printf ' LD %s\n' "$bin"
241- # shellcheck disable=SC2086
242- if [ "${bin##*/}" = "wget" ]; then
243- eval "$CC $LDFLAGS -o $bin $objs $libs $LDLIBS $TLS_LDLIBS"
244- else
245- eval "$CC $LDFLAGS -o $bin $objs $libs $LDLIBS"
246- fi
247+ local bin="$1" objs="" libs="" sep=0; shift
248+ for a do
249+ if [ "$a" = "--" ]; then sep=1
250+ elif [ "$sep" = 0 ]; then objs="$objs $a"
251+ else libs="$libs $a"
252+ fi
253+ done
254+ drain
255+ # shellcheck disable=SC2086
256+ any_newer_than "$bin" $objs || return 0
257+ printf ' LD %s\n' "$bin"
258+ # shellcheck disable=SC2086
259+ if [ "${bin##*/}" = "wget" ]; then
260+ eval "$CC $LDFLAGS -o $bin $objs $libs $LDLIBS $TLS_LDLIBS"
261+ else
262+ eval "$CC $LDFLAGS -o $bin $objs $libs $LDLIBS"
263+ fi
264 }
265
266 # writes to _objs rather than stdout so the caller avoids a subshell that
267 # would discard enqueued jobs
268 objs_for() {
269- local dir="$1" skip=" $2 " flags="$3" src base
270- _objs=""
271- for src in "$dir"/*.c; do
272- [ -f "$src" ] || continue
273- base=${src##*/}
274- case "$skip" in *" $base "*) continue ;; esac
275- compile_c "$src" "${src%.c}.o" $flags
276- _objs="$_objs ${src%.c}.o"
277- done
278+ local dir="$1" skip=" $2 " flags="$3" src base
279+ _objs=""
280+ for src in "$dir"/*.c; do
281+ [ -f "$src" ] || continue
282+ base=${src##*/}
283+ case "$skip" in *" $base "*) continue ;; esac
284+ compile_c "$src" "${src%.c}.o" $flags
285+ _objs="$_objs ${src%.c}.o"
286+ done
287 }
288
289 # static libraries
290 #
291 # both directories enqueued before the single drain so they compile in parallel
292 build_lib() {
293- local utf_objs util_objs redline_objs
294- objs_for shared/libutf "" ""
295- utf_objs="$_objs"
296- objs_for shared/libutil "" ""
297- util_objs="$_objs"
298- objs_for shared/libredline "" ""
299- redline_objs="$_objs"
300- drain
301- # shellcheck disable=SC2086
302- any_newer_than shared/libutf/libutf.a $utf_objs && {
303- printf ' AR shared/libutf/libutf.a\n'
304- $AR $ARFLAGS shared/libutf/libutf.a $utf_objs
305- $RANLIB shared/libutf/libutf.a
306- }
307- # shellcheck disable=SC2086
308- any_newer_than shared/libutil/libutil.a $util_objs && {
309- printf ' AR shared/libutil/libutil.a\n'
310- $AR $ARFLAGS shared/libutil/libutil.a $util_objs
311- $RANLIB shared/libutil/libutil.a
312- }
313- # shellcheck disable=SC2086
314- any_newer_than shared/libredline/libredline.a $redline_objs && {
315- printf ' AR shared/libredline/libredline.a\n'
316- $AR $ARFLAGS shared/libredline/libredline.a $redline_objs
317- $RANLIB shared/libredline/libredline.a
318- }
319- return 0
320+ local utf_objs util_objs redline_objs
321+ objs_for shared/libutf "" ""
322+ utf_objs="$_objs"
323+ objs_for shared/libutil "" ""
324+ util_objs="$_objs"
325+ objs_for shared/libredline "" ""
326+ redline_objs="$_objs"
327+ drain
328+ # shellcheck disable=SC2086
329+ any_newer_than shared/libutf/libutf.a $utf_objs && {
330+ printf ' AR shared/libutf/libutf.a\n'
331+ $AR $ARFLAGS shared/libutf/libutf.a $utf_objs
332+ $RANLIB shared/libutf/libutf.a
333+ }
334+ # shellcheck disable=SC2086
335+ any_newer_than shared/libutil/libutil.a $util_objs && {
336+ printf ' AR shared/libutil/libutil.a\n'
337+ $AR $ARFLAGS shared/libutil/libutil.a $util_objs
338+ $RANLIB shared/libutil/libutil.a
339+ }
340+ # shellcheck disable=SC2086
341+ any_newer_than shared/libredline/libredline.a $redline_objs && {
342+ printf ' AR shared/libredline/libredline.a\n'
343+ $AR $ARFLAGS shared/libredline/libredline.a $redline_objs
344+ $RANLIB shared/libredline/libredline.a
345+ }
346+ return 0
347 }
348
349 # per-tool category builder
350 #
351 cfgvar() {
352- local cat="$1" base="$2"
353- [ "$cat" = extra ] && cat=pseudo
354- printf 'BUILD_%s_%s' "$cat" "$base" | tr 'a-z-' 'A-Z_'
355+ local cat="$1" base="$2"
356+ [ "$cat" = extra ] && cat=pseudo
357+ printf 'BUILD_%s_%s' "$cat" "$base" | tr 'a-z-' 'A-Z_'
358 }
359
360 # individual flag overrides group flag
361 cfg_enabled() {
362- local _var="$1" _v
363- while [ -n "$_var" ]; do
364- eval "_v=\${${_var}-UNSET}"
365- if [ "$_v" = "1" ]; then
366- return 0
367- elif [ "$_v" = "0" ]; then
368- return 1
369- fi
370- case "$_var" in
371- *_[!_]*) _var=$(printf '%s' "$_var" | sed 's/_[^_]*$//') ;;
372- *) break ;;
373- esac
374- done
375- return 1
376+ local _var="$1" _v
377+ while [ -n "$_var" ]; do
378+ eval "_v=\${${_var}-UNSET}"
379+ if [ "$_v" = "1" ]; then
380+ return 0
381+ elif [ "$_v" = "0" ]; then
382+ return 1
383+ fi
384+ case "$_var" in
385+ *_[!_]*) _var=$(printf '%s' "$_var" | sed 's/_[^_]*$//') ;;
386+ *) break ;;
387+ esac
388+ done
389+ return 1
390 }
391
392 build_simple_tools() {
393- local cat="$1" src base var staged=""
394- for src in cmd/"$cat"/*.c; do
395- [ -f "$src" ] || continue
396- base=${src##*/}; base=${base%.c}
397- var=$(cfgvar "$cat" "$base")
398- cfg_enabled "$var" || continue
399- compile_c "$src" "${src%.c}.o"
400- staged="$staged ${src%.c}"
401- done
402- drain
403- local bin
404- for bin in $staged; do
405- if [ "${bin##*/}" = "diff" ]; then
406- link_bin "$bin" "${bin}.o" -- $LIB -lm
407- else
408- link_bin "$bin" "${bin}.o" -- $LIB
409- fi
410- done
411+ local cat="$1" src base var staged=""
412+ for src in cmd/"$cat"/*.c; do
413+ [ -f "$src" ] || continue
414+ base=${src##*/}; base=${base%.c}
415+ var=$(cfgvar "$cat" "$base")
416+ cfg_enabled "$var" || continue
417+ compile_c "$src" "${src%.c}.o"
418+ staged="$staged ${src%.c}"
419+ done
420+ drain
421+ local bin
422+ for bin in $staged; do
423+ if [ "${bin##*/}" = "diff" ]; then
424+ link_bin "$bin" "${bin}.o" -- $LIB -lm
425+ else
426+ link_bin "$bin" "${bin}.o" -- $LIB
427+ fi
428+ done
429 }
430
431 build_awk() {
432- cfg_enabled BUILD_POSIX_AWK || return 0
433- local dir=cmd/posix/awk
434-
435- any_newer_than "$dir/awkgram.tab.c" "$dir/awkgram.y" && {
436- if command -v yacc >/dev/null 2>&1; then
437- printf ' YACC %s/awkgram.tab.c\n' "$dir"
438- yacc -d -o "$dir/awkgram.tab.c" "$dir/awkgram.y"
439- if [ ! -f "$dir/awkgram.tab.h" ]; then
440- if [ -f y.tab.h ]; then
441- mv y.tab.h "$dir/awkgram.tab.h"
442- elif [ -f "$dir/y.tab.h" ]; then
443- mv "$dir/y.tab.h" "$dir/awkgram.tab.h"
444- fi
445- fi
446- elif command -v bison >/dev/null 2>&1; then
447- printf ' BISON %s/awkgram.tab.c\n' "$dir"
448- bison -d -o "$dir/awkgram.tab.c" "$dir/awkgram.y"
449- else
450- printf 'awk: no yacc/bison; using pre-generated awkgram.tab.c\n' >&2
451- fi
452- }
453-
454- any_newer_than "$dir/maketab" "$dir/maketab.c" "$dir/awkgram.tab.h" && {
455- printf ' CC %s/maketab\n' "$dir"
456- eval "$CC $CFLAGS -o $dir/maketab $dir/maketab.c"
457- }
458-
459- any_newer_than "$dir/proctab.c" "$dir/maketab" && {
460- printf ' GEN %s/proctab.c\n' "$dir"
461- "$dir/maketab" "$dir/awkgram.tab.h" > "$dir/proctab.c"
462- }
463-
464- EXTRA_HDR="$dir/awk.h $dir/awkgram.tab.h $dir/proto.h"
465- objs_for "$dir" maketab.c "-I$dir"
466- EXTRA_HDR=
467- link_bin "$dir/awk" $_objs -- $LIB -lm
468+ cfg_enabled BUILD_POSIX_AWK || return 0
469+ local dir=cmd/posix/awk
470+
471+ any_newer_than "$dir/awkgram.tab.c" "$dir/awkgram.y" && {
472+ if command -v yacc >/dev/null 2>&1; then
473+ printf ' YACC %s/awkgram.tab.c\n' "$dir"
474+ yacc -d -o "$dir/awkgram.tab.c" "$dir/awkgram.y"
475+ if [ ! -f "$dir/awkgram.tab.h" ]; then
476+ if [ -f y.tab.h ]; then
477+ mv y.tab.h "$dir/awkgram.tab.h"
478+ elif [ -f "$dir/y.tab.h" ]; then
479+ mv "$dir/y.tab.h" "$dir/awkgram.tab.h"
480+ fi
481+ fi
482+ elif command -v bison >/dev/null 2>&1; then
483+ printf ' BISON %s/awkgram.tab.c\n' "$dir"
484+ bison -d -o "$dir/awkgram.tab.c" "$dir/awkgram.y"
485+ else
486+ printf 'awk: no yacc/bison; using pre-generated awkgram.tab.c\n' >&2
487+ fi
488+ }
489+
490+ any_newer_than "$dir/maketab" "$dir/maketab.c" "$dir/awkgram.tab.h" && {
491+ printf ' CC %s/maketab\n' "$dir"
492+ eval "$CC $CFLAGS -o $dir/maketab $dir/maketab.c"
493+ }
494+
495+ any_newer_than "$dir/proctab.c" "$dir/maketab" && {
496+ printf ' GEN %s/proctab.c\n' "$dir"
497+ "$dir/maketab" "$dir/awkgram.tab.h" > "$dir/proctab.c"
498+ }
499+
500+ EXTRA_HDR="$dir/awk.h $dir/awkgram.tab.h $dir/proto.h"
501+ objs_for "$dir" maketab.c "-I$dir"
502+ EXTRA_HDR=
503+ link_bin "$dir/awk" $_objs -- $LIB -lm
504 }
505
506 build_sh() {
507- cfg_enabled BUILD_POSIX_SH || return 0
508- local dir=cmd/posix/sh
509-
510- any_newer_than "$dir/mknodes" "$dir/mknodes.c" && {
511- printf ' CC %s/mknodes\n' "$dir"
512- eval "$CC $CFLAGS -o $dir/mknodes $dir/mknodes.c"
513- }
514-
515- any_newer_than "$dir/mksyntax" "$dir/mksyntax.c" && {
516- printf ' CC %s/mksyntax\n' "$dir"
517- eval "$CC $CPPFLAGS -I$dir $CFLAGS -o $dir/mksyntax $dir/mksyntax.c"
518- }
519-
520- any_newer_than "$dir/token.h" "$dir/mktokens" && {
521- printf ' GEN %s/token.h\n' "$dir"
522- (cd "$dir" && sh mktokens)
523- }
524-
525- any_newer_than "$dir/syntax.c" "$dir/mksyntax" && {
526- printf ' GEN %s/syntax.c\n' "$dir"
527- (cd "$dir" && ./mksyntax)
528- }
529-
530- any_newer_than "$dir/nodes.c" "$dir/mknodes" "$dir/nodetypes" "$dir/nodes.c.pat" && {
531- printf ' GEN %s/nodes.c\n' "$dir"
532- (cd "$dir" && ./mknodes nodetypes nodes.c.pat)
533- }
534-
535- any_newer_than "$dir/builtins.c" "$dir/mkbuiltins" "$dir/builtins.def" "$dir/shell.h" && {
536- printf ' GEN %s/builtins.c\n' "$dir"
537- (cd "$dir" && sh mkbuiltins .)
538- }
539-
540- EXTRA_HDR="$dir/syntax.h $dir/nodes.h $dir/builtins.h $dir/token.h"
541- objs_for "$dir" "mknodes.c mksyntax.c" "-DSHELL -I$dir"
542- EXTRA_HDR=
543- link_bin "$dir/sh" $_objs -- $LIB
544+ cfg_enabled BUILD_POSIX_SH || return 0
545+ local dir=cmd/posix/sh
546+
547+ any_newer_than "$dir/mknodes" "$dir/mknodes.c" && {
548+ printf ' CC %s/mknodes\n' "$dir"
549+ eval "$CC $CFLAGS -o $dir/mknodes $dir/mknodes.c"
550+ }
551+
552+ any_newer_than "$dir/mksyntax" "$dir/mksyntax.c" && {
553+ printf ' CC %s/mksyntax\n' "$dir"
554+ eval "$CC $CPPFLAGS -I$dir $CFLAGS -o $dir/mksyntax $dir/mksyntax.c"
555+ }
556+
557+ any_newer_than "$dir/token.h" "$dir/mktokens" && {
558+ printf ' GEN %s/token.h\n' "$dir"
559+ (cd "$dir" && sh mktokens)
560+ }
561+
562+ any_newer_than "$dir/syntax.c" "$dir/mksyntax" && {
563+ printf ' GEN %s/syntax.c\n' "$dir"
564+ (cd "$dir" && ./mksyntax)
565+ }
566+
567+ any_newer_than "$dir/nodes.c" "$dir/mknodes" "$dir/nodetypes" "$dir/nodes.c.pat" && {
568+ printf ' GEN %s/nodes.c\n' "$dir"
569+ (cd "$dir" && ./mknodes nodetypes nodes.c.pat)
570+ }
571+
572+ any_newer_than "$dir/builtins.c" "$dir/mkbuiltins" "$dir/builtins.def" "$dir/shell.h" && {
573+ printf ' GEN %s/builtins.c\n' "$dir"
574+ (cd "$dir" && sh mkbuiltins .)
575+ }
576+
577+ EXTRA_HDR="$dir/syntax.h $dir/nodes.h $dir/builtins.h $dir/token.h"
578+ objs_for "$dir" "mknodes.c mksyntax.c" "-DSHELL -I$dir"
579+ EXTRA_HDR=
580+ link_bin "$dir/sh" $_objs -- $LIB
581 }
582
583 build_make() {
584- cfg_enabled BUILD_POSIX_MAKE || return 0
585- local dir=cmd/posix/make
586- EXTRA_HDR="$dir/make.h"
587- objs_for "$dir" "" ""
588- EXTRA_HDR=
589- link_bin "$dir/make" $_objs -- $LIB
590+ cfg_enabled BUILD_POSIX_MAKE || return 0
591+ local dir=cmd/posix/make
592+ EXTRA_HDR="$dir/make.h"
593+ objs_for "$dir" "" ""
594+ EXTRA_HDR=
595+ link_bin "$dir/make" $_objs -- $LIB
596 }
597
598 build_posix() {
599- cfg_enabled BUILD_POSIX_GETCONF && [ ! -f cmd/posix/getconf.h ] && {
600- printf ' GEN cmd/posix/getconf.h\n'
601- scripts/getconf.sh > cmd/posix/getconf.h || { rm -f cmd/posix/getconf.h; exit 1; }
602- }
603- build_simple_tools posix
604- build_awk
605- build_sh
606- build_make
607+ cfg_enabled BUILD_POSIX_GETCONF && [ ! -f cmd/posix/getconf.h ] && {
608+ printf ' GEN cmd/posix/getconf.h\n'
609+ scripts/getconf.sh > cmd/posix/getconf.h || { rm -f cmd/posix/getconf.h; exit 1; }
610+ }
611+ build_simple_tools posix
612+ build_awk
613+ build_sh
614+ build_make
615 }
616
617 # multi-file dev toolchain
618 #
619 build_ar() {
620- cfg_enabled BUILD_DEV_AR || return 0
621- local dir=cmd/dev/ar
622- objs_for "$dir" tinyar.c "-I$dir"
623- link_bin "$dir/ar" $_objs -- $LIB
624+ cfg_enabled BUILD_DEV_AR || return 0
625+ local dir=cmd/dev/ar
626+ objs_for "$dir" tinyar.c "-I$dir"
627+ link_bin "$dir/ar" $_objs -- $LIB
628 }
629
630 build_as() {
631- cfg_enabled BUILD_DEV_AS || return 0
632- local dir="cmd/dev/as"
633- local flags="-Icmd/dev/xcutil -I$dir -Ishared"
634- local objs=""
635- objs_for "cmd/dev/xcutil" "" "$flags"
636- objs="$objs $_objs"
637- objs_for "$dir" "" "$flags"
638- objs="$objs $_objs"
639- objs_for "$dir/arch/x64" "" "-Icmd/dev/xcutil -I$dir -I$dir/arch/x64 -Ishared"
640- objs="$objs $_objs"
641- link_bin "$dir/as" $objs -- $LIB
642+ cfg_enabled BUILD_DEV_AS || return 0
643+ local dir="cmd/dev/as"
644+ local flags="-Icmd/dev/xcutil -I$dir -Ishared"
645+ local objs=""
646+ objs_for "cmd/dev/xcutil" "" "$flags"
647+ objs="$objs $_objs"
648+ objs_for "$dir" "" "$flags"
649+ objs="$objs $_objs"
650+ objs_for "$dir/arch/x64" "" "-Icmd/dev/xcutil -I$dir -I$dir/arch/x64 -Ishared"
651+ objs="$objs $_objs"
652+ link_bin "$dir/as" $objs -- $LIB
653 }
654
655 build_ld() {
656- cfg_enabled BUILD_DEV_LD || return 0
657- local dir="cmd/dev/ld"
658- local flags="-Icmd/dev/xcutil -I$dir"
659- local objs=""
660- objs_for "cmd/dev/xcutil" "" "$flags"
661- objs="$objs $_objs"
662- objs_for "$dir" "" "$flags"
663- objs="$objs $_objs"
664- link_bin "$dir/ld" $objs -- $LIB
665+ cfg_enabled BUILD_DEV_LD || return 0
666+ local dir="cmd/dev/ld"
667+ local flags="-Icmd/dev/xcutil -I$dir"
668+ local objs=""
669+ objs_for "cmd/dev/xcutil" "" "$flags"
670+ objs="$objs $_objs"
671+ objs_for "$dir" "" "$flags"
672+ objs="$objs $_objs"
673+ link_bin "$dir/ld" $objs -- $LIB
674 }
675
676 build_cc() {
677- cfg_enabled BUILD_DEV_CC || return 0
678- local dir="cmd/dev/cc"
679- local cflags="-I$dir"
680- local common
681-
682- # compiled once, linked into both cc1 and cpp
683- objs_for "$dir" "driver.c cc1.c cpp.c" "$cflags"
684- common="$_objs"
685- drain
686-
687- compile_c "$dir/cc1.c" "$dir/cc1.o" $cflags
688- compile_c "$dir/cpp.c" "$dir/cpp.o" $cflags
689- compile_c "$dir/driver.c" "$dir/driver.o" $cflags
690- drain
691-
692- link_bin "$dir/cc1" "$dir/cc1.o" $common -- $LIB
693- link_bin "$dir/cpp" "$dir/cpp.o" $common -- $LIB
694- link_bin "$dir/cc" "$dir/driver.o" "$dir/util.o" -- $LIB
695+ cfg_enabled BUILD_DEV_CC || return 0
696+ local dir="cmd/dev/cc"
697+ local cflags="-I$dir"
698+ local common
699+
700+ # compiled once, linked into both cc1 and cpp
701+ objs_for "$dir" "driver.c cc1.c cpp.c" "$cflags"
702+ common="$_objs"
703+ drain
704+
705+ compile_c "$dir/cc1.c" "$dir/cc1.o" $cflags
706+ compile_c "$dir/cpp.c" "$dir/cpp.o" $cflags
707+ compile_c "$dir/driver.c" "$dir/driver.o" $cflags
708+ drain
709+
710+ link_bin "$dir/cc1" "$dir/cc1.o" $common -- $LIB
711+ link_bin "$dir/cpp" "$dir/cpp.o" $common -- $LIB
712+ link_bin "$dir/cc" "$dir/driver.o" "$dir/util.o" -- $LIB
713 }
714
715 build_dev() {
716- [ -f cmd/dev/configure ] && sh cmd/dev/configure
717- build_ar
718- build_as
719- build_ld
720- build_cc
721+ [ -f cmd/dev/configure ] && sh cmd/dev/configure
722+ build_ar
723+ build_as
724+ build_ld
725+ build_cc
726 }
727
728 # manual page generation
729 #
730 man_section() {
731- case "$1" in
732- */linux/*|*/net/*|*/xsi/*) printf '8\n' ;;
733- *) printf '1\n' ;;
734- esac
735+ case "$1" in
736+ */linux/*|*/net/*|*/xsi/*) printf '8\n' ;;
737+ *) printf '1\n' ;;
738+ esac
739 }
740
741 build_man_for() {
742- local var="$1" src="$2" base sec out_mdoc out_txt
743- cfg_enabled "$var" || return 0
744- [ -x scripts/mkman/mkman ] || { printf 'error: mkman not built\n' >&2; exit 1; }
745-
746- grep -qE '!man|\?man' "$src" || return 0
747-
748- base=${src##*/}; base=${base%.c}
749- sec=$(man_section "$src")
750-
751- mkdir -p "man/man${sec}"
752- out_mdoc="man/man${sec}/${base}.${sec}"
753- out_txt="man/man${sec}/${base}.${sec}.txt"
754- if any_newer_than "$out_mdoc" "$src" config.mk scripts/mkman/mkman; then
755- printf ' MAN %s\n' "$out_mdoc"
756- scripts/mkman/mkman -fmt mdoc -config config.mk -section "$sec" "$src" > "$out_mdoc"
757- fi
758- if any_newer_than "$out_txt" "$src" config.mk scripts/mkman/mkman; then
759- printf ' MAN %s\n' "$out_txt"
760- scripts/mkman/mkman -fmt txt -config config.mk -section "$sec" "$src" > "$out_txt"
761- fi
762+ local var="$1" src="$2" base sec out_mdoc out_txt
763+ cfg_enabled "$var" || return 0
764+ [ -x scripts/mkman/mkman ] || { printf 'error: mkman not built\n' >&2; exit 1; }
765+
766+ grep -qE '!man|\?man' "$src" || return 0
767+
768+ base=${src##*/}; base=${base%.c}
769+ sec=$(man_section "$src")
770+
771+ mkdir -p "man/man${sec}"
772+ out_mdoc="man/man${sec}/${base}.${sec}"
773+ out_txt="man/man${sec}/${base}.${sec}.txt"
774+ if any_newer_than "$out_mdoc" "$src" config.mk scripts/mkman/mkman; then
775+ printf ' MAN %s\n' "$out_mdoc"
776+ scripts/mkman/mkman -fmt mdoc -config config.mk -section "$sec" "$src" > "$out_mdoc"
777+ fi
778+ if any_newer_than "$out_txt" "$src" config.mk scripts/mkman/mkman; then
779+ printf ' MAN %s\n' "$out_txt"
780+ scripts/mkman/mkman -fmt txt -config config.mk -section "$sec" "$src" > "$out_txt"
781+ fi
782 }
783
784 build_man() {
785- local dir cat src base
786- if [ ! -x scripts/mkman/mkman ] || any_newer_than scripts/mkman/mkman scripts/mkman/main.go scripts/mkman/page.go scripts/mkman/parse.go scripts/mkman/mdoc.go; then
787- printf ' GO scripts/mkman/mkman\n'
788- (cd scripts/mkman && go build -o mkman .)
789- fi
790- for dir in cmd/*; do
791- [ -d "$dir" ] || continue
792- cat=${dir##*/}
793- for src in "$dir"/*.c; do
794- [ -f "$src" ] || continue
795- base=${src##*/}; base=${base%.c}
796- build_man_for "$(cfgvar "$cat" "$base")" "$src"
797- done
798- done
799+ local dir cat src base
800+ if [ ! -x scripts/mkman/mkman ] || any_newer_than scripts/mkman/mkman scripts/mkman/main.go scripts/mkman/page.go scripts/mkman/parse.go scripts/mkman/mdoc.go; then
801+ printf ' GO scripts/mkman/mkman\n'
802+ (cd scripts/mkman && go build -o mkman .)
803+ fi
804+ for dir in cmd/*; do
805+ [ -d "$dir" ] || continue
806+ cat=${dir##*/}
807+ for src in "$dir"/*.c; do
808+ [ -f "$src" ] || continue
809+ base=${src##*/}; base=${base%.c}
810+ build_man_for "$(cfgvar "$cat" "$base")" "$src"
811+ done
812+ done
813 }
814
815 # install and clean
816 #
817 do_install() {
818- local bin f sec
819- mkdir -p "$PREFIX/bin" "$MANPREFIX/man1" "$MANPREFIX/man8"
820- find cmd -type f ! -name '*.*' -perm -100 | while read -r bin; do
821- printf ' INSTALL %s/bin/%s\n' "$PREFIX" "${bin##*/}"
822- cp "$bin" "$PREFIX/bin/${bin##*/}"
823- chmod 755 "$PREFIX/bin/${bin##*/}"
824- done
825- find man/man1 man/man8 -type f -name '*.[18]' 2>/dev/null | while read -r f; do
826- sec=${f%/*}; sec=${sec##*/}
827- cp "$f" "$MANPREFIX/${sec}/${f##*/}"
828- done
829+ local bin f sec
830+ mkdir -p "$PREFIX/bin" "$MANPREFIX/man1" "$MANPREFIX/man8"
831+ find cmd -type f ! -name '*.*' -perm -100 | while read -r bin; do
832+ printf ' INSTALL %s/bin/%s\n' "$PREFIX" "${bin##*/}"
833+ cp "$bin" "$PREFIX/bin/${bin##*/}"
834+ chmod 755 "$PREFIX/bin/${bin##*/}"
835+ done
836+ find man/man1 man/man8 -type f -name '*.[18]' 2>/dev/null | while read -r f; do
837+ sec=${f%/*}; sec=${sec##*/}
838+ cp "$f" "$MANPREFIX/${sec}/${f##*/}"
839+ done
840 }
841
842 do_clean() {
843- find shared cmd -name '*.o' -exec rm -f {} +
844- find shared -name '*.a' -exec rm -f {} +
845- find cmd -type f ! -name '*.*' -perm -100 -exec rm -f {} +
846- rm -f shared/libaruuelf.so
847- rm -f cmd/posix/bc.c cmd/posix/getconf.h
848- rm -f cmd/posix/awk/maketab cmd/posix/awk/proctab.c
849- rm -f cmd/posix/awk/awkgram.tab.c cmd/posix/awk/awkgram.tab.h
850- rm -f cmd/posix/sh/mknodes cmd/posix/sh/mksyntax
851- rm -f cmd/posix/sh/token.h cmd/posix/sh/syntax.c cmd/posix/sh/syntax.h
852- rm -f cmd/posix/sh/nodes.c cmd/posix/sh/nodes.h
853- rm -f cmd/posix/sh/builtins.c cmd/posix/sh/builtins.h
854- rm -rf man/man1 man/man8
855- rm -rf aruu-box .box
856- rm -f scripts/mkman/mkman
857+ printf ' CLEAN object files\n'
858+ find shared cmd -name '*.o' -exec rm -f {} +
859+ printf ' CLEAN static libraries\n'
860+ find shared -name '*.a' -exec rm -f {} +
861+ printf ' CLEAN compiled binaries\n'
862+ find cmd -type f ! -name '*.*' -perm -100 -exec rm -f {} +
863+ printf ' CLEAN generated headers\n'
864+ rm -f cmd/posix/getconf.h
865+ rm -f cmd/posix/awk/awkgram.tab.c cmd/posix/awk/awkgram.tab.h
866+ rm -f cmd/posix/sh/token.h cmd/posix/sh/syntax.c cmd/posix/sh/syntax.h
867+ rm -f cmd/posix/sh/nodes.c cmd/posix/sh/nodes.h
868+ rm -f cmd/posix/sh/builtins.c cmd/posix/sh/builtins.h
869+ printf ' CLEAN generated sources\n'
870+ rm -f cmd/posix/awk/proctab.c
871+ rm -f cmd/posix/bc.c
872+ printf ' CLEAN build tools\n'
873+ rm -f cmd/posix/awk/maketab
874+ rm -f cmd/posix/sh/mknodes cmd/posix/sh/mksyntax
875+ rm -f scripts/mkman/mkman
876+ printf ' CLEAN dev artifacts\n'
877+ rm -f cmd/dev/cc/cc1 cmd/dev/cc/cpp cmd/dev/as/as cmd/dev/ld/ld cmd/dev/ar/ar
878+ rm -f shared/libaruuelf.so
879+ rm -f cmd/dev/config.h cmd/dev/cc/config.h cmd/dev/version.h
880+ printf ' CLEAN misc\n'
881+ rm -rf man/man1 man/man8
882+ rm -rf aruu-box .box
883+ printf ' CLEAN done\n'
884 }
885
886 case "$TARGET" in
887- all)
888- build_lib
889- build_posix
890- build_dev
891- build_simple_tools linux
892- build_simple_tools net
893- build_simple_tools xsi
894- build_simple_tools pseudo
895- build_simple_tools extra
896- ;;
897- lib) build_lib ;;
898- posix) build_lib; build_posix ;;
899- dev) build_lib; build_dev ;;
900- make) build_lib; build_make ;;
901- linux|net|xsi|pseudo|extra)
902- build_lib; build_simple_tools "$TARGET" ;;
903- man) build_man ;;
904- install) do_install ;;
905- clean) do_clean ;;
906- *)
907- printf 'usage: sh Makefile.sh [-jN] [-lN] [all|clean|install|man|lib|posix|linux|net|xsi|pseudo|extra|dev|make]\n' >&2
908- exit 1
909- ;;
910+ all)
911+ build_lib
912+ build_posix
913+ build_dev
914+ build_simple_tools linux
915+ build_simple_tools net
916+ build_simple_tools xsi
917+ build_simple_tools pseudo
918+ build_simple_tools extra
919+ ;;
920+ lib) build_lib ;;
921+ posix) build_lib; build_posix ;;
922+ dev) build_lib; build_dev ;;
923+ make) build_lib; build_make ;;
924+ linux|net|xsi|pseudo|extra)
925+ build_lib; build_simple_tools "$TARGET" ;;
926+ man) build_man ;;
927+ install) do_install ;;
928+ clean) do_clean ;;
929+ *)
930+ printf 'usage: sh Makefile.sh [-jN] [-lN] [all|clean|install|man|lib|posix|linux|net|xsi|pseudo|extra|dev|make]\n' >&2
931+ exit 1
932+ ;;
933 esac
+21,
-1
1@@ -40,6 +40,12 @@ posix)
2 FEATURE_SH_SETVAR=0; FEATURE_SH_WORDEXP=0
3 FEATURE_CAL_EXT=0
4 FEATURE_LS_COLOR=0
5+ FEATURE_DIFF3_MERGE=0; FEATURE_DIFF3_EDSCRIPT=0
6+ FEATURE_DIFF_CONTEXT=0; FEATURE_DIFF_UNIFIED=0
7+ FEATURE_DIFF_ED=0; FEATURE_DIFF_BRIEF=0
8+ FEATURE_DIFF_SIDEBYSIDE=0
9+ FEATURE_PATCH_BACKUP=0; FEATURE_PATCH_FUZZ=0
10+ FEATURE_PATCH_STRIP_CR=0
11 FEATURE_MODPROBE_SHOW_DEPENDS=0; FEATURE_MODPROBE_BLACKLIST=0
12 FEATURE_MODPROBE_SYSLOG=0; FEATURE_MODPROBE_DIR_OVERRIDE=0
13 FEATURE_DEPMOD_ALIAS=0; FEATURE_DEPMOD_SYMBOLS=0
14@@ -69,6 +75,12 @@ common)
15 FEATURE_SH_SETVAR=0; FEATURE_SH_WORDEXP=0
16 FEATURE_CAL_EXT=1
17 FEATURE_LS_COLOR=1
18+ FEATURE_DIFF3_MERGE=0; FEATURE_DIFF3_EDSCRIPT=1
19+ FEATURE_DIFF_CONTEXT=1; FEATURE_DIFF_UNIFIED=1
20+ FEATURE_DIFF_ED=1; FEATURE_DIFF_BRIEF=1
21+ FEATURE_DIFF_SIDEBYSIDE=0
22+ FEATURE_PATCH_BACKUP=1; FEATURE_PATCH_FUZZ=1
23+ FEATURE_PATCH_STRIP_CR=1
24 FEATURE_MODPROBE_SHOW_DEPENDS=1; FEATURE_MODPROBE_BLACKLIST=1
25 FEATURE_MODPROBE_SYSLOG=1; FEATURE_MODPROBE_DIR_OVERRIDE=1
26 FEATURE_DEPMOD_ALIAS=1; FEATURE_DEPMOD_SYMBOLS=1
27@@ -94,11 +106,18 @@ all)
28 FEATURE_STAT_FILESYSTEM=1; FEATURE_STAT_FORMAT=1
29 FEATURE_SORT_BIG=1; FEATURE_SORT_STABLE=1
30 FEATURE_OD_ENDIAN=1;
31- FEATURE_SH_HISTEDIT=1; FEATURE_SH_LOCAL=1
32+ FEATURE_SH_HISTEDIT=1
33+FEATURE_INPROC_EXEC=0 # set to 1 for aruu-box in-process dispatch; FEATURE_SH_LOCAL=1
34 FEATURE_SH_LET=1; FEATURE_SH_ULIMIT=1
35 FEATURE_SH_SETVAR=1; FEATURE_SH_WORDEXP=1
36 FEATURE_CAL_EXT=1
37 FEATURE_LS_COLOR=1
38+ FEATURE_DIFF3_MERGE=1; FEATURE_DIFF3_EDSCRIPT=1
39+ FEATURE_DIFF_CONTEXT=1; FEATURE_DIFF_UNIFIED=1
40+ FEATURE_DIFF_ED=1; FEATURE_DIFF_BRIEF=1
41+ FEATURE_DIFF_SIDEBYSIDE=1
42+ FEATURE_PATCH_BACKUP=1; FEATURE_PATCH_FUZZ=1
43+ FEATURE_PATCH_STRIP_CR=1
44 FEATURE_MODPROBE_SHOW_DEPENDS=1; FEATURE_MODPROBE_BLACKLIST=1
45 FEATURE_MODPROBE_SYSLOG=1; FEATURE_MODPROBE_DIR_OVERRIDE=1
46 FEATURE_DEPMOD_ALIAS=1; FEATURE_DEPMOD_SYMBOLS=1
47@@ -137,6 +156,7 @@ unset _p
48 # BUILD_POSIX_SH=0 # disable a tool when its group is active
49 # BUILD_DEV_AS=1 # enable a tool whose group isnt in PRESET_UTILS
50 FEATURE_SH_HISTEDIT=1
51+FEATURE_INPROC_EXEC=0 # set to 1 for aruu-box in-process dispatch
52 # tls backend: set exactly one to 1 to enable tls
53 FEATURE_USE_BEARSSL=0
54 FEATURE_USE_LIBRESSL=0
+97,
-96
1@@ -16,64 +16,65 @@ static int Lflag = 0;
2 static void
3 usage(void)
4 {
5- eprintf("usage: %s [-o format] [-s tag] [-U] [-L] [device ...]\n", argv0);
6+ eprintf("usage: %s [-o format] [-s tag] [-U] [-L] [device ...]\n", argv0);
7 }
8
9 static void
10 print_tag(const char *devname, const char *tag, const char *value)
11 {
12- if (sflag && strcasecmp(sflag, tag) != 0)
13- return;
14-
15- if (strcmp(oflag, "value") == 0) {
16- printf("%s\n", value);
17- } else if (strcmp(oflag, "export") == 0) {
18- printf("%s=%s\n", tag, value);
19- } else {
20- printf(" %s=\"%s\"", tag, value);
21- }
22+ (void)devname;
23+ if (sflag && strcasecmp(sflag, tag) != 0)
24+ return;
25+
26+ if (strcmp(oflag, "value") == 0) {
27+ printf("%s\n", value);
28+ } else if (strcmp(oflag, "export") == 0) {
29+ printf("%s=%s\n", tag, value);
30+ } else {
31+ printf(" %s=\"%s\"", tag, value);
32+ }
33 }
34
35 static int
36 do_blkid(const char *path)
37 {
38- struct BlockDev dev;
39- char type[64] = {0};
40- char label[256] = {0};
41- char uuid[256] = {0};
42- int res;
43-
44- if (blockdev_open(&dev, path, 0) < 0)
45- return -1;
46-
47- res = blockdev_detect_fs(&dev, type, sizeof(type), label, sizeof(label), uuid, sizeof(uuid));
48- if (res == 0) {
49- if (Uflag || Lflag) {
50- if (Uflag) {
51- printf("%s\n", uuid);
52- } else {
53- printf("%s\n", label);
54- }
55- } else {
56- if (strcmp(oflag, "export") == 0) {
57- printf("DEVNAME=%s\n", path);
58- } else if (strcmp(oflag, "value") != 0) {
59- printf("%s:", path);
60- }
61-
62- if (label[0])
63- print_tag(path, "LABEL", label);
64- if (uuid[0])
65- print_tag(path, "UUID", uuid);
66- print_tag(path, "TYPE", type);
67-
68- if (strcmp(oflag, "full") == 0)
69- printf("\n");
70- }
71- }
72-
73- blockdev_close(&dev);
74- return res == 0 ? 0 : -2;
75+ struct BlockDev dev;
76+ char type[64] = {0};
77+ char label[256] = {0};
78+ char uuid[256] = {0};
79+ int res;
80+
81+ if (blockdev_open(&dev, path, 0) < 0)
82+ return -1;
83+
84+ res = blockdev_detect_fs(&dev, type, sizeof(type), label, sizeof(label), uuid, sizeof(uuid));
85+ if (res == 0) {
86+ if (Uflag || Lflag) {
87+ if (Uflag) {
88+ printf("%s\n", uuid);
89+ } else {
90+ printf("%s\n", label);
91+ }
92+ } else {
93+ if (strcmp(oflag, "export") == 0) {
94+ printf("DEVNAME=%s\n", path);
95+ } else if (strcmp(oflag, "value") != 0) {
96+ printf("%s:", path);
97+ }
98+
99+ if (label[0])
100+ print_tag(path, "LABEL", label);
101+ if (uuid[0])
102+ print_tag(path, "UUID", uuid);
103+ print_tag(path, "TYPE", type);
104+
105+ if (strcmp(oflag, "full") == 0)
106+ printf("\n");
107+ }
108+ }
109+
110+ blockdev_close(&dev);
111+ return res == 0 ? 0 : -2;
112 }
113
114 // ?man blkid: print block device attributes
115@@ -83,52 +84,52 @@ do_blkid(const char *path)
116 int
117 main(int argc, char *argv[])
118 {
119- int ret = 0;
120-
121- ARGBEGIN {
122- // ?man -o:specify output format (full, value, export)
123- case 'o':
124- oflag = EARGF(usage());
125- break;
126- // ?man -s:only show specified tag (e.g. UUID, LABEL, TYPE)
127- case 's':
128- sflag = EARGF(usage());
129- break;
130- // ?man -U:print UUID only
131- case 'U':
132- Uflag = 1;
133- break;
134- // ?man -L:print volume label only
135- case 'L':
136- Lflag = 1;
137- break;
138- default:
139- usage();
140- } ARGEND
141-
142- if (argc > 0) {
143- for (; *argv; argv++) {
144- if (do_blkid(*argv) < 0)
145- ret = 1;
146- }
147- } else {
148- struct BlockDevInfo *list = blockdev_get_list();
149- struct BlockDevInfo *curr;
150- if (!list) {
151- return 1;
152- }
153- for (curr = list; curr; curr = curr->next) {
154- do_blkid(curr->path);
155- struct BlockDevInfo *part;
156- for (part = curr->parts; part; part = part->next) {
157- do_blkid(part->path);
158- }
159- }
160- blockdev_free_list(list);
161- }
162-
163- if (fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>"))
164- ret = 2;
165-
166- return ret;
167+ int ret = 0;
168+
169+ ARGBEGIN {
170+ // ?man -o:specify output format (full, value, export)
171+ case 'o':
172+ oflag = EARGF(usage());
173+ break;
174+ // ?man -s:only show specified tag (e.g. UUID, LABEL, TYPE)
175+ case 's':
176+ sflag = EARGF(usage());
177+ break;
178+ // ?man -U:print UUID only
179+ case 'U':
180+ Uflag = 1;
181+ break;
182+ // ?man -L:print volume label only
183+ case 'L':
184+ Lflag = 1;
185+ break;
186+ default:
187+ usage();
188+ } ARGEND
189+
190+ if (argc > 0) {
191+ for (; *argv; argv++) {
192+ if (do_blkid(*argv) < 0)
193+ ret = 1;
194+ }
195+ } else {
196+ struct BlockDevInfo *list = blockdev_get_list();
197+ struct BlockDevInfo *curr;
198+ if (!list) {
199+ return 1;
200+ }
201+ for (curr = list; curr; curr = curr->next) {
202+ do_blkid(curr->path);
203+ struct BlockDevInfo *part;
204+ for (part = curr->parts; part; part = part->next) {
205+ do_blkid(part->path);
206+ }
207+ }
208+ blockdev_free_list(list);
209+ }
210+
211+ if (fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>"))
212+ ret = 2;
213+
214+ return ret;
215 }
+4,
-3
1@@ -10,6 +10,7 @@
2 #include <string.h>
3 #include <unistd.h>
4
5+#include "paths.h"
6 #include "util.h"
7
8 #define KDGKBTYPE 0x4B33 /* get keyboard type */
9@@ -18,9 +19,9 @@
10 #define VT_WAITACTIVE 0x5607 /* wait for vt active */
11
12 static char *vt[] = {
13- "/proc/self/fd/0",
14- "/dev/console",
15- "/dev/tty",
16+ ARUU_LINUX_PATH_PROC "/self/fd/0",
17+ ARUU_PATH_DEVCONSOLE,
18+ ARUU_PATH_DEVTTY,
19 "/dev/tty0",
20 };
21
+5,
-4
1@@ -1,6 +1,7 @@
2
3
4 #include "fs.h"
5+#include "wexec.h"
6 #include "util.h"
7
8 #include <dirent.h>
9@@ -181,15 +182,15 @@ scan_cb(int fd, const char *name, struct stat *st, void *data, struct recursor *
10 fp = fopen(r->path, "r");
11 } else if (strcmp(comp, ".gz") == 0) {
12 snprintf(cmd, sizeof(cmd), "gzip -dc '%s'", r->path);
13- fp = popen(cmd, "r");
14+ fp = wpopen(cmd, NULL, "r");
15 is_pipe = 1;
16 } else if (strcmp(comp, ".xz") == 0) {
17 snprintf(cmd, sizeof(cmd), "xz -dc '%s'", r->path);
18- fp = popen(cmd, "r");
19+ fp = wpopen(cmd, NULL, "r");
20 is_pipe = 1;
21 } else if (strcmp(comp, ".zst") == 0) {
22 snprintf(cmd, sizeof(cmd), "zstd -dc '%s'", r->path);
23- fp = popen(cmd, "r");
24+ fp = wpopen(cmd, NULL, "r");
25 is_pipe = 1;
26 } else {
27 fp = fopen(r->path, "r");
28@@ -202,7 +203,7 @@ scan_cb(int fd, const char *name, struct stat *st, void *data, struct recursor *
29
30 buf = read_all(fp, &len);
31 if (is_pipe)
32- pclose(fp);
33+ wpclose(fp);
34 else
35 fclose(fp);
36
+2,
-1
1@@ -9,6 +9,7 @@
2 #include <stdio.h>
3 #include <unistd.h>
4
5+#include "paths.h"
6 #include "util.h"
7
8 enum {
9@@ -64,7 +65,7 @@ main(int argc, char *argv[])
10 } ARGEND;
11
12 if (!argc) {
13- eject("/dev/sr0");
14+ eject(ARUU_PATH_DEV "/sr0");
15 } else {
16 for (; *argv; argc--, argv++)
17 eject(*argv);
+1,
-0
1@@ -10,6 +10,7 @@
2 #include <stdlib.h>
3 #include <unistd.h>
4
5+#include "paths.h"
6 #include "util.h"
7
8 static void
+2,
-1
1@@ -14,6 +14,7 @@
2 #include <unistd.h>
3
4 #include "rtc.h"
5+#include "paths.h"
6 #include "util.h"
7
8 static void
9@@ -120,7 +121,7 @@ usage(void)
10 int
11 main(int argc, char *argv[])
12 {
13- char *dev = "/dev/rtc";
14+ char *dev = ARUU_PATH_DEV "/rtc";
15 int rflag = 0;
16 int sflag = 0;
17 int wflag = 0;
+2,
-1
1@@ -4,6 +4,7 @@
2 #include <string.h>
3
4 #include "text.h"
5+#include "paths.h"
6 #include "util.h"
7
8 static void parse_modline(char *buf, char **name, char **size,
9@@ -20,7 +21,7 @@ usage(void)
10 int
11 main(int argc, char *argv[])
12 {
13- const char *modfile = "/proc/modules";
14+ const char *modfile = ARUU_LINUX_PATH_PROC_MODULES;
15 FILE *fp;
16 char *buf = NULL;
17 char *name, *size, *refcount, *users;
+2,
-1
1@@ -6,6 +6,7 @@
2 #include <stdlib.h>
3
4 #include "text.h"
5+#include "paths.h"
6 #include "util.h"
7
8 static void
9@@ -57,6 +58,6 @@ main(int argc, char *argv[])
10 usage();
11 } ARGEND;
12
13- recurse_dir("/sys/bus/usb/devices", lsusb);
14+ recurse_dir(ARUU_LINUX_PATH_SYS_BUS_USB, lsusb);
15 return 0;
16 }
+2,
-1
1@@ -1,6 +1,7 @@
2
3 #include "arg.h"
4 #include "fs.h"
5+#include "paths.h"
6 #include "util.h"
7
8 #include <ctype.h>
9@@ -344,7 +345,7 @@ mark_loaded(void)
10 char *p;
11 struct Module *m;
12
13- if (!(fp = fopen("/proc/modules", "r")))
14+ if (!(fp = fopen(ARUU_LINUX_PATH_PROC_MODULES, "r")))
15 return;
16
17 while (fgets(line, sizeof(line), fp)) {
+8,
-6
1@@ -15,6 +15,8 @@
2 #include <unistd.h>
3
4 #include "text.h"
5+#include "paths.h"
6+#include "wexec.h"
7 #include "util.h"
8
9 #define FSOPTS_MAXLEN 512
10@@ -134,10 +136,10 @@ mounthelper(const char *fsname, const char *dir, const char *fstype)
11 eargv[i++] = dir;
12 eargv[i] = NULL;
13
14- execvp(eprog, (char * const *)eargv);
15+ wexecvp_self(eprog, (char *const *)eargv);
16 if (errno == ENOENT)
17 _exit(1);
18- weprintf("execvp:");
19+ weprintf("wexecvp:");
20 _exit(1);
21 break;
22 default:
23@@ -166,8 +168,8 @@ mounted(const char *dir)
24 weprintf("stat %s:", dir);
25 return 0;
26 }
27- if (!(fp = setmntent("/proc/mounts", "r")))
28- eprintf("setmntent %s:", "/proc/mounts");
29+ if (!(fp = setmntent(ARUU_LINUX_PATH_PROC_MOUNTS, "r")))
30+ eprintf("setmntent %s:", ARUU_LINUX_PATH_PROC_MOUNTS);
31
32 while ((me = getmntent_r(fp, &mebuf, linebuf, sizeof(linebuf)))) {
33 if (stat(me->mnt_dir, &st2) < 0) {
34@@ -197,7 +199,7 @@ int
35 main(int argc, char *argv[])
36 {
37 char *types = NULL, data[FSOPTS_MAXLEN] = "", *resolvpath = NULL;
38- char *files[] = { "/proc/mounts", "/etc/fstab", NULL };
39+ char *files[] = { ARUU_LINUX_PATH_PROC_MOUNTS, "/etc/fstab", NULL };
40 const char *source, *target;
41 struct mntent *me = NULL;
42 int aflag = 0, status = 0, i, r;
43@@ -263,7 +265,7 @@ main(int argc, char *argv[])
44
45 for (i = 0; files[i]; i++) {
46 if (!(fp = setmntent(files[i], "r"))) {
47- if (strcmp(files[i], "/proc/mounts") != 0)
48+ if (strcmp(files[i], ARUU_LINUX_PATH_PROC_MOUNTS) != 0)
49 weprintf("setmntent %s:", files[i]);
50 continue;
51 }
+3,
-2
1@@ -11,6 +11,7 @@
2 #include <string.h>
3 #include <unistd.h>
4
5+#include "paths.h"
6 #include "util.h"
7
8 static void
9@@ -81,11 +82,11 @@ main(int argc, char *argv[])
10 return 0;
11 }
12
13- fp = setmntent("/proc/mounts", "r");
14+ fp = setmntent(ARUU_LINUX_PATH_PROC_MOUNTS, "r");
15 if (!fp) {
16 if (qflag)
17 return 1;
18- eprintf("setmntent %s:", "/proc/mounts");
19+ eprintf("setmntent %s:", ARUU_LINUX_PATH_PROC_MOUNTS);
20 }
21 while ((me = getmntent(fp)) != NULL) {
22 if (stat(me->mnt_dir, &st2) < 0) {
+163,
-167
1@@ -9,155 +9,151 @@
2 #include <unistd.h>
3
4 #include "text.h"
5+#include "paths.h"
6 #include "util.h"
7
8 static void
9 replacestr(char *s, int a, int b)
10 {
11- for (; *s; s++)
12- if (*s == a)
13- *s = b;
14+ for (; *s; s++)
15+ if (*s == a)
16+ *s = b;
17 }
18
19 static int
20 getsysctl(char *variable, char **value)
21 {
22- char path[PATH_MAX];
23- char *p;
24- char *buf, *tmp, c;
25- int fd;
26- ssize_t n;
27- size_t sz, i;
28-
29- replacestr(variable, '.', '/');
30-
31- strlcpy(path, "/proc/sys/", sizeof(path));
32- if (strlcat(path, variable, sizeof(path)) >= sizeof(path)) {
33- replacestr(variable, '/', '.');
34- return -1;
35- }
36-
37- replacestr(variable, '/', '.');
38-
39- fd = open(path, O_RDONLY);
40- if (fd < 0)
41- return -1;
42-
43- i = 0;
44- sz = 1;
45- buf = NULL;
46- while (1) {
47- n = read(fd, &c, 1);
48- if (n < 0) {
49- close(fd);
50- free(buf);
51- return -1;
52- }
53- if (n == 0)
54- break;
55- if (i == sz - 1) {
56- sz *= 2;
57- tmp = realloc(buf, sz);
58- if (!tmp) {
59- close(fd);
60- free(buf);
61- return -1;
62- }
63- buf = tmp;
64- }
65- buf[i++] = c;
66- }
67- buf[i] = '\0';
68-
69- p = strrchr(buf, '\n');
70- if (p)
71- *p = '\0';
72-
73- *value = buf;
74-
75- close(fd);
76-
77- return 0;
78+ char path[PATH_MAX];
79+ char *p;
80+ char *buf, *tmp, c;
81+ int fd;
82+ ssize_t n;
83+ size_t sz, i;
84+
85+ replacestr(variable, '.', '/');
86+
87+ strlcpy(path, ARUU_LINUX_PATH_PROC_SYS "/", sizeof(path));
88+ if (strlcat(path, variable, sizeof(path)) >= sizeof(path)) {
89+ replacestr(variable, '/', '.');
90+ return -1;
91+ }
92+
93+ replacestr(variable, '/', '.');
94+
95+ fd = open(path, O_RDONLY);
96+ if (fd < 0)
97+ return -1;
98+
99+ i = 0;
100+ sz = 1;
101+ buf = NULL;
102+ while (1) {
103+ n = read(fd, &c, 1);
104+ if (n < 0) {
105+ close(fd);
106+ free(buf);
107+ return -1;
108+ }
109+ if (n == 0)
110+ break;
111+ if (i == sz - 1) {
112+ sz *= 2;
113+ tmp = erealloc(buf, sz);
114+ buf = tmp;
115+ }
116+ buf[i++] = c;
117+ }
118+ buf[i] = '\0';
119+
120+ p = strrchr(buf, '\n');
121+ if (p)
122+ *p = '\0';
123+
124+ *value = buf;
125+
126+ close(fd);
127+
128+ return 0;
129 }
130
131 static int
132 setsysctl(char *variable, char *value)
133 {
134- char path[PATH_MAX];
135- int fd;
136- ssize_t n;
137+ char path[PATH_MAX];
138+ int fd;
139+ ssize_t n;
140
141- replacestr(variable, '.', '/');
142+ replacestr(variable, '.', '/');
143
144- strlcpy(path, "/proc/sys/", sizeof(path));
145- if (strlcat(path, variable, sizeof(path)) >= sizeof(path)) {
146- replacestr(variable, '/', '.');
147- return -1;
148- }
149+ strlcpy(path, ARUU_LINUX_PATH_PROC_SYS "/", sizeof(path));
150+ if (strlcat(path, variable, sizeof(path)) >= sizeof(path)) {
151+ replacestr(variable, '/', '.');
152+ return -1;
153+ }
154
155- replacestr(variable, '/', '.');
156+ replacestr(variable, '/', '.');
157
158- fd = open(path, O_WRONLY);
159- if (fd < 0)
160- return -1;
161+ fd = open(path, O_WRONLY);
162+ if (fd < 0)
163+ return -1;
164
165- n = write(fd, value, strlen(value));
166- if ((size_t)n != strlen(value)) {
167- close(fd);
168- return -1;
169- }
170+ n = write(fd, value, strlen(value));
171+ if ((size_t)n != strlen(value)) {
172+ close(fd);
173+ return -1;
174+ }
175
176- close(fd);
177+ close(fd);
178
179- return 0;
180+ return 0;
181 }
182
183 static int
184 parsepair(char *pair)
185 {
186- char *p;
187- char *variable;
188- char *value;
189-
190- for (p = pair; *p; p++) {
191- if (p[0] == '.' && p[1] == '.') {
192- weprintf("malformed input: %s\n", pair);
193- return -1;
194- }
195- }
196- p = strchr(pair, '=');
197- if (p) {
198- if (p[1] == '\0') {
199- weprintf("malformed input: %s\n", pair);
200- return -1;
201- }
202- *p = '\0';
203- value = &p[1];
204- } else {
205- value = NULL;
206- }
207- variable = pair;
208- if (value) {
209- if (setsysctl(variable, value) < 0) {
210- weprintf("failed to set sysctl for %s\n", variable);
211- return -1;
212- }
213- } else {
214- if (getsysctl(variable, &value) < 0) {
215- weprintf("failed to get sysctl for %s\n", variable);
216- return -1;
217- }
218- printf("%s = %s\n", variable, value);
219- free(value);
220- }
221-
222- return 0;
223+ char *p;
224+ char *variable;
225+ char *value;
226+
227+ for (p = pair; *p; p++) {
228+ if (p[0] == '.' && p[1] == '.') {
229+ weprintf("malformed input: %s\n", pair);
230+ return -1;
231+ }
232+ }
233+ p = strchr(pair, '=');
234+ if (p) {
235+ if (p[1] == '\0') {
236+ weprintf("malformed input: %s\n", pair);
237+ return -1;
238+ }
239+ *p = '\0';
240+ value = &p[1];
241+ } else {
242+ value = NULL;
243+ }
244+ variable = pair;
245+ if (value) {
246+ if (setsysctl(variable, value) < 0) {
247+ weprintf("failed to set sysctl for %s\n", variable);
248+ return -1;
249+ }
250+ } else {
251+ if (getsysctl(variable, &value) < 0) {
252+ weprintf("failed to get sysctl for %s\n", variable);
253+ return -1;
254+ }
255+ printf("%s = %s\n", variable, value);
256+ free(value);
257+ }
258+
259+ return 0;
260 }
261
262 static void
263 usage(void)
264 {
265- eprintf("usage: %s [-p file] variable[=value]...\n", argv0);
266+ eprintf("usage: %s [-p file] variable[=value]...\n", argv0);
267 }
268
269 // ?man sysctl: configure kernel parameters
270@@ -166,54 +162,54 @@ usage(void)
271 int
272 main(int argc, char *argv[])
273 {
274- FILE *fp;
275- char *buf = NULL, *p;
276- char *file = NULL;
277- size_t size = 0;
278- int i;
279- int r = 0;
280-
281- ARGBEGIN {
282- // ?man -p:file: preserve file attributes
283- case 'p':
284- file = EARGF(usage());
285- break;
286- default:
287- usage();
288- } ARGEND;
289-
290- if (!file && argc < 1)
291- usage();
292-
293- if (!file) {
294- for (i = 0; i < argc; i++)
295- if (parsepair(argv[i]) < 0)
296- r = 1;
297- } else {
298- fp = fopen(file, "r");
299- if (!fp)
300- eprintf("fopen %s:", file);
301- while (agetline(&buf, &size, fp) != -1) {
302- p = buf;
303- for (p = buf; *p == ' ' || *p == '\t'; p++)
304- ;
305- if (*p == '#' || *p == '\n')
306- continue;
307- for (p = buf; *p; p++) {
308- if (*p == '\n') {
309- *p = '\0';
310- break;
311- }
312- }
313- p = buf;
314- if (parsepair(p) < 0)
315- r = 1;
316- }
317- if (ferror(fp))
318- eprintf("%s: read error:", file);
319- free(buf);
320- fclose(fp);
321- }
322-
323- return r;
324+ FILE *fp;
325+ char *buf = NULL, *p;
326+ char *file = NULL;
327+ size_t size = 0;
328+ int i;
329+ int r = 0;
330+
331+ ARGBEGIN {
332+ // ?man -p:file: preserve file attributes
333+ case 'p':
334+ file = EARGF(usage());
335+ break;
336+ default:
337+ usage();
338+ } ARGEND;
339+
340+ if (!file && argc < 1)
341+ usage();
342+
343+ if (!file) {
344+ for (i = 0; i < argc; i++)
345+ if (parsepair(argv[i]) < 0)
346+ r = 1;
347+ } else {
348+ fp = fopen(file, "r");
349+ if (!fp)
350+ eprintf("fopen %s:", file);
351+ while (agetline(&buf, &size, fp) != -1) {
352+ p = buf;
353+ for (p = buf; *p == ' ' || *p == '\t'; p++)
354+ ;
355+ if (*p == '#' || *p == '\n')
356+ continue;
357+ for (p = buf; *p; p++) {
358+ if (*p == '\n') {
359+ *p = '\0';
360+ break;
361+ }
362+ }
363+ p = buf;
364+ if (parsepair(p) < 0)
365+ r = 1;
366+ }
367+ if (ferror(fp))
368+ eprintf("%s: read error:", file);
369+ free(buf);
370+ fclose(fp);
371+ }
372+
373+ return r;
374 }
+1,
-0
1@@ -17,6 +17,7 @@
2 #include <linux/if.h>
3 #include <linux/if_tun.h>
4
5+#include "paths.h"
6 #include "util.h"
7
8 static int dflag;
+3,
-2
1@@ -8,6 +8,7 @@
2 #include <stdlib.h>
3 #include <string.h>
4
5+#include "paths.h"
6 #include "util.h"
7
8 #if FEATURE_UMOUNT_OPTIONS
9@@ -87,9 +88,9 @@ umountall(int flags
10 char **mntdirs = NULL;
11 int len = 0;
12
13- fp = setmntent("/proc/mounts", "r");
14+ fp = setmntent(ARUU_LINUX_PATH_PROC_MOUNTS, "r");
15 if (!fp)
16- eprintf("setmntent %s:", "/proc/mounts");
17+ eprintf("setmntent %s:", ARUU_LINUX_PATH_PROC_MOUNTS);
18 while ((me = getmntent(fp))) {
19 if (strcmp(me->mnt_type, "proc") == 0)
20 continue;
1@@ -7,6 +7,7 @@
2 #include <string.h>
3 #include <unistd.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 static void
9@@ -58,8 +59,8 @@ main(int argc, char *argv[])
10 if (unshare(flags) < 0)
11 eprintf("unshare:");
12
13- if (execvp(argv[0], argv) < 0)
14- eprintf("execvp:");
15+ if (0) wexecvp_self(argv[0], argv);
16+ eprintf("wexecvp:");
17
18 return 0;
19 }
+2,
-1
1@@ -10,9 +10,10 @@
2 #include <string.h>
3 #include <unistd.h>
4
5+#include "paths.h"
6 #include "util.h"
7
8-#define CONSOLE "/dev/console"
9+#define CONSOLE ARUU_PATH_DEVCONSOLE
10
11 #define VT_LOCKSWITCH 0x560B /* disallow vt switching */
12 #define VT_UNLOCKSWITCH 0x560C /* allow vt switching */
+428,
-424
1@@ -1,6 +1,7 @@
2 /* sdhcp: simple DHCP client, ported from git.2f30.org/sdhcp */
3 /* See LICENSE file for copyright and license details */
4 #include "arg.h"
5+#include "wexec.h"
6 #include "util.h"
7
8 #include <errno.h>
9@@ -23,67 +24,67 @@
10
11 /* bootp packet layout: fields are byte arrays to avoid alignment/endian issues */
12 struct Bootp {
13- unsigned char op [1];
14- unsigned char htype [1];
15- unsigned char hlen [1];
16- unsigned char hops [1];
17- unsigned char xid [4];
18- unsigned char secs [2];
19- unsigned char flags [2];
20- unsigned char ciaddr [4];
21- unsigned char yiaddr [4];
22- unsigned char siaddr [4];
23- unsigned char giaddr [4];
24- unsigned char chaddr [16];
25- unsigned char sname [64];
26- unsigned char file [128];
27- unsigned char magic [4];
28- unsigned char optdata [312-4];
29+ unsigned char op [1];
30+ unsigned char htype [1];
31+ unsigned char hlen [1];
32+ unsigned char hops [1];
33+ unsigned char xid [4];
34+ unsigned char secs [2];
35+ unsigned char flags [2];
36+ unsigned char ciaddr [4];
37+ unsigned char yiaddr [4];
38+ unsigned char siaddr [4];
39+ unsigned char giaddr [4];
40+ unsigned char chaddr [16];
41+ unsigned char sname [64];
42+ unsigned char file [128];
43+ unsigned char magic [4];
44+ unsigned char optdata [312-4];
45 };
46
47 enum {
48- DHCP_DISCOVER = 1,
49- DHCP_OFFER,
50- DHCP_REQUEST,
51- DHCP_DECLINE,
52- DHCP_ACK,
53- DHCP_NAK,
54- DHCP_RELEASE,
55- DHCP_INFORM,
56- /* internal sentinel values returned by dhcprecv */
57- TIMEOUT0 = 200,
58- TIMEOUT1,
59- TIMEOUT2,
60-
61- BOOT_REQUEST = 1,
62- BOOT_REPLY = 2,
63- /* bootp flags */
64- F_BROADCAST = 1 << 15,
65-
66- /* bootp options */
67- OB_PAD = 0,
68- OB_MASK = 1,
69- OB_ROUTER = 3,
70- OB_NAMESERVER = 5,
71- OB_DNSSERVER = 6,
72- OB_HOSTNAME = 12,
73- OB_BADDR = 28,
74- /* DHCP-specific options */
75- OD_IPADDR = 50, /* 0x32 */
76- OD_LEASE = 51,
77- OD_OVERLOAD = 52,
78- OD_TYPE = 53, /* 0x35 */
79- OD_SERVERID = 54, /* 0x36 */
80- OD_PARAMS = 55, /* 0x37 */
81- OD_MESSAGE = 56,
82- OD_MAXMSG = 57,
83- OD_RENEWALTIME = 58,
84- OD_REBINDINGTIME = 59,
85- OD_VENDORCLASS = 60,
86- OD_CLIENTID = 61, /* 0x3d */
87- OD_TFTPSERVER = 66,
88- OD_BOOTFILE = 67,
89- OB_END = 255,
90+ DHCP_DISCOVER = 1,
91+ DHCP_OFFER,
92+ DHCP_REQUEST,
93+ DHCP_DECLINE,
94+ DHCP_ACK,
95+ DHCP_NAK,
96+ DHCP_RELEASE,
97+ DHCP_INFORM,
98+ /* internal sentinel values returned by dhcprecv */
99+ TIMEOUT0 = 200,
100+ TIMEOUT1,
101+ TIMEOUT2,
102+
103+ BOOT_REQUEST = 1,
104+ BOOT_REPLY = 2,
105+ /* bootp flags */
106+ F_BROADCAST = 1 << 15,
107+
108+ /* bootp options */
109+ OB_PAD = 0,
110+ OB_MASK = 1,
111+ OB_ROUTER = 3,
112+ OB_NAMESERVER = 5,
113+ OB_DNSSERVER = 6,
114+ OB_HOSTNAME = 12,
115+ OB_BADDR = 28,
116+ /* DHCP-specific options */
117+ OD_IPADDR = 50, /* 0x32 */
118+ OD_LEASE = 51,
119+ OD_OVERLOAD = 52,
120+ OD_TYPE = 53, /* 0x35 */
121+ OD_SERVERID = 54, /* 0x36 */
122+ OD_PARAMS = 55, /* 0x37 */
123+ OD_MESSAGE = 56,
124+ OD_MAXMSG = 57,
125+ OD_RENEWALTIME = 58,
126+ OD_REBINDINGTIME = 59,
127+ OD_VENDORCLASS = 60,
128+ OD_CLIENTID = 61, /* 0x3d */
129+ OD_TFTPSERVER = 66,
130+ OD_BOOTFILE = 67,
131+ OB_END = 255,
132 };
133
134 enum { BROADCAST, UNICAST };
135@@ -118,485 +119,488 @@ static int fflag = 0;
136 static void
137 hnput(unsigned char *dst, uint32_t src, size_t n)
138 {
139- unsigned int i;
140+ unsigned int i;
141
142- for (i = 0; n--; i++)
143- dst[i] = (src >> (n * 8)) & 0xff;
144+ for (i = 0; n--; i++)
145+ dst[i] = (src >> (n * 8)) & 0xff;
146 }
147
148 static struct sockaddr *
149 iptoaddr(struct sockaddr *ifaddr, unsigned char ip[4], int port)
150 {
151- struct sockaddr_in *in = (struct sockaddr_in *)ifaddr;
152+ struct sockaddr_in *in = (struct sockaddr_in *)ifaddr;
153
154- in->sin_family = AF_INET;
155- in->sin_port = htons(port);
156- memcpy(&(in->sin_addr), ip, sizeof(in->sin_addr));
157+ in->sin_family = AF_INET;
158+ in->sin_port = htons(port);
159+ memcpy(&(in->sin_addr), ip, sizeof(in->sin_addr));
160
161- return ifaddr;
162+ return ifaddr;
163 }
164
165 /* sendto UDP wrapper: sends n bytes of data to bootp server port on ip */
166 static ssize_t
167 udpsend(unsigned char ip[4], int fd, void *data, size_t n)
168 {
169- struct sockaddr addr;
170- socklen_t addrlen = sizeof(addr);
171- ssize_t sent;
172+ struct sockaddr addr;
173+ socklen_t addrlen = sizeof(addr);
174+ ssize_t sent;
175
176- iptoaddr(&addr, ip, 67); /* bootp server */
177- if ((sent = sendto(fd, data, n, 0, &addr, addrlen)) == -1)
178- eprintf("sendto:");
179+ iptoaddr(&addr, ip, 67); /* bootp server */
180+ if ((sent = sendto(fd, data, n, 0, &addr, addrlen)) == -1)
181+ eprintf("sendto:");
182
183- return sent;
184+ return sent;
185 }
186
187 /* recvfrom UDP wrapper: receives into data from bootp client port */
188 static ssize_t
189 udprecv(unsigned char ip[4], int fd, void *data, size_t n)
190 {
191- struct sockaddr addr;
192- socklen_t addrlen = sizeof(addr);
193- ssize_t r;
194+ struct sockaddr addr;
195+ socklen_t addrlen = sizeof(addr);
196+ ssize_t r;
197
198- iptoaddr(&addr, ip, 68); /* bootp client */
199- if ((r = recvfrom(fd, data, n, 0, &addr, &addrlen)) == -1)
200- eprintf("recvfrom:");
201+ iptoaddr(&addr, ip, 68); /* bootp client */
202+ if ((r = recvfrom(fd, data, n, 0, &addr, &addrlen)) == -1)
203+ eprintf("recvfrom:");
204
205- return r;
206+ return r;
207 }
208
209 static void
210 setip(unsigned char ip[4], unsigned char mask[4], unsigned char gateway[4])
211 {
212- struct ifreq ifreq;
213- struct rtentry rtreq;
214- int fd;
215-
216- memset(&ifreq, 0, sizeof(ifreq));
217- memset(&rtreq, 0, sizeof(rtreq));
218-
219- strlcpy(ifreq.ifr_name, ifname, IF_NAMESIZE);
220- iptoaddr(&(ifreq.ifr_addr), ip, 0);
221- if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) == -1)
222- eprintf("can't set ip, socket:");
223- ioctl(fd, SIOCSIFADDR, &ifreq);
224- iptoaddr(&(ifreq.ifr_netmask), mask, 0);
225- ioctl(fd, SIOCSIFNETMASK, &ifreq);
226- ifreq.ifr_flags = IFF_UP | IFF_RUNNING | IFF_BROADCAST | IFF_MULTICAST;
227- ioctl(fd, SIOCSIFFLAGS, &ifreq);
228- /* default gw */
229- rtreq.rt_flags = RTF_UP | RTF_GATEWAY;
230- iptoaddr(&(rtreq.rt_gateway), gateway, 0);
231- iptoaddr(&(rtreq.rt_genmask), IP(0, 0, 0, 0), 0);
232- iptoaddr(&(rtreq.rt_dst), IP(0, 0, 0, 0), 0);
233- ioctl(fd, SIOCADDRT, &rtreq);
234-
235- close(fd);
236+ struct ifreq ifreq;
237+ struct rtentry rtreq;
238+ int fd;
239+
240+ memset(&ifreq, 0, sizeof(ifreq));
241+ memset(&rtreq, 0, sizeof(rtreq));
242+
243+ strlcpy(ifreq.ifr_name, ifname, IF_NAMESIZE);
244+ iptoaddr(&(ifreq.ifr_addr), ip, 0);
245+ if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) == -1)
246+ eprintf("can't set ip, socket:");
247+ ioctl(fd, SIOCSIFADDR, &ifreq);
248+ iptoaddr(&(ifreq.ifr_netmask), mask, 0);
249+ ioctl(fd, SIOCSIFNETMASK, &ifreq);
250+ ifreq.ifr_flags = IFF_UP | IFF_RUNNING | IFF_BROADCAST | IFF_MULTICAST;
251+ ioctl(fd, SIOCSIFFLAGS, &ifreq);
252+ /* default gw */
253+ rtreq.rt_flags = RTF_UP | RTF_GATEWAY;
254+ iptoaddr(&(rtreq.rt_gateway), gateway, 0);
255+ iptoaddr(&(rtreq.rt_genmask), IP(0, 0, 0, 0), 0);
256+ iptoaddr(&(rtreq.rt_dst), IP(0, 0, 0, 0), 0);
257+ ioctl(fd, SIOCADDRT, &rtreq);
258+
259+ close(fd);
260 }
261
262 /* copy contents of src path into dfd; silently skips missing files */
263 static void
264 appendfile(int dfd, char *src)
265 {
266- char buf[BUFSIZ];
267- int fd, n;
268-
269- if ((fd = open(src, O_RDONLY)) == -1)
270- return;
271- while ((n = read(fd, buf, sizeof(buf))) > 0)
272- writeall(dfd, buf, n);
273- close(fd);
274+ char buf[BUFSIZ];
275+ int fd, n;
276+
277+ if ((fd = open(src, O_RDONLY)) == -1)
278+ return;
279+ while ((n = read(fd, buf, sizeof(buf))) > 0)
280+ writeall(dfd, buf, n);
281+ close(fd);
282 }
283
284 static void
285 setdns(unsigned char ip[4])
286 {
287- char buf[128];
288- int fd, n;
289-
290- if ((fd = creat("/etc/resolv.conf", 0644)) == -1) {
291- weprintf("can't change /etc/resolv.conf:");
292- return;
293- }
294- appendfile(fd, "/etc/resolv.conf.head");
295- n = snprintf(buf, sizeof(buf), "\nnameserver %d.%d.%d.%d\n",
296- ip[0], ip[1], ip[2], ip[3]);
297- if (n > 0)
298- writeall(fd, buf, n);
299- appendfile(fd, "/etc/resolv.conf.tail");
300- close(fd);
301+ char buf[128];
302+ int fd, n;
303+
304+ if ((fd = creat("/etc/resolv.conf", 0644)) == -1) {
305+ weprintf("can't change /etc/resolv.conf:");
306+ return;
307+ }
308+ appendfile(fd, "/etc/resolv.conf.head");
309+ n = snprintf(buf, sizeof(buf), "\nnameserver %d.%d.%d.%d\n",
310+ ip[0], ip[1], ip[2], ip[3]);
311+ if (n > 0)
312+ writeall(fd, buf, n);
313+ appendfile(fd, "/etc/resolv.conf.tail");
314+ close(fd);
315 }
316
317 /* scan b's option data for opt; copy up to n bytes into data */
318 static void
319 optget(struct Bootp *b, void *data, int opt, int n)
320 {
321- unsigned char *p = b->optdata;
322- unsigned char *top = ((unsigned char *)b) + sizeof(*b);
323- int code, len;
324-
325- while (p < top) {
326- code = *p++;
327- if (code == OB_PAD)
328- continue;
329- if (code == OB_END || p == top)
330- break;
331- len = *p++;
332- if (len > top - p)
333- break;
334- if (code == opt) {
335- memcpy(data, p, MIN(len, n));
336- break;
337- }
338- p += len;
339- }
340+ unsigned char *p = b->optdata;
341+ unsigned char *top = ((unsigned char *)b) + sizeof(*b);
342+ int code, len;
343+
344+ while (p < top) {
345+ code = *p++;
346+ if (code == OB_PAD)
347+ continue;
348+ if (code == OB_END || p == top)
349+ break;
350+ len = *p++;
351+ if (len > top - p)
352+ break;
353+ if (code == opt) {
354+ memcpy(data, p, MIN(len, n));
355+ break;
356+ }
357+ p += len;
358+ }
359 }
360
361 /* append a raw-bytes option to p; return new write cursor */
362 static unsigned char *
363 optput(unsigned char *p, int opt, unsigned char *data, size_t len)
364 {
365- *p++ = opt;
366- *p++ = (unsigned char)len;
367- memcpy(p, data, len);
368+ *p++ = opt;
369+ *p++ = (unsigned char)len;
370+ memcpy(p, data, len);
371
372- return p + len;
373+ return p + len;
374 }
375
376 /* append a big-endian numeric option to p; return new write cursor */
377 static unsigned char *
378 hnoptput(unsigned char *p, int opt, uint32_t data, size_t len)
379 {
380- *p++ = opt;
381- *p++ = (unsigned char)len;
382- hnput(p, data, len);
383+ *p++ = opt;
384+ *p++ = (unsigned char)len;
385+ hnput(p, data, len);
386
387- return p + len;
388+ return p + len;
389 }
390
391 static void
392 dhcpsend(int type, int how)
393 {
394- unsigned char *ip, *p;
395-
396- memset(&bp, 0, sizeof(bp));
397- hnput(bp.op, BOOT_REQUEST, 1);
398- hnput(bp.htype, 1, 1);
399- hnput(bp.hlen, 6, 1);
400- memcpy(bp.xid, xid, sizeof(xid));
401- hnput(bp.flags, F_BROADCAST, sizeof(bp.flags));
402- hnput(bp.secs, time(NULL) - starttime, sizeof(bp.secs));
403- memcpy(bp.magic, magic, sizeof(bp.magic));
404- memcpy(bp.chaddr, hwaddr, sizeof(bp.chaddr));
405- p = bp.optdata;
406- p = hnoptput(p, OD_TYPE, type, 1);
407- p = optput(p, OD_CLIENTID, cid, sizeof(cid));
408- p = optput(p, OB_HOSTNAME, (unsigned char *)hostname, strlen(hostname));
409-
410- switch (type) {
411- case DHCP_DISCOVER:
412- break;
413- case DHCP_REQUEST:
414- p = optput(p, OD_IPADDR, client, sizeof(client));
415- p = optput(p, OD_SERVERID, server, sizeof(server));
416- break;
417- case DHCP_RELEASE:
418- memcpy(bp.ciaddr, client, sizeof(client));
419- p = optput(p, OD_IPADDR, client, sizeof(client));
420- p = optput(p, OD_SERVERID, server, sizeof(server));
421- break;
422- }
423- *p++ = OB_END;
424-
425- ip = (how == BROADCAST) ? IP(255, 255, 255, 255) : server;
426- udpsend(ip, sock, &bp, p - (unsigned char *)&bp);
427+ unsigned char *ip, *p;
428+
429+ memset(&bp, 0, sizeof(bp));
430+ hnput(bp.op, BOOT_REQUEST, 1);
431+ hnput(bp.htype, 1, 1);
432+ hnput(bp.hlen, 6, 1);
433+ memcpy(bp.xid, xid, sizeof(xid));
434+ hnput(bp.flags, F_BROADCAST, sizeof(bp.flags));
435+ hnput(bp.secs, time(NULL) - starttime, sizeof(bp.secs));
436+ memcpy(bp.magic, magic, sizeof(bp.magic));
437+ memcpy(bp.chaddr, hwaddr, sizeof(bp.chaddr));
438+ p = bp.optdata;
439+ p = hnoptput(p, OD_TYPE, type, 1);
440+ p = optput(p, OD_CLIENTID, cid, sizeof(cid));
441+ p = optput(p, OB_HOSTNAME, (unsigned char *)hostname, strlen(hostname));
442+
443+ switch (type) {
444+ case DHCP_DISCOVER:
445+ break;
446+ case DHCP_REQUEST:
447+ p = optput(p, OD_IPADDR, client, sizeof(client));
448+ p = optput(p, OD_SERVERID, server, sizeof(server));
449+ break;
450+ case DHCP_RELEASE:
451+ memcpy(bp.ciaddr, client, sizeof(client));
452+ p = optput(p, OD_IPADDR, client, sizeof(client));
453+ p = optput(p, OD_SERVERID, server, sizeof(server));
454+ break;
455+ }
456+ *p++ = OB_END;
457+
458+ ip = (how == BROADCAST) ? IP(255, 255, 255, 255) : server;
459+ udpsend(ip, sock, &bp, p - (unsigned char *)&bp);
460 }
461
462 /* block on poll; return DHCP message type or a TIMEOUT* sentinel */
463 static int
464 dhcprecv(void)
465 {
466- unsigned char type = 0;
467- uint64_t n;
468- struct pollfd pfd[] = {
469- { .fd = sock, .events = POLLIN },
470- { .fd = timers[0], .events = POLLIN },
471- { .fd = timers[1], .events = POLLIN },
472- { .fd = timers[2], .events = POLLIN },
473- };
474-
475- if (poll(pfd, LEN(pfd), -1) == -1)
476- eprintf("poll:");
477- if (pfd[0].revents) {
478- memset(&bp, 0, sizeof(bp));
479- udprecv(IP(255, 255, 255, 255), sock, &bp, sizeof(bp));
480- optget(&bp, &type, OD_TYPE, sizeof(type));
481- return type;
482- }
483- if (pfd[1].revents) {
484- type = TIMEOUT0;
485- read(timers[0], &n, sizeof(n));
486- }
487- if (pfd[2].revents) {
488- type = TIMEOUT1;
489- read(timers[1], &n, sizeof(n));
490- }
491- if (pfd[3].revents) {
492- type = TIMEOUT2;
493- read(timers[2], &n, sizeof(n));
494- }
495- return type;
496+ unsigned char type = 0;
497+ uint64_t n;
498+ struct pollfd pfd[] = {
499+ { .fd = sock, .events = POLLIN },
500+ { .fd = timers[0], .events = POLLIN },
501+ { .fd = timers[1], .events = POLLIN },
502+ { .fd = timers[2], .events = POLLIN },
503+ };
504+
505+ if (poll(pfd, LEN(pfd), -1) == -1)
506+ eprintf("poll:");
507+ if (pfd[0].revents) {
508+ memset(&bp, 0, sizeof(bp));
509+ udprecv(IP(255, 255, 255, 255), sock, &bp, sizeof(bp));
510+ optget(&bp, &type, OD_TYPE, sizeof(type));
511+ return type;
512+ }
513+ if (pfd[1].revents) {
514+ type = TIMEOUT0;
515+ read(timers[0], &n, sizeof(n));
516+ }
517+ if (pfd[2].revents) {
518+ type = TIMEOUT1;
519+ read(timers[1], &n, sizeof(n));
520+ }
521+ if (pfd[3].revents) {
522+ type = TIMEOUT2;
523+ read(timers[2], &n, sizeof(n));
524+ }
525+ return type;
526 }
527
528 static void
529 acceptlease(void)
530 {
531- char buf[128];
532-
533- if (iflag)
534- setip(client, mask, router);
535- if (dflag)
536- setdns(dns);
537- if (*program) {
538- snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
539- server[0], server[1], server[2], server[3]);
540- setenv("SERVER", buf, 1);
541- snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
542- client[0], client[1], client[2], client[3]);
543- setenv("CLIENT", buf, 1);
544- snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
545- mask[0], mask[1], mask[2], mask[3]);
546- setenv("MASK", buf, 1);
547- snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
548- router[0], router[1], router[2], router[3]);
549- setenv("ROUTER", buf, 1);
550- snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
551- dns[0], dns[1], dns[2], dns[3]);
552- setenv("DNS", buf, 1);
553- system(program);
554- }
555+ char buf[128];
556+
557+ if (iflag)
558+ setip(client, mask, router);
559+ if (dflag)
560+ setdns(dns);
561+ if (*program) {
562+ snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
563+ server[0], server[1], server[2], server[3]);
564+ setenv("SERVER", buf, 1);
565+ snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
566+ client[0], client[1], client[2], client[3]);
567+ setenv("CLIENT", buf, 1);
568+ snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
569+ mask[0], mask[1], mask[2], mask[3]);
570+ setenv("MASK", buf, 1);
571+ snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
572+ router[0], router[1], router[2], router[3]);
573+ setenv("ROUTER", buf, 1);
574+ snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
575+ dns[0], dns[1], dns[2], dns[3]);
576+ setenv("DNS", buf, 1);
577+ wsystem(program);
578+ }
579 }
580
581 static void
582 settimeout(int n, const struct itimerspec *ts)
583 {
584- if (timerfd_settime(timers[n], 0, ts, NULL) < 0)
585- eprintf("timerfd_settime:");
586+ if (timerfd_settime(timers[n], 0, ts, NULL) < 0)
587+ eprintf("timerfd_settime:");
588 }
589
590 /* set ts to expire halfway to the remaining time on timer n, minimum 60s */
591 static void
592 calctimeout(int n, struct itimerspec *ts)
593 {
594- if (timerfd_gettime(timers[n], ts) < 0)
595- eprintf("timerfd_gettime:");
596- ts->it_value.tv_nsec /= 2;
597- if (ts->it_value.tv_sec % 2)
598- ts->it_value.tv_nsec += 500000000;
599- ts->it_value.tv_sec /= 2;
600- if (ts->it_value.tv_sec < 60) {
601- ts->it_value.tv_sec = 60;
602- ts->it_value.tv_nsec = 0;
603- }
604+ if (timerfd_gettime(timers[n], ts) < 0)
605+ eprintf("timerfd_gettime:");
606+ ts->it_value.tv_nsec /= 2;
607+ if (ts->it_value.tv_sec % 2)
608+ ts->it_value.tv_nsec += 500000000;
609+ ts->it_value.tv_sec /= 2;
610+ if (ts->it_value.tv_sec < 60) {
611+ ts->it_value.tv_sec = 60;
612+ ts->it_value.tv_nsec = 0;
613+ }
614 }
615
616 /* RFC 2131 DHCP state machine */
617 static void
618 run(void)
619 {
620- int forked = 0, t;
621- struct itimerspec timeout = { 0 };
622- uint32_t renewaltime, rebindingtime, lease;
623+ int forked = 0, t;
624+ struct itimerspec timeout = { 0 };
625+ uint32_t renewaltime, rebindingtime, lease;
626
627 Init:
628- dhcpsend(DHCP_DISCOVER, BROADCAST);
629- timeout.it_value.tv_sec = 1;
630- timeout.it_value.tv_nsec = 0;
631- settimeout(0, &timeout);
632- goto Selecting;
633+ dhcpsend(DHCP_DISCOVER, BROADCAST);
634+ timeout.it_value.tv_sec = 1;
635+ timeout.it_value.tv_nsec = 0;
636+ settimeout(0, &timeout);
637+ goto Selecting;
638 Selecting:
639- for (;;) {
640- switch (dhcprecv()) {
641- case DHCP_OFFER:
642- memcpy(client, bp.yiaddr, sizeof(client));
643- optget(&bp, server, OD_SERVERID, sizeof(server));
644- goto Requesting;
645- case TIMEOUT0:
646- goto Init;
647- }
648- }
649+ for (;;) {
650+ switch (dhcprecv()) {
651+ case DHCP_OFFER:
652+ memcpy(client, bp.yiaddr, sizeof(client));
653+ optget(&bp, server, OD_SERVERID, sizeof(server));
654+ goto Requesting;
655+ case TIMEOUT0:
656+ goto Init;
657+ }
658+ }
659 Requesting:
660- for (t = 4; t <= 64; t *= 2) {
661- dhcpsend(DHCP_REQUEST, BROADCAST);
662- timeout.it_value.tv_sec = t;
663- settimeout(0, &timeout);
664- for (;;) {
665- switch (dhcprecv()) {
666- case DHCP_ACK:
667- goto Bound;
668- case DHCP_NAK:
669- goto Init;
670- case TIMEOUT0:
671- break;
672- default:
673- continue;
674- }
675- break;
676- }
677- }
678- /* no ACK after several DHCPREQUEST attempts */
679- goto Init;
680+ for (t = 4; t <= 64; t *= 2) {
681+ dhcpsend(DHCP_REQUEST, BROADCAST);
682+ timeout.it_value.tv_sec = t;
683+ settimeout(0, &timeout);
684+ for (;;) {
685+ switch (dhcprecv()) {
686+ case DHCP_ACK:
687+ goto Bound;
688+ case DHCP_NAK:
689+ goto Init;
690+ case TIMEOUT0:
691+ break;
692+ default:
693+ continue;
694+ }
695+ break;
696+ }
697+ }
698+ /* no ACK after several DHCPREQUEST attempts */
699+ goto Init;
700 Bound:
701- optget(&bp, mask, OB_MASK, sizeof(mask));
702- optget(&bp, router, OB_ROUTER, sizeof(router));
703- optget(&bp, dns, OB_DNSSERVER, sizeof(dns));
704- optget(&bp, &renewaltime, OD_RENEWALTIME, sizeof(renewaltime));
705- optget(&bp, &rebindingtime, OD_REBINDINGTIME, sizeof(rebindingtime));
706- optget(&bp, &lease, OD_LEASE, sizeof(lease));
707- renewaltime = ntohl(renewaltime);
708- rebindingtime = ntohl(rebindingtime);
709- lease = ntohl(lease);
710- acceptlease();
711- puts("Bound. Network configured.");
712- if (!fflag && !forked) {
713- if (fork())
714- exit(0);
715- forked = 1;
716- }
717- timeout.it_value.tv_sec = renewaltime;
718- settimeout(0, &timeout);
719- timeout.it_value.tv_sec = rebindingtime;
720- settimeout(1, &timeout);
721- timeout.it_value.tv_sec = lease;
722- settimeout(2, &timeout);
723- for (;;) {
724- switch (dhcprecv()) {
725- case TIMEOUT0: /* t1: enter renewing */
726- goto Renewing;
727- case TIMEOUT1: /* t2: enter rebinding */
728- goto Rebinding;
729- case TIMEOUT2: /* lease expired */
730- goto Init;
731- }
732- }
733+ optget(&bp, mask, OB_MASK, sizeof(mask));
734+ optget(&bp, router, OB_ROUTER, sizeof(router));
735+ optget(&bp, dns, OB_DNSSERVER, sizeof(dns));
736+ optget(&bp, &renewaltime, OD_RENEWALTIME, sizeof(renewaltime));
737+ optget(&bp, &rebindingtime, OD_REBINDINGTIME, sizeof(rebindingtime));
738+ optget(&bp, &lease, OD_LEASE, sizeof(lease));
739+ renewaltime = ntohl(renewaltime);
740+ rebindingtime = ntohl(rebindingtime);
741+ lease = ntohl(lease);
742+ acceptlease();
743+ puts("Bound. Network configured.");
744+ if (!fflag && !forked) {
745+ if (fork())
746+ exit(0);
747+ forked = 1;
748+ }
749+ timeout.it_value.tv_sec = renewaltime;
750+ settimeout(0, &timeout);
751+ timeout.it_value.tv_sec = rebindingtime;
752+ settimeout(1, &timeout);
753+ timeout.it_value.tv_sec = lease;
754+ settimeout(2, &timeout);
755+ for (;;) {
756+ switch (dhcprecv()) {
757+ case TIMEOUT0: /* t1: enter renewing */
758+ goto Renewing;
759+ case TIMEOUT1: /* t2: enter rebinding */
760+ goto Rebinding;
761+ case TIMEOUT2: /* lease expired */
762+ goto Init;
763+ }
764+ }
765 Renewing:
766- dhcpsend(DHCP_REQUEST, UNICAST);
767- calctimeout(1, &timeout);
768- settimeout(0, &timeout);
769- for (;;) {
770- switch (dhcprecv()) {
771- case DHCP_ACK:
772- goto Bound;
773- case TIMEOUT0: /* resend unicast */
774- goto Renewing;
775- case TIMEOUT1: /* t2 elapsed */
776- goto Rebinding;
777- case TIMEOUT2:
778- case DHCP_NAK:
779- goto Init;
780- }
781- }
782+ dhcpsend(DHCP_REQUEST, UNICAST);
783+ calctimeout(1, &timeout);
784+ settimeout(0, &timeout);
785+ for (;;) {
786+ switch (dhcprecv()) {
787+ case DHCP_ACK:
788+ goto Bound;
789+ case TIMEOUT0: /* resend unicast */
790+ goto Renewing;
791+ case TIMEOUT1: /* t2 elapsed */
792+ goto Rebinding;
793+ case TIMEOUT2:
794+ case DHCP_NAK:
795+ goto Init;
796+ }
797+ }
798 Rebinding:
799- calctimeout(2, &timeout);
800- settimeout(0, &timeout);
801- dhcpsend(DHCP_REQUEST, BROADCAST);
802- for (;;) {
803- switch (dhcprecv()) {
804- case DHCP_ACK:
805- goto Bound;
806- case TIMEOUT0: /* resend broadcast */
807- goto Rebinding;
808- case TIMEOUT2: /* lease expired */
809- case DHCP_NAK:
810- goto Init;
811- }
812- }
813+ calctimeout(2, &timeout);
814+ settimeout(0, &timeout);
815+ dhcpsend(DHCP_REQUEST, BROADCAST);
816+ for (;;) {
817+ switch (dhcprecv()) {
818+ case DHCP_ACK:
819+ goto Bound;
820+ case TIMEOUT0: /* resend broadcast */
821+ goto Rebinding;
822+ case TIMEOUT2: /* lease expired */
823+ case DHCP_NAK:
824+ goto Init;
825+ }
826+ }
827 }
828
829 static void
830 cleanexit(int unused)
831 {
832- (void)unused;
833- dhcpsend(DHCP_RELEASE, UNICAST);
834- _exit(0);
835+ (void)unused;
836+ dhcpsend(DHCP_RELEASE, UNICAST);
837+ _exit(0);
838 }
839
840 static void
841 usage(void)
842 {
843- eprintf("usage: %s [-d] [-e program] [-f] [-i] [ifname] [clientid]\n", argv0);
844+ eprintf("usage: %s [-d] [-e program] [-f] [-i] [ifname] [clientid]\n", argv0);
845 }
846
847+// ?man sdhcp: minimal DHCP client
848+// ?man arguments: [ifname] [clientid]
849+// ?man obtain an IPv4 lease via DHCP on the given interface
850 int
851 main(int argc, char *argv[])
852 {
853- struct ifreq ifreq;
854- struct sockaddr addr;
855- int bcast = 1;
856- int rnd;
857- size_t i;
858-
859- ARGBEGIN {
860- case 'd': /* don't update /etc/resolv.conf */
861- dflag = 0;
862- break;
863- case 'e': /* exec program on each lease */
864- program = EARGF(usage());
865- break;
866- case 'f': /* stay in foreground */
867- fflag = 1;
868- break;
869- case 'i': /* don't configure IP address */
870- iflag = 0;
871- break;
872- default:
873- usage();
874- break;
875- } ARGEND
876-
877- if (argc)
878- ifname = argv[0];
879- if (argc >= 2)
880- strlcpy((char *)cid, argv[1], sizeof(cid));
881-
882- memset(&ifreq, 0, sizeof(ifreq));
883- signal(SIGTERM, cleanexit);
884-
885- if (gethostname(hostname, sizeof(hostname)) == -1)
886- eprintf("gethostname:");
887-
888- if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
889- eprintf("socket:");
890- if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) == -1)
891- eprintf("setsockopt SO_BROADCAST:");
892-
893- strlcpy(ifreq.ifr_name, ifname, IF_NAMESIZE);
894- ioctl(sock, SIOCGIFINDEX, &ifreq);
895- if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof(ifreq)) == -1)
896- eprintf("setsockopt SO_BINDTODEVICE:");
897- iptoaddr(&addr, IP(255, 255, 255, 255), 68);
898- if (bind(sock, &addr, sizeof(addr)) != 0)
899- eprintf("bind:");
900- ioctl(sock, SIOCGIFHWADDR, &ifreq);
901- memcpy(hwaddr, ifreq.ifr_hwaddr.sa_data, sizeof(ifreq.ifr_hwaddr.sa_data));
902- if (!cid[0])
903- memcpy(cid, hwaddr, sizeof(cid));
904-
905- if ((rnd = open("/dev/urandom", O_RDONLY)) == -1)
906- eprintf("open /dev/urandom:");
907- if (read(rnd, xid, sizeof(xid)) != (ssize_t)sizeof(xid))
908- eprintf("read /dev/urandom:");
909- close(rnd);
910-
911- for (i = 0; i < LEN(timers); ++i) {
912- timers[i] = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC);
913- if (timers[i] == -1)
914- eprintf("timerfd_create:");
915- }
916-
917- starttime = time(NULL);
918- run();
919-
920- return 0;
921+ struct ifreq ifreq;
922+ struct sockaddr addr;
923+ int bcast = 1;
924+ int rnd;
925+ size_t i;
926+
927+ ARGBEGIN {
928+ case 'd': /* don't update /etc/resolv.conf */
929+ dflag = 0;
930+ break;
931+ case 'e': /* exec program on each lease */
932+ program = EARGF(usage());
933+ break;
934+ case 'f': /* stay in foreground */
935+ fflag = 1;
936+ break;
937+ case 'i': /* don't configure IP address */
938+ iflag = 0;
939+ break;
940+ default:
941+ usage();
942+ break;
943+ } ARGEND
944+
945+ if (argc)
946+ ifname = argv[0];
947+ if (argc >= 2)
948+ strlcpy((char *)cid, argv[1], sizeof(cid));
949+
950+ memset(&ifreq, 0, sizeof(ifreq));
951+ signal(SIGTERM, cleanexit);
952+
953+ if (gethostname(hostname, sizeof(hostname)) == -1)
954+ eprintf("gethostname:");
955+
956+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
957+ eprintf("socket:");
958+ if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) == -1)
959+ eprintf("setsockopt SO_BROADCAST:");
960+
961+ strlcpy(ifreq.ifr_name, ifname, IF_NAMESIZE);
962+ ioctl(sock, SIOCGIFINDEX, &ifreq);
963+ if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof(ifreq)) == -1)
964+ eprintf("setsockopt SO_BINDTODEVICE:");
965+ iptoaddr(&addr, IP(255, 255, 255, 255), 68);
966+ if (bind(sock, &addr, sizeof(addr)) != 0)
967+ eprintf("bind:");
968+ ioctl(sock, SIOCGIFHWADDR, &ifreq);
969+ memcpy(hwaddr, ifreq.ifr_hwaddr.sa_data, sizeof(ifreq.ifr_hwaddr.sa_data));
970+ if (!cid[0])
971+ memcpy(cid, hwaddr, sizeof(cid));
972+
973+ if ((rnd = open("/dev/urandom", O_RDONLY)) == -1)
974+ eprintf("open /dev/urandom:");
975+ if (read(rnd, xid, sizeof(xid)) != (ssize_t)sizeof(xid))
976+ eprintf("read /dev/urandom:");
977+ close(rnd);
978+
979+ for (i = 0; i < LEN(timers); ++i) {
980+ timers[i] = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC);
981+ if (timers[i] == -1)
982+ eprintf("timerfd_create:");
983+ }
984+
985+ starttime = time(NULL);
986+ run();
987+
988+ return 0;
989 }
+1997,
-1990
1@@ -1,19 +1,19 @@
2 /* See LICENSE file for copyright and license details. */
3+#include "paths.h"
4 #include "util.h"
5+#include "wexec.h"
6
7 #include <sys/stat.h>
8 #include <sys/wait.h>
9
10 #include <ctype.h>
11 #include <dirent.h>
12-#include <err.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <fnmatch.h>
16 #include <getopt.h>
17 #include <limits.h>
18 #include <math.h>
19-#include <paths.h>
20 #include <poll.h>
21 #include <regex.h>
22 #include <signal.h>
23@@ -86,114 +86,113 @@
24 #define COLORFLAG_ALWAYS 2
25
26 #define FUNCTION_CONTEXT_SIZE 55
27-#define _PATH_PR "/usr/bin/pr"
28
29 #ifndef roundup
30 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
31 #endif
32
33 struct Excludes {
34- char *pattern;
35- struct Excludes *next;
36+ char *pattern;
37+ struct Excludes *next;
38 };
39
40 struct Cand {
41- int x;
42- int y;
43- int pred;
44+ int x;
45+ int y;
46+ int pred;
47 };
48
49 struct Line {
50- int serial;
51- int value;
52+ int serial;
53+ int value;
54 };
55
56 struct ContextVec {
57- int a;
58- int b;
59- int c;
60- int d;
61+ int a;
62+ int b;
63+ int c;
64+ int d;
65 };
66
67 struct Pr {
68- int ostdout;
69- pid_t cpid;
70+ int ostdout;
71+ pid_t cpid;
72 };
73
74 struct Algorithm {
75- const char *name;
76- int id;
77+ const char *name;
78+ int id;
79 };
80
81 static struct Algorithm algorithms[] = {
82- {"stone", D_DIFFSTONE},
83- {"myers", D_DIFFMYERS},
84- {"patience", D_DIFFPATIENCE},
85- {NULL, D_DIFFNONE}
86+ {"stone", D_DIFFSTONE},
87+ {"myers", D_DIFFMYERS},
88+ {"patience", D_DIFFPATIENCE},
89+ {NULL, D_DIFFNONE}
90 };
91
92 /* options */
93 #define OPTIONS "0123456789A:aBbC:cdD:efF:HhI:iL:lnNPpqrS:sTtU:uwW:X:x:y"
94 enum {
95- OPT_TSIZE = CHAR_MAX + 1,
96- OPT_STRIPCR,
97- OPT_IGN_FN_CASE,
98- OPT_NO_IGN_FN_CASE,
99- OPT_NORMAL,
100- OPT_HELP,
101- OPT_HORIZON_LINES,
102- OPT_CHANGED_GROUP_FORMAT,
103- OPT_SUPPRESS_COMMON,
104- OPT_COLOR,
105- OPT_NO_DEREFERENCE,
106- OPT_VERSION,
107+ OPT_TSIZE = CHAR_MAX + 1,
108+ OPT_STRIPCR,
109+ OPT_IGN_FN_CASE,
110+ OPT_NO_IGN_FN_CASE,
111+ OPT_NORMAL,
112+ OPT_HELP,
113+ OPT_HORIZON_LINES,
114+ OPT_CHANGED_GROUP_FORMAT,
115+ OPT_SUPPRESS_COMMON,
116+ OPT_COLOR,
117+ OPT_NO_DEREFERENCE,
118+ OPT_VERSION,
119 };
120
121 static struct option longopts[] = {
122- { "algorithm", required_argument, 0, 'A' },
123- { "text", no_argument, 0, 'a' },
124- { "ignore-space-change", no_argument, 0, 'b' },
125- { "context", optional_argument, 0, 'C' },
126- { "ifdef", required_argument, 0, 'D' },
127- { "minimal", no_argument, 0, 'd' },
128- { "ed", no_argument, 0, 'e' },
129- { "forward-ed", no_argument, 0, 'f' },
130- { "show-function-line", required_argument, 0, 'F' },
131- { "speed-large-files", no_argument, NULL, 'H' },
132- { "ignore-blank-lines", no_argument, 0, 'B' },
133- { "ignore-matching-lines", required_argument, 0, 'I' },
134- { "ignore-case", no_argument, 0, 'i' },
135- { "paginate", no_argument, NULL, 'l' },
136- { "label", required_argument, 0, 'L' },
137- { "new-file", no_argument, 0, 'N' },
138- { "rcs", no_argument, 0, 'n' },
139- { "unidirectional-new-file", no_argument, 0, 'P' },
140- { "show-c-function", no_argument, 0, 'p' },
141- { "brief", no_argument, 0, 'q' },
142- { "recursive", no_argument, 0, 'r' },
143- { "report-identical-files", no_argument, 0, 's' },
144- { "starting-file", required_argument, 0, 'S' },
145- { "expand-tabs", no_argument, 0, 't' },
146- { "initial-tab", no_argument, 0, 'T' },
147- { "unified", optional_argument, 0, 'U' },
148- { "ignore-all-space", no_argument, 0, 'w' },
149- { "width", required_argument, 0, 'W' },
150- { "exclude", required_argument, 0, 'x' },
151- { "exclude-from", required_argument, 0, 'X' },
152- { "side-by-side", no_argument, NULL, 'y' },
153- { "ignore-file-name-case", no_argument, NULL, OPT_IGN_FN_CASE },
154- { "help", no_argument, NULL, OPT_HELP},
155- { "horizon-lines", required_argument, NULL, OPT_HORIZON_LINES },
156- { "no-dereference", no_argument, NULL, OPT_NO_DEREFERENCE},
157- { "no-ignore-file-name-case", no_argument, NULL, OPT_NO_IGN_FN_CASE },
158- { "normal", no_argument, NULL, OPT_NORMAL },
159- { "strip-trailing-cr", no_argument, NULL, OPT_STRIPCR },
160- { "tabsize", required_argument, NULL, OPT_TSIZE },
161- { "changed-group-format", required_argument, NULL, OPT_CHANGED_GROUP_FORMAT},
162- { "suppress-common-lines", no_argument, NULL, OPT_SUPPRESS_COMMON },
163- { "color", optional_argument, NULL, OPT_COLOR },
164- { "version", no_argument, NULL, OPT_VERSION},
165- { NULL, 0, 0, '\0'}
166+ { "algorithm", required_argument, 0, 'A' },
167+ { "text", no_argument, 0, 'a' },
168+ { "ignore-space-change", no_argument, 0, 'b' },
169+ { "context", optional_argument, 0, 'C' },
170+ { "ifdef", required_argument, 0, 'D' },
171+ { "minimal", no_argument, 0, 'd' },
172+ { "ed", no_argument, 0, 'e' },
173+ { "forward-ed", no_argument, 0, 'f' },
174+ { "show-function-line", required_argument, 0, 'F' },
175+ { "speed-large-files", no_argument, NULL, 'H' },
176+ { "ignore-blank-lines", no_argument, 0, 'B' },
177+ { "ignore-matching-lines", required_argument, 0, 'I' },
178+ { "ignore-case", no_argument, 0, 'i' },
179+ { "paginate", no_argument, NULL, 'l' },
180+ { "label", required_argument, 0, 'L' },
181+ { "new-file", no_argument, 0, 'N' },
182+ { "rcs", no_argument, 0, 'n' },
183+ { "unidirectional-new-file", no_argument, 0, 'P' },
184+ { "show-c-function", no_argument, 0, 'p' },
185+ { "brief", no_argument, 0, 'q' },
186+ { "recursive", no_argument, 0, 'r' },
187+ { "report-identical-files", no_argument, 0, 's' },
188+ { "starting-file", required_argument, 0, 'S' },
189+ { "expand-tabs", no_argument, 0, 't' },
190+ { "initial-tab", no_argument, 0, 'T' },
191+ { "unified", optional_argument, 0, 'U' },
192+ { "ignore-all-space", no_argument, 0, 'w' },
193+ { "width", required_argument, 0, 'W' },
194+ { "exclude", required_argument, 0, 'x' },
195+ { "exclude-from", required_argument, 0, 'X' },
196+ { "side-by-side", no_argument, NULL, 'y' },
197+ { "ignore-file-name-case", no_argument, NULL, OPT_IGN_FN_CASE },
198+ { "help", no_argument, NULL, OPT_HELP},
199+ { "horizon-lines", required_argument, NULL, OPT_HORIZON_LINES },
200+ { "no-dereference", no_argument, NULL, OPT_NO_DEREFERENCE},
201+ { "no-ignore-file-name-case", no_argument, NULL, OPT_NO_IGN_FN_CASE },
202+ { "normal", no_argument, NULL, OPT_NORMAL },
203+ { "strip-trailing-cr", no_argument, NULL, OPT_STRIPCR },
204+ { "tabsize", required_argument, NULL, OPT_TSIZE },
205+ { "changed-group-format", required_argument, NULL, OPT_CHANGED_GROUP_FORMAT},
206+ { "suppress-common-lines", no_argument, NULL, OPT_SUPPRESS_COMMON },
207+ { "color", optional_argument, NULL, OPT_COLOR },
208+ { "version", no_argument, NULL, OPT_VERSION},
209+ { NULL, 0, 0, '\0'}
210 };
211
212 static const char diff_version[] = "FreeBSD diff 20240307";
213@@ -213,9 +212,9 @@ struct Excludes *excludes_list;
214 regex_t ignore_re, most_recent_re;
215
216 enum Readhash {
217- RH_BINARY,
218- RH_OK,
219- RH_EOF
220+ RH_BINARY,
221+ RH_OK,
222+ RH_EOF
223 };
224
225 static struct Line *file[2];
226@@ -305,101 +304,109 @@ void stop_pr(struct Pr *);
227 static void
228 handle_sig(int signo)
229 {
230- write(sigpipe[1], &signo, sizeof(signo));
231+ write(sigpipe[1], &signo, sizeof(signo));
232 }
233
234 struct Pr *
235 start_pr(char *file1, char *file2)
236 {
237- int pfd[2];
238- pid_t pid;
239- char *header;
240- struct Pr *pr;
241-
242- pr = ecalloc(1, sizeof(*pr));
243- xasprintf(&header, "%s %s %s", diffargs, file1, file2);
244- signal(SIGPIPE, SIG_IGN);
245- fflush(stdout);
246- if (pipe(pfd) == -1)
247- err(2, "pipe");
248- if (sigpipe[0] < 0) {
249- if (pipe(sigpipe) == -1)
250- err(2, "pipe");
251- if (fcntl(sigpipe[0], F_SETFD, FD_CLOEXEC) == -1)
252- err(2, "fcntl");
253- if (fcntl(sigpipe[1], F_SETFD, FD_CLOEXEC) == -1)
254- err(2, "fcntl");
255- if (signal(SIGCHLD, handle_sig) == SIG_ERR)
256- err(2, "signal");
257- poll_fd.fd = sigpipe[0];
258- poll_fd.events = POLLIN;
259- }
260- poll_fd.revents = 0;
261- switch ((pid = fork())) {
262- case -1:
263- status |= 2;
264- free(header);
265- err(2, "no more processes");
266- case 0:
267- if (pfd[0] != STDIN_FILENO) {
268- dup2(pfd[0], STDIN_FILENO);
269- close(pfd[0]);
270- }
271- close(pfd[1]);
272- execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0);
273- _exit(127);
274- default:
275- if (pfd[1] != STDOUT_FILENO) {
276- pr->ostdout = dup(STDOUT_FILENO);
277- dup2(pfd[1], STDOUT_FILENO);
278- close(pfd[1]);
279- }
280- close(pfd[0]);
281- free(header);
282- pr->cpid = pid;
283- }
284- return pr;
285+ int pfd[2];
286+ pid_t pid;
287+ char *header;
288+ struct Pr *pr;
289+
290+ pr = ecalloc(1, sizeof(*pr));
291+ xasprintf(&header, "%s %s %s", diffargs, file1, file2);
292+ signal(SIGPIPE, SIG_IGN);
293+ fflush(stdout);
294+ if (pipe(pfd) == -1)
295+ enprintf(2, "pipe");
296+ if (sigpipe[0] < 0) {
297+ if (pipe(sigpipe) == -1)
298+ enprintf(2, "pipe");
299+ if (fcntl(sigpipe[0], F_SETFD, FD_CLOEXEC) == -1)
300+ enprintf(2, "fcntl");
301+ if (fcntl(sigpipe[1], F_SETFD, FD_CLOEXEC) == -1)
302+ enprintf(2, "fcntl");
303+ if (signal(SIGCHLD, handle_sig) == SIG_ERR)
304+ enprintf(2, "signal");
305+ poll_fd.fd = sigpipe[0];
306+ poll_fd.events = POLLIN;
307+ }
308+ poll_fd.revents = 0;
309+ switch ((pid = fork())) {
310+ case -1:
311+ status |= 2;
312+ free(header);
313+ enprintf(2, "no more processes");
314+ /* fallthrough */
315+ case 0:
316+ if (pfd[0] != STDIN_FILENO) {
317+ dup2(pfd[0], STDIN_FILENO);
318+ close(pfd[0]);
319+ }
320+ close(pfd[1]);
321+ {
322+ char *pr_argv[4];
323+ pr_argv[0] = "pr";
324+ pr_argv[1] = "-h";
325+ pr_argv[2] = header;
326+ pr_argv[3] = NULL;
327+ wexecvp_self("pr", pr_argv);
328+ }
329+ _exit(127);
330+ default:
331+ if (pfd[1] != STDOUT_FILENO) {
332+ pr->ostdout = dup(STDOUT_FILENO);
333+ dup2(pfd[1], STDOUT_FILENO);
334+ close(pfd[1]);
335+ }
336+ close(pfd[0]);
337+ free(header);
338+ pr->cpid = pid;
339+ }
340+ return pr;
341 }
342
343 void
344 stop_pr(struct Pr *pr)
345 {
346- int wstatus;
347- int done = 0;
348-
349- if (!pr)
350- return;
351-
352- fflush(stdout);
353- if (pr->ostdout != STDOUT_FILENO) {
354- close(STDOUT_FILENO);
355- dup2(pr->ostdout, STDOUT_FILENO);
356- close(pr->ostdout);
357- }
358- while (!done) {
359- pid_t wpid;
360- int npe = poll(&poll_fd, 1, -1);
361- if (npe == -1) {
362- if (errno == EINTR)
363- continue;
364- err(2, "poll");
365- }
366- if (poll_fd.revents != POLLIN)
367- continue;
368- if (read(poll_fd.fd, &npe, sizeof(npe)) < 0)
369- err(2, "read");
370- while ((wpid = waitpid(-1, &wstatus, WNOHANG)) > 0) {
371- if (wpid != pr->cpid)
372- continue;
373- if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0)
374- errx(2, "pr exited abnormally");
375- else if (WIFSIGNALED(wstatus))
376- errx(2, "pr killed by signal %d", WTERMSIG(wstatus));
377- done = 1;
378- break;
379- }
380- }
381- free(pr);
382+ int wstatus;
383+ int done = 0;
384+
385+ if (!pr)
386+ return;
387+
388+ fflush(stdout);
389+ if (pr->ostdout != STDOUT_FILENO) {
390+ close(STDOUT_FILENO);
391+ dup2(pr->ostdout, STDOUT_FILENO);
392+ close(pr->ostdout);
393+ }
394+ while (!done) {
395+ pid_t wpid;
396+ int npe = poll(&poll_fd, 1, -1);
397+ if (npe == -1) {
398+ if (errno == EINTR)
399+ continue;
400+ enprintf(2, "poll");
401+ }
402+ if (poll_fd.revents != POLLIN)
403+ continue;
404+ if (read(poll_fd.fd, &npe, sizeof(npe)) < 0)
405+ enprintf(2, "read");
406+ while ((wpid = waitpid(-1, &wstatus, WNOHANG)) > 0) {
407+ if (wpid != pr->cpid)
408+ continue;
409+ if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0)
410+ enprintf(2, "pr exited abnormally");
411+ else if (WIFSIGNALED(wstatus))
412+ enprintf(2, "pr killed by signal %d", WTERMSIG(wstatus));
413+ done = 1;
414+ break;
415+ }
416+ }
417+ free(pr);
418 }
419
420 // ?man diff: differential file and directory comparator
421@@ -408,1823 +415,1823 @@ stop_pr(struct Pr *pr)
422 int
423 main(int argc, char **argv)
424 {
425- const char *errstr = NULL;
426- char *ep, **oargv;
427- long l;
428- int ch, dflags, lastch, gotstdin, prevoptind, newarg;
429-
430- oargv = argv;
431- gotstdin = 0;
432- dflags = 0;
433- lastch = '\0';
434- prevoptind = 1;
435- newarg = 1;
436- diff_context = 3;
437- diff_format = D_UNSET;
438- diff_algorithm = D_DIFFMYERS;
439- diff_algorithm_set = 0;
440+ const char *errstr = NULL;
441+ char *ep, **oargv;
442+ long l;
443+ int ch, dflags, lastch, gotstdin, prevoptind, newarg;
444+
445+ oargv = argv;
446+ gotstdin = 0;
447+ dflags = 0;
448+ lastch = '\0';
449+ prevoptind = 1;
450+ newarg = 1;
451+ diff_context = 3;
452+ diff_format = D_UNSET;
453+ diff_algorithm = D_DIFFMYERS;
454+ diff_algorithm_set = 0;
455 #define FORMAT_MISMATCHED(type) \
456- (diff_format != D_UNSET && diff_format != (type))
457- while ((ch = getopt_long(argc, argv, OPTIONS, longopts, NULL)) != -1) {
458- // ?man -0: context length
459- // ?man -1: context length
460- // ?man -2: context length
461- // ?man -3: context length
462- // ?man -4: context length
463- // ?man -5: context length
464- // ?man -6: context length
465- // ?man -7: context length
466- // ?man -8: context length
467- // ?man -9: context length
468- switch (ch) {
469- case '0': case '1': case '2': case '3': case '4':
470- case '5': case '6': case '7': case '8': case '9':
471- if (newarg)
472- usage();
473- else if (lastch == 'c' || lastch == 'u')
474- diff_context = 0;
475- else if (!isdigit(lastch) || diff_context > INT_MAX / 10)
476- usage();
477- diff_context = (diff_context * 10) + (ch - '0');
478- break;
479- // ?man -A:algo: algorithm (stone, myers, patience)
480- case 'A':
481- diff_algorithm = D_DIFFNONE;
482- for (struct Algorithm *a = algorithms; a->name; a++) {
483- if (strcasecmp(optarg, a->name) == 0) {
484- diff_algorithm = a->id;
485- diff_algorithm_set = 1;
486- break;
487- }
488- }
489- if (diff_algorithm == D_DIFFNONE) {
490- printf("unknown algorithm: %s\n", optarg);
491- usage();
492- }
493- break;
494- // ?man -a: force text mode
495- case 'a':
496- dflags |= D_FORCEASCII;
497- break;
498- // ?man -b: ignore space changes
499- case 'b':
500- dflags |= D_FOLDBLANKS;
501- break;
502- // ?man -C:lines: context format
503- case 'C':
504- // ?man -c: context format
505- case 'c':
506- if (FORMAT_MISMATCHED(D_CONTEXT))
507- conflicting_format();
508- cflag = 1;
509- diff_format = D_CONTEXT;
510- if (optarg != NULL) {
511- l = strtol(optarg, &ep, 10);
512- if (*ep != '\0' || l < 0 || l >= INT_MAX)
513- usage();
514- diff_context = (int)l;
515- }
516- break;
517- // ?man -d: minimal diff search
518- case 'd':
519- dflags |= D_MINIMAL;
520- break;
521- // ?man -D:name: ifdef format
522- case 'D':
523- if (FORMAT_MISMATCHED(D_IFDEF))
524- conflicting_format();
525- diff_format = D_IFDEF;
526- ifdefname = optarg;
527- break;
528- // ?man -e: ed script format
529- case 'e':
530- if (FORMAT_MISMATCHED(D_EDIT))
531- conflicting_format();
532- diff_format = D_EDIT;
533- break;
534- // ?man -f: forward ed script format
535- case 'f':
536- if (FORMAT_MISMATCHED(D_REVERSE))
537- conflicting_format();
538- diff_format = D_REVERSE;
539- break;
540- // ?man -H: speed up large files (stub)
541- case 'H':
542- break;
543- // ?man -h: backward compatibility (stub)
544- case 'h':
545- break;
546- // ?man -B: ignore blank lines
547- case 'B':
548- dflags |= D_SKIPBLANKLINES;
549- break;
550- // ?man -F:pat: show function matching pattern
551- case 'F':
552- if (dflags & D_PROTOTYPE)
553- conflicting_format();
554- dflags |= D_MATCHLAST;
555- most_recent_pat = estrdup(optarg);
556- break;
557- // ?man -I:pat: ignore pattern matching lines
558- case 'I':
559- push_ignore_pats(optarg);
560- break;
561- // ?man -i: ignore case
562- case 'i':
563- dflags |= D_IGNORECASE;
564- break;
565- // ?man -L:label: custom label
566- case 'L':
567- if (label[0] == NULL)
568- label[0] = optarg;
569- else if (label[1] == NULL)
570- label[1] = optarg;
571- else
572- usage();
573- break;
574- // ?man -l: paginate output using pr
575- case 'l':
576- lflag = 1;
577- break;
578- // ?man -N: treat missing files as empty
579- case 'N':
580- Nflag = 1;
581- break;
582- // ?man -n: rcs format
583- case 'n':
584- if (FORMAT_MISMATCHED(D_NREVERSE))
585- conflicting_format();
586- diff_format = D_NREVERSE;
587- break;
588- // ?man -p: show C prototype context
589- case 'p':
590- if (dflags & D_MATCHLAST)
591- conflicting_format();
592- dflags |= D_PROTOTYPE;
593- break;
594- // ?man -P: treat missing destination files as empty
595- case 'P':
596- Pflag = 1;
597- break;
598- // ?man -r: recursive directory comparison
599- case 'r':
600- rflag = 1;
601- break;
602- // ?man -q: brief output (differ / same only)
603- case 'q':
604- if (FORMAT_MISMATCHED(D_BRIEF))
605- conflicting_format();
606- diff_format = D_BRIEF;
607- break;
608- // ?man -S:name: starting file in directory comparison
609- case 'S':
610- start = optarg;
611- break;
612- // ?man -s: report identical files
613- case 's':
614- sflag = 1;
615- break;
616- // ?man -T: initial tab alignment
617- case 'T':
618- Tflag = 1;
619- break;
620- // ?man -t: expand tabs in output
621- case 't':
622- dflags |= D_EXPANDTABS;
623- break;
624- // ?man -U:lines: unified context format
625- case 'U':
626- // ?man -u: unified context format
627- case 'u':
628- if (FORMAT_MISMATCHED(D_UNIFIED))
629- conflicting_format();
630- diff_format = D_UNIFIED;
631- if (optarg != NULL) {
632- l = strtol(optarg, &ep, 10);
633- if (*ep != '\0' || l < 0 || l >= INT_MAX)
634- usage();
635- diff_context = (int)l;
636- }
637- break;
638- // ?man -w: ignore all whitespace
639- case 'w':
640- dflags |= D_IGNOREBLANKS;
641- break;
642- // ?man -W:cols: column width for side-by-side
643- case 'W':
644- width = (int)strtonum(optarg, 1, INT_MAX, &errstr);
645- if (errstr) {
646- warnx("invalid width argument");
647- usage();
648- }
649- break;
650- // ?man -X:file: exclude patterns file
651- case 'X':
652- read_excludes_file(optarg);
653- break;
654- // ?man -x:pat: exclude pattern
655- case 'x':
656- push_excludes(optarg);
657- break;
658- // ?man -y: side by side format
659- case 'y':
660- if (FORMAT_MISMATCHED(D_SIDEBYSIDE))
661- conflicting_format();
662- diff_format = D_SIDEBYSIDE;
663- break;
664- case OPT_CHANGED_GROUP_FORMAT:
665- if (FORMAT_MISMATCHED(D_GFORMAT))
666- conflicting_format();
667- diff_format = D_GFORMAT;
668- group_format = optarg;
669- break;
670- case OPT_HELP:
671- help = 1;
672- usage();
673- break;
674- case OPT_HORIZON_LINES:
675- break;
676- case OPT_IGN_FN_CASE:
677- ignore_file_case = 1;
678- break;
679- case OPT_NO_IGN_FN_CASE:
680- ignore_file_case = 0;
681- break;
682- case OPT_NORMAL:
683- if (FORMAT_MISMATCHED(D_NORMAL))
684- conflicting_format();
685- diff_format = D_NORMAL;
686- break;
687- case OPT_TSIZE:
688- tabsize = (int)strtonum(optarg, 1, INT_MAX, &errstr);
689- if (errstr) {
690- warnx("invalid tabsize argument");
691- usage();
692- }
693- break;
694- case OPT_STRIPCR:
695- dflags |= D_STRIPCR;
696- break;
697- case OPT_SUPPRESS_COMMON:
698- suppress_common = 1;
699- break;
700- case OPT_COLOR:
701- if (optarg == NULL || strncmp(optarg, "auto", 4) == 0)
702- colorflag = COLORFLAG_AUTO;
703- else if (strncmp(optarg, "always", 6) == 0)
704- colorflag = COLORFLAG_ALWAYS;
705- else if (strncmp(optarg, "never", 5) == 0)
706- colorflag = COLORFLAG_NEVER;
707- else
708- errx(2, "unsupported color option %s", optarg);
709- break;
710- case OPT_NO_DEREFERENCE:
711- noderef = 1;
712- break;
713- case OPT_VERSION:
714- printf("%s\n", diff_version);
715- exit(0);
716- default:
717- usage();
718- break;
719- }
720- lastch = ch;
721- newarg = optind != prevoptind;
722- prevoptind = optind;
723- }
724- if (diff_format == D_UNSET && (dflags & D_PROTOTYPE) != 0)
725- diff_format = D_CONTEXT;
726- if (diff_format == D_UNSET)
727- diff_format = D_NORMAL;
728- argc -= optind;
729- argv += optind;
730-
731- if (do_color()) {
732- char *p;
733- const char *env;
734-
735- color = 1;
736- add_code = "32";
737- del_code = "31";
738- env = getenv("DIFFCOLORS");
739- if (env != NULL && *env != '\0' && (p = estrdup(env))) {
740- add_code = p;
741- strsep(&p, ":");
742- if (p != NULL)
743- del_code = p;
744- }
745- }
746-
747- if (argc != 2)
748- usage();
749- checked_regcomp(ignore_pats, &ignore_re);
750- checked_regcomp(most_recent_pat, &most_recent_re);
751- if (strcmp(argv[0], "-") == 0) {
752- fstat(STDIN_FILENO, &stb1);
753- gotstdin = 1;
754- } else if (stat(argv[0], &stb1) != 0) {
755- if (!Nflag || errno != ENOENT)
756- err(2, "%s", argv[0]);
757- dflags |= D_EMPTY1;
758- memset(&stb1, 0, sizeof(struct stat));
759- }
760-
761- if (strcmp(argv[1], "-") == 0) {
762- fstat(STDIN_FILENO, &stb2);
763- gotstdin = 1;
764- } else if (stat(argv[1], &stb2) != 0) {
765- if (!Nflag || errno != ENOENT)
766- err(2, "%s", argv[1]);
767- dflags |= D_EMPTY2;
768- memset(&stb2, 0, sizeof(stb2));
769- stb2.st_mode = stb1.st_mode;
770- }
771-
772- if (dflags & D_EMPTY1 && dflags & D_EMPTY2){
773- warn("%s", argv[0]);
774- warn("%s", argv[1]);
775- exit(2);
776- }
777-
778- if (stb1.st_mode == 0)
779- stb1.st_mode = stb2.st_mode;
780-
781- if (gotstdin && (S_ISDIR(stb1.st_mode) || S_ISDIR(stb2.st_mode)))
782- errx(2, "cant compare - to directory");
783- set_argstr(oargv, argv);
784- if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) {
785- if (diff_format == D_IFDEF)
786- errx(2, "-D option not supported with directories");
787- diffdir(argv[0], argv[1], dflags);
788- } else {
789- if (S_ISDIR(stb1.st_mode)) {
790- argv[0] = diff_splice(argv[0], argv[1]);
791- if (stat(argv[0], &stb1) == -1)
792- err(2, "%s", argv[0]);
793- }
794- if (S_ISDIR(stb2.st_mode)) {
795- argv[1] = diff_splice(argv[1], argv[0]);
796- if (stat(argv[1], &stb2) == -1)
797- err(2, "%s", argv[1]);
798- }
799- print_status(diffreg(argv[0], argv[1], dflags, 1), argv[0], argv[1], "");
800- }
801- if (fflush(stdout) != 0)
802- err(2, "stdout");
803- exit(status);
804+ (diff_format != D_UNSET && diff_format != (type))
805+ while ((ch = getopt_long(argc, argv, OPTIONS, longopts, NULL)) != -1) {
806+ // ?man -0: context length
807+ // ?man -1: context length
808+ // ?man -2: context length
809+ // ?man -3: context length
810+ // ?man -4: context length
811+ // ?man -5: context length
812+ // ?man -6: context length
813+ // ?man -7: context length
814+ // ?man -8: context length
815+ // ?man -9: context length
816+ switch (ch) {
817+ case '0': case '1': case '2': case '3': case '4':
818+ case '5': case '6': case '7': case '8': case '9':
819+ if (newarg)
820+ usage();
821+ else if (lastch == 'c' || lastch == 'u')
822+ diff_context = 0;
823+ else if (!isdigit(lastch) || diff_context > INT_MAX / 10)
824+ usage();
825+ diff_context = (diff_context * 10) + (ch - '0');
826+ break;
827+ // ?man -A:algo: algorithm (stone, myers, patience)
828+ case 'A':
829+ diff_algorithm = D_DIFFNONE;
830+ for (struct Algorithm *a = algorithms; a->name; a++) {
831+ if (strcasecmp(optarg, a->name) == 0) {
832+ diff_algorithm = a->id;
833+ diff_algorithm_set = 1;
834+ break;
835+ }
836+ }
837+ if (diff_algorithm == D_DIFFNONE) {
838+ printf("unknown algorithm: %s\n", optarg);
839+ usage();
840+ }
841+ break;
842+ // ?man -a: force text mode
843+ case 'a':
844+ dflags |= D_FORCEASCII;
845+ break;
846+ // ?man -b: ignore space changes
847+ case 'b':
848+ dflags |= D_FOLDBLANKS;
849+ break;
850+ // ?man -C:lines: context format
851+ case 'C':
852+ // ?man -c: context format
853+ case 'c':
854+ if (FORMAT_MISMATCHED(D_CONTEXT))
855+ conflicting_format();
856+ cflag = 1;
857+ diff_format = D_CONTEXT;
858+ if (optarg != NULL) {
859+ l = strtol(optarg, &ep, 10);
860+ if (*ep != '\0' || l < 0 || l >= INT_MAX)
861+ usage();
862+ diff_context = (int)l;
863+ }
864+ break;
865+ // ?man -d: minimal diff search
866+ case 'd':
867+ dflags |= D_MINIMAL;
868+ break;
869+ // ?man -D:name: ifdef format
870+ case 'D':
871+ if (FORMAT_MISMATCHED(D_IFDEF))
872+ conflicting_format();
873+ diff_format = D_IFDEF;
874+ ifdefname = optarg;
875+ break;
876+ // ?man -e: ed script format
877+ case 'e':
878+ if (FORMAT_MISMATCHED(D_EDIT))
879+ conflicting_format();
880+ diff_format = D_EDIT;
881+ break;
882+ // ?man -f: forward ed script format
883+ case 'f':
884+ if (FORMAT_MISMATCHED(D_REVERSE))
885+ conflicting_format();
886+ diff_format = D_REVERSE;
887+ break;
888+ // ?man -H: speed up large files (stub)
889+ case 'H':
890+ break;
891+ // ?man -h: backward compatibility (stub)
892+ case 'h':
893+ break;
894+ // ?man -B: ignore blank lines
895+ case 'B':
896+ dflags |= D_SKIPBLANKLINES;
897+ break;
898+ // ?man -F:pat: show function matching pattern
899+ case 'F':
900+ if (dflags & D_PROTOTYPE)
901+ conflicting_format();
902+ dflags |= D_MATCHLAST;
903+ most_recent_pat = estrdup(optarg);
904+ break;
905+ // ?man -I:pat: ignore pattern matching lines
906+ case 'I':
907+ push_ignore_pats(optarg);
908+ break;
909+ // ?man -i: ignore case
910+ case 'i':
911+ dflags |= D_IGNORECASE;
912+ break;
913+ // ?man -L:label: custom label
914+ case 'L':
915+ if (label[0] == NULL)
916+ label[0] = optarg;
917+ else if (label[1] == NULL)
918+ label[1] = optarg;
919+ else
920+ usage();
921+ break;
922+ // ?man -l: paginate output using pr
923+ case 'l':
924+ lflag = 1;
925+ break;
926+ // ?man -N: treat missing files as empty
927+ case 'N':
928+ Nflag = 1;
929+ break;
930+ // ?man -n: rcs format
931+ case 'n':
932+ if (FORMAT_MISMATCHED(D_NREVERSE))
933+ conflicting_format();
934+ diff_format = D_NREVERSE;
935+ break;
936+ // ?man -p: show C prototype context
937+ case 'p':
938+ if (dflags & D_MATCHLAST)
939+ conflicting_format();
940+ dflags |= D_PROTOTYPE;
941+ break;
942+ // ?man -P: treat missing destination files as empty
943+ case 'P':
944+ Pflag = 1;
945+ break;
946+ // ?man -r: recursive directory comparison
947+ case 'r':
948+ rflag = 1;
949+ break;
950+ // ?man -q: brief output (differ / same only)
951+ case 'q':
952+ if (FORMAT_MISMATCHED(D_BRIEF))
953+ conflicting_format();
954+ diff_format = D_BRIEF;
955+ break;
956+ // ?man -S:name: starting file in directory comparison
957+ case 'S':
958+ start = optarg;
959+ break;
960+ // ?man -s: report identical files
961+ case 's':
962+ sflag = 1;
963+ break;
964+ // ?man -T: initial tab alignment
965+ case 'T':
966+ Tflag = 1;
967+ break;
968+ // ?man -t: expand tabs in output
969+ case 't':
970+ dflags |= D_EXPANDTABS;
971+ break;
972+ // ?man -U:lines: unified context format
973+ case 'U':
974+ // ?man -u: unified context format
975+ case 'u':
976+ if (FORMAT_MISMATCHED(D_UNIFIED))
977+ conflicting_format();
978+ diff_format = D_UNIFIED;
979+ if (optarg != NULL) {
980+ l = strtol(optarg, &ep, 10);
981+ if (*ep != '\0' || l < 0 || l >= INT_MAX)
982+ usage();
983+ diff_context = (int)l;
984+ }
985+ break;
986+ // ?man -w: ignore all whitespace
987+ case 'w':
988+ dflags |= D_IGNOREBLANKS;
989+ break;
990+ // ?man -W:cols: column width for side-by-side
991+ case 'W':
992+ width = (int)strtonum(optarg, 1, INT_MAX, &errstr);
993+ if (errstr) {
994+ weprintf("invalid width argument");
995+ usage();
996+ }
997+ break;
998+ // ?man -X:file: exclude patterns file
999+ case 'X':
1000+ read_excludes_file(optarg);
1001+ break;
1002+ // ?man -x:pat: exclude pattern
1003+ case 'x':
1004+ push_excludes(optarg);
1005+ break;
1006+ // ?man -y: side by side format
1007+ case 'y':
1008+ if (FORMAT_MISMATCHED(D_SIDEBYSIDE))
1009+ conflicting_format();
1010+ diff_format = D_SIDEBYSIDE;
1011+ break;
1012+ case OPT_CHANGED_GROUP_FORMAT:
1013+ if (FORMAT_MISMATCHED(D_GFORMAT))
1014+ conflicting_format();
1015+ diff_format = D_GFORMAT;
1016+ group_format = optarg;
1017+ break;
1018+ case OPT_HELP:
1019+ help = 1;
1020+ usage();
1021+ break;
1022+ case OPT_HORIZON_LINES:
1023+ break;
1024+ case OPT_IGN_FN_CASE:
1025+ ignore_file_case = 1;
1026+ break;
1027+ case OPT_NO_IGN_FN_CASE:
1028+ ignore_file_case = 0;
1029+ break;
1030+ case OPT_NORMAL:
1031+ if (FORMAT_MISMATCHED(D_NORMAL))
1032+ conflicting_format();
1033+ diff_format = D_NORMAL;
1034+ break;
1035+ case OPT_TSIZE:
1036+ tabsize = (int)strtonum(optarg, 1, INT_MAX, &errstr);
1037+ if (errstr) {
1038+ weprintf("invalid tabsize argument");
1039+ usage();
1040+ }
1041+ break;
1042+ case OPT_STRIPCR:
1043+ dflags |= D_STRIPCR;
1044+ break;
1045+ case OPT_SUPPRESS_COMMON:
1046+ suppress_common = 1;
1047+ break;
1048+ case OPT_COLOR:
1049+ if (optarg == NULL || strncmp(optarg, "auto", 4) == 0)
1050+ colorflag = COLORFLAG_AUTO;
1051+ else if (strncmp(optarg, "always", 6) == 0)
1052+ colorflag = COLORFLAG_ALWAYS;
1053+ else if (strncmp(optarg, "never", 5) == 0)
1054+ colorflag = COLORFLAG_NEVER;
1055+ else
1056+ enprintf(2, "unsupported color option %s", optarg);
1057+ break;
1058+ case OPT_NO_DEREFERENCE:
1059+ noderef = 1;
1060+ break;
1061+ case OPT_VERSION:
1062+ printf("%s\n", diff_version);
1063+ exit(0);
1064+ default:
1065+ usage();
1066+ break;
1067+ }
1068+ lastch = ch;
1069+ newarg = optind != prevoptind;
1070+ prevoptind = optind;
1071+ }
1072+ if (diff_format == D_UNSET && (dflags & D_PROTOTYPE) != 0)
1073+ diff_format = D_CONTEXT;
1074+ if (diff_format == D_UNSET)
1075+ diff_format = D_NORMAL;
1076+ argc -= optind;
1077+ argv += optind;
1078+
1079+ if (do_color()) {
1080+ char *p;
1081+ const char *env;
1082+
1083+ color = 1;
1084+ add_code = "32";
1085+ del_code = "31";
1086+ env = getenv("DIFFCOLORS");
1087+ if (env != NULL && *env != '\0' && (p = estrdup(env))) {
1088+ add_code = p;
1089+ strsep(&p, ":");
1090+ if (p != NULL)
1091+ del_code = p;
1092+ }
1093+ }
1094+
1095+ if (argc != 2)
1096+ usage();
1097+ checked_regcomp(ignore_pats, &ignore_re);
1098+ checked_regcomp(most_recent_pat, &most_recent_re);
1099+ if (strcmp(argv[0], "-") == 0) {
1100+ fstat(STDIN_FILENO, &stb1);
1101+ gotstdin = 1;
1102+ } else if (stat(argv[0], &stb1) != 0) {
1103+ if (!Nflag || errno != ENOENT)
1104+ enprintf(2, "%s", argv[0]);
1105+ dflags |= D_EMPTY1;
1106+ memset(&stb1, 0, sizeof(struct stat));
1107+ }
1108+
1109+ if (strcmp(argv[1], "-") == 0) {
1110+ fstat(STDIN_FILENO, &stb2);
1111+ gotstdin = 1;
1112+ } else if (stat(argv[1], &stb2) != 0) {
1113+ if (!Nflag || errno != ENOENT)
1114+ enprintf(2, "%s", argv[1]);
1115+ dflags |= D_EMPTY2;
1116+ memset(&stb2, 0, sizeof(stb2));
1117+ stb2.st_mode = stb1.st_mode;
1118+ }
1119+
1120+ if (dflags & D_EMPTY1 && dflags & D_EMPTY2){
1121+ weprintf("%s", argv[0]);
1122+ weprintf("%s", argv[1]);
1123+ exit(2);
1124+ }
1125+
1126+ if (stb1.st_mode == 0)
1127+ stb1.st_mode = stb2.st_mode;
1128+
1129+ if (gotstdin && (S_ISDIR(stb1.st_mode) || S_ISDIR(stb2.st_mode)))
1130+ enprintf(2, "cant compare - to directory");
1131+ set_argstr(oargv, argv);
1132+ if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) {
1133+ if (diff_format == D_IFDEF)
1134+ enprintf(2, "-D option not supported with directories");
1135+ diffdir(argv[0], argv[1], dflags);
1136+ } else {
1137+ if (S_ISDIR(stb1.st_mode)) {
1138+ argv[0] = diff_splice(argv[0], argv[1]);
1139+ if (stat(argv[0], &stb1) == -1)
1140+ enprintf(2, "%s", argv[0]);
1141+ }
1142+ if (S_ISDIR(stb2.st_mode)) {
1143+ argv[1] = diff_splice(argv[1], argv[0]);
1144+ if (stat(argv[1], &stb2) == -1)
1145+ enprintf(2, "%s", argv[1]);
1146+ }
1147+ print_status(diffreg(argv[0], argv[1], dflags, 1), argv[0], argv[1], "");
1148+ }
1149+ if (fflush(stdout) != 0)
1150+ enprintf(2, "stdout");
1151+ exit(status);
1152 }
1153
1154 static void
1155 checked_regcomp(char const *pattern, regex_t *comp)
1156 {
1157- char buf[BUFSIZ];
1158- int error;
1159-
1160- if (pattern == NULL)
1161- return;
1162-
1163- error = regcomp(comp, pattern, REG_NEWLINE | REG_EXTENDED);
1164- if (error != 0) {
1165- regerror(error, comp, buf, sizeof(buf));
1166- if (*pattern != '\0')
1167- errx(2, "%s: %s", pattern, buf);
1168- else
1169- errx(2, "%s", buf);
1170- }
1171+ char buf[BUFSIZ];
1172+ int error;
1173+
1174+ if (pattern == NULL)
1175+ return;
1176+
1177+ error = regcomp(comp, pattern, REG_NEWLINE | REG_EXTENDED);
1178+ if (error != 0) {
1179+ regerror(error, comp, buf, sizeof(buf));
1180+ if (*pattern != '\0')
1181+ enprintf(2, "%s: %s", pattern, buf);
1182+ else
1183+ enprintf(2, "%s", buf);
1184+ }
1185 }
1186
1187 static void
1188 set_argstr(char **av, char **ave)
1189 {
1190- size_t argsize;
1191- char **ap;
1192-
1193- argsize = strlen("diff") + 1;
1194- for (ap = av + 1; ap < ave; ap++) {
1195- if (strcmp(*ap, "--") != 0)
1196- argsize += 1 + strlen(*ap);
1197- }
1198- diffargs = emalloc(argsize);
1199- strlcpy(diffargs, "diff", argsize);
1200- for (ap = av + 1; ap < ave; ap++) {
1201- if (strcmp(*ap, "--") != 0) {
1202- strlcat(diffargs, " ", argsize);
1203- strlcat(diffargs, *ap, argsize);
1204- }
1205- }
1206+ size_t argsize;
1207+ char **ap;
1208+
1209+ argsize = strlen("diff") + 1;
1210+ for (ap = av + 1; ap < ave; ap++) {
1211+ if (strcmp(*ap, "--") != 0)
1212+ argsize += 1 + strlen(*ap);
1213+ }
1214+ diffargs = emalloc(argsize);
1215+ strlcpy(diffargs, "diff", argsize);
1216+ for (ap = av + 1; ap < ave; ap++) {
1217+ if (strcmp(*ap, "--") != 0) {
1218+ strlcat(diffargs, " ", argsize);
1219+ strlcat(diffargs, *ap, argsize);
1220+ }
1221+ }
1222 }
1223
1224 static void
1225 read_excludes_file(char *file)
1226 {
1227- FILE *fp;
1228- char *pattern = NULL;
1229- size_t blen = 0;
1230- ssize_t len;
1231-
1232- if (strcmp(file, "-") == 0)
1233- fp = stdin;
1234- else if ((fp = fopen(file, "r")) == NULL)
1235- err(2, "%s", file);
1236- while ((len = getline(&pattern, &blen, fp)) >= 0) {
1237- if ((len > 0) && (pattern[len - 1] == '\n'))
1238- pattern[len - 1] = '\0';
1239- push_excludes(pattern);
1240- pattern = NULL;
1241- blen = 0;
1242- }
1243- free(pattern);
1244- if (strcmp(file, "-") != 0)
1245- fclose(fp);
1246+ FILE *fp;
1247+ char *pattern = NULL;
1248+ size_t blen = 0;
1249+ ssize_t len;
1250+
1251+ if (strcmp(file, "-") == 0)
1252+ fp = stdin;
1253+ else if ((fp = fopen(file, "r")) == NULL)
1254+ enprintf(2, "%s", file);
1255+ while ((len = getline(&pattern, &blen, fp)) >= 0) {
1256+ if ((len > 0) && (pattern[len - 1] == '\n'))
1257+ pattern[len - 1] = '\0';
1258+ push_excludes(pattern);
1259+ pattern = NULL;
1260+ blen = 0;
1261+ }
1262+ free(pattern);
1263+ if (strcmp(file, "-") != 0)
1264+ fclose(fp);
1265 }
1266
1267 static void
1268 push_excludes(char *pattern)
1269 {
1270- struct Excludes *entry;
1271+ struct Excludes *entry;
1272
1273- entry = emalloc(sizeof(*entry));
1274- entry->pattern = pattern;
1275- entry->next = excludes_list;
1276- excludes_list = entry;
1277+ entry = emalloc(sizeof(*entry));
1278+ entry->pattern = pattern;
1279+ entry->next = excludes_list;
1280+ excludes_list = entry;
1281 }
1282
1283 static void
1284 push_ignore_pats(char *pattern)
1285 {
1286- size_t len;
1287-
1288- if (ignore_pats == NULL)
1289- ignore_pats = estrdup(pattern);
1290- else {
1291- len = strlen(ignore_pats) + strlen(pattern) + 2;
1292- ignore_pats = ereallocarray(ignore_pats, 1, len);
1293- strlcat(ignore_pats, "|", len);
1294- strlcat(ignore_pats, pattern, len);
1295- }
1296+ size_t len;
1297+
1298+ if (ignore_pats == NULL)
1299+ ignore_pats = estrdup(pattern);
1300+ else {
1301+ len = strlen(ignore_pats) + strlen(pattern) + 2;
1302+ ignore_pats = ereallocarray(ignore_pats, 1, len);
1303+ strlcat(ignore_pats, "|", len);
1304+ strlcat(ignore_pats, pattern, len);
1305+ }
1306 }
1307
1308 void
1309 print_status(int val, char *path1, char *path2, const char *entry)
1310 {
1311- if (label[0] != NULL)
1312- path1 = label[0];
1313- if (label[1] != NULL)
1314- path2 = label[1];
1315-
1316- switch (val) {
1317- case D_BINARY:
1318- printf("Binary files %s%s and %s%s differ\n", path1, entry, path2, entry);
1319- break;
1320- case D_DIFFER:
1321- if (diff_format == D_BRIEF)
1322- printf("Files %s%s and %s%s differ\n", path1, entry, path2, entry);
1323- break;
1324- case D_SAME:
1325- if (sflag)
1326- printf("Files %s%s and %s%s are identical\n", path1, entry, path2, entry);
1327- break;
1328- case D_MISMATCH1:
1329- printf("File %s%s is directory, %s%s is file\n", path1, entry, path2, entry);
1330- break;
1331- case D_MISMATCH2:
1332- printf("File %s%s is file, %s%s is directory\n", path1, entry, path2, entry);
1333- break;
1334- case D_SKIPPED1:
1335- printf("File %s%s is not regular file or directory\n", path1, entry);
1336- break;
1337- case D_SKIPPED2:
1338- printf("File %s%s is not regular file or directory\n", path2, entry);
1339- break;
1340- }
1341+ if (label[0] != NULL)
1342+ path1 = label[0];
1343+ if (label[1] != NULL)
1344+ path2 = label[1];
1345+
1346+ switch (val) {
1347+ case D_BINARY:
1348+ printf("Binary files %s%s and %s%s differ\n", path1, entry, path2, entry);
1349+ break;
1350+ case D_DIFFER:
1351+ if (diff_format == D_BRIEF)
1352+ printf("Files %s%s and %s%s differ\n", path1, entry, path2, entry);
1353+ break;
1354+ case D_SAME:
1355+ if (sflag)
1356+ printf("Files %s%s and %s%s are identical\n", path1, entry, path2, entry);
1357+ break;
1358+ case D_MISMATCH1:
1359+ printf("File %s%s is directory, %s%s is file\n", path1, entry, path2, entry);
1360+ break;
1361+ case D_MISMATCH2:
1362+ printf("File %s%s is file, %s%s is directory\n", path1, entry, path2, entry);
1363+ break;
1364+ case D_SKIPPED1:
1365+ printf("File %s%s is not regular file or directory\n", path1, entry);
1366+ break;
1367+ case D_SKIPPED2:
1368+ printf("File %s%s is not regular file or directory\n", path2, entry);
1369+ break;
1370+ }
1371 }
1372
1373 static void
1374 usage(void)
1375 {
1376- fprintf(stderr, "usage: diff [-aBbdipTtw] [-c|-e|-f|-n|-q|-u|-y] [-A algo] "
1377- "[-I pattern] [-F pattern] [-L label] file1 file2\n");
1378- exit(2);
1379+ fprintf(stderr, "usage: diff [-aBbdipTtw] [-c|-e|-f|-n|-q|-u|-y] [-A algo] "
1380+ "[-I pattern] [-F pattern] [-L label] file1 file2\n");
1381+ exit(2);
1382 }
1383
1384 static void
1385 conflicting_format(void)
1386 {
1387- errx(2, "conflicting output format options");
1388+ enprintf(2, "conflicting output format options");
1389 }
1390
1391 static char *
1392 diff_splice(char *dir, char *file)
1393 {
1394- char *p, *res;
1395+ char *p, *res;
1396
1397- p = strrchr(file, '/');
1398- p = p ? p + 1 : file;
1399- xasprintf(&res, "%s/%s", dir, p);
1400- return res;
1401+ p = strrchr(file, '/');
1402+ p = p ? p + 1 : file;
1403+ xasprintf(&res, "%s/%s", dir, p);
1404+ return res;
1405 }
1406
1407 static void
1408 xasprintf(char **strp, const char *fmt, ...)
1409 {
1410- va_list ap;
1411- int r;
1412-
1413- va_start(ap, fmt);
1414- r = vasprintf(strp, fmt, ap);
1415- va_end(ap);
1416- if (r == -1)
1417- err(2, "asprintf");
1418+ va_list ap;
1419+ int r;
1420+
1421+ va_start(ap, fmt);
1422+ r = vasprintf(strp, fmt, ap);
1423+ va_end(ap);
1424+ if (r == -1)
1425+ enprintf(2, "asprintf");
1426 }
1427
1428 static int
1429 cup2low(int c)
1430 {
1431- return tolower(c);
1432+ return tolower(c);
1433 }
1434
1435 static int
1436 clow2low(int c)
1437 {
1438- return c;
1439+ return c;
1440 }
1441
1442 static int
1443 do_color(void)
1444 {
1445- if (colorflag == COLORFLAG_ALWAYS)
1446- return 1;
1447- if (colorflag == COLORFLAG_NEVER)
1448- return 0;
1449- if (isatty(STDOUT_FILENO)) {
1450- char *term = getenv("COLORTERM");
1451- if (term && *term != '\0')
1452- return 1;
1453- }
1454- return 0;
1455+ if (colorflag == COLORFLAG_ALWAYS)
1456+ return 1;
1457+ if (colorflag == COLORFLAG_NEVER)
1458+ return 0;
1459+ if (isatty(STDOUT_FILENO)) {
1460+ char *term = getenv("COLORTERM");
1461+ if (term && *term != '\0')
1462+ return 1;
1463+ }
1464+ return 0;
1465 }
1466
1467 void
1468 diffdir(char *p1, char *p2, int flags)
1469 {
1470- struct dirent *dent1, **dp1, **edp1, **dirp1 = NULL;
1471- struct dirent *dent2, **dp2, **edp2, **dirp2 = NULL;
1472- size_t dirlen1, dirlen2;
1473- char path1[PATH_MAX], path2[PATH_MAX];
1474- int pos;
1475-
1476- edp1 = edp2 = NULL;
1477- dirlen1 = strlcpy(path1, *p1 ? p1 : ".", sizeof(path1));
1478- if (dirlen1 >= sizeof(path1) - 1) {
1479- errno = ENAMETOOLONG;
1480- warn("%s", p1);
1481- status |= 2;
1482- return;
1483- }
1484- if (path1[dirlen1 - 1] != '/') {
1485- path1[dirlen1++] = '/';
1486- path1[dirlen1] = '\0';
1487- }
1488- dirlen2 = strlcpy(path2, *p2 ? p2 : ".", sizeof(path2));
1489- if (dirlen2 >= sizeof(path2) - 1) {
1490- errno = ENAMETOOLONG;
1491- warn("%s", p2);
1492- status |= 2;
1493- return;
1494- }
1495- if (path2[dirlen2 - 1] != '/') {
1496- path2[dirlen2++] = '/';
1497- path2[dirlen2] = '\0';
1498- }
1499-
1500- pos = scandir(path1, &dirp1, selectfile, alphasort);
1501- if (pos == -1) {
1502- if (errno == ENOENT && (Nflag || Pflag))
1503- pos = 0;
1504- else {
1505- warn("%s", path1);
1506- goto closem;
1507- }
1508- }
1509- dp1 = dirp1;
1510- edp1 = dirp1 + pos;
1511-
1512- pos = scandir(path2, &dirp2, selectfile, alphasort);
1513- if (pos == -1) {
1514- if (errno == ENOENT && Nflag)
1515- pos = 0;
1516- else {
1517- warn("%s", path2);
1518- goto closem;
1519- }
1520- }
1521- dp2 = dirp2;
1522- edp2 = dirp2 + pos;
1523-
1524- if (start != NULL) {
1525- while (dp1 != edp1 && strcmp((*dp1)->d_name, start) < 0)
1526- dp1++;
1527- while (dp2 != edp2 && strcmp((*dp2)->d_name, start) < 0)
1528- dp2++;
1529- }
1530-
1531- while (dp1 != edp1 || dp2 != edp2) {
1532- dent1 = dp1 != edp1 ? *dp1 : NULL;
1533- dent2 = dp2 != edp2 ? *dp2 : NULL;
1534-
1535- pos = dent1 == NULL ? 1 : dent2 == NULL ? -1 :
1536- ignore_file_case ? strcasecmp(dent1->d_name, dent2->d_name) :
1537- strcmp(dent1->d_name, dent2->d_name);
1538- if (pos == 0) {
1539- diffit(dent1, path1, dirlen1, dent2, path2, dirlen2, flags);
1540- dp1++;
1541- dp2++;
1542- } else if (pos < 0) {
1543- if (Nflag)
1544- diffit(dent1, path1, dirlen1, dent2, path2, dirlen2, flags);
1545- else {
1546- print_only(path1, dirlen1, dent1->d_name);
1547- status |= 1;
1548- }
1549- dp1++;
1550- } else {
1551- if (Nflag || Pflag)
1552- diffit(dent2, path1, dirlen1, dent1, path2, dirlen2, flags);
1553- else {
1554- print_only(path2, dirlen2, dent2->d_name);
1555- status |= 1;
1556- }
1557- dp2++;
1558- }
1559- }
1560+ struct dirent *dent1, **dp1, **edp1, **dirp1 = NULL;
1561+ struct dirent *dent2, **dp2, **edp2, **dirp2 = NULL;
1562+ size_t dirlen1, dirlen2;
1563+ char path1[PATH_MAX], path2[PATH_MAX];
1564+ int pos;
1565+
1566+ edp1 = edp2 = NULL;
1567+ dirlen1 = strlcpy(path1, *p1 ? p1 : ".", sizeof(path1));
1568+ if (dirlen1 >= sizeof(path1) - 1) {
1569+ errno = ENAMETOOLONG;
1570+ weprintf("%s", p1);
1571+ status |= 2;
1572+ return;
1573+ }
1574+ if (path1[dirlen1 - 1] != '/') {
1575+ path1[dirlen1++] = '/';
1576+ path1[dirlen1] = '\0';
1577+ }
1578+ dirlen2 = strlcpy(path2, *p2 ? p2 : ".", sizeof(path2));
1579+ if (dirlen2 >= sizeof(path2) - 1) {
1580+ errno = ENAMETOOLONG;
1581+ weprintf("%s", p2);
1582+ status |= 2;
1583+ return;
1584+ }
1585+ if (path2[dirlen2 - 1] != '/') {
1586+ path2[dirlen2++] = '/';
1587+ path2[dirlen2] = '\0';
1588+ }
1589+
1590+ pos = scandir(path1, &dirp1, selectfile, alphasort);
1591+ if (pos == -1) {
1592+ if (errno == ENOENT && (Nflag || Pflag))
1593+ pos = 0;
1594+ else {
1595+ weprintf("%s", path1);
1596+ goto closem;
1597+ }
1598+ }
1599+ dp1 = dirp1;
1600+ edp1 = dirp1 + pos;
1601+
1602+ pos = scandir(path2, &dirp2, selectfile, alphasort);
1603+ if (pos == -1) {
1604+ if (errno == ENOENT && Nflag)
1605+ pos = 0;
1606+ else {
1607+ weprintf("%s", path2);
1608+ goto closem;
1609+ }
1610+ }
1611+ dp2 = dirp2;
1612+ edp2 = dirp2 + pos;
1613+
1614+ if (start != NULL) {
1615+ while (dp1 != edp1 && strcmp((*dp1)->d_name, start) < 0)
1616+ dp1++;
1617+ while (dp2 != edp2 && strcmp((*dp2)->d_name, start) < 0)
1618+ dp2++;
1619+ }
1620+
1621+ while (dp1 != edp1 || dp2 != edp2) {
1622+ dent1 = dp1 != edp1 ? *dp1 : NULL;
1623+ dent2 = dp2 != edp2 ? *dp2 : NULL;
1624+
1625+ pos = dent1 == NULL ? 1 : dent2 == NULL ? -1 :
1626+ ignore_file_case ? strcasecmp(dent1->d_name, dent2->d_name) :
1627+ strcmp(dent1->d_name, dent2->d_name);
1628+ if (pos == 0) {
1629+ diffit(dent1, path1, dirlen1, dent2, path2, dirlen2, flags);
1630+ dp1++;
1631+ dp2++;
1632+ } else if (pos < 0) {
1633+ if (Nflag)
1634+ diffit(dent1, path1, dirlen1, dent2, path2, dirlen2, flags);
1635+ else {
1636+ print_only(path1, dirlen1, dent1->d_name);
1637+ status |= 1;
1638+ }
1639+ dp1++;
1640+ } else {
1641+ if (Nflag || Pflag)
1642+ diffit(dent2, path1, dirlen1, dent1, path2, dirlen2, flags);
1643+ else {
1644+ print_only(path2, dirlen2, dent2->d_name);
1645+ status |= 1;
1646+ }
1647+ dp2++;
1648+ }
1649+ }
1650
1651 closem:
1652- if (dirp1 != NULL) {
1653- for (dp1 = dirp1; dp1 < edp1; dp1++)
1654- free(*dp1);
1655- free(dirp1);
1656- }
1657- if (dirp2 != NULL) {
1658- for (dp2 = dirp2; dp2 < edp2; dp2++)
1659- free(*dp2);
1660- free(dirp2);
1661- }
1662+ if (dirp1 != NULL) {
1663+ for (dp1 = dirp1; dp1 < edp1; dp1++)
1664+ free(*dp1);
1665+ free(dirp1);
1666+ }
1667+ if (dirp2 != NULL) {
1668+ for (dp2 = dirp2; dp2 < edp2; dp2++)
1669+ free(*dp2);
1670+ free(dirp2);
1671+ }
1672 }
1673
1674 static void
1675 diffit(struct dirent *dp, char *path1, size_t plen1, struct dirent *dp2,
1676 char *path2, size_t plen2, int flags)
1677 {
1678- flags |= D_HEADER;
1679- strlcpy(path1 + plen1, dp->d_name, PATH_MAX - plen1);
1680-
1681- if (ignore_file_case && strcasecmp(dp->d_name, dp2->d_name) == 0)
1682- strlcpy(path2 + plen2, dp2->d_name, PATH_MAX - plen2);
1683- else
1684- strlcpy(path2 + plen2, dp->d_name, PATH_MAX - plen2);
1685-
1686- if (noderef) {
1687- if (lstat(path1, &stb1) != 0) {
1688- if (!(Nflag || Pflag) || errno != ENOENT) {
1689- warn("%s", path1);
1690- return;
1691- }
1692- flags |= D_EMPTY1;
1693- memset(&stb1, 0, sizeof(stb1));
1694- }
1695-
1696- if (lstat(path2, &stb2) != 0) {
1697- if (!Nflag || errno != ENOENT) {
1698- warn("%s", path2);
1699- return;
1700- }
1701- flags |= D_EMPTY2;
1702- memset(&stb2, 0, sizeof(stb2));
1703- stb2.st_mode = stb1.st_mode;
1704- }
1705- if (stb1.st_mode == 0)
1706- stb1.st_mode = stb2.st_mode;
1707- if (S_ISLNK(stb1.st_mode) || S_ISLNK(stb2.st_mode)) {
1708- if (S_ISLNK(stb1.st_mode) && S_ISLNK(stb2.st_mode)) {
1709- char buf1[PATH_MAX];
1710- char buf2[PATH_MAX];
1711- ssize_t len1;
1712- ssize_t len2;
1713-
1714- len1 = readlink(path1, buf1, sizeof(buf1));
1715- len2 = readlink(path2, buf2, sizeof(buf2));
1716- if (len1 < 0 || len2 < 0) {
1717- perror("reading links");
1718- return;
1719- }
1720- buf1[len1] = '\0';
1721- buf2[len2] = '\0';
1722- if (len1 != len2 || strncmp(buf1, buf2, len1) != 0) {
1723- printf("Symbolic links %s and %s differ\n", path1, path2);
1724- status |= 1;
1725- }
1726- return;
1727- }
1728- printf("File %s is a %s while file %s is a %s\n",
1729- path1, S_ISLNK(stb1.st_mode) ? "symbolic link" :
1730- S_ISDIR(stb1.st_mode) ? "directory" : "file",
1731- path2, S_ISLNK(stb2.st_mode) ? "symbolic link" :
1732- S_ISDIR(stb2.st_mode) ? "directory" : "file");
1733- status |= 1;
1734- return;
1735- }
1736- } else {
1737- if (stat(path1, &stb1) != 0) {
1738- if (!(Nflag || Pflag) || errno != ENOENT) {
1739- warn("%s", path1);
1740- return;
1741- }
1742- flags |= D_EMPTY1;
1743- memset(&stb1, 0, sizeof(stb1));
1744- }
1745-
1746- if (stat(path2, &stb2) != 0) {
1747- if (!Nflag || errno != ENOENT) {
1748- warn("%s", path2);
1749- return;
1750- }
1751- flags |= D_EMPTY2;
1752- memset(&stb2, 0, sizeof(stb2));
1753- stb2.st_mode = stb1.st_mode;
1754- }
1755- if (stb1.st_mode == 0)
1756- stb1.st_mode = stb2.st_mode;
1757- }
1758- if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) {
1759- if (rflag)
1760- diffdir(path1, path2, flags);
1761- else
1762- printf("Common subdirectories: %s and %s\n", path1, path2);
1763- return;
1764- }
1765- if (!S_ISREG(stb1.st_mode) && !S_ISDIR(stb1.st_mode))
1766- dp->d_status = D_SKIPPED1;
1767- else if (!S_ISREG(stb2.st_mode) && !S_ISDIR(stb2.st_mode))
1768- dp->d_status = D_SKIPPED2;
1769- else
1770- dp->d_status = diffreg(path1, path2, flags, 0);
1771- print_status(dp->d_status, path1, path2, "");
1772+ flags |= D_HEADER;
1773+ strlcpy(path1 + plen1, dp->d_name, PATH_MAX - plen1);
1774+
1775+ if (ignore_file_case && strcasecmp(dp->d_name, dp2->d_name) == 0)
1776+ strlcpy(path2 + plen2, dp2->d_name, PATH_MAX - plen2);
1777+ else
1778+ strlcpy(path2 + plen2, dp->d_name, PATH_MAX - plen2);
1779+
1780+ if (noderef) {
1781+ if (lstat(path1, &stb1) != 0) {
1782+ if (!(Nflag || Pflag) || errno != ENOENT) {
1783+ weprintf("%s", path1);
1784+ return;
1785+ }
1786+ flags |= D_EMPTY1;
1787+ memset(&stb1, 0, sizeof(stb1));
1788+ }
1789+
1790+ if (lstat(path2, &stb2) != 0) {
1791+ if (!Nflag || errno != ENOENT) {
1792+ weprintf("%s", path2);
1793+ return;
1794+ }
1795+ flags |= D_EMPTY2;
1796+ memset(&stb2, 0, sizeof(stb2));
1797+ stb2.st_mode = stb1.st_mode;
1798+ }
1799+ if (stb1.st_mode == 0)
1800+ stb1.st_mode = stb2.st_mode;
1801+ if (S_ISLNK(stb1.st_mode) || S_ISLNK(stb2.st_mode)) {
1802+ if (S_ISLNK(stb1.st_mode) && S_ISLNK(stb2.st_mode)) {
1803+ char buf1[PATH_MAX];
1804+ char buf2[PATH_MAX];
1805+ ssize_t len1;
1806+ ssize_t len2;
1807+
1808+ len1 = readlink(path1, buf1, sizeof(buf1));
1809+ len2 = readlink(path2, buf2, sizeof(buf2));
1810+ if (len1 < 0 || len2 < 0) {
1811+ perror("reading links");
1812+ return;
1813+ }
1814+ buf1[len1] = '\0';
1815+ buf2[len2] = '\0';
1816+ if (len1 != len2 || strncmp(buf1, buf2, len1) != 0) {
1817+ printf("Symbolic links %s and %s differ\n", path1, path2);
1818+ status |= 1;
1819+ }
1820+ return;
1821+ }
1822+ printf("File %s is a %s while file %s is a %s\n",
1823+ path1, S_ISLNK(stb1.st_mode) ? "symbolic link" :
1824+ S_ISDIR(stb1.st_mode) ? "directory" : "file",
1825+ path2, S_ISLNK(stb2.st_mode) ? "symbolic link" :
1826+ S_ISDIR(stb2.st_mode) ? "directory" : "file");
1827+ status |= 1;
1828+ return;
1829+ }
1830+ } else {
1831+ if (stat(path1, &stb1) != 0) {
1832+ if (!(Nflag || Pflag) || errno != ENOENT) {
1833+ weprintf("%s", path1);
1834+ return;
1835+ }
1836+ flags |= D_EMPTY1;
1837+ memset(&stb1, 0, sizeof(stb1));
1838+ }
1839+
1840+ if (stat(path2, &stb2) != 0) {
1841+ if (!Nflag || errno != ENOENT) {
1842+ weprintf("%s", path2);
1843+ return;
1844+ }
1845+ flags |= D_EMPTY2;
1846+ memset(&stb2, 0, sizeof(stb2));
1847+ stb2.st_mode = stb1.st_mode;
1848+ }
1849+ if (stb1.st_mode == 0)
1850+ stb1.st_mode = stb2.st_mode;
1851+ }
1852+ if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) {
1853+ if (rflag)
1854+ diffdir(path1, path2, flags);
1855+ else
1856+ printf("Common subdirectories: %s and %s\n", path1, path2);
1857+ return;
1858+ }
1859+ if (!S_ISREG(stb1.st_mode) && !S_ISDIR(stb1.st_mode))
1860+ dp->d_status = D_SKIPPED1;
1861+ else if (!S_ISREG(stb2.st_mode) && !S_ISDIR(stb2.st_mode))
1862+ dp->d_status = D_SKIPPED2;
1863+ else
1864+ dp->d_status = diffreg(path1, path2, flags, 0);
1865+ print_status(dp->d_status, path1, path2, "");
1866 }
1867
1868 static int
1869 selectfile(const struct dirent *dp)
1870 {
1871- struct Excludes *excl;
1872+ struct Excludes *excl;
1873
1874- if (dp->d_fileno == 0)
1875- return 0;
1876+ if (dp->d_fileno == 0)
1877+ return 0;
1878
1879- if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
1880- (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
1881- return 0;
1882+ if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
1883+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
1884+ return 0;
1885
1886- for (excl = excludes_list; excl != NULL; excl = excl->next)
1887- if (fnmatch(excl->pattern, dp->d_name, FNM_PATHNAME) == 0)
1888- return 0;
1889+ for (excl = excludes_list; excl != NULL; excl = excl->next)
1890+ if (fnmatch(excl->pattern, dp->d_name, FNM_PATHNAME) == 0)
1891+ return 0;
1892
1893- return 1;
1894+ return 1;
1895 }
1896
1897 void
1898 print_only(const char *path, size_t dirlen, const char *entry)
1899 {
1900- if (dirlen > 1)
1901- dirlen--;
1902- printf("Only in %.*s: %s\n", (int)dirlen, path, entry);
1903+ if (dirlen > 1)
1904+ dirlen--;
1905+ printf("Only in %.*s: %s\n", (int)dirlen, path, entry);
1906 }
1907
1908 int
1909 diffreg(char *file1, char *file2, int flags, int capsicum)
1910 {
1911- FILE *f1, *f2;
1912- int i, rval;
1913- struct Pr *pr = NULL;
1914-
1915- f1 = f2 = NULL;
1916- rval = D_SAME;
1917- anychange = 0;
1918- lastline = 0;
1919- lastmatchline = 0;
1920-
1921- if (diff_format == D_SIDEBYSIDE) {
1922- if (flags & D_EXPANDTABS) {
1923- if (width > 3)
1924- hw = (width - 3) / 2;
1925- else
1926- hw = 0;
1927- } else if (width <= 3 || width <= tabsize) {
1928- hw = 0;
1929- } else {
1930- hw = (width - 3) / 2;
1931- while (hw > 0 && roundup(hw + 3, tabsize) + hw > width)
1932- hw--;
1933- if (width - (roundup(hw + 3, tabsize) + hw) < tabsize)
1934- width = roundup(hw + 3, tabsize) + hw;
1935- }
1936- lpad = (width - hw * 2 - 1) / 2;
1937- rpad = (width - hw * 2 - 1) - lpad;
1938- }
1939-
1940- if (flags & D_IGNORECASE)
1941- chrtran = cup2low;
1942- else
1943- chrtran = clow2low;
1944- if (S_ISDIR(stb1.st_mode) != S_ISDIR(stb2.st_mode))
1945- return S_ISDIR(stb1.st_mode) ? D_MISMATCH1 : D_MISMATCH2;
1946- if (strcmp(file1, "-") == 0 && strcmp(file2, "-") == 0)
1947- goto closem;
1948-
1949- if (flags & D_EMPTY1)
1950- f1 = fopen(_PATH_DEVNULL, "r");
1951- else {
1952- if (!S_ISREG(stb1.st_mode)) {
1953- if ((f1 = opentemp(file1)) == NULL || fstat(fileno(f1), &stb1) == -1) {
1954- warn("%s", file1);
1955- rval = D_ERROR;
1956- status |= 2;
1957- goto closem;
1958- }
1959- } else if (strcmp(file1, "-") == 0)
1960- f1 = stdin;
1961- else
1962- f1 = fopen(file1, "r");
1963- }
1964- if (f1 == NULL) {
1965- warn("%s", file1);
1966- rval = D_ERROR;
1967- status |= 2;
1968- goto closem;
1969- }
1970-
1971- if (flags & D_EMPTY2)
1972- f2 = fopen(_PATH_DEVNULL, "r");
1973- else {
1974- if (!S_ISREG(stb2.st_mode)) {
1975- if ((f2 = opentemp(file2)) == NULL || fstat(fileno(f2), &stb2) == -1) {
1976- warn("%s", file2);
1977- rval = D_ERROR;
1978- status |= 2;
1979- goto closem;
1980- }
1981- } else if (strcmp(file2, "-") == 0)
1982- f2 = stdin;
1983- else
1984- f2 = fopen(file2, "r");
1985- }
1986- if (f2 == NULL) {
1987- warn("%s", file2);
1988- rval = D_ERROR;
1989- status |= 2;
1990- goto closem;
1991- }
1992-
1993- if (lflag)
1994- pr = start_pr(file1, file2);
1995-
1996- (void)capsicum;
1997-
1998- switch (files_differ(f1, f2, flags)) {
1999- case 0:
2000- goto closem;
2001- case 1:
2002- break;
2003- default:
2004- rval = D_ERROR;
2005- status |= 2;
2006- goto closem;
2007- }
2008-
2009- if (diff_format == D_BRIEF && ignore_pats == NULL &&
2010- (flags & (D_FOLDBLANKS|D_IGNOREBLANKS|D_IGNORECASE|D_SKIPBLANKLINES|D_STRIPCR)) == 0)
2011- {
2012- rval = D_DIFFER;
2013- status |= 1;
2014- goto closem;
2015- }
2016- if ((flags & D_FORCEASCII) != 0) {
2017- prepare(0, f1, stb1.st_size, flags);
2018- prepare(1, f2, stb2.st_size, flags);
2019- } else if (!asciifile(f1) || !asciifile(f2) ||
2020- !prepare(0, f1, stb1.st_size, flags) ||
2021- !prepare(1, f2, stb2.st_size, flags)) {
2022- rval = D_BINARY;
2023- status |= 1;
2024- goto closem;
2025- }
2026- if (len[0] > INT_MAX - 2)
2027- errno = EFBIG, err(1, "%s", file1);
2028- if (len[1] > INT_MAX - 2)
2029- errno = EFBIG, err(1, "%s", file2);
2030-
2031- prune();
2032- sort(sfile[0], slen[0]);
2033- sort(sfile[1], slen[1]);
2034-
2035- member = (int *)file[1];
2036- equiv(sfile[0], slen[0], sfile[1], slen[1], member);
2037- member = ereallocarray(member, slen[1] + 2, sizeof(*member));
2038-
2039- class = (int *)file[0];
2040- unsort(sfile[0], slen[0], class);
2041- class = ereallocarray(class, slen[0] + 2, sizeof(*class));
2042-
2043- klist = ecalloc(slen[0] + 2, sizeof(*klist));
2044- clen = 0;
2045- clistlen = 100;
2046- clist = ecalloc(clistlen, sizeof(*clist));
2047- i = stone(class, slen[0], member, klist, flags);
2048- free(member);
2049- free(class);
2050-
2051- J = ereallocarray(J, len[0] + 2, sizeof(*J));
2052- unravel(klist[i]);
2053- free(clist);
2054- free(klist);
2055-
2056- ixold = ereallocarray(ixold, len[0] + 2, sizeof(*ixold));
2057- ixnew = ereallocarray(ixnew, len[1] + 2, sizeof(*ixnew));
2058- check(f1, f2, flags);
2059- output(file1, f1, file2, f2, flags);
2060+ FILE *f1, *f2;
2061+ int i, rval;
2062+ struct Pr *pr = NULL;
2063+
2064+ f1 = f2 = NULL;
2065+ rval = D_SAME;
2066+ anychange = 0;
2067+ lastline = 0;
2068+ lastmatchline = 0;
2069+
2070+ if (diff_format == D_SIDEBYSIDE) {
2071+ if (flags & D_EXPANDTABS) {
2072+ if (width > 3)
2073+ hw = (width - 3) / 2;
2074+ else
2075+ hw = 0;
2076+ } else if (width <= 3 || width <= tabsize) {
2077+ hw = 0;
2078+ } else {
2079+ hw = (width - 3) / 2;
2080+ while (hw > 0 && roundup(hw + 3, tabsize) + hw > width)
2081+ hw--;
2082+ if (width - (roundup(hw + 3, tabsize) + hw) < tabsize)
2083+ width = roundup(hw + 3, tabsize) + hw;
2084+ }
2085+ lpad = (width - hw * 2 - 1) / 2;
2086+ rpad = (width - hw * 2 - 1) - lpad;
2087+ }
2088+
2089+ if (flags & D_IGNORECASE)
2090+ chrtran = cup2low;
2091+ else
2092+ chrtran = clow2low;
2093+ if (S_ISDIR(stb1.st_mode) != S_ISDIR(stb2.st_mode))
2094+ return S_ISDIR(stb1.st_mode) ? D_MISMATCH1 : D_MISMATCH2;
2095+ if (strcmp(file1, "-") == 0 && strcmp(file2, "-") == 0)
2096+ goto closem;
2097+
2098+ if (flags & D_EMPTY1)
2099+ f1 = fopen(ARUU_PATH_DEVNULL, "r");
2100+ else {
2101+ if (!S_ISREG(stb1.st_mode)) {
2102+ if ((f1 = opentemp(file1)) == NULL || fstat(fileno(f1), &stb1) == -1) {
2103+ weprintf("%s", file1);
2104+ rval = D_ERROR;
2105+ status |= 2;
2106+ goto closem;
2107+ }
2108+ } else if (strcmp(file1, "-") == 0)
2109+ f1 = stdin;
2110+ else
2111+ f1 = fopen(file1, "r");
2112+ }
2113+ if (f1 == NULL) {
2114+ weprintf("%s", file1);
2115+ rval = D_ERROR;
2116+ status |= 2;
2117+ goto closem;
2118+ }
2119+
2120+ if (flags & D_EMPTY2)
2121+ f2 = fopen(ARUU_PATH_DEVNULL, "r");
2122+ else {
2123+ if (!S_ISREG(stb2.st_mode)) {
2124+ if ((f2 = opentemp(file2)) == NULL || fstat(fileno(f2), &stb2) == -1) {
2125+ weprintf("%s", file2);
2126+ rval = D_ERROR;
2127+ status |= 2;
2128+ goto closem;
2129+ }
2130+ } else if (strcmp(file2, "-") == 0)
2131+ f2 = stdin;
2132+ else
2133+ f2 = fopen(file2, "r");
2134+ }
2135+ if (f2 == NULL) {
2136+ weprintf("%s", file2);
2137+ rval = D_ERROR;
2138+ status |= 2;
2139+ goto closem;
2140+ }
2141+
2142+ if (lflag)
2143+ pr = start_pr(file1, file2);
2144+
2145+ (void)capsicum;
2146+
2147+ switch (files_differ(f1, f2, flags)) {
2148+ case 0:
2149+ goto closem;
2150+ case 1:
2151+ break;
2152+ default:
2153+ rval = D_ERROR;
2154+ status |= 2;
2155+ goto closem;
2156+ }
2157+
2158+ if (diff_format == D_BRIEF && ignore_pats == NULL &&
2159+ (flags & (D_FOLDBLANKS|D_IGNOREBLANKS|D_IGNORECASE|D_SKIPBLANKLINES|D_STRIPCR)) == 0)
2160+ {
2161+ rval = D_DIFFER;
2162+ status |= 1;
2163+ goto closem;
2164+ }
2165+ if ((flags & D_FORCEASCII) != 0) {
2166+ prepare(0, f1, stb1.st_size, flags);
2167+ prepare(1, f2, stb2.st_size, flags);
2168+ } else if (!asciifile(f1) || !asciifile(f2) ||
2169+ !prepare(0, f1, stb1.st_size, flags) ||
2170+ !prepare(1, f2, stb2.st_size, flags)) {
2171+ rval = D_BINARY;
2172+ status |= 1;
2173+ goto closem;
2174+ }
2175+ if (len[0] > INT_MAX - 2)
2176+ errno = EFBIG, enprintf(1, "%s", file1);
2177+ if (len[1] > INT_MAX - 2)
2178+ errno = EFBIG, enprintf(1, "%s", file2);
2179+
2180+ prune();
2181+ sort(sfile[0], slen[0]);
2182+ sort(sfile[1], slen[1]);
2183+
2184+ member = (int *)file[1];
2185+ equiv(sfile[0], slen[0], sfile[1], slen[1], member);
2186+ member = ereallocarray(member, slen[1] + 2, sizeof(*member));
2187+
2188+ class = (int *)file[0];
2189+ unsort(sfile[0], slen[0], class);
2190+ class = ereallocarray(class, slen[0] + 2, sizeof(*class));
2191+
2192+ klist = ecalloc(slen[0] + 2, sizeof(*klist));
2193+ clen = 0;
2194+ clistlen = 100;
2195+ clist = ecalloc(clistlen, sizeof(*clist));
2196+ i = stone(class, slen[0], member, klist, flags);
2197+ free(member);
2198+ free(class);
2199+
2200+ J = ereallocarray(J, len[0] + 2, sizeof(*J));
2201+ unravel(klist[i]);
2202+ free(clist);
2203+ free(klist);
2204+
2205+ ixold = ereallocarray(ixold, len[0] + 2, sizeof(*ixold));
2206+ ixnew = ereallocarray(ixnew, len[1] + 2, sizeof(*ixnew));
2207+ check(f1, f2, flags);
2208+ output(file1, f1, file2, f2, flags);
2209
2210 closem:
2211- if (pr != NULL)
2212- stop_pr(pr);
2213- if (anychange) {
2214- status |= 1;
2215- if (rval == D_SAME)
2216- rval = D_DIFFER;
2217- }
2218- if (f1 != NULL && f1 != stdin)
2219- fclose(f1);
2220- if (f2 != NULL && f2 != stdin)
2221- fclose(f2);
2222-
2223- return rval;
2224+ if (pr != NULL)
2225+ stop_pr(pr);
2226+ if (anychange) {
2227+ status |= 1;
2228+ if (rval == D_SAME)
2229+ rval = D_DIFFER;
2230+ }
2231+ if (f1 != NULL && f1 != stdin)
2232+ fclose(f1);
2233+ if (f2 != NULL && f2 != stdin)
2234+ fclose(f2);
2235+
2236+ return rval;
2237 }
2238
2239 static int
2240 files_differ(FILE *f1, FILE *f2, int flags)
2241 {
2242- char buf1[BUFSIZ], buf2[BUFSIZ];
2243- size_t i, j;
2244-
2245- if ((flags & (D_EMPTY1|D_EMPTY2)) || stb1.st_size != stb2.st_size ||
2246- (stb1.st_mode & S_IFMT) != (stb2.st_mode & S_IFMT))
2247- return 1;
2248-
2249- if (stb1.st_dev == stb2.st_dev && stb1.st_ino == stb2.st_ino)
2250- return 0;
2251-
2252- for (;;) {
2253- i = fread(buf1, 1, sizeof(buf1), f1);
2254- j = fread(buf2, 1, sizeof(buf2), f2);
2255- if ((!i && ferror(f1)) || (!j && ferror(f2)))
2256- return -1;
2257- if (i != j)
2258- return 1;
2259- if (i == 0)
2260- return 0;
2261- if (memcmp(buf1, buf2, i) != 0)
2262- return 1;
2263- }
2264+ char buf1[BUFSIZ], buf2[BUFSIZ];
2265+ size_t i, j;
2266+
2267+ if ((flags & (D_EMPTY1|D_EMPTY2)) || stb1.st_size != stb2.st_size ||
2268+ (stb1.st_mode & S_IFMT) != (stb2.st_mode & S_IFMT))
2269+ return 1;
2270+
2271+ if (stb1.st_dev == stb2.st_dev && stb1.st_ino == stb2.st_ino)
2272+ return 0;
2273+
2274+ for (;;) {
2275+ i = fread(buf1, 1, sizeof(buf1), f1);
2276+ j = fread(buf2, 1, sizeof(buf2), f2);
2277+ if ((!i && ferror(f1)) || (!j && ferror(f2)))
2278+ return -1;
2279+ if (i != j)
2280+ return 1;
2281+ if (i == 0)
2282+ return 0;
2283+ if (memcmp(buf1, buf2, i) != 0)
2284+ return 1;
2285+ }
2286 }
2287
2288 static FILE *
2289 opentemp(const char *f)
2290 {
2291- char buf[BUFSIZ], tempfile[PATH_MAX];
2292- ssize_t nread;
2293- int ifd, ofd;
2294-
2295- if (strcmp(f, "-") == 0)
2296- ifd = STDIN_FILENO;
2297- else if ((ifd = open(f, O_RDONLY, 0644)) == -1)
2298- return NULL;
2299-
2300- strlcpy(tempfile, _PATH_TMP "/diff.XXXXXXXX", sizeof(tempfile));
2301- if ((ofd = mkstemp(tempfile)) == -1) {
2302- close(ifd);
2303- return NULL;
2304- }
2305- unlink(tempfile);
2306- while ((nread = read(ifd, buf, BUFSIZ)) > 0) {
2307- if (write(ofd, buf, nread) != nread) {
2308- close(ifd);
2309- close(ofd);
2310- return NULL;
2311- }
2312- }
2313- close(ifd);
2314- lseek(ofd, (off_t)0, SEEK_SET);
2315- return fdopen(ofd, "r");
2316+ char buf[BUFSIZ], tempfile[PATH_MAX];
2317+ ssize_t nread;
2318+ int ifd, ofd;
2319+
2320+ if (strcmp(f, "-") == 0)
2321+ ifd = STDIN_FILENO;
2322+ else if ((ifd = open(f, O_RDONLY, 0644)) == -1)
2323+ return NULL;
2324+
2325+ strlcpy(tempfile, ARUU_PATH_TMP "/diff.XXXXXXXX", sizeof(tempfile));
2326+ if ((ofd = mkstemp(tempfile)) == -1) {
2327+ close(ifd);
2328+ return NULL;
2329+ }
2330+ unlink(tempfile);
2331+ while ((nread = read(ifd, buf, BUFSIZ)) > 0) {
2332+ if (write(ofd, buf, nread) != nread) {
2333+ close(ifd);
2334+ close(ofd);
2335+ return NULL;
2336+ }
2337+ }
2338+ close(ifd);
2339+ lseek(ofd, (off_t)0, SEEK_SET);
2340+ return fdopen(ofd, "r");
2341 }
2342
2343 static int
2344 prepare(int i, FILE *fd, size_t filesize, int flags)
2345 {
2346- struct Line *p;
2347- unsigned h;
2348- size_t sz, j = 0;
2349- enum Readhash r;
2350-
2351- rewind(fd);
2352- sz = filesize / 25;
2353- if (sz < 100)
2354- sz = 100;
2355-
2356- p = ecalloc(sz + 3, sizeof(*p));
2357- while ((r = readhash(fd, flags, &h)) != RH_EOF) {
2358- if (r == RH_BINARY)
2359- return 0;
2360- if (j == SIZE_MAX)
2361- break;
2362- if (j == sz) {
2363- sz = sz * 3 / 2;
2364- p = ereallocarray(p, sz + 3, sizeof(*p));
2365- }
2366- p[++j].value = h;
2367- }
2368- len[i] = j;
2369- file[i] = p;
2370- return 1;
2371+ struct Line *p;
2372+ unsigned h;
2373+ size_t sz, j = 0;
2374+ enum Readhash r;
2375+
2376+ rewind(fd);
2377+ sz = filesize / 25;
2378+ if (sz < 100)
2379+ sz = 100;
2380+
2381+ p = ecalloc(sz + 3, sizeof(*p));
2382+ while ((r = readhash(fd, flags, &h)) != RH_EOF) {
2383+ if (r == RH_BINARY)
2384+ return 0;
2385+ if (j == SIZE_MAX)
2386+ break;
2387+ if (j == sz) {
2388+ sz = sz * 3 / 2;
2389+ p = ereallocarray(p, sz + 3, sizeof(*p));
2390+ }
2391+ p[++j].value = h;
2392+ }
2393+ len[i] = j;
2394+ file[i] = p;
2395+ return 1;
2396 }
2397
2398 static void
2399 prune(void)
2400 {
2401- size_t i, j;
2402-
2403- for (pref = 0; pref < len[0] && pref < len[1] &&
2404- file[0][pref + 1].value == file[1][pref + 1].value;
2405- pref++)
2406- ;
2407- for (suff = 0; suff < len[0] - pref && suff < len[1] - pref &&
2408- file[0][len[0] - suff].value == file[1][len[1] - suff].value;
2409- suff++)
2410- ;
2411- for (j = 0; j < 2; j++) {
2412- sfile[j] = file[j] + pref;
2413- slen[j] = len[j] - pref - suff;
2414- for (i = 0; i <= slen[j]; i++)
2415- sfile[j][i].serial = i;
2416- }
2417+ size_t i, j;
2418+
2419+ for (pref = 0; pref < len[0] && pref < len[1] &&
2420+ file[0][pref + 1].value == file[1][pref + 1].value;
2421+ pref++)
2422+ ;
2423+ for (suff = 0; suff < len[0] - pref && suff < len[1] - pref &&
2424+ file[0][len[0] - suff].value == file[1][len[1] - suff].value;
2425+ suff++)
2426+ ;
2427+ for (j = 0; j < 2; j++) {
2428+ sfile[j] = file[j] + pref;
2429+ slen[j] = len[j] - pref - suff;
2430+ for (i = 0; i <= slen[j]; i++)
2431+ sfile[j][i].serial = i;
2432+ }
2433 }
2434
2435 static void
2436 equiv(struct Line *a, int n, struct Line *b, int m, int *c)
2437 {
2438- int i, j;
2439-
2440- i = j = 1;
2441- while (i <= n && j <= m) {
2442- if (a[i].value < b[j].value)
2443- a[i++].value = 0;
2444- else if (a[i].value == b[j].value)
2445- a[i++].value = j;
2446- else
2447- j++;
2448- }
2449- while (i <= n)
2450- a[i++].value = 0;
2451- b[m + 1].value = 0;
2452- j = 0;
2453- while (++j <= m) {
2454- c[j] = -b[j].serial;
2455- while (b[j + 1].value == b[j].value) {
2456- j++;
2457- c[j] = b[j].serial;
2458- }
2459- }
2460- c[j] = -1;
2461+ int i, j;
2462+
2463+ i = j = 1;
2464+ while (i <= n && j <= m) {
2465+ if (a[i].value < b[j].value)
2466+ a[i++].value = 0;
2467+ else if (a[i].value == b[j].value)
2468+ a[i++].value = j;
2469+ else
2470+ j++;
2471+ }
2472+ while (i <= n)
2473+ a[i++].value = 0;
2474+ b[m + 1].value = 0;
2475+ j = 0;
2476+ while (++j <= m) {
2477+ c[j] = -b[j].serial;
2478+ while (b[j + 1].value == b[j].value) {
2479+ j++;
2480+ c[j] = b[j].serial;
2481+ }
2482+ }
2483+ c[j] = -1;
2484 }
2485
2486 static int
2487 stone(int *a, int n, int *b, int *c, int flags)
2488 {
2489- int i, k, y, j, l;
2490- int oldc, tc, oldl, sq;
2491- unsigned numtries, bound;
2492-
2493- if (flags & D_MINIMAL)
2494- bound = UINT_MAX;
2495- else {
2496- sq = sqrt(n);
2497- bound = MAX(256, sq);
2498- }
2499-
2500- k = 0;
2501- c[0] = newcand(0, 0, 0);
2502- for (i = 1; i <= n; i++) {
2503- j = a[i];
2504- if (j == 0)
2505- continue;
2506- y = -b[j];
2507- oldl = 0;
2508- oldc = c[0];
2509- numtries = 0;
2510- do {
2511- if (y <= clist[oldc].y)
2512- continue;
2513- l = search(c, k, y);
2514- if (l != oldl + 1)
2515- oldc = c[l - 1];
2516- if (l <= k) {
2517- if (clist[c[l]].y <= y)
2518- continue;
2519- tc = c[l];
2520- c[l] = newcand(i, y, oldc);
2521- oldc = tc;
2522- oldl = l;
2523- numtries++;
2524- } else {
2525- c[l] = newcand(i, y, oldc);
2526- k++;
2527- break;
2528- }
2529- } while ((y = b[++j]) > 0 && numtries < bound);
2530- }
2531- return k;
2532+ int i, k, y, j, l;
2533+ int oldc, tc, oldl, sq;
2534+ unsigned numtries, bound;
2535+
2536+ if (flags & D_MINIMAL)
2537+ bound = UINT_MAX;
2538+ else {
2539+ sq = sqrt(n);
2540+ bound = MAX(256, sq);
2541+ }
2542+
2543+ k = 0;
2544+ c[0] = newcand(0, 0, 0);
2545+ for (i = 1; i <= n; i++) {
2546+ j = a[i];
2547+ if (j == 0)
2548+ continue;
2549+ y = -b[j];
2550+ oldl = 0;
2551+ oldc = c[0];
2552+ numtries = 0;
2553+ do {
2554+ if (y <= clist[oldc].y)
2555+ continue;
2556+ l = search(c, k, y);
2557+ if (l != oldl + 1)
2558+ oldc = c[l - 1];
2559+ if (l <= k) {
2560+ if (clist[c[l]].y <= y)
2561+ continue;
2562+ tc = c[l];
2563+ c[l] = newcand(i, y, oldc);
2564+ oldc = tc;
2565+ oldl = l;
2566+ numtries++;
2567+ } else {
2568+ c[l] = newcand(i, y, oldc);
2569+ k++;
2570+ break;
2571+ }
2572+ } while ((y = b[++j]) > 0 && numtries < bound);
2573+ }
2574+ return k;
2575 }
2576
2577 static int
2578 newcand(int x, int y, int pred)
2579 {
2580- struct Cand *q;
2581-
2582- if (clen == clistlen) {
2583- clistlen = clistlen * 11 / 10;
2584- clist = ereallocarray(clist, clistlen, sizeof(*clist));
2585- }
2586- q = clist + clen;
2587- q->x = x;
2588- q->y = y;
2589- q->pred = pred;
2590- return clen++;
2591+ struct Cand *q;
2592+
2593+ if (clen == clistlen) {
2594+ clistlen = clistlen * 11 / 10;
2595+ clist = ereallocarray(clist, clistlen, sizeof(*clist));
2596+ }
2597+ q = clist + clen;
2598+ q->x = x;
2599+ q->y = y;
2600+ q->pred = pred;
2601+ return clen++;
2602 }
2603
2604 static int
2605 search(int *c, int k, int y)
2606 {
2607- int i, j, l, t;
2608-
2609- if (clist[c[k]].y < y)
2610- return k + 1;
2611- i = 0;
2612- j = k + 1;
2613- for (;;) {
2614- l = (i + j) / 2;
2615- if (l <= i)
2616- break;
2617- t = clist[c[l]].y;
2618- if (t > y)
2619- j = l;
2620- else if (t < y)
2621- i = l;
2622- else
2623- return l;
2624- }
2625- return l + 1;
2626+ int i, j, l, t;
2627+
2628+ if (clist[c[k]].y < y)
2629+ return k + 1;
2630+ i = 0;
2631+ j = k + 1;
2632+ for (;;) {
2633+ l = (i + j) / 2;
2634+ if (l <= i)
2635+ break;
2636+ t = clist[c[l]].y;
2637+ if (t > y)
2638+ j = l;
2639+ else if (t < y)
2640+ i = l;
2641+ else
2642+ return l;
2643+ }
2644+ return l + 1;
2645 }
2646
2647 static void
2648 unravel(int p)
2649 {
2650- struct Cand *q;
2651- size_t i;
2652-
2653- for (i = 0; i <= len[0]; i++)
2654- J[i] = i <= pref ? i :
2655- i > len[0] - suff ? i + len[1] - len[0] : 0;
2656- for (q = clist + p; q->y != 0; q = clist + q->pred)
2657- J[q->x + pref] = q->y + pref;
2658+ struct Cand *q;
2659+ size_t i;
2660+
2661+ for (i = 0; i <= len[0]; i++)
2662+ J[i] = i <= pref ? i :
2663+ i > len[0] - suff ? i + len[1] - len[0] : 0;
2664+ for (q = clist + p; q->y != 0; q = clist + q->pred)
2665+ J[q->x + pref] = q->y + pref;
2666 }
2667
2668 static void
2669 check(FILE *f1, FILE *f2, int flags)
2670 {
2671- int i, j, c, d;
2672- long ctold, ctnew;
2673-
2674- rewind(f1);
2675- rewind(f2);
2676- j = 1;
2677- ixold[0] = ixnew[0] = 0;
2678- ctold = ctnew = 0;
2679- for (i = 1; i <= (int)len[0]; i++) {
2680- if (J[i] == 0) {
2681- ixold[i] = ctold += skipline(f1);
2682- continue;
2683- }
2684- while (j < J[i]) {
2685- ixnew[j] = ctnew += skipline(f2);
2686- j++;
2687- }
2688- if (flags & (D_FOLDBLANKS | D_IGNOREBLANKS | D_IGNORECASE | D_STRIPCR)) {
2689- for (;;) {
2690- c = getc(f1);
2691- d = getc(f2);
2692- if (flags & (D_FOLDBLANKS | D_IGNOREBLANKS)) {
2693- if (c == EOF && isspace(d)) {
2694- ctnew++;
2695- break;
2696- } else if (isspace(c) && d == EOF) {
2697- ctold++;
2698- break;
2699- }
2700- }
2701- ctold++;
2702- ctnew++;
2703- if (flags & D_STRIPCR && (c == '\r' || d == '\r')) {
2704- if (c == '\r') {
2705- if ((c = getc(f1)) == '\n')
2706- ctold++;
2707- else
2708- ungetc(c, f1);
2709- }
2710- if (d == '\r') {
2711- if ((d = getc(f2)) == '\n')
2712- ctnew++;
2713- else
2714- ungetc(d, f2);
2715- }
2716- break;
2717- }
2718- if ((flags & D_FOLDBLANKS) && isspace(c) && isspace(d)) {
2719- do {
2720- if (c == '\n')
2721- break;
2722- ctold++;
2723- } while (isspace(c = getc(f1)));
2724- do {
2725- if (d == '\n')
2726- break;
2727- ctnew++;
2728- } while (isspace(d = getc(f2)));
2729- } else if (flags & D_IGNOREBLANKS) {
2730- while (isspace(c) && c != '\n') {
2731- c = getc(f1);
2732- ctold++;
2733- }
2734- while (isspace(d) && d != '\n') {
2735- d = getc(f2);
2736- ctnew++;
2737- }
2738- }
2739- if (chrtran(c) != chrtran(d)) {
2740- J[i] = 0;
2741- if (c != '\n' && c != EOF)
2742- ctold += skipline(f1);
2743- if (d != '\n' && c != EOF)
2744- ctnew += skipline(f2);
2745- break;
2746- }
2747- if (c == '\n' || c == EOF)
2748- break;
2749- }
2750- } else {
2751- for (;;) {
2752- ctold++;
2753- ctnew++;
2754- if ((c = getc(f1)) != (d = getc(f2))) {
2755- J[i] = 0;
2756- if (c != '\n' && c != EOF)
2757- ctold += skipline(f1);
2758- if (d != '\n' && c != EOF)
2759- ctnew += skipline(f2);
2760- break;
2761- }
2762- if (c == '\n' || c == EOF)
2763- break;
2764- }
2765- }
2766- ixold[i] = ctold;
2767- ixnew[j] = ctnew;
2768- j++;
2769- }
2770- for (; j <= (int)len[1]; j++) {
2771- ixnew[j] = ctnew += skipline(f2);
2772- }
2773+ int i, j, c, d;
2774+ long ctold, ctnew;
2775+
2776+ rewind(f1);
2777+ rewind(f2);
2778+ j = 1;
2779+ ixold[0] = ixnew[0] = 0;
2780+ ctold = ctnew = 0;
2781+ for (i = 1; i <= (int)len[0]; i++) {
2782+ if (J[i] == 0) {
2783+ ixold[i] = ctold += skipline(f1);
2784+ continue;
2785+ }
2786+ while (j < J[i]) {
2787+ ixnew[j] = ctnew += skipline(f2);
2788+ j++;
2789+ }
2790+ if (flags & (D_FOLDBLANKS | D_IGNOREBLANKS | D_IGNORECASE | D_STRIPCR)) {
2791+ for (;;) {
2792+ c = getc(f1);
2793+ d = getc(f2);
2794+ if (flags & (D_FOLDBLANKS | D_IGNOREBLANKS)) {
2795+ if (c == EOF && isspace(d)) {
2796+ ctnew++;
2797+ break;
2798+ } else if (isspace(c) && d == EOF) {
2799+ ctold++;
2800+ break;
2801+ }
2802+ }
2803+ ctold++;
2804+ ctnew++;
2805+ if (flags & D_STRIPCR && (c == '\r' || d == '\r')) {
2806+ if (c == '\r') {
2807+ if ((c = getc(f1)) == '\n')
2808+ ctold++;
2809+ else
2810+ ungetc(c, f1);
2811+ }
2812+ if (d == '\r') {
2813+ if ((d = getc(f2)) == '\n')
2814+ ctnew++;
2815+ else
2816+ ungetc(d, f2);
2817+ }
2818+ break;
2819+ }
2820+ if ((flags & D_FOLDBLANKS) && isspace(c) && isspace(d)) {
2821+ do {
2822+ if (c == '\n')
2823+ break;
2824+ ctold++;
2825+ } while (isspace(c = getc(f1)));
2826+ do {
2827+ if (d == '\n')
2828+ break;
2829+ ctnew++;
2830+ } while (isspace(d = getc(f2)));
2831+ } else if (flags & D_IGNOREBLANKS) {
2832+ while (isspace(c) && c != '\n') {
2833+ c = getc(f1);
2834+ ctold++;
2835+ }
2836+ while (isspace(d) && d != '\n') {
2837+ d = getc(f2);
2838+ ctnew++;
2839+ }
2840+ }
2841+ if (chrtran(c) != chrtran(d)) {
2842+ J[i] = 0;
2843+ if (c != '\n' && c != EOF)
2844+ ctold += skipline(f1);
2845+ if (d != '\n' && c != EOF)
2846+ ctnew += skipline(f2);
2847+ break;
2848+ }
2849+ if (c == '\n' || c == EOF)
2850+ break;
2851+ }
2852+ } else {
2853+ for (;;) {
2854+ ctold++;
2855+ ctnew++;
2856+ if ((c = getc(f1)) != (d = getc(f2))) {
2857+ J[i] = 0;
2858+ if (c != '\n' && c != EOF)
2859+ ctold += skipline(f1);
2860+ if (d != '\n' && c != EOF)
2861+ ctnew += skipline(f2);
2862+ break;
2863+ }
2864+ if (c == '\n' || c == EOF)
2865+ break;
2866+ }
2867+ }
2868+ ixold[i] = ctold;
2869+ ixnew[j] = ctnew;
2870+ j++;
2871+ }
2872+ for (; j <= (int)len[1]; j++) {
2873+ ixnew[j] = ctnew += skipline(f2);
2874+ }
2875 }
2876
2877 static void
2878 sort(struct Line *a, int n)
2879 {
2880- struct Line *ai, *aim, w;
2881- int j, m = 0, k;
2882-
2883- if (n == 0)
2884- return;
2885- for (j = 1; j <= n; j *= 2)
2886- m = 2 * j - 1;
2887- for (m /= 2; m != 0; m /= 2) {
2888- k = n - m;
2889- for (j = 1; j <= k; j++) {
2890- for (ai = &a[j]; ai > a; ai -= m) {
2891- aim = &ai[m];
2892- if (aim < ai)
2893- break;
2894- if (aim->value > ai[0].value ||
2895- (aim->value == ai[0].value && aim->serial > ai[0].serial))
2896- break;
2897- w.value = ai[0].value;
2898- ai[0].value = aim->value;
2899- aim->value = w.value;
2900- w.serial = ai[0].serial;
2901- ai[0].serial = aim->serial;
2902- aim->serial = w.serial;
2903- }
2904- }
2905- }
2906+ struct Line *ai, *aim, w;
2907+ int j, m = 0, k;
2908+
2909+ if (n == 0)
2910+ return;
2911+ for (j = 1; j <= n; j *= 2)
2912+ m = 2 * j - 1;
2913+ for (m /= 2; m != 0; m /= 2) {
2914+ k = n - m;
2915+ for (j = 1; j <= k; j++) {
2916+ for (ai = &a[j]; ai > a; ai -= m) {
2917+ aim = &ai[m];
2918+ if (aim < ai)
2919+ break;
2920+ if (aim->value > ai[0].value ||
2921+ (aim->value == ai[0].value && aim->serial > ai[0].serial))
2922+ break;
2923+ w.value = ai[0].value;
2924+ ai[0].value = aim->value;
2925+ aim->value = w.value;
2926+ w.serial = ai[0].serial;
2927+ ai[0].serial = aim->serial;
2928+ aim->serial = w.serial;
2929+ }
2930+ }
2931+ }
2932 }
2933
2934 static void
2935 unsort(struct Line *f, int l, int *b)
2936 {
2937- int *a, i;
2938-
2939- a = ecalloc(l + 1, sizeof(*a));
2940- for (i = 1; i <= l; i++)
2941- a[f[i].serial] = f[i].value;
2942- for (i = 1; i <= l; i++)
2943- b[i] = a[i];
2944- free(a);
2945+ int *a, i;
2946+
2947+ a = ecalloc(l + 1, sizeof(*a));
2948+ for (i = 1; i <= l; i++)
2949+ a[f[i].serial] = f[i].value;
2950+ for (i = 1; i <= l; i++)
2951+ b[i] = a[i];
2952+ free(a);
2953 }
2954
2955 static int
2956 skipline(FILE *f)
2957 {
2958- int i, c;
2959+ int i, c;
2960
2961- for (i = 1; (c = getc(f)) != '\n' && c != EOF; i++)
2962- continue;
2963- return i;
2964+ for (i = 1; (c = getc(f)) != '\n' && c != EOF; i++)
2965+ continue;
2966+ return i;
2967 }
2968
2969 static void
2970 output(char *file1, FILE *f1, char *file2, FILE *f2, int flags)
2971 {
2972- int i, j, m, i0, i1, j0, j1, nc;
2973-
2974- rewind(f1);
2975- rewind(f2);
2976- m = len[0];
2977- J[0] = 0;
2978- J[m + 1] = len[1] + 1;
2979- if (diff_format != D_EDIT) {
2980- for (i0 = 1; i0 <= m; i0 = i1 + 1) {
2981- while (i0 <= m && J[i0] == J[i0 - 1] + 1) {
2982- if (diff_format == D_SIDEBYSIDE && suppress_common != 1) {
2983- nc = fetch(ixold, i0, i0, f1, '\0', 1, flags);
2984- print_space(nc, hw - nc + lpad + 1 + rpad, flags);
2985- fetch(ixnew, J[i0], J[i0], f2, '\0', 0, flags);
2986- printf("\n");
2987- }
2988- i0++;
2989- }
2990- j0 = J[i0 - 1] + 1;
2991- i1 = i0 - 1;
2992- while (i1 < m && J[i1 + 1] == 0)
2993- i1++;
2994- j1 = J[i1 + 1] - 1;
2995- J[i1] = j1;
2996-
2997- if (diff_format == D_SIDEBYSIDE) {
2998- for (i = i0, j = j0; i <= i1 && j <= j1; i++, j++)
2999- change(file1, f1, file2, f2, i, i, j, j, &flags);
3000- while (i <= i1) {
3001- change(file1, f1, file2, f2, i, i, j + 1, j, &flags);
3002- i++;
3003- }
3004- while (j <= j1) {
3005- change(file1, f1, file2, f2, i + 1, i, j, j, &flags);
3006- j++;
3007- }
3008- } else
3009- change(file1, f1, file2, f2, i0, i1, j0, j1, &flags);
3010- }
3011- } else {
3012- for (i0 = m; i0 >= 1; i0 = i1 - 1) {
3013- while (i0 >= 1 && J[i0] == J[i0 + 1] - 1 && J[i0] != 0)
3014- i0--;
3015- j0 = J[i0 + 1] - 1;
3016- i1 = i0 + 1;
3017- while (i1 > 1 && J[i1 - 1] == 0)
3018- i1--;
3019- j1 = J[i1 - 1] + 1;
3020- J[i1] = j1;
3021- change(file1, f1, file2, f2, i1, i0, j1, j0, &flags);
3022- }
3023- }
3024- if (m == 0)
3025- change(file1, f1, file2, f2, 1, 0, 1, len[1], &flags);
3026- if (diff_format == D_IFDEF || diff_format == D_GFORMAT) {
3027- for (;;) {
3028+ int i, j, m, i0, i1, j0, j1, nc;
3029+
3030+ rewind(f1);
3031+ rewind(f2);
3032+ m = len[0];
3033+ J[0] = 0;
3034+ J[m + 1] = len[1] + 1;
3035+ if (diff_format != D_EDIT) {
3036+ for (i0 = 1; i0 <= m; i0 = i1 + 1) {
3037+ while (i0 <= m && J[i0] == J[i0 - 1] + 1) {
3038+ if (diff_format == D_SIDEBYSIDE && suppress_common != 1) {
3039+ nc = fetch(ixold, i0, i0, f1, '\0', 1, flags);
3040+ print_space(nc, hw - nc + lpad + 1 + rpad, flags);
3041+ fetch(ixnew, J[i0], J[i0], f2, '\0', 0, flags);
3042+ printf("\n");
3043+ }
3044+ i0++;
3045+ }
3046+ j0 = J[i0 - 1] + 1;
3047+ i1 = i0 - 1;
3048+ while (i1 < m && J[i1 + 1] == 0)
3049+ i1++;
3050+ j1 = J[i1 + 1] - 1;
3051+ J[i1] = j1;
3052+
3053+ if (diff_format == D_SIDEBYSIDE) {
3054+ for (i = i0, j = j0; i <= i1 && j <= j1; i++, j++)
3055+ change(file1, f1, file2, f2, i, i, j, j, &flags);
3056+ while (i <= i1) {
3057+ change(file1, f1, file2, f2, i, i, j + 1, j, &flags);
3058+ i++;
3059+ }
3060+ while (j <= j1) {
3061+ change(file1, f1, file2, f2, i + 1, i, j, j, &flags);
3062+ j++;
3063+ }
3064+ } else
3065+ change(file1, f1, file2, f2, i0, i1, j0, j1, &flags);
3066+ }
3067+ } else {
3068+ for (i0 = m; i0 >= 1; i0 = i1 - 1) {
3069+ while (i0 >= 1 && J[i0] == J[i0 + 1] - 1 && J[i0] != 0)
3070+ i0--;
3071+ j0 = J[i0 + 1] - 1;
3072+ i1 = i0 + 1;
3073+ while (i1 > 1 && J[i1 - 1] == 0)
3074+ i1--;
3075+ j1 = J[i1 - 1] + 1;
3076+ J[i1] = j1;
3077+ change(file1, f1, file2, f2, i1, i0, j1, j0, &flags);
3078+ }
3079+ }
3080+ if (m == 0)
3081+ change(file1, f1, file2, f2, 1, 0, 1, len[1], &flags);
3082+ if (diff_format == D_IFDEF || diff_format == D_GFORMAT) {
3083+ for (;;) {
3084 #define c i0
3085- if ((c = getc(f1)) == EOF)
3086- return;
3087- printf("%c", c);
3088- }
3089+ if ((c = getc(f1)) == EOF)
3090+ return;
3091+ printf("%c", c);
3092+ }
3093 #undef c
3094- }
3095- if (anychange != 0) {
3096- if (diff_format == D_CONTEXT)
3097- dump_context_vec(f1, f2, flags);
3098- else if (diff_format == D_UNIFIED)
3099- dump_unified_vec(f1, f2, flags);
3100- }
3101+ }
3102+ if (anychange != 0) {
3103+ if (diff_format == D_CONTEXT)
3104+ dump_context_vec(f1, f2, flags);
3105+ else if (diff_format == D_UNIFIED)
3106+ dump_unified_vec(f1, f2, flags);
3107+ }
3108 }
3109
3110 static void
3111 range(int a, int b, const char *separator)
3112 {
3113- printf("%d", a > b ? b : a);
3114- if (a < b)
3115- printf("%s%d", separator, b);
3116+ printf("%d", a > b ? b : a);
3117+ if (a < b)
3118+ printf("%s%d", separator, b);
3119 }
3120
3121 static void
3122 uni_range(int a, int b)
3123 {
3124- if (a < b)
3125- printf("%d,%d", a, b - a + 1);
3126- else if (a == b)
3127- printf("%d", b);
3128- else
3129- printf("%d,0", b);
3130+ if (a < b)
3131+ printf("%d,%d", a, b - a + 1);
3132+ else if (a == b)
3133+ printf("%d", b);
3134+ else
3135+ printf("%d,0", b);
3136 }
3137
3138 static char *
3139 preadline(int fd, size_t rlen, off_t off)
3140 {
3141- char *line;
3142- ssize_t nr;
3143-
3144- line = emalloc(rlen + 1);
3145- if ((nr = pread(fd, line, rlen, off)) == -1)
3146- err(2, "preadline");
3147- if (nr > 0 && line[nr-1] == '\n')
3148- nr--;
3149- line[nr] = '\0';
3150- return line;
3151+ char *line;
3152+ ssize_t nr;
3153+
3154+ line = emalloc(rlen + 1);
3155+ if ((nr = pread(fd, line, rlen, off)) == -1)
3156+ enprintf(2, "preadline");
3157+ if (nr > 0 && line[nr-1] == '\n')
3158+ nr--;
3159+ line[nr] = '\0';
3160+ return line;
3161 }
3162
3163 static int
3164 ignoreline_pattern(char *line)
3165 {
3166- int ret;
3167+ int ret;
3168
3169- ret = regexec(&ignore_re, line, 0, NULL, 0);
3170- return ret == 0;
3171+ ret = regexec(&ignore_re, line, 0, NULL, 0);
3172+ return ret == 0;
3173 }
3174
3175 static int
3176 ignoreline(char *line, int skip_blanks)
3177 {
3178- if (skip_blanks && *line == '\0')
3179- return 1;
3180- if (ignore_pats != NULL && ignoreline_pattern(line))
3181- return 1;
3182- return 0;
3183+ if (skip_blanks && *line == '\0')
3184+ return 1;
3185+ if (ignore_pats != NULL && ignoreline_pattern(line))
3186+ return 1;
3187+ return 0;
3188 }
3189
3190 static void
3191 change(char *file1, FILE *f1, char *file2, FILE *f2, int a, int b, int c, int d,
3192 int *pflags)
3193 {
3194- static size_t max_context = 64;
3195- long curpos;
3196- int i, nc;
3197- const char *walk;
3198- int skip_blanks, ignore;
3199+ static size_t max_context = 64;
3200+ long curpos;
3201+ int i, nc;
3202+ const char *walk;
3203+ int skip_blanks, ignore;
3204
3205- skip_blanks = (*pflags & D_SKIPBLANKLINES);
3206+ skip_blanks = (*pflags & D_SKIPBLANKLINES);
3207 restart:
3208- if ((diff_format != D_IFDEF || diff_format == D_GFORMAT) && a > b && c > d)
3209- return;
3210- if (ignore_pats != NULL || skip_blanks) {
3211- char *line;
3212- if (a <= b) {
3213- for (i = a; i <= b; i++) {
3214- line = preadline(fileno(f1), ixold[i] - ixold[i - 1], ixold[i - 1]);
3215- ignore = ignoreline(line, skip_blanks);
3216- free(line);
3217- if (!ignore)
3218- goto proceed;
3219- }
3220- }
3221- if (a > b || c <= d) {
3222- for (i = c; i <= d; i++) {
3223- line = preadline(fileno(f2), ixnew[i] - ixnew[i - 1], ixnew[i - 1]);
3224- ignore = ignoreline(line, skip_blanks);
3225- free(line);
3226- if (!ignore)
3227- goto proceed;
3228- }
3229- }
3230- return;
3231- }
3232+ if ((diff_format != D_IFDEF || diff_format == D_GFORMAT) && a > b && c > d)
3233+ return;
3234+ if (ignore_pats != NULL || skip_blanks) {
3235+ char *line;
3236+ if (a <= b) {
3237+ for (i = a; i <= b; i++) {
3238+ line = preadline(fileno(f1), ixold[i] - ixold[i - 1], ixold[i - 1]);
3239+ ignore = ignoreline(line, skip_blanks);
3240+ free(line);
3241+ if (!ignore)
3242+ goto proceed;
3243+ }
3244+ }
3245+ if (a > b || c <= d) {
3246+ for (i = c; i <= d; i++) {
3247+ line = preadline(fileno(f2), ixnew[i] - ixnew[i - 1], ixnew[i - 1]);
3248+ ignore = ignoreline(line, skip_blanks);
3249+ free(line);
3250+ if (!ignore)
3251+ goto proceed;
3252+ }
3253+ }
3254+ return;
3255+ }
3256 proceed:
3257- if (*pflags & D_HEADER && diff_format != D_BRIEF) {
3258- printf("%s %s %s\n", diffargs, file1, file2);
3259- *pflags &= ~D_HEADER;
3260- }
3261- if (diff_format == D_CONTEXT || diff_format == D_UNIFIED) {
3262- if (context_vec_start == NULL || context_vec_ptr == context_vec_end - 1) {
3263- ptrdiff_t offset = -1;
3264-
3265- if (context_vec_start != NULL)
3266- offset = context_vec_ptr - context_vec_start;
3267- max_context <<= 1;
3268- context_vec_start = ereallocarray(context_vec_start, max_context, sizeof(*context_vec_start));
3269- context_vec_end = context_vec_start + max_context;
3270- context_vec_ptr = context_vec_start + offset;
3271- }
3272- if (anychange == 0) {
3273- print_header(file1, file2);
3274- anychange = 1;
3275- } else if (a > context_vec_ptr->b + (2 * diff_context) + 1 &&
3276- c > context_vec_ptr->d + (2 * diff_context) + 1) {
3277- if (diff_format == D_CONTEXT)
3278- dump_context_vec(f1, f2, *pflags);
3279- else
3280- dump_unified_vec(f1, f2, *pflags);
3281- }
3282- context_vec_ptr++;
3283- context_vec_ptr->a = a;
3284- context_vec_ptr->b = b;
3285- context_vec_ptr->c = c;
3286- context_vec_ptr->d = d;
3287- return;
3288- }
3289- if (anychange == 0)
3290- anychange = 1;
3291- switch (diff_format) {
3292- case D_BRIEF:
3293- return;
3294- case D_NORMAL:
3295- case D_EDIT:
3296- range(a, b, ",");
3297- printf("%c", a > b ? 'a' : c > d ? 'd' : 'c');
3298- if (diff_format == D_NORMAL)
3299- range(c, d, ",");
3300- printf("\n");
3301- break;
3302- case D_REVERSE:
3303- printf("%c", a > b ? 'a' : c > d ? 'd' : 'c');
3304- range(a, b, " ");
3305- printf("\n");
3306- break;
3307- case D_NREVERSE:
3308- if (a > b)
3309- printf("a%d %d\n", b, d - c + 1);
3310- else {
3311- printf("d%d %d\n", a, b - a + 1);
3312- if (!(c > d))
3313- printf("a%d %d\n", b, d - c + 1);
3314- }
3315- break;
3316- }
3317- if (diff_format == D_GFORMAT) {
3318- curpos = ftell(f1);
3319- nc = ixold[a > b ? b : a - 1] - curpos;
3320- for (i = 0; i < nc; i++)
3321- printf("%c", getc(f1));
3322- for (walk = group_format; *walk != '\0'; walk++) {
3323- if (*walk == '%') {
3324- walk++;
3325- switch (*walk) {
3326- case '<':
3327- fetch(ixold, a, b, f1, '<', 1, *pflags);
3328- break;
3329- case '>':
3330- fetch(ixnew, c, d, f2, '>', 0, *pflags);
3331- break;
3332- default:
3333- printf("%%%c", *walk);
3334- break;
3335- }
3336- continue;
3337- }
3338- printf("%c", *walk);
3339- }
3340- }
3341- if (diff_format == D_SIDEBYSIDE) {
3342- if (color && a > b)
3343- printf("\033[%sm", add_code);
3344- else if (color && c > d)
3345- printf("\033[%sm", del_code);
3346- if (a > b) {
3347- print_space(0, hw + lpad, *pflags);
3348- } else {
3349- nc = fetch(ixold, a, b, f1, '\0', 1, *pflags);
3350- print_space(nc, hw - nc + lpad, *pflags);
3351- }
3352- if (color && a > b)
3353- printf("\033[%sm", add_code);
3354- else if (color && c > d)
3355- printf("\033[%sm", del_code);
3356- printf("%c", (a > b) ? '>' : ((c > d) ? '<' : '|'));
3357- if (color && c > d)
3358- printf("\033[m");
3359- print_space(hw + lpad + 1, rpad, *pflags);
3360- fetch(ixnew, c, d, f2, '\0', 0, *pflags);
3361- printf("\n");
3362- }
3363- if (diff_format == D_NORMAL || diff_format == D_IFDEF) {
3364- fetch(ixold, a, b, f1, '<', 1, *pflags);
3365- if (a <= b && c <= d && diff_format == D_NORMAL)
3366- printf("---\n");
3367- }
3368- if (diff_format != D_GFORMAT && diff_format != D_SIDEBYSIDE)
3369- fetch(ixnew, c, d, f2, diff_format == D_NORMAL ? '>' : '\0', 0, *pflags);
3370- if (edoffset != 0 && diff_format == D_EDIT) {
3371- printf(".\n");
3372- printf("%ds/.//\n", a + edoffset - 1);
3373- b = a + edoffset - 1;
3374- a = b + 1;
3375- c += edoffset;
3376- goto restart;
3377- }
3378- if ((diff_format == D_EDIT || diff_format == D_REVERSE) && c <= d)
3379- printf(".\n");
3380- if (inifdef) {
3381- printf("#endif /* %s */\n", ifdefname);
3382- inifdef = 0;
3383- }
3384+ if (*pflags & D_HEADER && diff_format != D_BRIEF) {
3385+ printf("%s %s %s\n", diffargs, file1, file2);
3386+ *pflags &= ~D_HEADER;
3387+ }
3388+ if (diff_format == D_CONTEXT || diff_format == D_UNIFIED) {
3389+ if (context_vec_start == NULL || context_vec_ptr == context_vec_end - 1) {
3390+ ptrdiff_t offset = -1;
3391+
3392+ if (context_vec_start != NULL)
3393+ offset = context_vec_ptr - context_vec_start;
3394+ max_context <<= 1;
3395+ context_vec_start = ereallocarray(context_vec_start, max_context, sizeof(*context_vec_start));
3396+ context_vec_end = context_vec_start + max_context;
3397+ context_vec_ptr = context_vec_start + offset;
3398+ }
3399+ if (anychange == 0) {
3400+ print_header(file1, file2);
3401+ anychange = 1;
3402+ } else if (a > context_vec_ptr->b + (2 * diff_context) + 1 &&
3403+ c > context_vec_ptr->d + (2 * diff_context) + 1) {
3404+ if (diff_format == D_CONTEXT)
3405+ dump_context_vec(f1, f2, *pflags);
3406+ else
3407+ dump_unified_vec(f1, f2, *pflags);
3408+ }
3409+ context_vec_ptr++;
3410+ context_vec_ptr->a = a;
3411+ context_vec_ptr->b = b;
3412+ context_vec_ptr->c = c;
3413+ context_vec_ptr->d = d;
3414+ return;
3415+ }
3416+ if (anychange == 0)
3417+ anychange = 1;
3418+ switch (diff_format) {
3419+ case D_BRIEF:
3420+ return;
3421+ case D_NORMAL:
3422+ case D_EDIT:
3423+ range(a, b, ",");
3424+ printf("%c", a > b ? 'a' : c > d ? 'd' : 'c');
3425+ if (diff_format == D_NORMAL)
3426+ range(c, d, ",");
3427+ printf("\n");
3428+ break;
3429+ case D_REVERSE:
3430+ printf("%c", a > b ? 'a' : c > d ? 'd' : 'c');
3431+ range(a, b, " ");
3432+ printf("\n");
3433+ break;
3434+ case D_NREVERSE:
3435+ if (a > b)
3436+ printf("a%d %d\n", b, d - c + 1);
3437+ else {
3438+ printf("d%d %d\n", a, b - a + 1);
3439+ if (!(c > d))
3440+ printf("a%d %d\n", b, d - c + 1);
3441+ }
3442+ break;
3443+ }
3444+ if (diff_format == D_GFORMAT) {
3445+ curpos = ftell(f1);
3446+ nc = ixold[a > b ? b : a - 1] - curpos;
3447+ for (i = 0; i < nc; i++)
3448+ printf("%c", getc(f1));
3449+ for (walk = group_format; *walk != '\0'; walk++) {
3450+ if (*walk == '%') {
3451+ walk++;
3452+ switch (*walk) {
3453+ case '<':
3454+ fetch(ixold, a, b, f1, '<', 1, *pflags);
3455+ break;
3456+ case '>':
3457+ fetch(ixnew, c, d, f2, '>', 0, *pflags);
3458+ break;
3459+ default:
3460+ printf("%%%c", *walk);
3461+ break;
3462+ }
3463+ continue;
3464+ }
3465+ printf("%c", *walk);
3466+ }
3467+ }
3468+ if (diff_format == D_SIDEBYSIDE) {
3469+ if (color && a > b)
3470+ printf("\033[%sm", add_code);
3471+ else if (color && c > d)
3472+ printf("\033[%sm", del_code);
3473+ if (a > b) {
3474+ print_space(0, hw + lpad, *pflags);
3475+ } else {
3476+ nc = fetch(ixold, a, b, f1, '\0', 1, *pflags);
3477+ print_space(nc, hw - nc + lpad, *pflags);
3478+ }
3479+ if (color && a > b)
3480+ printf("\033[%sm", add_code);
3481+ else if (color && c > d)
3482+ printf("\033[%sm", del_code);
3483+ printf("%c", (a > b) ? '>' : ((c > d) ? '<' : '|'));
3484+ if (color && c > d)
3485+ printf("\033[m");
3486+ print_space(hw + lpad + 1, rpad, *pflags);
3487+ fetch(ixnew, c, d, f2, '\0', 0, *pflags);
3488+ printf("\n");
3489+ }
3490+ if (diff_format == D_NORMAL || diff_format == D_IFDEF) {
3491+ fetch(ixold, a, b, f1, '<', 1, *pflags);
3492+ if (a <= b && c <= d && diff_format == D_NORMAL)
3493+ printf("---\n");
3494+ }
3495+ if (diff_format != D_GFORMAT && diff_format != D_SIDEBYSIDE)
3496+ fetch(ixnew, c, d, f2, diff_format == D_NORMAL ? '>' : '\0', 0, *pflags);
3497+ if (edoffset != 0 && diff_format == D_EDIT) {
3498+ printf(".\n");
3499+ printf("%ds/.//\n", a + edoffset - 1);
3500+ b = a + edoffset - 1;
3501+ a = b + 1;
3502+ c += edoffset;
3503+ goto restart;
3504+ }
3505+ if ((diff_format == D_EDIT || diff_format == D_REVERSE) && c <= d)
3506+ printf(".\n");
3507+ if (inifdef) {
3508+ printf("#endif /* %s */\n", ifdefname);
3509+ inifdef = 0;
3510+ }
3511 }
3512
3513 static int
3514 fetch(long *f, int a, int b, FILE *lb, int ch, int oldfile, int flags)
3515 {
3516- int i, j, c, lastc, col, nc, newcol;
3517-
3518- edoffset = 0;
3519- nc = 0;
3520- col = 0;
3521- if ((diff_format == D_IFDEF) && oldfile) {
3522- long curpos = ftell(lb);
3523- nc = f[a > b ? b : a - 1] - curpos;
3524- for (i = 0; i < nc; i++)
3525- printf("%c", getc(lb));
3526- }
3527- if (a > b)
3528- return 0;
3529- if (diff_format == D_IFDEF) {
3530- if (inifdef) {
3531- printf("#else /* %s%s */\n",
3532- oldfile == 1 ? "!" : "", ifdefname);
3533- } else {
3534- if (oldfile)
3535- printf("#ifndef %s\n", ifdefname);
3536- else
3537- printf("#ifdef %s\n", ifdefname);
3538- }
3539- inifdef = 1 + oldfile;
3540- }
3541- for (i = a; i <= b; i++) {
3542- fseek(lb, f[i - 1], SEEK_SET);
3543- nc = f[i] - f[i - 1];
3544- if (diff_format == D_SIDEBYSIDE && hw < nc)
3545- nc = hw;
3546- if (diff_format != D_IFDEF && diff_format != D_GFORMAT && ch != '\0') {
3547- if (color && (ch == '>' || ch == '+'))
3548- printf("\033[%sm", add_code);
3549- else if (color && (ch == '<' || ch == '-'))
3550- printf("\033[%sm", del_code);
3551- printf("%c", ch);
3552- if (Tflag && (diff_format == D_NORMAL ||
3553- diff_format == D_CONTEXT ||
3554- diff_format == D_UNIFIED))
3555- printf("\t");
3556- else if (diff_format != D_UNIFIED)
3557- printf(" ");
3558- }
3559- col = j = 0;
3560- lastc = '\0';
3561- while (j < nc && (hw == 0 || col < hw)) {
3562- c = getc(lb);
3563- if (flags & D_STRIPCR && c == '\r') {
3564- if ((c = getc(lb)) == '\n')
3565- j++;
3566- else {
3567- ungetc(c, lb);
3568- c = '\r';
3569- }
3570- }
3571- if (c == EOF) {
3572- if (diff_format == D_EDIT ||
3573- diff_format == D_REVERSE ||
3574- diff_format == D_NREVERSE)
3575- warnx("No newline at end of file");
3576- else
3577- printf("\n\\ No newline at end of file\n");
3578- return col;
3579- }
3580- if (c == '\t') {
3581- newcol = roundup(col + 1, tabsize);
3582- if ((flags & D_EXPANDTABS) == 0) {
3583- if (hw > 0 && newcol >= hw)
3584- return col;
3585- printf("\t");
3586- } else {
3587- if (hw > 0 && newcol > hw)
3588- newcol = hw;
3589- printf("%*s", newcol - col, "");
3590- }
3591- col = newcol;
3592- } else {
3593- if (diff_format == D_EDIT && j == 1 && c == '\n' && lastc == '.') {
3594- printf(".\n");
3595- edoffset = i - a + 1;
3596- return edoffset;
3597- }
3598- if (diff_format != D_SIDEBYSIDE || c != '\n') {
3599- if (color && c == '\n')
3600- printf("\033[m%c", c);
3601- else
3602- printf("%c", c);
3603- col++;
3604- }
3605- }
3606- j++;
3607- lastc = c;
3608- }
3609- }
3610- if (color && diff_format == D_SIDEBYSIDE)
3611- printf("\033[m");
3612- return col;
3613+ int i, j, c, lastc, col, nc, newcol;
3614+
3615+ edoffset = 0;
3616+ nc = 0;
3617+ col = 0;
3618+ if ((diff_format == D_IFDEF) && oldfile) {
3619+ long curpos = ftell(lb);
3620+ nc = f[a > b ? b : a - 1] - curpos;
3621+ for (i = 0; i < nc; i++)
3622+ printf("%c", getc(lb));
3623+ }
3624+ if (a > b)
3625+ return 0;
3626+ if (diff_format == D_IFDEF) {
3627+ if (inifdef) {
3628+ printf("#else /* %s%s */\n",
3629+ oldfile == 1 ? "!" : "", ifdefname);
3630+ } else {
3631+ if (oldfile)
3632+ printf("#ifndef %s\n", ifdefname);
3633+ else
3634+ printf("#ifdef %s\n", ifdefname);
3635+ }
3636+ inifdef = 1 + oldfile;
3637+ }
3638+ for (i = a; i <= b; i++) {
3639+ fseek(lb, f[i - 1], SEEK_SET);
3640+ nc = f[i] - f[i - 1];
3641+ if (diff_format == D_SIDEBYSIDE && hw < nc)
3642+ nc = hw;
3643+ if (diff_format != D_IFDEF && diff_format != D_GFORMAT && ch != '\0') {
3644+ if (color && (ch == '>' || ch == '+'))
3645+ printf("\033[%sm", add_code);
3646+ else if (color && (ch == '<' || ch == '-'))
3647+ printf("\033[%sm", del_code);
3648+ printf("%c", ch);
3649+ if (Tflag && (diff_format == D_NORMAL ||
3650+ diff_format == D_CONTEXT ||
3651+ diff_format == D_UNIFIED))
3652+ printf("\t");
3653+ else if (diff_format != D_UNIFIED)
3654+ printf(" ");
3655+ }
3656+ col = j = 0;
3657+ lastc = '\0';
3658+ while (j < nc && (hw == 0 || col < hw)) {
3659+ c = getc(lb);
3660+ if (flags & D_STRIPCR && c == '\r') {
3661+ if ((c = getc(lb)) == '\n')
3662+ j++;
3663+ else {
3664+ ungetc(c, lb);
3665+ c = '\r';
3666+ }
3667+ }
3668+ if (c == EOF) {
3669+ if (diff_format == D_EDIT ||
3670+ diff_format == D_REVERSE ||
3671+ diff_format == D_NREVERSE)
3672+ weprintf("No newline at end of file");
3673+ else
3674+ printf("\n\\ No newline at end of file\n");
3675+ return col;
3676+ }
3677+ if (c == '\t') {
3678+ newcol = roundup(col + 1, tabsize);
3679+ if ((flags & D_EXPANDTABS) == 0) {
3680+ if (hw > 0 && newcol >= hw)
3681+ return col;
3682+ printf("\t");
3683+ } else {
3684+ if (hw > 0 && newcol > hw)
3685+ newcol = hw;
3686+ printf("%*s", newcol - col, "");
3687+ }
3688+ col = newcol;
3689+ } else {
3690+ if (diff_format == D_EDIT && j == 1 && c == '\n' && lastc == '.') {
3691+ printf(".\n");
3692+ edoffset = i - a + 1;
3693+ return edoffset;
3694+ }
3695+ if (diff_format != D_SIDEBYSIDE || c != '\n') {
3696+ if (color && c == '\n')
3697+ printf("\033[m%c", c);
3698+ else
3699+ printf("%c", c);
3700+ col++;
3701+ }
3702+ }
3703+ j++;
3704+ lastc = c;
3705+ }
3706+ }
3707+ if (color && diff_format == D_SIDEBYSIDE)
3708+ printf("\033[m");
3709+ return col;
3710 }
3711
3712 static enum Readhash
3713 readhash(FILE *f, int flags, unsigned *hash)
3714 {
3715- int i, t, space;
3716- unsigned sum;
3717-
3718- sum = 1;
3719- space = 0;
3720- for (i = 0;;) {
3721- switch (t = getc(f)) {
3722- case '\0':
3723- if ((flags & D_FORCEASCII) == 0)
3724- return RH_BINARY;
3725- goto hashchar;
3726- case '\r':
3727- if (flags & D_STRIPCR) {
3728- t = getc(f);
3729- if (t == '\n')
3730- break;
3731- ungetc(t, f);
3732- }
3733- /* FALLTHROUGH */
3734- case '\t':
3735- case '\v':
3736- case '\f':
3737- case ' ':
3738- if ((flags & (D_FOLDBLANKS|D_IGNOREBLANKS)) != 0) {
3739- space++;
3740- continue;
3741- }
3742- /* FALLTHROUGH */
3743- default:
3744- hashchar:
3745- if (space && (flags & D_IGNOREBLANKS) == 0) {
3746- i++;
3747- space = 0;
3748- }
3749- sum = sum * 127 + chrtran(t);
3750- i++;
3751- continue;
3752- case EOF:
3753- if (i == 0)
3754- return RH_EOF;
3755- /* FALLTHROUGH */
3756- case '\n':
3757- break;
3758- }
3759- break;
3760- }
3761- *hash = sum;
3762- return RH_OK;
3763+ int i, t, space;
3764+ unsigned sum;
3765+
3766+ sum = 1;
3767+ space = 0;
3768+ for (i = 0;;) {
3769+ switch (t = getc(f)) {
3770+ case '\0':
3771+ if ((flags & D_FORCEASCII) == 0)
3772+ return RH_BINARY;
3773+ goto hashchar;
3774+ case '\r':
3775+ if (flags & D_STRIPCR) {
3776+ t = getc(f);
3777+ if (t == '\n')
3778+ break;
3779+ ungetc(t, f);
3780+ }
3781+ /* FALLTHROUGH */
3782+ case '\t':
3783+ case '\v':
3784+ case '\f':
3785+ case ' ':
3786+ if ((flags & (D_FOLDBLANKS|D_IGNOREBLANKS)) != 0) {
3787+ space++;
3788+ continue;
3789+ }
3790+ /* FALLTHROUGH */
3791+ default:
3792+ hashchar:
3793+ if (space && (flags & D_IGNOREBLANKS) == 0) {
3794+ i++;
3795+ space = 0;
3796+ }
3797+ sum = sum * 127 + chrtran(t);
3798+ i++;
3799+ continue;
3800+ case EOF:
3801+ if (i == 0)
3802+ return RH_EOF;
3803+ /* FALLTHROUGH */
3804+ case '\n':
3805+ break;
3806+ }
3807+ break;
3808+ }
3809+ *hash = sum;
3810+ return RH_OK;
3811 }
3812
3813 static int
3814 asciifile(FILE *f)
3815 {
3816- unsigned char buf[BUFSIZ];
3817- size_t cnt;
3818+ unsigned char buf[BUFSIZ];
3819+ size_t cnt;
3820
3821- if (f == NULL)
3822- return 1;
3823+ if (f == NULL)
3824+ return 1;
3825
3826- rewind(f);
3827- cnt = fread(buf, 1, sizeof(buf), f);
3828- return memchr(buf, '\0', cnt) == NULL;
3829+ rewind(f);
3830+ cnt = fread(buf, 1, sizeof(buf), f);
3831+ return memchr(buf, '\0', cnt) == NULL;
3832 }
3833
3834 #define begins_with(s, pre) (strncmp(s, pre, sizeof(pre) - 1) == 0)
3835@@ -2232,258 +2239,258 @@ asciifile(FILE *f)
3836 static char *
3837 match_function(const long *f, int pos, FILE *fp)
3838 {
3839- char buf[FUNCTION_CONTEXT_SIZE];
3840- size_t nc;
3841- int last = lastline;
3842- const char *state = NULL;
3843-
3844- lastline = pos;
3845- for (; pos > last; pos--) {
3846- fseek(fp, f[pos - 1], SEEK_SET);
3847- nc = f[pos] - f[pos - 1];
3848- if (nc >= sizeof(buf))
3849- nc = sizeof(buf) - 1;
3850- nc = fread(buf, 1, nc, fp);
3851- if (nc == 0)
3852- continue;
3853- buf[nc] = '\0';
3854- buf[strcspn(buf, "\n")] = '\0';
3855- if (most_recent_pat != NULL) {
3856- int ret = regexec(&most_recent_re, buf, 0, NULL, 0);
3857- if (ret != 0)
3858- continue;
3859- strlcpy(lastbuf, buf, sizeof(lastbuf));
3860- lastmatchline = pos;
3861- return lastbuf;
3862- } else if (isalpha(buf[0]) || buf[0] == '_' || buf[0] == '$' || buf[0] == '-' || buf[0] == '+') {
3863- if (begins_with(buf, "private:")) {
3864- if (!state)
3865- state = " (private)";
3866- } else if (begins_with(buf, "protected:")) {
3867- if (!state)
3868- state = " (protected)";
3869- } else if (begins_with(buf, "public:")) {
3870- if (!state)
3871- state = " (public)";
3872- } else {
3873- strlcpy(lastbuf, buf, sizeof(lastbuf));
3874- if (state)
3875- strlcat(lastbuf, state, sizeof(lastbuf));
3876- lastmatchline = pos;
3877- return lastbuf;
3878- }
3879- }
3880- }
3881- return lastmatchline > 0 ? lastbuf : NULL;
3882+ char buf[FUNCTION_CONTEXT_SIZE];
3883+ size_t nc;
3884+ int last = lastline;
3885+ const char *state = NULL;
3886+
3887+ lastline = pos;
3888+ for (; pos > last; pos--) {
3889+ fseek(fp, f[pos - 1], SEEK_SET);
3890+ nc = f[pos] - f[pos - 1];
3891+ if (nc >= sizeof(buf))
3892+ nc = sizeof(buf) - 1;
3893+ nc = fread(buf, 1, nc, fp);
3894+ if (nc == 0)
3895+ continue;
3896+ buf[nc] = '\0';
3897+ buf[strcspn(buf, "\n")] = '\0';
3898+ if (most_recent_pat != NULL) {
3899+ int ret = regexec(&most_recent_re, buf, 0, NULL, 0);
3900+ if (ret != 0)
3901+ continue;
3902+ strlcpy(lastbuf, buf, sizeof(lastbuf));
3903+ lastmatchline = pos;
3904+ return lastbuf;
3905+ } else if (isalpha(buf[0]) || buf[0] == '_' || buf[0] == '$' || buf[0] == '-' || buf[0] == '+') {
3906+ if (begins_with(buf, "private:")) {
3907+ if (!state)
3908+ state = " (private)";
3909+ } else if (begins_with(buf, "protected:")) {
3910+ if (!state)
3911+ state = " (protected)";
3912+ } else if (begins_with(buf, "public:")) {
3913+ if (!state)
3914+ state = " (public)";
3915+ } else {
3916+ strlcpy(lastbuf, buf, sizeof(lastbuf));
3917+ if (state)
3918+ strlcat(lastbuf, state, sizeof(lastbuf));
3919+ lastmatchline = pos;
3920+ return lastbuf;
3921+ }
3922+ }
3923+ }
3924+ return lastmatchline > 0 ? lastbuf : NULL;
3925 }
3926
3927 static void
3928 dump_context_vec(FILE *f1, FILE *f2, int flags)
3929 {
3930- struct ContextVec *cvp = context_vec_start;
3931- int lowa, upb, lowc, upd, do_output;
3932- int a, b, c, d;
3933- char ch, *f;
3934-
3935- if (context_vec_start > context_vec_ptr)
3936- return;
3937-
3938- b = d = 0;
3939- lowa = MAX(1, cvp->a - diff_context);
3940- upb = MIN((int)len[0], context_vec_ptr->b + diff_context);
3941- lowc = MAX(1, cvp->c - diff_context);
3942- upd = MIN((int)len[1], context_vec_ptr->d + diff_context);
3943-
3944- printf("***************");
3945- if (flags & (D_PROTOTYPE | D_MATCHLAST)) {
3946- f = match_function(ixold, cvp->a - 1, f1);
3947- if (f != NULL)
3948- printf(" %s", f);
3949- }
3950- printf("\n*** ");
3951- range(lowa, upb, ",");
3952- printf(" ****\n");
3953-
3954- do_output = 0;
3955- for (; cvp <= context_vec_ptr; cvp++)
3956- if (cvp->a <= cvp->b) {
3957- cvp = context_vec_start;
3958- do_output++;
3959- break;
3960- }
3961- if (do_output) {
3962- while (cvp <= context_vec_ptr) {
3963- a = cvp->a;
3964- b = cvp->b;
3965- c = cvp->c;
3966- d = cvp->d;
3967-
3968- if (a <= b && c <= d)
3969- ch = 'c';
3970- else
3971- ch = (a <= b) ? 'd' : 'a';
3972-
3973- if (ch == 'a')
3974- fetch(ixold, lowa, b, f1, ' ', 0, flags);
3975- else {
3976- fetch(ixold, lowa, a - 1, f1, ' ', 0, flags);
3977- fetch(ixold, a, b, f1, ch == 'c' ? '!' : '-', 0, flags);
3978- }
3979- lowa = b + 1;
3980- cvp++;
3981- }
3982- fetch(ixold, b + 1, upb, f1, ' ', 0, flags);
3983- }
3984-
3985- printf("--- ");
3986- range(lowc, upd, ",");
3987- printf(" ----\n");
3988-
3989- do_output = 0;
3990- for (cvp = context_vec_start; cvp <= context_vec_ptr; cvp++)
3991- if (cvp->c <= cvp->d) {
3992- cvp = context_vec_start;
3993- do_output++;
3994- break;
3995- }
3996- if (do_output) {
3997- while (cvp <= context_vec_ptr) {
3998- a = cvp->a;
3999- b = cvp->b;
4000- c = cvp->c;
4001- d = cvp->d;
4002-
4003- if (a <= b && c <= d)
4004- ch = 'c';
4005- else
4006- ch = (a <= b) ? 'd' : 'a';
4007-
4008- if (ch == 'd')
4009- fetch(ixnew, lowc, d, f2, ' ', 0, flags);
4010- else {
4011- fetch(ixnew, lowc, c - 1, f2, ' ', 0, flags);
4012- fetch(ixnew, c, d, f2, ch == 'c' ? '!' : '+', 0, flags);
4013- }
4014- lowc = d + 1;
4015- cvp++;
4016- }
4017- fetch(ixnew, d + 1, upd, f2, ' ', 0, flags);
4018- }
4019- context_vec_ptr = context_vec_start - 1;
4020+ struct ContextVec *cvp = context_vec_start;
4021+ int lowa, upb, lowc, upd, do_output;
4022+ int a, b, c, d;
4023+ char ch, *f;
4024+
4025+ if (context_vec_start > context_vec_ptr)
4026+ return;
4027+
4028+ b = d = 0;
4029+ lowa = MAX(1, cvp->a - diff_context);
4030+ upb = MIN((int)len[0], context_vec_ptr->b + diff_context);
4031+ lowc = MAX(1, cvp->c - diff_context);
4032+ upd = MIN((int)len[1], context_vec_ptr->d + diff_context);
4033+
4034+ printf("***************");
4035+ if (flags & (D_PROTOTYPE | D_MATCHLAST)) {
4036+ f = match_function(ixold, cvp->a - 1, f1);
4037+ if (f != NULL)
4038+ printf(" %s", f);
4039+ }
4040+ printf("\n*** ");
4041+ range(lowa, upb, ",");
4042+ printf(" ****\n");
4043+
4044+ do_output = 0;
4045+ for (; cvp <= context_vec_ptr; cvp++)
4046+ if (cvp->a <= cvp->b) {
4047+ cvp = context_vec_start;
4048+ do_output++;
4049+ break;
4050+ }
4051+ if (do_output) {
4052+ while (cvp <= context_vec_ptr) {
4053+ a = cvp->a;
4054+ b = cvp->b;
4055+ c = cvp->c;
4056+ d = cvp->d;
4057+
4058+ if (a <= b && c <= d)
4059+ ch = 'c';
4060+ else
4061+ ch = (a <= b) ? 'd' : 'a';
4062+
4063+ if (ch == 'a')
4064+ fetch(ixold, lowa, b, f1, ' ', 0, flags);
4065+ else {
4066+ fetch(ixold, lowa, a - 1, f1, ' ', 0, flags);
4067+ fetch(ixold, a, b, f1, ch == 'c' ? '!' : '-', 0, flags);
4068+ }
4069+ lowa = b + 1;
4070+ cvp++;
4071+ }
4072+ fetch(ixold, b + 1, upb, f1, ' ', 0, flags);
4073+ }
4074+
4075+ printf("--- ");
4076+ range(lowc, upd, ",");
4077+ printf(" ----\n");
4078+
4079+ do_output = 0;
4080+ for (cvp = context_vec_start; cvp <= context_vec_ptr; cvp++)
4081+ if (cvp->c <= cvp->d) {
4082+ cvp = context_vec_start;
4083+ do_output++;
4084+ break;
4085+ }
4086+ if (do_output) {
4087+ while (cvp <= context_vec_ptr) {
4088+ a = cvp->a;
4089+ b = cvp->b;
4090+ c = cvp->c;
4091+ d = cvp->d;
4092+
4093+ if (a <= b && c <= d)
4094+ ch = 'c';
4095+ else
4096+ ch = (a <= b) ? 'd' : 'a';
4097+
4098+ if (ch == 'd')
4099+ fetch(ixnew, lowc, d, f2, ' ', 0, flags);
4100+ else {
4101+ fetch(ixnew, lowc, c - 1, f2, ' ', 0, flags);
4102+ fetch(ixnew, c, d, f2, ch == 'c' ? '!' : '+', 0, flags);
4103+ }
4104+ lowc = d + 1;
4105+ cvp++;
4106+ }
4107+ fetch(ixnew, d + 1, upd, f2, ' ', 0, flags);
4108+ }
4109+ context_vec_ptr = context_vec_start - 1;
4110 }
4111
4112 static void
4113 dump_unified_vec(FILE *f1, FILE *f2, int flags)
4114 {
4115- struct ContextVec *cvp = context_vec_start;
4116- int lowa, upb, lowc, upd;
4117- int a, b, c, d;
4118- char ch, *f;
4119-
4120- if (context_vec_start > context_vec_ptr)
4121- return;
4122-
4123- b = d = 0;
4124- lowa = MAX(1, cvp->a - diff_context);
4125- upb = MIN((int)len[0], context_vec_ptr->b + diff_context);
4126- lowc = MAX(1, cvp->c - diff_context);
4127- upd = MIN((int)len[1], context_vec_ptr->d + diff_context);
4128-
4129- printf("@@ -");
4130- uni_range(lowa, upb);
4131- printf(" +");
4132- uni_range(lowc, upd);
4133- printf(" @@");
4134- if (flags & (D_PROTOTYPE | D_MATCHLAST)) {
4135- f = match_function(ixold, cvp->a - 1, f1);
4136- if (f != NULL)
4137- printf(" %s", f);
4138- }
4139- printf("\n");
4140-
4141- for (; cvp <= context_vec_ptr; cvp++) {
4142- a = cvp->a;
4143- b = cvp->b;
4144- c = cvp->c;
4145- d = cvp->d;
4146-
4147- if (a <= b && c <= d)
4148- ch = 'c';
4149- else
4150- ch = (a <= b) ? 'd' : 'a';
4151-
4152- switch (ch) {
4153- case 'c':
4154- fetch(ixold, lowa, a - 1, f1, ' ', 0, flags);
4155- fetch(ixold, a, b, f1, '-', 0, flags);
4156- fetch(ixnew, c, d, f2, '+', 0, flags);
4157- break;
4158- case 'd':
4159- fetch(ixold, lowa, a - 1, f1, ' ', 0, flags);
4160- fetch(ixold, a, b, f1, '-', 0, flags);
4161- break;
4162- case 'a':
4163- fetch(ixnew, lowc, c - 1, f2, ' ', 0, flags);
4164- fetch(ixnew, c, d, f2, '+', 0, flags);
4165- break;
4166- }
4167- lowa = b + 1;
4168- lowc = d + 1;
4169- }
4170- fetch(ixnew, d + 1, upd, f2, ' ', 0, flags);
4171- context_vec_ptr = context_vec_start - 1;
4172+ struct ContextVec *cvp = context_vec_start;
4173+ int lowa, upb, lowc, upd;
4174+ int a, b, c, d;
4175+ char ch, *f;
4176+
4177+ if (context_vec_start > context_vec_ptr)
4178+ return;
4179+
4180+ b = d = 0;
4181+ lowa = MAX(1, cvp->a - diff_context);
4182+ upb = MIN((int)len[0], context_vec_ptr->b + diff_context);
4183+ lowc = MAX(1, cvp->c - diff_context);
4184+ upd = MIN((int)len[1], context_vec_ptr->d + diff_context);
4185+
4186+ printf("@@ -");
4187+ uni_range(lowa, upb);
4188+ printf(" +");
4189+ uni_range(lowc, upd);
4190+ printf(" @@");
4191+ if (flags & (D_PROTOTYPE | D_MATCHLAST)) {
4192+ f = match_function(ixold, cvp->a - 1, f1);
4193+ if (f != NULL)
4194+ printf(" %s", f);
4195+ }
4196+ printf("\n");
4197+
4198+ for (; cvp <= context_vec_ptr; cvp++) {
4199+ a = cvp->a;
4200+ b = cvp->b;
4201+ c = cvp->c;
4202+ d = cvp->d;
4203+
4204+ if (a <= b && c <= d)
4205+ ch = 'c';
4206+ else
4207+ ch = (a <= b) ? 'd' : 'a';
4208+
4209+ switch (ch) {
4210+ case 'c':
4211+ fetch(ixold, lowa, a - 1, f1, ' ', 0, flags);
4212+ fetch(ixold, a, b, f1, '-', 0, flags);
4213+ fetch(ixnew, c, d, f2, '+', 0, flags);
4214+ break;
4215+ case 'd':
4216+ fetch(ixold, lowa, a - 1, f1, ' ', 0, flags);
4217+ fetch(ixold, a, b, f1, '-', 0, flags);
4218+ break;
4219+ case 'a':
4220+ fetch(ixnew, lowc, c - 1, f2, ' ', 0, flags);
4221+ fetch(ixnew, c, d, f2, '+', 0, flags);
4222+ break;
4223+ }
4224+ lowa = b + 1;
4225+ lowc = d + 1;
4226+ }
4227+ fetch(ixnew, d + 1, upd, f2, ' ', 0, flags);
4228+ context_vec_ptr = context_vec_start - 1;
4229 }
4230
4231 static void
4232 print_header(const char *file1, const char *file2)
4233 {
4234- const char *time_format;
4235- char buf[256];
4236- struct tm tm1, tm2, *tm_ptr1, *tm_ptr2;
4237- int nsec1 = stb1.st_mtim.tv_nsec;
4238- int nsec2 = stb2.st_mtim.tv_nsec;
4239-
4240- time_format = "%Y-%m-%d %H:%M:%S";
4241- if (cflag)
4242- time_format = "%c";
4243- tm_ptr1 = localtime_r(&stb1.st_mtime, &tm1);
4244- tm_ptr2 = localtime_r(&stb2.st_mtime, &tm2);
4245- if (label[0] != NULL)
4246- printf("%s %s\n", diff_format == D_CONTEXT ? "***" : "---", label[0]);
4247- else {
4248- strftime(buf, sizeof(buf), time_format, tm_ptr1);
4249- printf("%s %s\t%s", diff_format == D_CONTEXT ? "***" : "---", file1, buf);
4250- if (!cflag) {
4251- strftime(buf, sizeof(buf), "%z", tm_ptr1);
4252- printf(".%.9d %s", nsec1, buf);
4253- }
4254- printf("\n");
4255- }
4256- if (label[1] != NULL)
4257- printf("%s %s\n", diff_format == D_CONTEXT ? "---" : "+++", label[1]);
4258- else {
4259- strftime(buf, sizeof(buf), time_format, tm_ptr2);
4260- printf("%s %s\t%s", diff_format == D_CONTEXT ? "---" : "+++", file2, buf);
4261- if (!cflag) {
4262- strftime(buf, sizeof(buf), "%z", tm_ptr2);
4263- printf(".%.9d %s", nsec2, buf);
4264- }
4265- printf("\n");
4266- }
4267+ const char *time_format;
4268+ char buf[256];
4269+ struct tm tm1, tm2, *tm_ptr1, *tm_ptr2;
4270+ int nsec1 = stb1.st_mtim.tv_nsec;
4271+ int nsec2 = stb2.st_mtim.tv_nsec;
4272+
4273+ time_format = "%Y-%m-%d %H:%M:%S";
4274+ if (cflag)
4275+ time_format = "%c";
4276+ tm_ptr1 = localtime_r(&stb1.st_mtime, &tm1);
4277+ tm_ptr2 = localtime_r(&stb2.st_mtime, &tm2);
4278+ if (label[0] != NULL)
4279+ printf("%s %s\n", diff_format == D_CONTEXT ? "***" : "---", label[0]);
4280+ else {
4281+ strftime(buf, sizeof(buf), time_format, tm_ptr1);
4282+ printf("%s %s\t%s", diff_format == D_CONTEXT ? "***" : "---", file1, buf);
4283+ if (!cflag) {
4284+ strftime(buf, sizeof(buf), "%z", tm_ptr1);
4285+ printf(".%.9d %s", nsec1, buf);
4286+ }
4287+ printf("\n");
4288+ }
4289+ if (label[1] != NULL)
4290+ printf("%s %s\n", diff_format == D_CONTEXT ? "---" : "+++", label[1]);
4291+ else {
4292+ strftime(buf, sizeof(buf), time_format, tm_ptr2);
4293+ printf("%s %s\t%s", diff_format == D_CONTEXT ? "---" : "+++", file2, buf);
4294+ if (!cflag) {
4295+ strftime(buf, sizeof(buf), "%z", tm_ptr2);
4296+ printf(".%.9d %s", nsec2, buf);
4297+ }
4298+ printf("\n");
4299+ }
4300 }
4301
4302 static void
4303 print_space(int nc, int n, int flags)
4304 {
4305- int col, newcol, tabstop;
4306-
4307- col = nc;
4308- newcol = nc + n;
4309- if ((flags & D_EXPANDTABS) == 0) {
4310- while ((tabstop = roundup(col + 1, tabsize)) <= newcol) {
4311- printf("\t");
4312- col = tabstop;
4313- }
4314- }
4315- printf("%*s", newcol - col, "");
4316+ int col, newcol, tabstop;
4317+
4318+ col = nc;
4319+ newcol = nc + n;
4320+ if ((flags & D_EXPANDTABS) == 0) {
4321+ while ((tabstop = roundup(col + 1, tabsize)) <= newcol) {
4322+ printf("\t");
4323+ col = tabstop;
4324+ }
4325+ }
4326+ printf("%*s", newcol - col, "");
4327 }
+446,
-838
1@@ -1,894 +1,502 @@
2 /* See LICENSE file for copyright and license details. */
3+#include "config.h"
4+#include "diffutil.h"
5 #include "util.h"
6
7-#include <sys/types.h>
8-#include <sys/wait.h>
9-
10 #include <ctype.h>
11-#include <err.h>
12-#include <errno.h>
13-#include <fcntl.h>
14-#include <stdarg.h>
15-#include <getopt.h>
16-#include <inttypes.h>
17-#include <limits.h>
18-#include <poll.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23
24-struct Range {
25- int from;
26- int to;
27+struct region {
28+ size_t from;
29+ size_t to;
30 };
31
32-struct Diff {
33-#define DIFF_TYPE1 1
34-#define DIFF_TYPE2 2
35-#define DIFF_TYPE3 3
36- int type;
37-
38- struct Range old;
39- struct Range new;
40+struct pair_hunk {
41+ struct region old;
42+ struct region new;
43 };
44
45-#define EFLAG_NONE 0
46-#define EFLAG_OVERLAP 1
47-#define EFLAG_NOOVERLAP 2
48-#define EFLAG_UNMERGED 3
49-
50-static size_t szchanges;
51-
52-static struct Diff *d13;
53-static struct Diff *d23;
54-static struct Diff *de;
55-static char *overlap;
56-static int overlapcnt;
57-static FILE *fp[3];
58-static int cline[3];
59-static int sigpipe[2];
60-static int last[4];
61-static int Aflag, eflag, iflag, mflag, Tflag;
62-static int oflag;
63-static int strip_cr;
64-static char *f1mark, *f2mark, *f3mark;
65-static const char *oldmark = "<<<<<<<";
66-static const char *orgmark = "|||||||";
67-static const char *newmark = ">>>>>>>";
68-static const char *divider = "=======";
69-
70-static int duplicate(struct Range *, struct Range *);
71-static int edit(struct Diff *, int, int, int);
72-static char *getchange(FILE *);
73-static char *get_line(FILE *, size_t *);
74-static int readin(int, struct Diff **);
75-static int skip(int, int, const char *);
76-static void change(int, struct Range *, int);
77-static void keep(int, struct Range *);
78-static void merge(int, int);
79-static void prange(struct Range *, int);
80-static void repos(int);
81-static void separate(const char *);
82-static void edscript(int);
83-static void Ascript(int);
84-static void mergescript(int);
85-static void increase(void);
86-static void usage(void);
87-static void printrange(FILE *, struct Range *);
88-static void diffexec(const char *, char **, int *);
89-static int strtoi(char *, char **);
90-static void handle_sig(int);
91-static void xasprintf(char **, const char *, ...);
92-
93-static const char diff3_version[] = "FreeBSD diff3 20240925";
94-
95-enum {
96- DIFFPROG_OPT,
97- STRIPCR_OPT,
98- HELP_OPT,
99- VERSION_OPT
100+enum hunk_kind {
101+ HUNK_NONE,
102+ HUNK_TYPE1,
103+ HUNK_TYPE2,
104+ HUNK_TYPE3,
105 };
106
107-#define DIFF_PATH "/usr/bin/diff"
108-
109-#define OPTIONS "3aAeEiL:mTxX"
110-static struct option longopts[] = {
111- { "ed", no_argument, NULL, 'e' },
112- { "show-overlap", no_argument, NULL, 'E' },
113- { "overlap-only", no_argument, NULL, 'x' },
114- { "initial-tab", no_argument, NULL, 'T' },
115- { "text", no_argument, NULL, 'a' },
116- { "strip-trailing-cr", no_argument, NULL, STRIPCR_OPT },
117- { "show-all", no_argument, NULL, 'A' },
118- { "easy-only", no_argument, NULL, '3' },
119- { "merge", no_argument, NULL, 'm' },
120- { "label", required_argument, NULL, 'L' },
121- { "diff-program", required_argument, NULL, DIFFPROG_OPT },
122- { "help", no_argument, NULL, HELP_OPT},
123- { "version", no_argument, NULL, VERSION_OPT}
124+struct three_hunk {
125+ enum hunk_kind kind;
126+ struct region r1;
127+ struct region r2;
128+ struct region r3;
129+ int dup;
130 };
131
132-static void
133-usage(void)
134-{
135- fprintf(stderr, "usage: diff3 [-3aAeEimTxX] [-L label1] [-L label2] "
136- "[-L label3] file1 file2 file3\n");
137-}
138-
139-static int
140-strtoi(char *str, char **end)
141-{
142- intmax_t num;
143-
144- errno = 0;
145- num = strtoimax(str, end, 10);
146- if ((end != NULL && *end == str) ||
147- num < 0 || num > INT_MAX ||
148- errno == EINVAL || errno == ERANGE)
149- err(1, "error in diff output");
150- return (int)num;
151-}
152-
153-static int
154-readin(int fd, struct Diff **dd)
155-{
156- int a, b, c, d;
157- int i;
158- char kind, *p;
159- FILE *f;
160-
161- f = fdopen(fd, "r");
162- if (f == NULL)
163- err(2, "fdopen");
164- for (i = 0; (p = getchange(f)) != NULL; i++) {
165- if ((size_t)i >= szchanges - 1)
166- increase();
167-
168- a = b = strtoi(p, &p);
169- if (*p == ',')
170- b = strtoi(p + 1, &p);
171- kind = *p++;
172- c = d = strtoi(p, &p);
173- if (*p == ',')
174- d = strtoi(p + 1, &p);
175- if (*p != '\n')
176- errx(1, "error in diff output");
177- if (kind == 'a')
178- a++;
179- else if (kind == 'c')
180- /* nothing */ ;
181- else if (kind == 'd')
182- c++;
183- else
184- errx(1, "error in diff output");
185- b++;
186- d++;
187- if (b < a || d < c)
188- errx(1, "error in diff output");
189- (*dd)[i].old.from = a;
190- (*dd)[i].old.to = b;
191- (*dd)[i].new.from = c;
192- (*dd)[i].new.to = d;
193- if (i > 0) {
194- if ((*dd)[i].old.from < (*dd)[i - 1].old.to ||
195- (*dd)[i].new.from < (*dd)[i - 1].new.to)
196- errx(1, "diff output out of order");
197- }
198- }
199- if (i > 0) {
200- (*dd)[i].old.from = (*dd)[i].old.to = (*dd)[i - 1].old.to;
201- (*dd)[i].new.from = (*dd)[i].new.to = (*dd)[i - 1].new.to;
202- }
203- fclose(f);
204- return i;
205-}
206+static int aflag;
207+static int Tflag;
208+static int eflag;
209+static int Eflag;
210+static int xflag;
211+static int Xflag;
212+static int Aflag;
213+static int mflag;
214+static int iflag;
215+static int strip_cr;
216+static char *labels[3];
217+static int nlabels;
218
219 static void
220-diffexec(const char *diffprog, char **diffargv, int fd[])
221-{
222- switch (fork()) {
223- case 0:
224- close(fd[0]);
225- if (dup2(fd[1], STDOUT_FILENO) == -1)
226- err(2, "child could not duplicate descriptor");
227- close(fd[1]);
228- execvp(diffprog, diffargv);
229- err(2, "could not execute diff: %s", diffprog);
230- break;
231- case -1:
232- err(2, "could not fork");
233- break;
234- }
235- close(fd[1]);
236-}
237-
238-static char *
239-getchange(FILE *b)
240-{
241- char *line;
242-
243- while ((line = get_line(b, NULL)) != NULL) {
244- if (isdigit((unsigned char)line[0]))
245- return line;
246- }
247- return NULL;
248-}
249-
250-static char *
251-get_line(FILE *b, size_t *n)
252+usage(void)
253 {
254- ssize_t len;
255- static char *buf = NULL;
256- static size_t bufsize = 0;
257-
258- if ((len = getline(&buf, &bufsize, b)) < 0)
259- return NULL;
260-
261- if (strip_cr && len >= 2 && strcmp("\r\n", &(buf[len - 2])) == 0) {
262- buf[len - 2] = '\n';
263- buf[len - 1] = '\0';
264- len--;
265- }
266-
267- if (n != NULL)
268- *n = len;
269-
270- return buf;
271+ eprintf("usage: %s [-3aAeEimTxX] [-L label] file1 file2 file3\n", argv0);
272 }
273
274 static void
275-merge(int m1, int m2)
276+convert_hunks(const struct diffhunks *in, struct pair_hunk **out, size_t *outn)
277 {
278- struct Diff *d1, *d2, *d3;
279- int j, t1, t2;
280- int dup = 0;
281-
282- d1 = d13;
283- d2 = d23;
284- j = 0;
285-
286- for (;;) {
287- t1 = (d1 < d13 + m1);
288- t2 = (d2 < d23 + m2);
289- if (!t1 && !t2)
290- break;
291-
292- if (!t2 || (t1 && d1->new.to < d2->new.from)) {
293- if (eflag == EFLAG_NONE) {
294- separate("1");
295- change(1, &d1->old, 0);
296- keep(2, &d1->new);
297- change(3, &d1->new, 0);
298- } else if (eflag == EFLAG_OVERLAP) {
299- j = edit(d2, dup, j, DIFF_TYPE1);
300- }
301- d1++;
302- continue;
303- }
304- if (!t1 || (t2 && d2->new.to < d1->new.from)) {
305- if (eflag == EFLAG_NONE) {
306- separate("2");
307- keep(1, &d2->new);
308- change(3, &d2->new, 0);
309- change(2, &d2->old, 0);
310- } else if (Aflag || mflag) {
311- if (eflag == EFLAG_UNMERGED)
312- j = edit(d2, dup, j, DIFF_TYPE2);
313- }
314- d2++;
315- continue;
316- }
317- if (d1 + 1 < d13 + m1 && d1->new.to >= d1[1].new.from) {
318- d1[1].old.from = d1->old.from;
319- d1[1].new.from = d1->new.from;
320- d1++;
321- continue;
322- }
323- if (d2 + 1 < d23 + m2 && d2->new.to >= d2[1].new.from) {
324- d2[1].old.from = d2->old.from;
325- d2[1].new.from = d2->new.from;
326- d2++;
327- continue;
328- }
329- if (d1->new.from == d2->new.from && d1->new.to == d2->new.to) {
330- dup = duplicate(&d1->old, &d2->old);
331- if (eflag == EFLAG_NONE) {
332- separate(dup ? "3" : "");
333- change(1, &d1->old, dup);
334- change(2, &d2->old, 0);
335- d3 = d1->old.to > d1->old.from ? d1 : d2;
336- change(3, &d3->new, 0);
337- } else {
338- j = edit(d1, dup, j, DIFF_TYPE3);
339- }
340- dup = 0;
341- d1++;
342- d2++;
343- continue;
344- }
345- if (d1->new.from < d2->new.from) {
346- d2->old.from -= d2->new.from - d1->new.from;
347- d2->new.from = d1->new.from;
348- } else if (d2->new.from < d1->new.from) {
349- d1->old.from -= d1->new.from - d2->new.from;
350- d1->new.from = d2->new.from;
351- }
352- if (d1->new.to > d2->new.to) {
353- d2->old.to += d1->new.to - d2->new.to;
354- d2->new.to = d1->new.to;
355- } else if (d2->new.to > d1->new.to) {
356- d1->old.to += d2->new.to - d1->new.to;
357- d1->new.to = d2->new.to;
358- }
359- }
360-
361- if (mflag)
362- mergescript(j);
363- else if (Aflag)
364- Ascript(j);
365- else if (eflag)
366- edscript(j);
367+ size_t i;
368+ struct pair_hunk *p;
369+
370+ p = ecalloc(in->n + 1, sizeof(*p));
371+ for (i = 0; i < in->n; i++) {
372+ p[i].old.from = in->v[i].old.from;
373+ p[i].old.to = in->v[i].old.to;
374+ p[i].new.from = in->v[i].new.from;
375+ p[i].new.to = in->v[i].new.to;
376+ }
377+ *out = p;
378+ *outn = in->n;
379 }
380
381-static void
382-separate(const char *s)
383+static int
384+region_same(const struct difffile *a, struct region *ra,
385+ const struct difffile *b, struct region *rb)
386 {
387- printf("====%s\n", s);
388+ size_t i;
389+ if (ra->to - ra->from != rb->to - rb->from)
390+ return 0;
391+ for (i = 0; i < ra->to - ra->from; i++) {
392+ if (a->lines[ra->from + i].len != b->lines[rb->from + i].len)
393+ return 0;
394+ if (memcmp(a->lines[ra->from + i].data,
395+ b->lines[rb->from + i].data,
396+ a->lines[ra->from + i].len) != 0)
397+ return 0;
398+ }
399+ return 1;
400 }
401
402-static void
403-change(int i, struct Range *rold, int dup)
404+static int
405+merge_hunks(const struct difffile *f1, const struct difffile *f2,
406+ const struct difffile *f3,
407+ const struct pair_hunk *d13, size_t n13,
408+ const struct pair_hunk *d23, size_t n23,
409+ struct three_hunk **out, size_t *outn)
410 {
411- printf("%d:", i);
412- last[i] = rold->to;
413- prange(rold, 0);
414- if (dup)
415- return;
416- i--;
417- skip(i, rold->from, NULL);
418- skip(i, rold->to, " ");
419+ struct three_hunk *hs;
420+ size_t i, j, k, cap;
421+ int have1, have2;
422+ size_t a1, a2, b1, b2;
423+
424+ cap = n13 + n23 + 4;
425+ hs = ecalloc(cap, sizeof(*hs));
426+ k = 0;
427+ i = j = 0;
428+
429+ while (i < n13 || j < n23) {
430+ have1 = i < n13;
431+ have2 = j < n23;
432+ a1 = have1 ? d13[i].new.from : 0;
433+ a2 = have1 ? d13[i].new.to : 0;
434+ b1 = have2 ? d23[j].old.from : 0;
435+ b2 = have2 ? d23[j].old.to : 0;
436+
437+ if (have1 && (!have2 || a2 <= b1)) {
438+ if (k + 1 >= cap) {
439+ cap *= 2;
440+ hs = erealloc(hs, cap * sizeof(*hs));
441+ }
442+ hs[k].kind = HUNK_TYPE1;
443+ hs[k].r1.from = d13[i].old.from;
444+ hs[k].r1.to = d13[i].old.to;
445+ hs[k].r2.from = d13[i].new.from;
446+ hs[k].r2.to = d13[i].new.to;
447+ hs[k].r3.from = d13[i].new.from;
448+ hs[k].r3.to = d13[i].new.to;
449+ hs[k].dup = 0;
450+ k++;
451+ i++;
452+ continue;
453+ }
454+ if (have2 && (!have1 || b2 < a1)) {
455+ if (k + 1 >= cap) {
456+ cap *= 2;
457+ hs = erealloc(hs, cap * sizeof(*hs));
458+ }
459+ hs[k].kind = HUNK_TYPE2;
460+ hs[k].r1.from = d23[j].old.from;
461+ hs[k].r1.to = d23[j].old.to;
462+ hs[k].r2.from = d23[j].old.from;
463+ hs[k].r2.to = d23[j].old.to;
464+ hs[k].r3.from = d23[j].new.from;
465+ hs[k].r3.to = d23[j].new.to;
466+ hs[k].dup = 0;
467+ k++;
468+ j++;
469+ continue;
470+ }
471+ {
472+ struct region r2;
473+ size_t extra_pre, extra_post;
474+
475+ r2.from = a1 < b1 ? a1 : b1;
476+ r2.to = a2 > b2 ? a2 : b2;
477+ extra_pre = (a1 > b1) ? (a1 - b1) : (b1 - a1);
478+ extra_post = (a2 > b2) ? (a2 - b2) : (b2 - a2);
479+ if (k + 1 >= cap) {
480+ cap *= 2;
481+ hs = erealloc(hs, cap * sizeof(*hs));
482+ }
483+ hs[k].kind = HUNK_TYPE3;
484+ hs[k].r2 = r2;
485+ if (a1 >= b1) {
486+ hs[k].r1.from = d13[i].old.from - extra_pre;
487+ hs[k].r1.to = d13[i].old.to + extra_post;
488+ } else {
489+ hs[k].r1.from = d13[i].old.from;
490+ hs[k].r1.to = d13[i].old.to + (extra_pre + extra_post);
491+ }
492+ if (b1 >= a1) {
493+ hs[k].r3.from = d23[j].new.from - extra_pre;
494+ hs[k].r3.to = d23[j].new.to + extra_post;
495+ } else {
496+ hs[k].r3.from = d23[j].new.from;
497+ hs[k].r3.to = d23[j].new.to + (extra_pre + extra_post);
498+ }
499+ hs[k].dup = region_same(f1, &hs[k].r1, f3, &hs[k].r3);
500+ k++;
501+ i++;
502+ j++;
503+ }
504+ }
505+ *out = hs;
506+ *outn = k;
507+ (void)f1; (void)f2; (void)f3;
508+ return 0;
509 }
510
511 static void
512-prange(struct Range *rold, int delete)
513+print_lines(const struct difffile *f, size_t from, size_t to)
514 {
515- if (rold->to <= rold->from)
516- printf("%da\n", rold->from - 1);
517- else {
518- printf("%d", rold->from);
519- if (rold->to > rold->from + 1)
520- printf(",%d", rold->to - 1);
521- if (delete)
522- printf("d\n");
523- else
524- printf("c\n");
525- }
526+ size_t i;
527+ for (i = from; i < to; i++) {
528+ fwrite(f->lines[i].data, 1, f->lines[i].len, stdout);
529+ fputc('\n', stdout);
530+ }
531 }
532
533 static void
534-keep(int i, struct Range *rnew)
535+print_range_cmd(FILE *out, size_t from, size_t to, char op)
536 {
537- int delta;
538- struct Range trange;
539-
540- delta = last[3] - last[i];
541- trange.from = rnew->from - delta;
542- trange.to = rnew->to - delta;
543- change(i, &trange, 1);
544+ if (to <= from) {
545+ fprintf(out, "%zua\n", from == 0 ? 0 : from);
546+ } else {
547+ fprintf(out, "%zu", from + 1);
548+ if (to - from > 1)
549+ fprintf(out, ",%zu", to);
550+ fprintf(out, "%c\n", op);
551+ }
552 }
553
554 static int
555-skip(int i, int from, const char *pr)
556+format_normal(const struct three_hunk *hs, size_t n,
557+ const struct difffile *f1, const struct difffile *f2,
558+ const struct difffile *f3)
559 {
560- size_t j, n;
561- char *line;
562-
563- for (n = 0; cline[i] < from - 1; n += j) {
564- if ((line = get_line(fp[i], &j)) == NULL)
565- errx(EXIT_FAILURE, "logic error");
566- if (pr != NULL)
567- printf("%s%s", Tflag == 1 ? "\t" : pr, line);
568- cline[i]++;
569- }
570- return (int)n;
571+ size_t i;
572+ for (i = 0; i < n; i++) {
573+ const struct three_hunk *h = &hs[i];
574+ const char *tag = "";
575+ if (h->kind == HUNK_TYPE1) tag = "1";
576+ else if (h->kind == HUNK_TYPE2) tag = "2";
577+ else if (h->kind == HUNK_TYPE3) tag = h->dup ? "3" : "";
578+ printf("====%s\n", tag);
579+ if (h->kind == HUNK_TYPE1) {
580+ printf("1:%zu", h->r1.from + 1);
581+ if (h->r1.to - h->r1.from > 1)
582+ printf(",%zu", h->r1.to);
583+ printf("a\n");
584+ printf("3:%zu", h->r3.from + 1);
585+ if (h->r3.to - h->r3.from > 1)
586+ printf(",%zu", h->r3.to);
587+ printf("a\n");
588+ print_lines(f1, h->r1.from, h->r1.to);
589+ } else if (h->kind == HUNK_TYPE2) {
590+ printf("2:%zu", h->r2.from + 1);
591+ if (h->r2.to - h->r2.from > 1)
592+ printf(",%zu", h->r2.to);
593+ printf("a\n");
594+ printf("3:%zu", h->r3.from + 1);
595+ if (h->r3.to - h->r3.from > 1)
596+ printf(",%zu", h->r3.to);
597+ printf("a\n");
598+ print_lines(f3, h->r3.from, h->r3.to);
599+ } else {
600+ printf("1:%zu", h->r1.from + 1);
601+ if (h->r1.to - h->r1.from > 1)
602+ printf(",%zu", h->r1.to);
603+ printf("c\n");
604+ printf("2:%zu", h->r2.from + 1);
605+ if (h->r2.to - h->r2.from > 1)
606+ printf(",%zu", h->r2.to);
607+ printf("c\n");
608+ printf("3:%zu", h->r3.from + 1);
609+ if (h->r3.to - h->r3.from > 1)
610+ printf(",%zu", h->r3.to);
611+ printf("c\n");
612+ print_lines(f1, h->r1.from, h->r1.to);
613+ print_lines(f3, h->r3.from, h->r3.to);
614+ }
615+ }
616+ (void)f2;
617+ return 0;
618 }
619
620 static int
621-duplicate(struct Range *r1, struct Range *r2)
622+format_ed(const struct three_hunk *hs, size_t n, int overlap_only,
623+ int show_all, const struct difffile *f2, const struct difffile *f3)
624 {
625- int c, d;
626- int nchar;
627- int nline;
628-
629- if (r1->to-r1->from != r2->to-r2->from)
630- return 0;
631- skip(0, r1->from, NULL);
632- skip(1, r2->from, NULL);
633- nchar = 0;
634- for (nline = 0; nline < r1->to - r1->from; nline++) {
635- do {
636- c = getc(fp[0]);
637- d = getc(fp[1]);
638- if (c == -1 && d == -1)
639- break;
640- if (c == -1 || d == -1)
641- errx(EXIT_FAILURE, "logic error");
642- nchar++;
643- if (c != d) {
644- repos(nchar);
645- return 0;
646- }
647- } while (c != '\n');
648- }
649- repos(nchar);
650- return 1;
651-}
652-
653-static void
654-repos(int nchar)
655-{
656- int i;
657-
658- for (i = 0; i < 2; i++)
659- (void)fseek(fp[i], (long)-nchar, SEEK_CUR);
660+ size_t i;
661+ for (i = n; i > 0; i--) {
662+ const struct three_hunk *h = &hs[i - 1];
663+
664+ if (h->kind == HUNK_TYPE1) {
665+ if (h->r1.to == h->r1.from) {
666+ print_range_cmd(stdout, h->r2.from, h->r2.from, 'a');
667+ print_lines(f2, h->r2.from, h->r2.from);
668+ printf(".\n");
669+ } else {
670+ print_range_cmd(stdout, h->r2.from, h->r2.to, 'c');
671+ print_lines(f2, h->r1.from, h->r1.to);
672+ printf(".\n");
673+ }
674+ continue;
675+ }
676+ if (h->kind == HUNK_TYPE2) {
677+ print_range_cmd(stdout, h->r2.from, h->r2.to, 'c');
678+ print_lines(f3, h->r3.from, h->r3.to);
679+ printf(".\n");
680+ continue;
681+ }
682+ if (h->dup) {
683+ print_range_cmd(stdout, h->r2.from, h->r2.to, 'c');
684+ print_lines(f2, h->r1.from, h->r1.to);
685+ printf(".\n");
686+ continue;
687+ }
688+ if (overlap_only)
689+ continue;
690+ if (show_all) {
691+ print_range_cmd(stdout, h->r2.from, h->r2.to, 'c');
692+ print_lines(f3, h->r3.from, h->r3.to);
693+ printf(".\n");
694+ }
695+ }
696+ return 0;
697 }
698
699+#if FEATURE_DIFF3_MERGE
700 static int
701-edit(struct Diff *diff, int dup, int j, int difftype)
702-{
703- if (!(eflag == EFLAG_UNMERGED ||
704- (!dup && eflag == EFLAG_OVERLAP) ||
705- (dup && eflag == EFLAG_NOOVERLAP))) {
706- return j;
707- }
708- j++;
709- overlap[j] = !dup;
710- if (!dup)
711- overlapcnt++;
712-
713- de[j].type = difftype;
714- de[j].old.from = diff->old.from;
715- de[j].old.to = diff->old.to;
716- de[j].new.from = diff->new.from;
717- de[j].new.to = diff->new.to;
718- return j;
719-}
720-
721-static void
722-printrange(FILE *p, struct Range *r)
723-{
724- char *line = NULL;
725- size_t len = 0;
726- int i = 1;
727-
728- if (r->from == r->to)
729- return;
730-
731- if (r->from > r->to)
732- errx(EXIT_FAILURE, "invalid print range");
733-
734- fseek(p, 0L, SEEK_SET);
735- while (getline(&line, &len, p) > 0) {
736- if (i >= r->from)
737- printf("%s", line);
738- if (++i > r->to - 1)
739- break;
740- }
741- free(line);
742-}
743-
744-static void
745-edscript(int n)
746-{
747- int delete;
748- struct Range *new, *old;
749-
750- for (; n > 0; n--) {
751- new = &de[n].new;
752- old = &de[n].old;
753-
754- delete = (new->from == new->to);
755- if (de[n].type == DIFF_TYPE1) {
756- if (delete)
757- printf("%dd\n", new->from - 1);
758- else if (old->from == new->from && old->to == new->to) {
759- printf("%dc\n", old->from);
760- printrange(fp[2], old);
761- printf(".\n");
762- }
763- continue;
764- } else {
765- if (!oflag || !overlap[n]) {
766- prange(old, delete);
767- } else {
768- printf("%da\n", old->to - 1);
769- printf("%s\n", divider);
770- }
771- printrange(fp[2], new);
772- if (!oflag || !overlap[n]) {
773- if (!delete)
774- printf(".\n");
775- } else {
776- printf("%s %s\n.\n", newmark, f3mark);
777- printf("%da\n%s %s\n.\n", old->from - 1, oldmark, f1mark);
778- }
779- }
780- }
781- if (iflag)
782- printf("w\nq\n");
783-
784- exit(eflag == EFLAG_NONE ? overlapcnt : 0);
785-}
786-
787-static void
788-Ascript(int n)
789-{
790- int startmark;
791- int deletenew;
792- int deleteold;
793- struct Range *new, *old;
794-
795- for (; n > 0; n--) {
796- new = &de[n].new;
797- old = &de[n].old;
798- deletenew = (new->from == new->to);
799- deleteold = (old->from == old->to);
800-
801- if (de[n].type == DIFF_TYPE2) {
802- if (!oflag || !overlap[n]) {
803- prange(old, deletenew);
804- printrange(fp[2], new);
805- } else {
806- startmark = new->to - 1;
807- printf("%da\n", startmark);
808- printf("%s %s\n", newmark, f3mark);
809- printf(".\n");
810- printf("%da\n", startmark - (new->to - new->from));
811- printf("%s %s\n", oldmark, f2mark);
812- if (!deleteold)
813- printrange(fp[1], old);
814- printf("%s\n.\n", divider);
815- }
816- } else if (de[n].type == DIFF_TYPE3) {
817- startmark = old->to - 1;
818- if (!oflag || !overlap[n]) {
819- prange(old, deletenew);
820- printrange(fp[2], new);
821- } else {
822- printf("%da\n", startmark);
823- printf("%s %s\n", orgmark, f2mark);
824- if (deleteold) {
825- struct Range r;
826- r.from = old->from-1;
827- r.to = new->to;
828- printrange(fp[1], &r);
829- } else
830- printrange(fp[1], old);
831- printf("%s\n", divider);
832- printrange(fp[2], new);
833- }
834- if (!oflag || !overlap[n]) {
835- if (!deletenew)
836- printf(".\n");
837- } else {
838- printf("%s %s\n.\n", newmark, f3mark);
839- printf("%da\n%s %s\n.\n", startmark - (old->to - old->from), oldmark, f1mark);
840- }
841- }
842- }
843- if (iflag)
844- printf("w\nq\n");
845-
846- exit(overlapcnt > 0);
847-}
848-
849-static void
850-mergescript(int i)
851-{
852- struct Range r, *new, *old;
853- int n;
854- int delete = 0;
855-
856- r.from = 1;
857- r.to = 1;
858-
859- for (n = 1; n <= i; n++) {
860- new = &de[n].new;
861- old = &de[n].old;
862-
863- delete = (new->from == new->to);
864- if (de[n].type == DIFF_TYPE1 && delete)
865- r.to = new->from - 1;
866- else if (de[n].type == DIFF_TYPE3 && (old->from == old->to)) {
867- r.from = old->from - 1;
868- r.to = new->from;
869- } else
870- r.to = old->from;
871-
872- printrange(fp[0], &r);
873- switch (de[n].type) {
874- case DIFF_TYPE1:
875- if (!delete)
876- printrange(fp[2], new);
877- break;
878- case DIFF_TYPE2:
879- printf("%s %s\n", oldmark, f2mark);
880- printrange(fp[1], old);
881- printf("%s\n", divider);
882- printrange(fp[2], new);
883- printf("%s %s\n", newmark, f3mark);
884- break;
885- case DIFF_TYPE3:
886- if (!oflag || !overlap[n]) {
887- printrange(fp[2], new);
888- } else {
889- printf("%s %s\n", oldmark, f1mark);
890- printrange(fp[0], old);
891- if (eflag != EFLAG_OVERLAP) {
892- printf("%s %s\n", orgmark, f2mark);
893- if (old->from == old->to) {
894- struct Range or;
895- or.from = old->from - 1;
896- or.to = new->to;
897- printrange(fp[1], &or);
898- } else {
899- printrange(fp[1], old);
900- }
901- }
902- printf("%s\n", divider);
903- printrange(fp[2], new);
904- printf("%s %s\n", newmark, f3mark);
905- }
906- break;
907- default:
908- printf("Error: Unhandled diff type - exiting\n");
909- exit(EXIT_FAILURE);
910- }
911-
912- if (old->from == old->to)
913- r.from = new->to;
914- else
915- r.from = old->to;
916- }
917-
918- new = &de[n-1].new;
919- old = &de[n-1].old;
920-
921- if (old->from == new->from && old->to == new->to)
922- r.from--;
923- else if (new->from == new->to)
924- r.from = old->from;
925-
926- r.to = INT_MAX;
927- printrange(fp[2], &r);
928- exit(overlapcnt > 0);
929-}
930-
931-static void
932-increase(void)
933-{
934- struct Diff *p;
935- char *q;
936- size_t newsz, incr;
937-
938- newsz = szchanges == 0 ? 64 : 2 * szchanges;
939- incr = newsz - szchanges;
940-
941- p = ereallocarray(d13, newsz, sizeof(*p));
942- memset(p + szchanges, 0, incr * sizeof(*p));
943- d13 = p;
944-
945- p = ereallocarray(d23, newsz, sizeof(*p));
946- memset(p + szchanges, 0, incr * sizeof(*p));
947- d23 = p;
948-
949- p = ereallocarray(de, newsz, sizeof(*p));
950- memset(p + szchanges, 0, incr * sizeof(*p));
951- de = p;
952-
953- q = ereallocarray(overlap, newsz, 1);
954- memset(q + szchanges, 0, incr * 1);
955- overlap = q;
956- szchanges = newsz;
957-}
958-
959-static void
960-handle_sig(int signo)
961-{
962- write(sigpipe[1], &signo, sizeof(signo));
963-}
964-
965-static void
966-xasprintf(char **strp, const char *fmt, ...)
967+format_merge(const struct three_hunk *hs, size_t n,
968+ const struct difffile *f1, const struct difffile *f2,
969+ const struct difffile *f3)
970 {
971- va_list ap;
972- int r;
973-
974- va_start(ap, fmt);
975- r = vasprintf(strp, fmt, ap);
976- va_end(ap);
977- if (r == -1)
978- err(2, "asprintf");
979+ size_t i, j;
980+ size_t cursor;
981+ const char *l1, *l2, *l3;
982+
983+ l1 = nlabels >= 1 ? labels[0] : "file1";
984+ l2 = nlabels >= 2 ? labels[1] : "file2";
985+ l3 = nlabels >= 3 ? labels[2] : "file3";
986+ cursor = 0;
987+ for (i = 0; i < n; i++) {
988+ const struct three_hunk *h = &hs[i];
989+ for (j = cursor; j < h->r2.from; j++) {
990+ fwrite(f2->lines[j].data, 1, f2->lines[j].len, stdout);
991+ fputc('\n', stdout);
992+ }
993+ cursor = h->r2.to;
994+ if (h->kind == HUNK_TYPE1) {
995+ print_lines(f1, h->r1.from, h->r1.to);
996+ } else if (h->kind == HUNK_TYPE2) {
997+ print_lines(f3, h->r3.from, h->r3.to);
998+ } else if (h->dup) {
999+ print_lines(f1, h->r1.from, h->r1.to);
1000+ } else {
1001+ printf("<<<<<<< %s\n", l1);
1002+ print_lines(f1, h->r1.from, h->r1.to);
1003+ printf("||||||| %s\n", l2);
1004+ print_lines(f2, h->r2.from, h->r2.to);
1005+ printf("=======\n");
1006+ print_lines(f3, h->r3.from, h->r3.to);
1007+ printf(">>>>>>> %s\n", l3);
1008+ }
1009+ }
1010+ for (j = cursor; j < f2->nlines; j++) {
1011+ fwrite(f2->lines[j].data, 1, f2->lines[j].len, stdout);
1012+ fputc('\n', stdout);
1013+ }
1014+ return 0;
1015 }
1016+#endif
1017
1018-// ?man diff3: 3-way differential file comparison
1019+// ?man diff3: three-way file comparison
1020 // ?man arguments: file1 file2 file3
1021-// ?man synopsis: [-3aAeEiL:mTxX] [--diff-program program] [--strip-trailing-cr] [-L label1] [-L label2] [-L label3] file1 file2 file3
1022+// ?man compare three files line by line and show the differences
1023 int
1024-main(int argc, char **argv)
1025+main(int argc, char *argv[])
1026 {
1027- int ch, nblabels, status, m, n, npe, nleft;
1028- char *labels[] = { NULL, NULL, NULL };
1029- const char *diffprog = DIFF_PATH;
1030- char *file1, *file2, *file3;
1031- char *diffargv[7];
1032- int diffargc = 0;
1033- int fd13[2], fd23[2], signo;
1034- pid_t wpid;
1035- struct pollfd pfd;
1036-
1037- nblabels = 0;
1038- eflag = EFLAG_NONE;
1039- oflag = 0;
1040- diffargv[diffargc++] = (char *)diffprog;
1041- while ((ch = getopt_long(argc, argv, OPTIONS, longopts, NULL)) != -1) {
1042- // ?man -3: output changes specific only to file3
1043- switch (ch) {
1044- case '3':
1045- eflag = EFLAG_NOOVERLAP;
1046- break;
1047- // ?man -a: treat files as text
1048- case 'a':
1049- diffargv[diffargc++] = "-a";
1050- break;
1051- // ?man -A: output all changes bracketing conflicts
1052- case 'A':
1053- Aflag = 1;
1054- break;
1055- // ?man -e: output ed script
1056- case 'e':
1057- eflag = EFLAG_UNMERGED;
1058- break;
1059- // ?man -E: show overlapping changes
1060- case 'E':
1061- eflag = EFLAG_OVERLAP;
1062- oflag = 1;
1063- break;
1064- // ?man -i: append w and q ed commands
1065- case 'i':
1066- iflag = 1;
1067- break;
1068- // ?man -L:label: define label
1069- case 'L':
1070- oflag = 1;
1071- if (nblabels >= 3)
1072- errx(2, "too many file label options");
1073- labels[nblabels++] = optarg;
1074- break;
1075- // ?man -m: merge output
1076- case 'm':
1077- Aflag = 1;
1078- oflag = 1;
1079- mflag = 1;
1080- break;
1081- // ?man -T: use tab prefix in normal listing
1082- case 'T':
1083- Tflag = 1;
1084- break;
1085- // ?man -x: output script with changes specific to all three
1086- case 'x':
1087- eflag = EFLAG_OVERLAP;
1088- break;
1089- // ?man -X: show overlapping changes
1090- case 'X':
1091- oflag = 1;
1092- eflag = EFLAG_OVERLAP;
1093- break;
1094- case DIFFPROG_OPT:
1095- diffprog = optarg;
1096- break;
1097- case STRIPCR_OPT:
1098- strip_cr = 1;
1099- diffargv[diffargc++] = "--strip-trailing-cr";
1100- break;
1101- case HELP_OPT:
1102- usage();
1103- exit(0);
1104- case VERSION_OPT:
1105- printf("%s\n", diff3_version);
1106- exit(0);
1107- }
1108- }
1109- argc -= optind;
1110- argv += optind;
1111-
1112- if (Aflag) {
1113- if (eflag == EFLAG_NONE)
1114- eflag = EFLAG_UNMERGED;
1115- oflag = 1;
1116- }
1117-
1118- if (argc != 3) {
1119- usage();
1120- exit(2);
1121- }
1122-
1123- file1 = argv[0];
1124- file2 = argv[1];
1125- file3 = argv[2];
1126-
1127- if (oflag) {
1128- xasprintf(&f1mark, "%s", labels[0] != NULL ? labels[0] : file1);
1129- xasprintf(&f2mark, "%s", labels[1] != NULL ? labels[1] : file2);
1130- xasprintf(&f3mark, "%s", labels[2] != NULL ? labels[2] : file3);
1131- }
1132- fp[0] = fopen(file1, "r");
1133- if (fp[0] == NULL)
1134- err(2, "Can't open %s", file1);
1135-
1136- fp[1] = fopen(file2, "r");
1137- if (fp[1] == NULL)
1138- err(2, "Can't open %s", file2);
1139-
1140- fp[2] = fopen(file3, "r");
1141- if (fp[2] == NULL)
1142- err(2, "Can't open %s", file3);
1143-
1144- if (pipe(fd13))
1145- err(2, "pipe");
1146- if (pipe(fd23))
1147- err(2, "pipe");
1148- if (pipe(sigpipe))
1149- err(2, "pipe");
1150- if (fcntl(sigpipe[0], F_SETFD, FD_CLOEXEC))
1151- err(2, "fcntl");
1152- if (fcntl(sigpipe[1], F_SETFD, FD_CLOEXEC))
1153- err(2, "fcntl");
1154-
1155- pfd.fd = sigpipe[0];
1156- pfd.events = POLLIN;
1157- pfd.revents = 0;
1158-
1159- if (signal(SIGCHLD, handle_sig) == SIG_ERR)
1160- err(2, "signal");
1161-
1162- diffargv[diffargc] = file1;
1163- diffargv[diffargc + 1] = file3;
1164- diffargv[diffargc + 2] = NULL;
1165-
1166- nleft = 0;
1167- diffexec(diffprog, diffargv, fd13);
1168- nleft++;
1169-
1170- diffargv[diffargc] = file2;
1171- diffexec(diffprog, diffargv, fd23);
1172- nleft++;
1173-
1174- increase();
1175- m = readin(fd13[0], &d13);
1176- n = readin(fd23[0], &d23);
1177-
1178- while (nleft > 0) {
1179- npe = poll(&pfd, 1, -1);
1180- if (npe == -1) {
1181- if (errno == EINTR)
1182- continue;
1183- err(2, "poll");
1184- }
1185- if (pfd.revents != POLLIN)
1186- continue;
1187- if (read(pfd.fd, &signo, sizeof(signo)) < 0)
1188- err(2, "read");
1189- while ((wpid = waitpid(-1, &status, WNOHANG)) > 0) {
1190- if (WIFEXITED(status) && WEXITSTATUS(status) >= 2)
1191- errx(2, "diff exited abnormally");
1192- else if (WIFSIGNALED(status))
1193- errx(2, "diff killed by signal %d", WTERMSIG(status));
1194- nleft--;
1195- }
1196- }
1197- merge(m, n);
1198-
1199- return EXIT_SUCCESS;
1200+ struct difffile f1, f2, f3;
1201+ struct pair_hunk *d13, *d23;
1202+ size_t n13, n23;
1203+ struct three_hunk *hs;
1204+ size_t nhunks;
1205+ struct diffhunks raw13, raw23;
1206+ struct diffopts opts;
1207+ int ret, conflicts;
1208+
1209+ ARGBEGIN {
1210+ case '3':
1211+ // ?man -3: like -A but skip overlapping changes
1212+ Aflag = 1;
1213+ break;
1214+ case 'a':
1215+ // ?man -a: treat all files as text
1216+ aflag = 1;
1217+ break;
1218+ case 'A':
1219+ // ?man -A: emit ed script with all changes including overlaps
1220+ Aflag = 1;
1221+ break;
1222+ case 'e':
1223+ // ?man -e: emit ed script to apply non-overlapping changes
1224+ eflag = 1;
1225+ break;
1226+ case 'E':
1227+ // ?man -E: like -e but include overlap markers
1228+ Eflag = 1;
1229+ break;
1230+#if FEATURE_DIFF3_MERGE
1231+ case 'i':
1232+ // ?man -i: ignore case when comparing lines
1233+ iflag = 1;
1234+ break;
1235+ case 'L':
1236+ // ?man -L:label: use label in place of file name in merge output
1237+ if (nlabels >= 3)
1238+ usage();
1239+ labels[nlabels++] = EARGF(usage());
1240+ break;
1241+ case 'm':
1242+ // ?man -m: emit merged output with conflict markers
1243+ mflag = 1;
1244+ break;
1245+ case 'T':
1246+ // ?man -T: prefix output lines with a tab
1247+ Tflag = 1;
1248+ break;
1249+#endif
1250+ case 'x':
1251+ // ?man -x: emit ed script for overlapping changes only
1252+ xflag = 1;
1253+ break;
1254+ case 'X':
1255+ // ?man -X: emit ed script for overlapping changes with markers
1256+ Xflag = 1;
1257+ break;
1258+ default:
1259+ usage();
1260+ } ARGEND
1261+
1262+ if (argc != 3)
1263+ usage();
1264+
1265+ if (diff_load(&f1, argv[0]) < 0)
1266+ return 2;
1267+ if (diff_load(&f2, argv[1]) < 0) {
1268+ diff_free(&f1);
1269+ return 2;
1270+ }
1271+ if (diff_load(&f3, argv[2]) < 0) {
1272+ diff_free(&f1);
1273+ diff_free(&f2);
1274+ return 2;
1275+ }
1276+
1277+ memset(&opts, 0, sizeof(opts));
1278+ opts.format = DIFF_NORMAL;
1279+ opts.ignore_case = iflag;
1280+ opts.strip_cr = strip_cr;
1281+ opts.context = 3;
1282+
1283+ if (diff_compute(&raw13, &f1, &f2, &opts) < 0 ||
1284+ diff_compute(&raw23, &f2, &f3, &opts) < 0) {
1285+ diff_free(&f1); diff_free(&f2); diff_free(&f3);
1286+ return 2;
1287+ }
1288+ convert_hunks(&raw13, &d13, &n13);
1289+ convert_hunks(&raw23, &d23, &n23);
1290+
1291+ if (merge_hunks(&f1, &f2, &f3, d13, n13, d23, n23, &hs, &nhunks) < 0) {
1292+ diff_hunks_free(&raw13);
1293+ diff_hunks_free(&raw23);
1294+ free(d13); free(d23);
1295+ diff_free(&f1); diff_free(&f2); diff_free(&f3);
1296+ return 2;
1297+ }
1298+
1299+ ret = 0;
1300+ conflicts = 0;
1301+ if (nhunks == 0) {
1302+ ret = 0;
1303+ } else {
1304+#if FEATURE_DIFF3_MERGE
1305+ if (mflag) {
1306+ size_t i;
1307+ for (i = 0; i < nhunks; i++)
1308+ if (hs[i].kind == HUNK_TYPE3 && !hs[i].dup)
1309+ conflicts++;
1310+ format_merge(hs, nhunks, &f1, &f2, &f3);
1311+ ret = conflicts ? 1 : 0;
1312+ } else
1313+#endif
1314+ if (eflag || Eflag) {
1315+ format_ed(hs, nhunks, Eflag && !eflag, 0, &f2, &f3);
1316+ ret = 1;
1317+ } else if (xflag) {
1318+ format_ed(hs, nhunks, 1, 0, &f2, &f3);
1319+ ret = 1;
1320+ } else if (Xflag) {
1321+ format_ed(hs, nhunks, 0, 1, &f2, &f3);
1322+ ret = 1;
1323+ } else if (Aflag) {
1324+ format_ed(hs, nhunks, 0, 1, &f2, &f3);
1325+ ret = 1;
1326+ } else {
1327+ format_normal(hs, nhunks, &f1, &f2, &f3);
1328+ ret = 1;
1329+ }
1330+ }
1331+
1332+ if (fshut(stdout, "<stdout>"))
1333+ ret = 2;
1334+
1335+ diff_hunks_free(&raw13);
1336+ diff_hunks_free(&raw23);
1337+ free(d13); free(d23);
1338+ free(hs);
1339+ diff_free(&f1); diff_free(&f2); diff_free(&f3);
1340+ return ret;
1341 }
+8,
-7
1@@ -15,6 +15,7 @@
2 #include <stdlib.h>
3 #include <string.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 #define REGEXSIZE 100
9@@ -837,13 +838,13 @@ dowrite(const char *fname, int trunc)
10 char *mode;
11
12 if (fp) {
13- sh ? pclose(fp) : fclose(fp);
14+ sh ? wpclose(fp) : fclose(fp);
15 fp = NULL;
16 }
17
18 if (fname[0] == '!') {
19 sh = 1;
20- if((fp = popen(expandcmd(), "w")) == NULL)
21+ if((fp = wpopen(expandcmd(), NULL, "w")) == NULL)
22 error("bad exec");
23 } else {
24 sh = 0;
25@@ -865,7 +866,7 @@ dowrite(const char *fname, int trunc)
26
27 aux = fp;
28 fp = NULL;
29- r = sh ? pclose(aux) : fclose(aux);
30+ r = sh ? wpclose(aux) : fclose(aux);
31 if (r)
32 error("input/output error");
33 strcpy(savfname, fname);
34@@ -890,13 +891,13 @@ doread(const char *fname)
35 static FILE *fp;
36
37 if (fp) {
38- sh ? pclose(fp) : fclose(fp);
39+ sh ? wpclose(fp) : fclose(fp);
40 fp = NULL;
41 }
42
43 if(fname[0] == '!') {
44 sh = 1;
45- if((fp = popen(expandcmd(), "r")) == NULL)
46+ if((fp = wpopen(expandcmd(), NULL, "r")) == NULL)
47 error("bad exec");
48 } else if ((fp = fopen(fname, "r")) == NULL) {
49 error("cannot open input file");
50@@ -921,7 +922,7 @@ doread(const char *fname)
51
52 aux = fp;
53 fp = NULL;
54- r = sh ? pclose(aux) : fclose(aux);
55+ r = sh ? wpclose(aux) : fclose(aux);
56 if (r)
57 error("input/output error");
58 }
59@@ -1153,7 +1154,7 @@ copy(int where)
60 static void
61 execsh(void)
62 {
63- system(expandcmd());
64+ wsystem(expandcmd());
65 if (optdiag)
66 puts("!");
67 }
+3,
-2
1@@ -7,6 +7,7 @@
2 #include <string.h>
3 #include <unistd.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 extern char **environ;
9@@ -43,9 +44,9 @@ main(int argc, char *argv[])
10 putenv(*argv);
11
12 if (*argv) {
13- execvp(*argv, argv);
14+ wexecvp_self(*argv, argv);
15 savederrno = errno;
16- weprintf("execvp %s:", *argv);
17+ weprintf("wexecvp %s:", *argv);
18 _exit(126 + (savederrno == ENOENT));
19 }
20
+2,
-1
1@@ -2,6 +2,7 @@
2
3
4 #include "config.h"
5+#include "wexec.h"
6 #include "util.h"
7
8 #include <dirent.h>
9@@ -344,7 +345,7 @@ spawn(char *argv[])
10 eprintf("fork:");
11 break;
12 case 0:
13- execvp(*argv, argv);
14+ wexecvp_self(*argv, argv);
15 weprintf("exec %s failed:", *argv);
16 _exit(1);
17 }
+236,
-251
1@@ -31,288 +31,268 @@ volatile sig_atomic_t stop;
2 void
3 debug(char *fmt, ...)
4 {
5- va_list va;
6+ va_list va;
7
8- if (!dflag)
9- return;
10+ if (!dflag)
11+ return;
12
13- va_start(va, fmt);
14- vfprintf(stdout, fmt, va);
15- fputc('\n', stdout);
16- va_end(va);
17+ va_start(va, fmt);
18+ vfprintf(stdout, fmt, va);
19+ fputc('\n', stdout);
20+ va_end(va);
21 }
22
23 int
24 hash(char *name)
25 {
26- int c;
27- unsigned h = 5381;
28+ int c;
29+ unsigned h = 5381;
30
31- while ((c = *name++))
32- h = h*33 ^ c;
33+ while ((c = *name++))
34+ h = h*33 ^ c;
35
36- return h;
37-}
38-
39-void *
40-emalloc(size_t siz)
41-{
42- void *p;
43-
44- if ((p = malloc(siz)) == NULL) {
45- perror("make");
46- exit(EXIT_FAILURE);
47- }
48-
49- return p;
50-}
51-
52-void *
53-erealloc(void *p, size_t siz)
54-{
55- if ((p = realloc(p, siz)) == NULL) {
56- perror("make");
57- exit(EXIT_FAILURE);
58- }
59-
60- return p;
61-}
62-
63-char *
64-estrdup(char *s)
65-{
66- size_t len;
67-
68- len = strlen(s) + 1;
69- return memcpy(emalloc(len), s, len);
70+ return h;
71 }
72
73 void
74 sighandler(int signo)
75 {
76- killchild();
77- stop = signo;
78+ killchild();
79+ stop = signo;
80 }
81
82 static void
83 usage(void)
84 {
85- fputs("usage: make [-eiknprSstd] [-f file] [-j jobs] "
86- "[macro=value ...] [target ...]\n",
87- stderr);
88- exit(EXIT_FAILURE);
89+ fputs("usage: make [-eiknprSstd] [-f file] [-j jobs] "
90+ "[macro=value ...] [target ...]\n",
91+ stderr);
92+ exit(EXIT_FAILURE);
93 }
94
95 static char *
96 getarg(char **args, char ***argv)
97 {
98- char *s;
99+ char *s;
100
101- if ((*args)[1]) {
102- s = (*args) + 1;
103- *args += strlen(*args) - 1;
104- return s;
105- }
106+ if ((*args)[1]) {
107+ s = (*args) + 1;
108+ *args += strlen(*args) - 1;
109+ return s;
110+ }
111
112- if (!argv)
113- usage();
114+ if (!argv)
115+ usage();
116
117- if ((*argv)[1] == NULL)
118- usage();
119- (*argv)++;
120+ if ((*argv)[1] == NULL)
121+ usage();
122+ (*argv)++;
123
124- return **argv;
125+ return **argv;
126 }
127
128 static void
129 appendmakeflags(char *text)
130 {
131- int n;
132- char *s, *t, *fmt;
133+ int n;
134+ char *s, *t, *fmt;
135
136- s = getmacro("MAKEFLAGS");
137- fmt = *s ? "%s %s" : "%s%s";
138- n = snprintf(NULL, 0, fmt, s, text);
139+ s = getmacro("MAKEFLAGS");
140+ fmt = *s ? "%s %s" : "%s%s";
141+ n = snprintf(NULL, 0, fmt, s, text);
142
143- t = emalloc(n+1);
144- snprintf(t, n+1, fmt, s, text);
145- setmacro("MAKEFLAGS", t, MAKEFLAGS, EXPORT);
146+ t = emalloc(n+1);
147+ snprintf(t, n+1, fmt, s, text);
148+ setmacro("MAKEFLAGS", t, MAKEFLAGS, EXPORT);
149
150- free(t);
151+ free(t);
152 }
153
154 static int
155 hasargs(int c)
156 {
157- return c == 'f' || c == 'j';
158+ return c == 'f' || c == 'j';
159 }
160
161 static void
162 parseflag(int flag, char **args, char ***argv)
163 {
164- if (hasargs(flag))
165- getarg(args, argv);
166-
167- switch (flag) {
168- case 'j':
169- case 'f':
170- break;
171- case 'e':
172- eflag = 1;
173- appendmakeflags("-e");
174- break;
175- case 'i':
176- iflag = 1;
177- appendmakeflags("-i");
178- break;
179- case 'k':
180- kflag = 1;
181- appendmakeflags("-k");
182- break;
183- case 'n':
184- nflag = 1;
185- appendmakeflags("-n");
186- break;
187- case 'p':
188- pflag = 1;
189- break;
190- case 'q':
191- qflag = 1;
192- appendmakeflags("-q");
193- break;
194- case 'r':
195- addtarget(".SUFFIXES", 0);
196- appendmakeflags("-r");
197- break;
198- case 'S':
199- kflag = 0;
200- appendmakeflags("-S");
201- break;
202- case 's':
203- sflag = 1;
204- appendmakeflags("-s");
205- break;
206- case 't':
207- tflag = 1;
208- appendmakeflags("-t");
209- break;
210- case 'd':
211- dflag = 1;
212- appendmakeflags("-d");
213- break;
214- default:
215- usage();
216- }
217+ if (hasargs(flag))
218+ getarg(args, argv);
219+
220+ switch (flag) {
221+ case 'j':
222+ /* ?man -j:jobs: number of parallel jobs (accepted, runs serially) */
223+ case 'f':
224+ /* ?man -f:file: read rules from file instead of makefile or Makefile */
225+ break;
226+ case 'e':
227+ /* ?man -e: environment variables override makefile assignments */
228+ eflag = 1;
229+ appendmakeflags("-e");
230+ break;
231+ case 'i':
232+ /* ?man -i: ignore errors from executed commands */
233+ iflag = 1;
234+ appendmakeflags("-i");
235+ break;
236+ case 'k':
237+ /* ?man -k: continue building other targets after an error */
238+ kflag = 1;
239+ appendmakeflags("-k");
240+ break;
241+ case 'n':
242+ /* ?man -n: print commands without executing them */
243+ nflag = 1;
244+ appendmakeflags("-n");
245+ break;
246+ case 'p':
247+ /* ?man -p: print the rule and macro database then exit */
248+ pflag = 1;
249+ break;
250+ case 'q':
251+ /* ?man -q: question mode, return zero if up to date, one otherwise */
252+ qflag = 1;
253+ appendmakeflags("-q");
254+ break;
255+ case 'r':
256+ /* ?man -r: clear the built-in suffix rules and variables */
257+ addtarget(".SUFFIXES", 0);
258+ appendmakeflags("-r");
259+ break;
260+ case 'S':
261+ /* ?man -S: cancel a previous -k, stop on first error */
262+ kflag = 0;
263+ appendmakeflags("-S");
264+ break;
265+ case 's':
266+ /* ?man -s: silent, do not echo commands before running them */
267+ sflag = 1;
268+ appendmakeflags("-s");
269+ break;
270+ case 't':
271+ /* ?man -t: touch targets instead of rebuilding them */
272+ tflag = 1;
273+ appendmakeflags("-t");
274+ break;
275+ case 'd':
276+ /* ?man -d: enable debug output */
277+ dflag = 1;
278+ appendmakeflags("-d");
279+ break;
280+ default:
281+ usage();
282+ }
283 }
284
285 static int
286 assign(char *s, int where, int export)
287 {
288- int pos;
289- char *t;
290+ int pos;
291+ char *t;
292
293- if ((t = strchr(s, '=')) == NULL)
294- return 0;
295+ if ((t = strchr(s, '=')) == NULL)
296+ return 0;
297
298- pos = t - s;
299+ pos = t - s;
300
301- appendmakeflags(s);
302- t = estrdup(s);
303- t[pos] = '\0';
304+ appendmakeflags(s);
305+ t = estrdup(s);
306+ t[pos] = '\0';
307
308- setmacro(t, t+pos+1, where, export);
309- free(t);
310- return 1;
311+ setmacro(t, t+pos+1, where, export);
312+ free(t);
313+ return 1;
314 }
315
316 static void
317 parseargv(char **argv, char ***targets, int where, int export)
318 {
319- char *s;
320- char *hm = NULL;
321-
322- for ( ; *argv; ++argv) {
323- s = *argv;
324- if (hm == NULL && strcmp(s, "--") == 0) {
325- hm = *argv;
326- } else if (hm && s[0] == '-') {
327- break;
328- } else if (s[0] != '-') {
329- if (!assign(s, where, export))
330- break;
331- continue;
332- }
333- while (hm == NULL && *++s)
334- parseflag(*s, &s, &argv);
335- }
336-
337- if (targets)
338- *targets = argv;
339+ char *s;
340+ char *hm = NULL;
341+
342+ for ( ; *argv; ++argv) {
343+ s = *argv;
344+ if (hm == NULL && strcmp(s, "--") == 0) {
345+ hm = *argv;
346+ } else if (hm && s[0] == '-') {
347+ break;
348+ } else if (s[0] != '-') {
349+ if (!assign(s, where, export))
350+ break;
351+ continue;
352+ }
353+ while (hm == NULL && *++s)
354+ parseflag(*s, &s, &argv);
355+ }
356+
357+ if (targets)
358+ *targets = argv;
359 }
360
361 static void
362 parsemakeflags(void)
363 {
364- int n;
365- char *s, *flags, **arr;
366-
367- if ((flags = getenv("MAKEFLAGS")) == NULL)
368- return;
369-
370- setmacro("MAKEFLAGS", "", MAKEFLAGS, EXPORT);
371-
372- while (*flags == ' ' || *flags == '\t')
373- flags++;
374-
375- if (flags[0] != '-' && !strchr(flags, '=')) {
376- while (*flags) {
377- parseflag(*flags, &flags, NULL);
378- flags++;
379- }
380- } else {
381- n = 0;
382- arr = NULL;
383- for (s = strtok(flags, " \t"); s; s = strtok(NULL, " \t")) {
384- n++;
385- arr = erealloc(arr, sizeof(char *) * (n+1));
386- arr[n-1] = s;
387- arr[n] = NULL;
388- }
389-
390- if (arr)
391- parseargv(arr, NULL, MAKEFLAGS, NOEXPORT);
392- free(arr);
393- }
394+ int n;
395+ char *s, *flags, **arr;
396+
397+ if ((flags = getenv("MAKEFLAGS")) == NULL)
398+ return;
399+
400+ setmacro("MAKEFLAGS", "", MAKEFLAGS, EXPORT);
401+
402+ while (*flags == ' ' || *flags == '\t')
403+ flags++;
404+
405+ if (flags[0] != '-' && !strchr(flags, '=')) {
406+ while (*flags) {
407+ parseflag(*flags, &flags, NULL);
408+ flags++;
409+ }
410+ } else {
411+ n = 0;
412+ arr = NULL;
413+ for (s = strtok(flags, " \t"); s; s = strtok(NULL, " \t")) {
414+ n++;
415+ arr = erealloc(arr, sizeof(char *) * (n+1));
416+ arr[n-1] = s;
417+ arr[n] = NULL;
418+ }
419+
420+ if (arr)
421+ parseargv(arr, NULL, MAKEFLAGS, NOEXPORT);
422+ free(arr);
423+ }
424 }
425
426 static void
427 parsemakefiles(char **argv)
428 {
429- char *s, *arg;
430- int c, hasmake;
431-
432- hasmake = 0;
433- for ( ; *argv && **argv == '-'; ++argv) {
434- for (s = *argv; (c = *s); ++s) {
435- if (hasargs(c))
436- arg = getarg(&s, &argv);
437-
438- if (c == 'f') {
439- if (strcmp(arg, "-") == 0)
440- arg = NULL;
441- parse(arg);
442- hasmake = 1;
443- }
444- }
445- }
446-
447- if (hasmake)
448- return;
449-
450- if (parse("makefile"))
451- return;
452- if (parse("Makefile"))
453- return;
454+ char *s, *arg;
455+ int c, hasmake;
456+
457+ hasmake = 0;
458+ for ( ; *argv && **argv == '-'; ++argv) {
459+ for (s = *argv; (c = *s); ++s) {
460+ if (hasargs(c))
461+ arg = getarg(&s, &argv);
462+
463+ if (c == 'f') {
464+ if (strcmp(arg, "-") == 0)
465+ arg = NULL;
466+ parse(arg);
467+ hasmake = 1;
468+ }
469+ }
470+ }
471+
472+ if (hasmake)
473+ return;
474+
475+ if (parse("makefile"))
476+ return;
477+ if (parse("Makefile"))
478+ return;
479 }
480
481 /*
482@@ -323,57 +303,62 @@ parsemakefiles(char **argv)
483 static void
484 enadebug(char *argv[])
485 {
486- int c;
487- char *p;
488-
489- for ( ; *argv && **argv == '-'; ++argv) {
490- p = *argv;
491- for (++p; (c = *p); ++p) {
492- if (hasargs(c))
493- getarg(&p, &argv);
494- if (c == 'd')
495- dflag = 1;
496- }
497- }
498+ int c;
499+ char *p;
500+
501+ for ( ; *argv && **argv == '-'; ++argv) {
502+ p = *argv;
503+ for (++p; (c = *p); ++p) {
504+ if (hasargs(c))
505+ getarg(&p, &argv);
506+ if (c == 'd')
507+ dflag = 1;
508+ }
509+ }
510 }
511
512+// ?man make: maintain program dependencies
513+// ?man arguments: [name=value ...] [target ...]
514+// ?man update files based on dependency rules in a makefile.
515+// ?man if no -f is given, make tries makefile then Makefile.
516+// ?man if no target is given the first non-dot target in the makefile is built.
517 int
518 main(int argc, char *argv[])
519 {
520- char *arg0, **targets;
521+ char *arg0, **targets;
522
523- (void)argc;
524+ (void)argc;
525
526- signal(SIGINT, sighandler);
527- signal(SIGHUP, sighandler);
528- signal(SIGTERM, sighandler);
529- signal(SIGQUIT, sighandler);
530+ signal(SIGINT, sighandler);
531+ signal(SIGHUP, sighandler);
532+ signal(SIGTERM, sighandler);
533+ signal(SIGQUIT, sighandler);
534
535- targets = NULL;
536- arg0 = *argv++;
537+ targets = NULL;
538+ arg0 = *argv++;
539
540- enadebug(argv);
541- inject(defaults);
542- setmacro("MAKE", arg0, MAKEFILE, NOEXPORT);
543+ enadebug(argv);
544+ inject(defaults);
545+ setmacro("MAKE", arg0, MAKEFILE, NOEXPORT);
546
547- parsemakeflags();
548- parseargv(argv, &targets, CMDLINE, EXPORT);
549- parsemakefiles(argv);
550+ parsemakeflags();
551+ parseargv(argv, &targets, CMDLINE, EXPORT);
552+ parsemakefiles(argv);
553
554- if (pflag) {
555- dumpmacros();
556- dumprules();
557- exit(EXIT_SUCCESS);
558- }
559+ if (pflag) {
560+ dumpmacros();
561+ dumprules();
562+ exit(EXIT_SUCCESS);
563+ }
564
565- if (!*targets) {
566- build(NULL);
567- } else {
568- while (*targets)
569- build(*targets++);
570- }
571+ if (!*targets) {
572+ build(NULL);
573+ } else {
574+ while (*targets)
575+ build(*targets++);
576+ }
577
578- exit(exitstatus);
579+ exit(exitstatus);
580
581- return 0;
582+ return 0;
583 }
+26,
-27
1@@ -1,52 +1,51 @@
2 #include <stddef.h>
3 #include <time.h>
4
5+#include "util.h"
6+#include "wexec.h"
7+
8 typedef struct target Target;
9
10 enum {
11- NOEXPORT,
12- EXPORT,
13+ NOEXPORT,
14+ EXPORT,
15 };
16
17 enum {
18- UNDEF,
19- ENVIRON,
20- CMDLINE,
21- INTERNAL,
22- MAKEFILE,
23- MAKEFLAGS,
24+ UNDEF,
25+ ENVIRON,
26+ CMDLINE,
27+ INTERNAL,
28+ MAKEFILE,
29+ MAKEFLAGS,
30 };
31
32 struct loc {
33- char *fname;
34- int lineno;
35+ char *fname;
36+ int lineno;
37 };
38
39 struct action {
40- char *line;
41- struct loc loc;
42+ char *line;
43+ struct loc loc;
44 };
45
46 struct target {
47- char *name;
48- char *target;
49- char *req;
50- time_t stamp;
51- int defined;
52+ char *name;
53+ char *target;
54+ char *req;
55+ time_t stamp;
56+ int defined;
57
58- int ndeps;
59- struct target **deps;
60+ int ndeps;
61+ struct target **deps;
62
63- int nactions;
64- struct action *actions;
65+ int nactions;
66+ struct action *actions;
67
68- struct target *next;
69+ struct target *next;
70 };
71
72-void *emalloc(size_t);
73-void *erealloc(void *, size_t);
74-char *estrdup(char *);
75-
76 void dumprules(void);
77 void dumpmacros(void);
78
79@@ -57,7 +56,7 @@ int build(char *);
80 int hash(char *);
81 int parse(char *);
82 void debug(char *, ...);
83-void error(char *, ...);
84+void error(char *, ...) __attribute__((noreturn));
85 void warning(char *, ...);
86 void adddep(char *, char *);
87 void addrule(char *, struct action *, int);
+1133,
-760
1@@ -17,37 +17,37 @@
2 typedef struct macro Macro;
3
4 enum inputype {
5- FTFILE,
6- FTEXPAN,
7+ FTFILE,
8+ FTEXPAN,
9 };
10
11 enum {
12- STBEGIN,
13- STINTERNAL,
14- STREPLACE,
15- STTO,
16- STEND,
17+ STBEGIN,
18+ STINTERNAL,
19+ STREPLACE,
20+ STTO,
21+ STEND,
22 };
23
24 struct input {
25- int siz;
26- int type;
27+ int siz;
28+ int type;
29
30- FILE *fp;
31- struct loc loc;
32+ FILE *fp;
33+ struct loc loc;
34
35- int pos;
36- char *buf;
37+ int pos;
38+ char *buf;
39
40- struct input *prev;
41+ struct input *prev;
42 };
43
44 struct macro {
45- char *name;
46- char *value;
47- int where;
48+ char *name;
49+ char *value;
50+ int where;
51
52- struct macro *next;
53+ struct macro *next;
54 };
55
56 static struct input *input;
57@@ -58,352 +58,617 @@ static Macro *htab[TABSIZ];
58 void
59 dumpmacros(void)
60 {
61- Macro **pp, *p;
62+ Macro **pp, *p;
63
64- for (pp = htab; pp < &htab[TABSIZ]; ++pp) {
65- for (p = *pp; p; p = p->next)
66- printf("%s = %s\n", p->name, getmacro(p->name));
67- }
68+ for (pp = htab; pp < &htab[TABSIZ]; ++pp) {
69+ for (p = *pp; p; p = p->next)
70+ printf("%s = %s\n", p->name, getmacro(p->name));
71+ }
72 }
73
74 static Macro *
75 lookup(char *name)
76 {
77- Macro *mp;
78- int h = hash(name) & (TABSIZ-1);
79+ Macro *mp;
80+ int h = hash(name) & (TABSIZ-1);
81
82- for (mp = htab[h]; mp && strcmp(mp->name, name); mp = mp->next)
83- ;
84+ for (mp = htab[h]; mp && strcmp(mp->name, name); mp = mp->next)
85+ ;
86
87- if (mp)
88- return mp;
89+ if (mp)
90+ return mp;
91
92- mp = emalloc(sizeof(*mp));
93- mp->name = estrdup(name);
94- mp->value = estrdup("");
95- mp->next = htab[h];
96- mp->where = UNDEF;
97- htab[h] = mp;
98+ mp = emalloc(sizeof(*mp));
99+ mp->name = estrdup(name);
100+ mp->value = estrdup("");
101+ mp->next = htab[h];
102+ mp->where = UNDEF;
103+ htab[h] = mp;
104
105- return mp;
106+ return mp;
107 }
108
109 static char *
110 macroinfo(char *name, int *pwhere, Macro **mpp)
111 {
112- char *s, *t;
113- int hide, where;
114- Macro *mp = lookup(name);
115-
116- hide = 0;
117- if (!strcmp(name, "SHELL") || !strcmp(name, "MAKEFLAGS"))
118- hide = 1;
119-
120- s = mp->value;
121- where = mp->where;
122-
123- if (!hide && (where == UNDEF || where == INTERNAL || eflag)) {
124- t = getenv(name);
125- if (t) {
126- where = ENVIRON;
127- s = t;
128- }
129- }
130-
131- if (pwhere)
132- *pwhere = where;
133- if (mpp)
134- *mpp = mp;
135-
136- return s;
137+ char *s, *t;
138+ int hide, where;
139+ Macro *mp = lookup(name);
140+
141+ hide = 0;
142+ if (!strcmp(name, "SHELL") || !strcmp(name, "MAKEFLAGS"))
143+ hide = 1;
144+
145+ s = mp->value;
146+ where = mp->where;
147+
148+ if (!hide && (where == UNDEF || where == INTERNAL || eflag)) {
149+ t = getenv(name);
150+ if (t) {
151+ where = ENVIRON;
152+ s = t;
153+ }
154+ }
155+
156+ if (pwhere)
157+ *pwhere = where;
158+ if (mpp)
159+ *mpp = mp;
160+
161+ return s;
162 }
163
164 char *
165 getmacro(char *name)
166 {
167- return macroinfo(name, NULL, NULL);
168+ return macroinfo(name, NULL, NULL);
169 }
170
171 void
172 setmacro(char *name, char *val, int where, int export)
173 {
174- int owhere, set;
175- char *s;
176- Macro *mp;
177-
178- assert(where != ENVIRON);
179-
180- s = macroinfo(name, &owhere, &mp);
181-
182- /*
183- * Default values are defined before anything else, and marked
184- * as INTERNAL because they are injected as parseable text, and
185- * MAKEFILE and INTERNAL variables are always overriden. ENVIRON
186- * macros are generated in macroinfo() and this is why this function
187- * should not receive a where == ENVIRON ever.
188- */
189- switch (owhere) {
190- case UNDEF:
191- case INTERNAL:
192- case MAKEFILE:
193- set = 1;
194- break;
195- case ENVIRON:
196- set = (where == MAKEFLAGS || where == CMDLINE);
197- set |= (where == MAKEFILE && !eflag);
198- break;
199- case MAKEFLAGS:
200- set = (where == CMDLINE || where == MAKEFLAGS);
201- break;
202- case CMDLINE:
203- set = (where == CMDLINE);
204- break;
205- default:
206- abort();
207- }
208-
209- if (!set) {
210- debug("hidding override of %s from '%s' to '%s'", name, s, val);
211- } else {
212- debug("override %s from '%s' to '%s'", name, s, val);
213- free(mp->value);
214- mp->value = estrdup(val);
215- mp->where = where;
216-
217- if (export && strcmp(name, "SHELL") != 0) {
218- debug("exporting macro %s", name);
219- exportvar(name, val);
220- }
221- }
222+ int owhere, set;
223+ char *s;
224+ Macro *mp;
225+
226+ assert(where != ENVIRON);
227+
228+ s = macroinfo(name, &owhere, &mp);
229+
230+ /*
231+ * Default values are defined before anything else, and marked
232+ * as INTERNAL because they are injected as parseable text, and
233+ * MAKEFILE and INTERNAL variables are always overriden. ENVIRON
234+ * macros are generated in macroinfo() and this is why this function
235+ * should not receive a where == ENVIRON ever.
236+ */
237+ switch (owhere) {
238+ case UNDEF:
239+ case INTERNAL:
240+ case MAKEFILE:
241+ set = 1;
242+ break;
243+ case ENVIRON:
244+ set = (where == MAKEFLAGS || where == CMDLINE);
245+ set |= (where == MAKEFILE && !eflag);
246+ break;
247+ case MAKEFLAGS:
248+ set = (where == CMDLINE || where == MAKEFLAGS);
249+ break;
250+ case CMDLINE:
251+ set = (where == CMDLINE);
252+ break;
253+ default:
254+ abort();
255+ }
256+
257+ if (!set) {
258+ debug("hidding override of %s from '%s' to '%s'", name, s, val);
259+ } else {
260+ debug("override %s from '%s' to '%s'", name, s, val);
261+ free(mp->value);
262+ mp->value = estrdup(val);
263+ mp->where = where;
264+
265+ if (export && strcmp(name, "SHELL") != 0) {
266+ debug("exporting macro %s", name);
267+ exportvar(name, val);
268+ }
269+ }
270 }
271
272 void
273 freeloc(struct loc *loc)
274 {
275- free(loc->fname);
276+ free(loc->fname);
277 }
278
279 static struct loc *
280 getloc(void)
281 {
282- struct input *ip;
283+ struct input *ip;
284
285- for (ip = input; ip && ip->type != FTFILE; ip = ip->prev)
286- ;
287- if (!ip)
288- return NULL;
289+ for (ip = input; ip && ip->type != FTFILE; ip = ip->prev)
290+ ;
291+ if (!ip)
292+ return NULL;
293
294- return &ip->loc;
295+ return &ip->loc;
296 }
297
298
299 void
300 error(char *fmt, ...)
301 {
302- va_list va;
303- struct loc *loc;
304+ va_list va;
305+ struct loc *loc;
306
307- fprintf(stderr, "make: error: ");
308- if ((loc = getloc()) != NULL)
309- fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno);
310+ fprintf(stderr, "make: error: ");
311+ if ((loc = getloc()) != NULL)
312+ fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno);
313
314- va_start(va, fmt);
315- vfprintf(stderr, fmt, va);
316- va_end(va);
317- putc('\n', stderr);
318+ va_start(va, fmt);
319+ vfprintf(stderr, fmt, va);
320+ va_end(va);
321+ putc('\n', stderr);
322
323- exit(EXIT_FAILURE);
324+ exit(EXIT_FAILURE);
325 }
326
327 void
328 warning(char *fmt, ...)
329 {
330- va_list va;
331- struct loc *loc;
332+ va_list va;
333+ struct loc *loc;
334
335- fprintf(stderr, "make: warning: ");
336- if ((loc = getloc()) != NULL)
337- fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno);
338+ fprintf(stderr, "make: warning: ");
339+ if ((loc = getloc()) != NULL)
340+ fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno);
341
342- va_start(va, fmt);
343- vfprintf(stderr, fmt, va);
344- va_end(va);
345- putc('\n', stderr);
346+ va_start(va, fmt);
347+ vfprintf(stderr, fmt, va);
348+ va_end(va);
349+ putc('\n', stderr);
350 }
351
352 static void
353 pop(void)
354 {
355- struct input *ip = input->prev;
356+ struct input *ip = input->prev;
357
358- if (input->type == FTFILE) {
359- if (input->fp)
360- fclose(input->fp);
361- freeloc(&input->loc);
362- }
363- free(input->buf);
364- free(input);
365+ if (input->type == FTFILE) {
366+ if (input->fp)
367+ fclose(input->fp);
368+ freeloc(&input->loc);
369+ }
370+ free(input->buf);
371+ free(input);
372
373- input = ip;
374+ input = ip;
375 }
376
377 static void
378 push(int type, ...)
379 {
380- int line, len, pos;
381- FILE *fp = NULL;
382- char *buf, *s, *fname = NULL;
383- va_list va;
384- struct input *ip;
385-
386- va_start(va, type);
387- switch (type) {
388- case FTFILE:
389- fp = va_arg(va, FILE *);
390- s = va_arg(va, char *);
391- line = va_arg(va, int);
392- fname = estrdup(s);
393- buf = emalloc(BUFSIZ);
394- pos = len = BUFSIZ;
395- break;
396- case FTEXPAN:
397- s = va_arg(va, char *);
398- buf = estrdup(s);
399- line = pos = 0;
400- len = strlen(s);
401- break;
402- }
403- va_end(va);
404-
405- ip = emalloc(sizeof(*ip));
406- ip->siz = len;
407- ip->buf = buf;
408- ip->type = type;
409- ip->fp = fp;
410- ip->loc.fname = fname;
411- ip->loc.lineno = line;
412- ip->pos = pos;
413- ip->prev = input;
414-
415- input = ip;
416+ int line, len, pos;
417+ FILE *fp = NULL;
418+ char *buf, *s, *fname = NULL;
419+ va_list va;
420+ struct input *ip;
421+
422+ va_start(va, type);
423+ switch (type) {
424+ case FTFILE:
425+ fp = va_arg(va, FILE *);
426+ s = va_arg(va, char *);
427+ line = va_arg(va, int);
428+ fname = estrdup(s);
429+ buf = emalloc(BUFSIZ);
430+ pos = len = BUFSIZ;
431+ break;
432+ case FTEXPAN:
433+ s = va_arg(va, char *);
434+ buf = estrdup(s);
435+ line = pos = 0;
436+ len = strlen(s);
437+ break;
438+ }
439+ va_end(va);
440+
441+ ip = emalloc(sizeof(*ip));
442+ ip->siz = len;
443+ ip->buf = buf;
444+ ip->type = type;
445+ ip->fp = fp;
446+ ip->loc.fname = fname;
447+ ip->loc.lineno = line;
448+ ip->pos = pos;
449+ ip->prev = input;
450+
451+ input = ip;
452 }
453
454 static char *
455 trim(char *s)
456 {
457- size_t len;
458+ size_t len;
459
460- while (isspace(*s))
461- s++;
462+ while (isspace(*s))
463+ s++;
464
465- for (len = strlen(s); len > 0 && isspace(s[len-1]); --len)
466- s[len-1] = '\0';
467+ for (len = strlen(s); len > 0 && isspace(s[len-1]); --len)
468+ s[len-1] = '\0';
469
470- return s;
471+ return s;
472 }
473
474 static void
475 include(char *s)
476 {
477- FILE *fp;
478- char *fil, *t;
479+ FILE *fp;
480+ char *fil, *t, *end;
481+
482+ s = trim(s);
483+ if (*s == '<' || *s == '"') {
484+ char delim = (*s == '<') ? '>' : '"';
485+ s++;
486+ end = strchr(s, delim);
487+ if (end)
488+ *end = '\0';
489+ }
490+ fil = expandstring(s, NULL, getloc());
491+
492+ t = trim(fil);
493+ if (strlen(t) != 0) {
494+ debug("including '%s'", t);
495+ if ((fp = fopen(t, "r")) == NULL)
496+ error("opening %s:%s", t, strerror(errno));
497+ push(FTFILE, fp, t, 0);
498+ }
499+
500+ free(fil);
501+}
502+
503+static void
504+sinclude(char *s)
505+{
506+ FILE *fp;
507+ char *fil, *t, *end;
508+
509+ s = trim(s);
510+ if (*s == '<' || *s == '"') {
511+ char delim = (*s == '<') ? '>' : '"';
512+ s++;
513+ end = strchr(s, delim);
514+ if (end)
515+ *end = '\0';
516+ }
517+ fil = expandstring(s, NULL, getloc());
518+
519+ t = trim(fil);
520+ if (strlen(t) != 0) {
521+ debug("trying to include '%s'", t);
522+ if ((fp = fopen(t, "r")) != NULL)
523+ push(FTFILE, fp, t, 0);
524+ else
525+ debug("skipping missing include %s", t);
526+ }
527+
528+ free(fil);
529+}
530+
531+#define MAXCOND 32
532+static struct {
533+ int active;
534+ int matched;
535+ int parent_active;
536+} condstack[MAXCOND];
537+static int conddepth = 0;
538+
539+static int
540+cond_active(void)
541+{
542+ if (conddepth == 0)
543+ return 1;
544+ return condstack[conddepth].active && condstack[conddepth].parent_active;
545+}
546+
547+static void
548+cond_if(int truth)
549+{
550+ int parent;
551+ if (conddepth >= MAXCOND)
552+ error("too many nested .if directives");
553+ parent = cond_active();
554+ conddepth++;
555+ condstack[conddepth].parent_active = parent;
556+ condstack[conddepth].matched = truth;
557+ condstack[conddepth].active = truth;
558+}
559+
560+static void
561+cond_elif(int truth)
562+{
563+ if (conddepth == 0)
564+ error(".elif without .if");
565+ if (condstack[conddepth].matched)
566+ condstack[conddepth].active = 0;
567+ else {
568+ condstack[conddepth].matched = condstack[conddepth].matched || truth;
569+ condstack[conddepth].active = truth;
570+ }
571+}
572
573- s = trim(s);
574- fil = expandstring(s, NULL, getloc());
575+static void
576+cond_else(void)
577+{
578+ if (conddepth == 0)
579+ error(".else without .if");
580+ condstack[conddepth].active = !condstack[conddepth].matched;
581+ condstack[conddepth].matched = 1;
582+}
583
584- t = trim(fil);
585- if (strlen(t) != 0) {
586- debug("including '%s'", t);
587- if ((fp = fopen(t, "r")) == NULL)
588- error("opening %s:%s", t, strerror(errno));
589- push(FTFILE, fp, t, 0);
590- }
591+static void
592+cond_endif(void)
593+{
594+ if (conddepth == 0)
595+ error(".endif without .if");
596+ conddepth--;
597+}
598
599- free(fil);
600+static int
601+eval_if(char *expr)
602+{
603+ char *s, *p, *var, *val, *end;
604+ int neg = 0, result;
605+
606+ s = trim(expr);
607+ if (!*s)
608+ return 0;
609+
610+ while (*s == '(') {
611+ end = s + strlen(s);
612+ if (end > s && end[-1] == ')') end[-1] = '\0';
613+ s++;
614+ s = trim(s);
615+ }
616+
617+ if (*s == '!') {
618+ neg = 1;
619+ s++;
620+ s = trim(s);
621+ }
622+
623+ if (strncmp(s, "defined", 7) == 0 && (s[7] == '(' || s[7] == ' ')) {
624+ var = trim(s + 7);
625+ if (*var == '(') var++;
626+ end = var + strlen(var);
627+ if (end > var && end[-1] == ')') end[-1] = '\0';
628+ var = trim(var);
629+ result = getmacro(var)[0] != '\0';
630+ return neg ? !result : result;
631+ }
632+
633+ if (strncmp(s, "make", 4) == 0 && (s[4] == '(' || s[4] == ' ')) {
634+ var = trim(s + 4);
635+ if (*var == '(') var++;
636+ end = var + strlen(var);
637+ if (end > var && end[-1] == ')') end[-1] = '\0';
638+ var = trim(var);
639+ result = getmacro(var)[0] != '\0';
640+ return neg ? !result : result;
641+ }
642+
643+ {
644+ char *expanded = expandstring(s, NULL, getloc());
645+ s = expanded;
646+ }
647+
648+ p = strstr(s, "==");
649+ if (!p) p = strstr(s, "!=");
650+ if (p) {
651+ int eq = (p[1] == '=');
652+ *p = '\0';
653+ val = trim(p + 2);
654+ var = trim(s);
655+ {
656+ char *ev = expandstring(var, NULL, getloc());
657+ result = strcmp(ev, val) == 0;
658+ free(ev);
659+ }
660+ if (!eq) result = !result;
661+ free(s);
662+ return neg ? !result : result;
663+ }
664+
665+ /* bare expression: true if non-empty after expansion */
666+ result = s[0] != '\0';
667+ free(s);
668+ return neg ? !result : result;
669 }
670
671 static char *
672 nextline(void)
673 {
674- int c;
675- FILE *fp;
676- char *s, *lim;
677+ int c;
678+ FILE *fp;
679+ char *s, *lim;
680
681- assert(input->type == FTFILE);
682+ assert(input->type == FTFILE);
683
684 repeat:
685- fp = input->fp;
686- if (!fp || feof(fp))
687- return NULL;
688-
689- lim = &input->buf[input->siz];
690- for (s = input->buf; s < lim; *s++ = c) {
691- c = getc(fp);
692- if (c == '\n' || c == EOF) {
693- input->loc.lineno++;
694- *s++ = '\n';
695- break;
696- }
697- if (c > UCHAR_MAX || c < 0)
698- error("invalid character '%c' (%d)", c, c);
699- }
700-
701-
702- if (s == lim)
703- error("too long line");
704- if (ferror(fp))
705- error(strerror(errno));
706- *s = '\0';
707-
708- if (!strcmp(input->buf, ""))
709- goto repeat;
710-
711- if (!strncmp(input->buf, "include", 7) && isblank(input->buf[7])) {
712- input->pos = input->siz;
713- include(input->buf+7);
714- goto repeat;
715- }
716-
717- input->pos = 0;
718-
719-
720- return input->buf;
721+ fp = input->fp;
722+ if (!fp || feof(fp))
723+ return NULL;
724+
725+ lim = &input->buf[input->siz];
726+ for (s = input->buf; s < lim; *s++ = c) {
727+ c = getc(fp);
728+ if (c == '\n' || c == EOF) {
729+ input->loc.lineno++;
730+ *s++ = '\n';
731+ break;
732+ }
733+ if (c > UCHAR_MAX || c < 0)
734+ error("invalid character '%c' (%d)", c, c);
735+ }
736+
737+
738+ if (s == lim)
739+ error("too long line");
740+ if (ferror(fp))
741+ error(strerror(errno));
742+ *s = '\0';
743+
744+ if (!strcmp(input->buf, ""))
745+ goto repeat;
746+
747+ /* bmake style .include / .sinclude / .-include */
748+ if (input->buf[0] == '.') {
749+ char *d = input->buf + 1;
750+ size_t dl;
751+ /* strip trailing whitespace/newline so strcmp works */
752+ dl = strlen(d);
753+ while (dl > 0 && isspace((unsigned char)d[dl-1]))
754+ d[--dl] = '\0';
755+ if (strncmp(d, "include", 7) == 0 && isblank(d[7])) {
756+ input->pos = input->siz;
757+ if (cond_active()) include(d + 7);
758+ goto repeat;
759+ }
760+ if (strncmp(d, "sinclude", 8) == 0 && isblank(d[8])) {
761+ input->pos = input->siz;
762+ if (cond_active()) sinclude(d + 8);
763+ goto repeat;
764+ }
765+ if (strncmp(d, "-include", 8) == 0 && isblank(d[8])) {
766+ input->pos = input->siz;
767+ if (cond_active()) sinclude(d + 8);
768+ goto repeat;
769+ }
770+ if (strncmp(d, "optinclude", 10) == 0 && isblank(d[10])) {
771+ input->pos = input->siz;
772+ if (cond_active()) sinclude(d + 10);
773+ goto repeat;
774+ }
775+ /* conditionals */
776+ if (strncmp(d, "if", 2) == 0 && (isblank(d[2]) || d[2] == '\0')) {
777+ if (cond_active()) {
778+ if (d[2] == '\0')
779+ cond_if(eval_if(""));
780+ else
781+ cond_if(eval_if(d + 3));
782+ } else {
783+ cond_if(0);
784+ }
785+ goto repeat;
786+ }
787+ if (strncmp(d, "ifdef", 5) == 0 && (isblank(d[5]) || d[5] == '\0')) {
788+ if (cond_active()) {
789+ char *v = trim(d[5] ? d + 6 : "");
790+ cond_if(getmacro(v)[0] != '\0');
791+ } else {
792+ cond_if(0);
793+ }
794+ goto repeat;
795+ }
796+ if (strncmp(d, "ifndef", 6) == 0 && (isblank(d[6]) || d[6] == '\0')) {
797+ if (cond_active()) {
798+ char *v = trim(d[6] ? d + 7 : "");
799+ cond_if(getmacro(v)[0] == '\0');
800+ } else {
801+ cond_if(0);
802+ }
803+ goto repeat;
804+ }
805+ if (strncmp(d, "elif", 4) == 0 && (isblank(d[4]) || d[4] == '\0')) {
806+ if (condstack[conddepth].parent_active)
807+ cond_elif(eval_if(d[4] ? d + 5 : ""));
808+ else
809+ cond_elif(0);
810+ goto repeat;
811+ }
812+ if (strcmp(d, "else") == 0) {
813+ cond_else();
814+ goto repeat;
815+ }
816+ if (strcmp(d, "endif") == 0) {
817+ cond_endif();
818+ goto repeat;
819+ }
820+ if (strncmp(d, "error", 5) == 0 && isblank(d[5])) {
821+ if (cond_active())
822+ error("%s", trim(d + 6));
823+ goto repeat;
824+ }
825+ if (strncmp(d, "warning", 7) == 0 && isblank(d[7])) {
826+ if (cond_active())
827+ warning("%s", trim(d + 8));
828+ goto repeat;
829+ }
830+ }
831+
832+ /* POSIX include */
833+ if (!strncmp(input->buf, "include", 7) && isblank(input->buf[7])) {
834+ input->pos = input->siz;
835+ if (cond_active()) include(input->buf+7);
836+ goto repeat;
837+ }
838+
839+ /* sinclude / -include (GNU/POSIX style without dot) */
840+ if ((!strncmp(input->buf, "sinclude", 8) && isblank(input->buf[8])) ||
841+ (!strncmp(input->buf, "-include", 8) && isblank(input->buf[8]))) {
842+ input->pos = input->siz;
843+ if (cond_active()) sinclude(input->buf + 8);
844+ goto repeat;
845+ }
846+
847+ /* if we are inside an inactive conditional branch, skip this line */
848+ if (!cond_active()) {
849+ input->pos = input->siz;
850+ goto repeat;
851+ }
852+
853+ input->pos = 0;
854+
855+
856+ return input->buf;
857 }
858
859 static int
860 empty(struct input *ip)
861 {
862- return ip->pos == ip->siz || ip->buf[ip->pos] == '\0';
863+ return ip->pos == ip->siz || ip->buf[ip->pos] == '\0';
864 }
865
866 static int
867 moreinput(void)
868 {
869- while (input) {
870- if (!empty(input))
871- break;
872-
873- switch (input->type) {
874- case FTEXPAN:
875- pop();
876- break;
877- case FTFILE:
878- if (!nextline())
879- pop();
880- break;
881- }
882- }
883-
884- return input != NULL;
885+ while (input) {
886+ if (!empty(input))
887+ break;
888+
889+ switch (input->type) {
890+ case FTEXPAN:
891+ pop();
892+ break;
893+ case FTFILE:
894+ if (!nextline())
895+ pop();
896+ break;
897+ }
898+ }
899+
900+ return input != NULL;
901 }
902
903 static int
904 nextc(void)
905 {
906- if (!moreinput())
907- return EOF;
908+ if (!moreinput())
909+ return EOF;
910
911- return input->buf[input->pos++];
912+ return input->buf[input->pos++];
913 }
914
915 /*
916@@ -415,284 +680,302 @@ nextc(void)
917 static int
918 ahead(void)
919 {
920- return input->buf[input->pos];
921+ return input->buf[input->pos];
922 }
923
924 static int
925 back(int c)
926 {
927- if (c == EOF)
928- return c;
929- assert(input->pos > 0);
930- return input->buf[--input->pos] = c;
931+ if (c == EOF)
932+ return c;
933+ assert(input->pos > 0);
934+ return input->buf[--input->pos] = c;
935 }
936
937 static void
938 comment(void)
939 {
940- int c;
941+ int c;
942
943- while ((c = nextc()) != EOF && c != '\n') {
944- if (c == '\\' && nextc() == EOF)
945- break;
946- }
947+ while ((c = nextc()) != EOF && c != '\n') {
948+ if (c == '\\' && nextc() == EOF)
949+ break;
950+ }
951 }
952
953 static void
954 skipspaces(void)
955 {
956- int c;
957+ int c;
958
959- for (c = nextc(); c == ' ' || c == '\t'; c = nextc())
960- ;
961- back(c);
962+ for (c = nextc(); c == ' ' || c == '\t'; c = nextc())
963+ ;
964+ back(c);
965 }
966
967 static int
968 validchar(int c)
969 {
970- if (c == EOF)
971- return 0;
972- return c == '.' || c == '/' || c == '_' || c == '-' || isalnum(c);
973+ if (c == EOF)
974+ return 0;
975+ return c == '.' || c == '/' || c == '_' || c == '-' || isalnum(c);
976 }
977
978 static char *
979 expandmacro(char *name)
980 {
981- char *s;
982+ char *s;
983
984- s = expandstring(getmacro(name), NULL, getloc());
985- debug("macro %s expanded to '%s'", name, s);
986+ s = expandstring(getmacro(name), NULL, getloc());
987+ debug("macro %s expanded to '%s'", name, s);
988
989- return s;
990+ return s;
991 }
992
993 static void
994 replace(char *line, char *repl, char *to)
995 {
996- int siz, at, len, replsiz, tosiz, pos;
997- char *oline, *cur, *buf;
998-
999- debug("replacing '%s', with '%s' to '%s'", line, repl, to);
1000- oline = line;
1001- tosiz = strlen(to);
1002- replsiz = strlen(repl);
1003-
1004- buf = NULL;
1005- for (pos = 0; *line; pos += siz) {
1006- cur = NULL;
1007- siz = 0;
1008-
1009- for (siz = 0; *line == ' ' || *line == '\t'; ++siz) {
1010- cur = erealloc(cur, siz+1);
1011- cur[siz] = *line++;
1012- }
1013-
1014- len = strcspn(line, " \t");
1015- at = len - replsiz;
1016- if (at < 0 || memcmp(line + at, repl, replsiz)) {
1017- cur = erealloc(cur, siz + len);
1018- memcpy(cur + siz, line, len);
1019- siz += len;
1020- } else {
1021- cur = erealloc(cur, siz + at + tosiz);
1022- memcpy(cur + siz, line, at);
1023- memcpy(cur + siz + at, to, tosiz);
1024- siz += at + tosiz;
1025- }
1026-
1027- line += len;
1028- buf = erealloc(buf, pos + siz);
1029- memcpy(buf + pos, cur, siz);
1030- free(cur);
1031- }
1032-
1033- if (pos > 0) {
1034- buf = erealloc(buf, pos + 1);
1035- buf[pos] = '\0';
1036- debug("\treplace '%s' with '%s'", oline, buf);
1037- push(FTEXPAN, buf);
1038- }
1039-
1040- free(buf);
1041+ int siz, at, len, replsiz, tosiz, pos;
1042+ char *oline, *cur, *buf;
1043+
1044+ debug("replacing '%s', with '%s' to '%s'", line, repl, to);
1045+ oline = line;
1046+ tosiz = strlen(to);
1047+ replsiz = strlen(repl);
1048+
1049+ buf = NULL;
1050+ for (pos = 0; *line; pos += siz) {
1051+ cur = NULL;
1052+ siz = 0;
1053+
1054+ for (siz = 0; *line == ' ' || *line == '\t'; ++siz) {
1055+ cur = erealloc(cur, siz+1);
1056+ cur[siz] = *line++;
1057+ }
1058+
1059+ len = strcspn(line, " \t");
1060+ at = len - replsiz;
1061+ if (at < 0 || memcmp(line + at, repl, replsiz)) {
1062+ cur = erealloc(cur, siz + len);
1063+ memcpy(cur + siz, line, len);
1064+ siz += len;
1065+ } else {
1066+ cur = erealloc(cur, siz + at + tosiz);
1067+ memcpy(cur + siz, line, at);
1068+ memcpy(cur + siz + at, to, tosiz);
1069+ siz += at + tosiz;
1070+ }
1071+
1072+ line += len;
1073+ buf = erealloc(buf, pos + siz);
1074+ memcpy(buf + pos, cur, siz);
1075+ free(cur);
1076+ }
1077+
1078+ if (pos > 0) {
1079+ buf = erealloc(buf, pos + 1);
1080+ buf[pos] = '\0';
1081+ debug("\treplace '%s' with '%s'", oline, buf);
1082+ push(FTEXPAN, buf);
1083+ }
1084+
1085+ free(buf);
1086 }
1087
1088 static void
1089 expandsimple(Target *tp)
1090 {
1091- char *s;
1092- Target **p;
1093- int len, c;
1094-
1095- switch (c = nextc()) {
1096- case '@':
1097- if (!tp || !tp->target)
1098- return;
1099- push(FTEXPAN, tp->target);
1100- break;
1101- case '<':
1102- if (!tp || !tp->req)
1103- return;
1104- push(FTEXPAN, tp->req);
1105- break;
1106- case '*':
1107- if (!tp || !tp->target)
1108- return;
1109- s = strrchr(tp->target, '.');
1110- if (!s) {
1111- push(FTEXPAN, tp->target);
1112- return;
1113- }
1114-
1115- len = s - tp->target;
1116- s = emalloc(len+1);
1117- memcpy(s, tp->target, len);
1118- s[len] = '\0';
1119- push(FTEXPAN, s);
1120- free(s);
1121- break;
1122- case '?':
1123- if (!tp)
1124- return;
1125-
1126- if (tp->req && stamp(tp->req) > tp->stamp) {
1127- push(FTEXPAN, " ");
1128- push(FTEXPAN, tp->req);
1129- }
1130-
1131- for (p = tp->deps; p && *p; ++p) {
1132- if (stamp((*p)->name) > tp->stamp) {
1133- push(FTEXPAN, " ");
1134- push(FTEXPAN, (*p)->name);
1135- }
1136- }
1137- break;
1138- default:
1139- token[0] = c;
1140- token[1] = '\0';
1141- s = expandmacro(token);
1142- push(FTEXPAN, s);
1143- free(s);
1144- break;
1145- }
1146+ char *s;
1147+ Target **p;
1148+ int len, c, first;
1149+
1150+ switch (c = nextc()) {
1151+ case '@':
1152+ if (!tp || !tp->target)
1153+ return;
1154+ push(FTEXPAN, tp->target);
1155+ break;
1156+ case '<':
1157+ if (!tp || !tp->req)
1158+ return;
1159+ push(FTEXPAN, tp->req);
1160+ break;
1161+ case '*':
1162+ if (!tp || !tp->target)
1163+ return;
1164+ s = strrchr(tp->target, '.');
1165+ if (!s) {
1166+ push(FTEXPAN, tp->target);
1167+ return;
1168+ }
1169+
1170+ len = s - tp->target;
1171+ s = emalloc(len+1);
1172+ memcpy(s, tp->target, len);
1173+ s[len] = '\0';
1174+ push(FTEXPAN, s);
1175+ free(s);
1176+ break;
1177+ case '?':
1178+ if (!tp)
1179+ return;
1180+
1181+ if (tp->req && stamp(tp->req) > tp->stamp) {
1182+ push(FTEXPAN, " ");
1183+ push(FTEXPAN, tp->req);
1184+ }
1185+
1186+ for (p = tp->deps; p && *p; ++p) {
1187+ if (stamp((*p)->name) > tp->stamp) {
1188+ push(FTEXPAN, " ");
1189+ push(FTEXPAN, (*p)->name);
1190+ }
1191+ }
1192+ break;
1193+ case '>':
1194+ case '^':
1195+ if (!tp)
1196+ return;
1197+ first = 1;
1198+ if (tp->req) {
1199+ push(FTEXPAN, tp->req);
1200+ first = 0;
1201+ }
1202+ for (p = tp->deps; p && *p; ++p) {
1203+ if (!first)
1204+ push(FTEXPAN, " ");
1205+ push(FTEXPAN, (*p)->name);
1206+ first = 0;
1207+ }
1208+ break;
1209+ default:
1210+ token[0] = c;
1211+ token[1] = '\0';
1212+ s = expandmacro(token);
1213+ push(FTEXPAN, s);
1214+ free(s);
1215+ break;
1216+ }
1217 }
1218
1219 static int
1220 internal(int ch)
1221 {
1222- switch (ch) {
1223- case '@':
1224- case '?':
1225- case '*':
1226- case '<':
1227- return 1;
1228- default:
1229- return 0;
1230- }
1231+ switch (ch) {
1232+ case '@':
1233+ case '?':
1234+ case '*':
1235+ case '<':
1236+ case '>':
1237+ case '^':
1238+ return 1;
1239+ default:
1240+ return 0;
1241+ }
1242 }
1243
1244 static void
1245 expansion(Target *tp)
1246 {
1247- int delim, c, repli, toi, namei, st;
1248- char name[MAXTOKEN], repl[MAXREPL], to[MAXREPL];
1249- char *s, *erepl;
1250-
1251- c = nextc();
1252- if (c == '(')
1253- delim = ')';
1254- else if (c == '{')
1255- delim = '}';
1256- else
1257- delim = 0;
1258-
1259- if (!delim) {
1260- back(c);
1261- expandsimple(tp);
1262- return;
1263- }
1264-
1265- s = NULL;
1266- namei = repli = toi = 0;
1267- st = STBEGIN;
1268-
1269- while (st != STEND && (c = nextc()) != EOF) {
1270- switch (st) {
1271- case STBEGIN:
1272- if (c == ':') {
1273- st = STREPLACE;
1274- name[namei] = '\0';
1275- s = expandmacro(name);
1276- break;
1277- }
1278- if (c == delim) {
1279- name[namei] = '\0';
1280- s = expandmacro(name);
1281- goto no_replace;
1282- }
1283- if (namei == MAXTOKEN-1)
1284- error("expansion text too long");
1285-
1286- if (namei == 0 && internal(c)) {
1287- name[namei++] = '$';
1288- name[namei++] = c;
1289- name[namei] = '\0';
1290- st = STINTERNAL;
1291- s = expandstring(name, tp, getloc());
1292- break;
1293- }
1294-
1295- if (!validchar(c))
1296- error("invalid macro name in expansion");
1297- name[namei++] = c;
1298- break;
1299- case STINTERNAL:
1300- if (c == delim)
1301- goto no_replace;
1302- if (c != ':')
1303- error("invalid internal macro in expansion");
1304- st = STREPLACE;
1305- break;
1306- case STREPLACE:
1307- if (c == '=') {
1308- st = STTO;
1309- break;
1310- }
1311- if (c == delim)
1312- error("invalid replacement pattern in expansion");
1313- if (repli == MAXREPL-1)
1314- error("macro replacement too big");
1315- repl[repli++] = c;
1316- break;
1317- case STTO:
1318- if (c == delim) {
1319- st = STEND;
1320- break;
1321- }
1322-
1323- if (toi == MAXREPL-1)
1324- error("macro substiturion too big");
1325- to[toi++] = c;
1326- break;
1327- }
1328- }
1329-
1330- if (c == EOF)
1331- error("found eof while parsing expansion");
1332-
1333- repl[repli] = '\0';
1334- to[toi] = '\0';
1335-
1336- erepl = expandstring(repl, tp, getloc());
1337- replace(s, erepl, to);
1338-
1339- free(erepl);
1340- free(s);
1341- return;
1342+ int delim, c, repli, toi, namei, st;
1343+ char name[MAXTOKEN], repl[MAXREPL], to[MAXREPL];
1344+ char *s, *erepl;
1345+
1346+ c = nextc();
1347+ if (c == '(')
1348+ delim = ')';
1349+ else if (c == '{')
1350+ delim = '}';
1351+ else
1352+ delim = 0;
1353+
1354+ if (!delim) {
1355+ back(c);
1356+ expandsimple(tp);
1357+ return;
1358+ }
1359+
1360+ s = NULL;
1361+ namei = repli = toi = 0;
1362+ st = STBEGIN;
1363+
1364+ while (st != STEND && (c = nextc()) != EOF) {
1365+ switch (st) {
1366+ case STBEGIN:
1367+ if (c == ':') {
1368+ st = STREPLACE;
1369+ name[namei] = '\0';
1370+ s = expandmacro(name);
1371+ break;
1372+ }
1373+ if (c == delim) {
1374+ name[namei] = '\0';
1375+ s = expandmacro(name);
1376+ goto no_replace;
1377+ }
1378+ if (namei == MAXTOKEN-1)
1379+ error("expansion text too long");
1380+
1381+ if (namei == 0 && internal(c)) {
1382+ name[namei++] = '$';
1383+ name[namei++] = c;
1384+ name[namei] = '\0';
1385+ st = STINTERNAL;
1386+ s = expandstring(name, tp, getloc());
1387+ break;
1388+ }
1389+
1390+ if (!validchar(c))
1391+ error("invalid macro name in expansion");
1392+ name[namei++] = c;
1393+ break;
1394+ case STINTERNAL:
1395+ if (c == delim)
1396+ goto no_replace;
1397+ if (c != ':')
1398+ error("invalid internal macro in expansion");
1399+ st = STREPLACE;
1400+ break;
1401+ case STREPLACE:
1402+ if (c == '=') {
1403+ st = STTO;
1404+ break;
1405+ }
1406+ if (c == delim)
1407+ error("invalid replacement pattern in expansion");
1408+ if (repli == MAXREPL-1)
1409+ error("macro replacement too big");
1410+ repl[repli++] = c;
1411+ break;
1412+ case STTO:
1413+ if (c == delim) {
1414+ st = STEND;
1415+ break;
1416+ }
1417+
1418+ if (toi == MAXREPL-1)
1419+ error("macro substiturion too big");
1420+ to[toi++] = c;
1421+ break;
1422+ }
1423+ }
1424+
1425+ if (c == EOF)
1426+ error("found eof while parsing expansion");
1427+
1428+ repl[repli] = '\0';
1429+ to[toi] = '\0';
1430+
1431+ erepl = expandstring(repl, tp, getloc());
1432+ replace(s, erepl, to);
1433+
1434+ free(erepl);
1435+ free(s);
1436+ return;
1437
1438 no_replace:
1439- push(FTEXPAN, s);
1440- free(s);
1441+ push(FTEXPAN, s);
1442+ free(s);
1443 }
1444
1445 /*
1446@@ -705,330 +988,420 @@ no_replace:
1447 char *
1448 expandstring(char *line, Target *tp, struct loc *loc)
1449 {
1450- int c, n;
1451- char *s;
1452- struct input *ip = input;
1453-
1454- input = NULL;
1455- push(FTFILE, NULL, loc->fname, loc->lineno);
1456- push(FTEXPAN, line);
1457-
1458- n = 0;
1459- s = NULL;
1460- while ((c = nextc()) != EOF) {
1461- if (c != '$') {
1462- s = erealloc(s, ++n);
1463- s[n-1] = c;
1464- continue;
1465- }
1466-
1467- if ((c = nextc()) == '$') {
1468- s = erealloc(s, n += 2);
1469- s[n-2] = '$';
1470- s[n-1] = '$';
1471- } else {
1472- back(c);
1473- expansion(tp);
1474- }
1475- }
1476-
1477- s = erealloc(s, n+1);
1478- s[n] = '\0';
1479- input = ip;
1480-
1481- return s;
1482+ int c, n;
1483+ char *s;
1484+ struct input *ip = input;
1485+
1486+ input = NULL;
1487+ push(FTFILE, NULL, loc->fname, loc->lineno);
1488+ push(FTEXPAN, line);
1489+
1490+ n = 0;
1491+ s = NULL;
1492+ while ((c = nextc()) != EOF) {
1493+ if (c != '$') {
1494+ s = erealloc(s, ++n);
1495+ s[n-1] = c;
1496+ continue;
1497+ }
1498+
1499+ if ((c = nextc()) == '$') {
1500+ s = erealloc(s, n += 2);
1501+ s[n-2] = '$';
1502+ s[n-1] = '$';
1503+ } else {
1504+ back(c);
1505+ expansion(tp);
1506+ }
1507+ }
1508+
1509+ s = erealloc(s, n+1);
1510+ s[n] = '\0';
1511+ input = ip;
1512+
1513+ return s;
1514 }
1515
1516 static int
1517 item(void)
1518 {
1519- int c;
1520- char *s;
1521- char buf[MAXTOKEN];
1522-
1523- for (s = buf; s < &buf[MAXTOKEN] - 1; ) {
1524- c = nextc();
1525- if (c == '$' && ahead() != '$')
1526- expansion(NULL);
1527- else if (validchar(c))
1528- *s++ = c;
1529- else
1530- break;
1531- }
1532- back(c);
1533-
1534- if (s >= &buf[MAXTOKEN] - 1)
1535- error("token too long");
1536- if (s == buf)
1537- error("invalid empty token");
1538- *s++ = '\0';
1539- memcpy(token, buf, s - buf);
1540-
1541- return ITEM;
1542+ int c;
1543+ char *s;
1544+ char buf[MAXTOKEN];
1545+
1546+ for (s = buf; s < &buf[MAXTOKEN] - 1; ) {
1547+ c = nextc();
1548+ if (c == '$' && ahead() != '$')
1549+ expansion(NULL);
1550+ else if (validchar(c))
1551+ *s++ = c;
1552+ else
1553+ break;
1554+ }
1555+ back(c);
1556+
1557+ if (s >= &buf[MAXTOKEN] - 1)
1558+ error("token too long");
1559+ if (s == buf)
1560+ error("invalid empty token");
1561+ *s++ = '\0';
1562+ memcpy(token, buf, s - buf);
1563+
1564+ return ITEM;
1565 }
1566
1567 static int
1568 next(void)
1569 {
1570- int c;
1571+ int c;
1572
1573 repeat:
1574- /*
1575- * It is better to avoid skipspaces() here, because
1576- * it can generate the need for 2 calls to back(),
1577- * and we need the character anyway.
1578- */
1579- c = nextc();
1580- if (c == ' ' || c == '\t')
1581- goto repeat;
1582-
1583- if (c == '\\') {
1584- if ((c = nextc()) == '\n')
1585- goto repeat;
1586- back(c);
1587- c = '\\';
1588- }
1589-
1590- switch (c) {
1591- case EOF:
1592- strcpy(token, "<EOF>");
1593- tok = EOF;
1594- break;
1595- case '$':
1596- if ((c = nextc()) == '$')
1597- goto single;
1598- back(c);
1599- expansion(NULL);
1600- goto repeat;
1601- case '#':
1602- comment();
1603- c = '\n';
1604- /* fallthrough */
1605- case ';':
1606- case ':':
1607- case '=':
1608- case '\n':
1609- single:
1610- token[0] = c;
1611- token[1] = '\0';
1612- tok = c;
1613- break;
1614- default:
1615- if (!validchar(c))
1616- error("unexpected character '%c'", c);
1617- back(c);
1618- tok = item();
1619- break;
1620- }
1621-
1622- return tok;
1623+ /*
1624+ * It is better to avoid skipspaces() here, because
1625+ * it can generate the need for 2 calls to back(),
1626+ * and we need the character anyway.
1627+ */
1628+ c = nextc();
1629+ if (c == ' ' || c == '\t')
1630+ goto repeat;
1631+
1632+ if (c == '\\') {
1633+ if ((c = nextc()) == '\n')
1634+ goto repeat;
1635+ back(c);
1636+ c = '\\';
1637+ }
1638+
1639+ switch (c) {
1640+ case EOF:
1641+ strcpy(token, "<EOF>");
1642+ tok = EOF;
1643+ break;
1644+ case '$':
1645+ if ((c = nextc()) == '$')
1646+ goto single;
1647+ back(c);
1648+ expansion(NULL);
1649+ goto repeat;
1650+ case '#':
1651+ comment();
1652+ c = '\n';
1653+ /* fallthrough */
1654+ case ';':
1655+ case ':':
1656+ case '=':
1657+ case '\n':
1658+ single:
1659+ token[0] = c;
1660+ token[1] = '\0';
1661+ tok = c;
1662+ break;
1663+ case '+':
1664+ if (nextc() == '=') {
1665+ token[0] = '+';
1666+ token[1] = '=';
1667+ token[2] = '\0';
1668+ tok = '+';
1669+ break;
1670+ }
1671+ error("unexpected character '+'");
1672+ case '!':
1673+ if (nextc() == '=') {
1674+ token[0] = '!';
1675+ token[1] = '=';
1676+ token[2] = '\0';
1677+ tok = '!';
1678+ break;
1679+ }
1680+ error("unexpected character '!'");
1681+ default:
1682+ if (!validchar(c))
1683+ error("unexpected character '%c'", c);
1684+ back(c);
1685+ tok = item();
1686+ break;
1687+ }
1688+
1689+ return tok;
1690 }
1691
1692 static char *
1693 readmacrodef(void)
1694 {
1695- int n, c;
1696- char *line;
1697-
1698- n = 0;
1699- line = NULL;
1700- while ((c = nextc()) != EOF) {
1701- line = erealloc(line, n+1);
1702- if (c == '\n')
1703- break;
1704- if (c == '#') {
1705- comment();
1706- break;
1707- }
1708- if (c == '\\') {
1709- if ((c = nextc()) != '\n') {
1710- back(c);
1711- c = '\\';
1712- } else {
1713- skipspaces();
1714- c = ' ';
1715- }
1716- }
1717-
1718- line[n++] = c;
1719- }
1720- if (c == EOF)
1721- error("EOF while looking for end of line");
1722- line[n] = '\0';
1723-
1724- return line;
1725+ int n, c;
1726+ char *line;
1727+
1728+ n = 0;
1729+ line = NULL;
1730+ while ((c = nextc()) != EOF) {
1731+ line = erealloc(line, n+1);
1732+ if (c == '\n')
1733+ break;
1734+ if (c == '#') {
1735+ comment();
1736+ break;
1737+ }
1738+ if (c == '\\') {
1739+ if ((c = nextc()) != '\n') {
1740+ back(c);
1741+ c = '\\';
1742+ } else {
1743+ skipspaces();
1744+ c = ' ';
1745+ }
1746+ }
1747+
1748+ line[n++] = c;
1749+ }
1750+ if (c == EOF)
1751+ error("EOF while looking for end of line");
1752+ line[n] = '\0';
1753+
1754+ return line;
1755 }
1756
1757 static struct action
1758 readcmd(void)
1759 {
1760- int n, c;
1761- struct loc *loc;
1762- struct action act;
1763-
1764- skipspaces();
1765-
1766- loc = getloc();
1767- act.loc.fname = estrdup(loc->fname);
1768- act.loc.lineno = loc->lineno;
1769-
1770- n = 0;
1771- act.line = NULL;
1772- while ((c = nextc()) != EOF) {
1773- act.line = erealloc(act.line, n+1);
1774- if (c == '\n')
1775- break;
1776- if (c == '\\') {
1777- if ((c = nextc()) == '\n') {
1778- if ((c = nextc()) != '\t')
1779- back(c);
1780- continue;
1781- }
1782- back(c);
1783- c = '\\';
1784- }
1785- act.line[n++] = c;
1786- }
1787- if (c == EOF)
1788- error("EOF while looking for end of command");
1789- act.line[n] = '\0';
1790-
1791- return act;
1792+ int n, c;
1793+ struct loc *loc;
1794+ struct action act;
1795+
1796+ skipspaces();
1797+
1798+ loc = getloc();
1799+ act.loc.fname = estrdup(loc->fname);
1800+ act.loc.lineno = loc->lineno;
1801+
1802+ n = 0;
1803+ act.line = NULL;
1804+ while ((c = nextc()) != EOF) {
1805+ act.line = erealloc(act.line, n+1);
1806+ if (c == '\n')
1807+ break;
1808+ if (c == '\\') {
1809+ if ((c = nextc()) == '\n') {
1810+ if ((c = nextc()) != '\t')
1811+ back(c);
1812+ continue;
1813+ }
1814+ back(c);
1815+ c = '\\';
1816+ }
1817+ act.line[n++] = c;
1818+ }
1819+ if (c == EOF)
1820+ error("EOF while looking for end of command");
1821+ act.line[n] = '\0';
1822+
1823+ return act;
1824 }
1825
1826 static void
1827 rule(char *targets[], int ntargets)
1828 {
1829- int c, i, j, ndeps, nactions;
1830- struct action *acts;
1831- char **deps = NULL;
1832-
1833- if (ntargets == 0)
1834- error("missing target");
1835-
1836- for (ndeps = 0; next() == ITEM; ++ndeps) {
1837- deps = erealloc(deps, (ndeps+1) * sizeof(char *));
1838- deps[ndeps] = estrdup(token);
1839- }
1840-
1841- if (tok != '\n' && tok != ';')
1842- error("garbage at the end of the line");
1843-
1844- nactions = 0;
1845- acts = NULL;
1846- if (tok == ';') {
1847- nactions++;
1848- acts = erealloc(acts, nactions * sizeof(*acts));
1849- acts[nactions-1] = readcmd();
1850- }
1851-
1852- for (;;) {
1853- if ((c = nextc()) == '#') {
1854- comment();
1855- continue;
1856- }
1857- if (c != '\t')
1858- break;
1859- nactions++;
1860- acts = erealloc(acts, nactions * sizeof(*acts));
1861- acts[nactions-1] = readcmd();
1862- }
1863- back(c);
1864-
1865- for (i = 0; i < ntargets; i++) {
1866- addtarget(targets[i], ndeps);
1867- for (j = 0; j < ndeps; j++)
1868- adddep(targets[i], deps[j]);
1869- if (nactions > 0)
1870- addrule(targets[i], acts, nactions);
1871- }
1872-
1873- for (i = 0; i < ndeps; i++)
1874- free(deps[i]);
1875- free(deps);
1876-
1877- for (i = 0; i < nactions; i++) {
1878- free(acts[i].line);
1879- freeloc(&acts[i].loc);
1880- }
1881- free(acts);
1882+ int c, i, j, ndeps, nactions;
1883+ struct action *acts;
1884+ char **deps = NULL;
1885+
1886+ if (ntargets == 0)
1887+ error("missing target");
1888+
1889+ for (ndeps = 0; next() == ITEM; ++ndeps) {
1890+ deps = erealloc(deps, (ndeps+1) * sizeof(char *));
1891+ deps[ndeps] = estrdup(token);
1892+ }
1893+
1894+ if (tok != '\n' && tok != ';')
1895+ error("garbage at the end of the line");
1896+
1897+ nactions = 0;
1898+ acts = NULL;
1899+ if (tok == ';') {
1900+ nactions++;
1901+ acts = erealloc(acts, nactions * sizeof(*acts));
1902+ acts[nactions-1] = readcmd();
1903+ }
1904+
1905+ for (;;) {
1906+ if ((c = nextc()) == '#') {
1907+ comment();
1908+ continue;
1909+ }
1910+ if (c != '\t')
1911+ break;
1912+ nactions++;
1913+ acts = erealloc(acts, nactions * sizeof(*acts));
1914+ acts[nactions-1] = readcmd();
1915+ }
1916+ back(c);
1917+
1918+ for (i = 0; i < ntargets; i++) {
1919+ addtarget(targets[i], ndeps);
1920+ for (j = 0; j < ndeps; j++)
1921+ adddep(targets[i], deps[j]);
1922+ if (nactions > 0)
1923+ addrule(targets[i], acts, nactions);
1924+ }
1925+
1926+ for (i = 0; i < ndeps; i++)
1927+ free(deps[i]);
1928+ free(deps);
1929+
1930+ for (i = 0; i < nactions; i++) {
1931+ free(acts[i].line);
1932+ freeloc(&acts[i].loc);
1933+ }
1934+ free(acts);
1935 }
1936
1937 static void
1938 assign(char *macros[], int where, int n)
1939 {
1940- char *defs;
1941+ char *defs;
1942
1943- if (n != 1)
1944- error("invalid macro definition");
1945+ if (n != 1)
1946+ error("invalid macro definition");
1947
1948- skipspaces();
1949- defs = readmacrodef();
1950- setmacro(*macros, defs, where, NOEXPORT);
1951- free(defs);
1952+ skipspaces();
1953+ defs = readmacrodef();
1954+ setmacro(*macros, defs, where, NOEXPORT);
1955+ free(defs);
1956+}
1957+
1958+static void
1959+assign_append(char *macros[], int where, int n)
1960+{
1961+ char *defs, *old, *new;
1962+ size_t olen, dlen;
1963+
1964+ if (n != 1)
1965+ error("invalid macro definition");
1966+
1967+ skipspaces();
1968+ defs = readmacrodef();
1969+ old = getmacro(*macros);
1970+ olen = strlen(old);
1971+ dlen = strlen(defs);
1972+ /* old + " " + defs + '\0' */
1973+ new = emalloc(olen + (olen > 0 ? 1 : 0) + dlen + 1);
1974+ memcpy(new, old, olen);
1975+ if (olen > 0)
1976+ new[olen++] = ' ';
1977+ memcpy(new + olen, defs, dlen);
1978+ new[olen + dlen] = '\0';
1979+ setmacro(*macros, new, where, NOEXPORT);
1980+ free(new);
1981+ free(defs);
1982+}
1983+
1984+static void
1985+assign_shell(char *macros[], int where, int n)
1986+{
1987+ char *cmd, *out;
1988+ FILE *p;
1989+ size_t cap, len;
1990+ int c;
1991+
1992+ if (n != 1)
1993+ error("invalid macro definition");
1994+
1995+ skipspaces();
1996+ cmd = readmacrodef();
1997+ {
1998+ char *expanded = expandstring(cmd, NULL, getloc());
1999+ free(cmd);
2000+ cmd = expanded;
2001+ }
2002+ p = wpopen(cmd, NULL, "r");
2003+ if (!p)
2004+ error("popen: %s", strerror(errno));
2005+ cap = 64;
2006+ out = emalloc(cap);
2007+ len = 0;
2008+ while ((c = getc(p)) != EOF) {
2009+ if (len + 1 >= cap) {
2010+ cap *= 2;
2011+ out = erealloc(out, cap);
2012+ }
2013+ if (c == '\n')
2014+ break;
2015+ out[len++] = c;
2016+ }
2017+ out[len] = '\0';
2018+ wpclose(p);
2019+ setmacro(*macros, out, where, NOEXPORT);
2020+ free(out);
2021+ free(cmd);
2022 }
2023
2024 void
2025 parseinput(int where)
2026 {
2027- int i, n;
2028- char **targets;
2029-
2030- while (moreinput()) {
2031- n = 0;
2032- targets = NULL;
2033-
2034- next();
2035- if (tok == '\n')
2036- continue;
2037-
2038- while (tok == ITEM) {
2039- n++;
2040- targets = erealloc(targets, n * sizeof(char *));
2041- targets[n-1] = estrdup(token);
2042- next();
2043- }
2044-
2045- switch (tok) {
2046- case ':':
2047- rule(targets, n);
2048- break;
2049- case '=':
2050- assign(targets, where, n);
2051- break;
2052- default:
2053- error("unexpected token '%s'(%d)", token, tok);
2054- }
2055-
2056- for (i = 0; i < n; i++)
2057- free(targets[i]);
2058- free(targets);
2059- }
2060+ int i, n;
2061+ char **targets;
2062+
2063+ while (moreinput()) {
2064+ n = 0;
2065+ targets = NULL;
2066+
2067+ next();
2068+ if (tok == '\n')
2069+ continue;
2070+
2071+ while (tok == ITEM) {
2072+ n++;
2073+ targets = erealloc(targets, n * sizeof(char *));
2074+ targets[n-1] = estrdup(token);
2075+ next();
2076+ }
2077+
2078+ switch (tok) {
2079+ case ':':
2080+ rule(targets, n);
2081+ break;
2082+ case '=':
2083+ assign(targets, where, n);
2084+ break;
2085+ case '+':
2086+ assign_append(targets, where, n);
2087+ break;
2088+ case '!':
2089+ assign_shell(targets, where, n);
2090+ break;
2091+ default:
2092+ error("unexpected token '%s'(%d)", token, tok);
2093+ }
2094+
2095+ for (i = 0; i < n; i++)
2096+ free(targets[i]);
2097+ free(targets);
2098+ }
2099 }
2100
2101 int
2102 parse(char *fname)
2103 {
2104- FILE *fp;
2105+ FILE *fp;
2106
2107- if (!fname) {
2108- fp = stdin;
2109- fname = "<stdin>";
2110- } else if ((fp = fopen(fname, "r")) == NULL) {
2111- return 0;
2112- }
2113+ if (!fname) {
2114+ fp = stdin;
2115+ fname = "<stdin>";
2116+ } else if ((fp = fopen(fname, "r")) == NULL) {
2117+ return 0;
2118+ }
2119
2120- debug("parsing %s", fname);
2121- push(FTFILE, fp, fname, 0);
2122- parseinput(MAKEFILE);
2123+ debug("parsing %s", fname);
2124+ push(FTFILE, fp, fname, 0);
2125+ parseinput(MAKEFILE);
2126
2127- return 1;
2128+ return 1;
2129 }
2130
2131 void
2132 inject(char *s)
2133 {
2134- push(FTFILE, NULL, "<internal>", 0);
2135- push(FTEXPAN, s);
2136- parseinput(INTERNAL);
2137+ push(FTFILE, NULL, "<internal>", 0);
2138+ push(FTEXPAN, s);
2139+ parseinput(INTERNAL);
2140 }
+473,
-450
1@@ -14,554 +14,577 @@ static Target *htab[TABSIZ], *deftarget;
2 void
3 dumprules(void)
4 {
5- int i;
6- Target **pp, **q, *p;
7-
8- for (pp = htab; pp < &htab[TABSIZ]; ++pp) {
9- for (p = *pp; p; p = p->next) {
10- if (!p->defined)
11- continue;
12- printf("%s:", p->name);
13- for (q = p->deps; q && *q; ++q)
14- printf(" %s", (*q)->name);
15- putchar('\n');
16- for (i = 0; i < p->nactions; i++)
17- printf("\t%s\n", p->actions[i].line);
18- putchar('\n');
19- }
20- }
21+ int i;
22+ Target **pp, **q, *p;
23+
24+ for (pp = htab; pp < &htab[TABSIZ]; ++pp) {
25+ for (p = *pp; p; p = p->next) {
26+ if (!p->defined)
27+ continue;
28+ printf("%s:", p->name);
29+ for (q = p->deps; q && *q; ++q)
30+ printf(" %s", (*q)->name);
31+ putchar('\n');
32+ for (i = 0; i < p->nactions; i++)
33+ printf("\t%s\n", p->actions[i].line);
34+ putchar('\n');
35+ }
36+ }
37 }
38
39 static Target *
40 lookup(char *name)
41 {
42- Target *tp;
43- int h = hash(name) & (TABSIZ-1);
44-
45- for (tp = htab[h]; tp && strcmp(tp->name, name); tp = tp->next)
46- ;
47-
48- if (tp)
49- return tp;
50-
51- tp = emalloc(sizeof(*tp));
52- tp->name = estrdup(name);
53- tp->target = tp->name;
54- tp->req = NULL;
55- tp->ndeps = 0;
56- tp->deps = NULL;
57- tp->actions = NULL;
58- tp->nactions = 0;
59- tp->next = htab[h];
60- tp->defined = 0;
61- htab[h] = tp;
62-
63- return tp;
64+ Target *tp;
65+ int h = hash(name) & (TABSIZ-1);
66+
67+ for (tp = htab[h]; tp && strcmp(tp->name, name); tp = tp->next)
68+ ;
69+
70+ if (tp)
71+ return tp;
72+
73+ tp = emalloc(sizeof(*tp));
74+ tp->name = estrdup(name);
75+ tp->target = tp->name;
76+ tp->req = NULL;
77+ tp->ndeps = 0;
78+ tp->deps = NULL;
79+ tp->actions = NULL;
80+ tp->nactions = 0;
81+ tp->next = htab[h];
82+ tp->defined = 0;
83+ htab[h] = tp;
84+
85+ return tp;
86 }
87
88 static void
89 cleanup(Target *tp)
90 {
91- int sig, precious;
92- Target *p, **q;
93-
94- sig = stop;
95- printf("make: signal %d arrived\n", sig);
96-
97- precious = 0;
98- p = lookup(".PRECIOUS");
99- for (q = p->deps; q && *q; q++) {
100- if (strcmp((*q)->name, tp->name) == 0) {
101- precious = 1;
102- break;
103- }
104- }
105-
106- if (!precious && !nflag && !qflag && !is_dir(tp->name)) {
107- printf("make: trying to remove target %s\n", tp->name);
108- remove(tp->name);
109- }
110-
111- signal(sig, SIG_DFL);
112- raise(sig);
113+ int sig, precious;
114+ Target *p, **q;
115+
116+ sig = stop;
117+ printf("make: signal %d arrived\n", sig);
118+
119+ precious = 0;
120+ p = lookup(".PRECIOUS");
121+ for (q = p->deps; q && *q; q++) {
122+ if (strcmp((*q)->name, tp->name) == 0) {
123+ precious = 1;
124+ break;
125+ }
126+ }
127+
128+ if (!precious && !nflag && !qflag && !is_dir(tp->name)) {
129+ printf("make: trying to remove target %s\n", tp->name);
130+ remove(tp->name);
131+ }
132+
133+ signal(sig, SIG_DFL);
134+ raise(sig);
135 }
136
137 static int
138 depends(char *target, char *dep)
139 {
140- Target **p, *tp = lookup(target);
141+ Target **p, *tp = lookup(target);
142
143- for (p = tp->deps; p && *p; ++p) {
144- if (strcmp((*p)->name, dep) == 0)
145- return 1;
146- }
147+ for (p = tp->deps; p && *p; ++p) {
148+ if (strcmp((*p)->name, dep) == 0)
149+ return 1;
150+ }
151
152- return 0;
153+ return 0;
154 }
155
156 void
157 addtarget(char *target, int ndeps)
158 {
159- Target *tp = lookup(target);
160-
161- tp->defined = 1;
162- if (!deftarget && target[0] != '.') {
163- deftarget = tp;
164- return;
165- }
166-
167- if (strcmp(target, ".SUFFIXES") == 0 && ndeps == 0) {
168- free(tp->deps);
169- tp->deps = NULL;
170- tp->ndeps = 0;
171- return;
172- }
173-
174- if (strcmp(target, ".DEFAULT") == 0) {
175- if (ndeps > 0)
176- error("DEFAULT rule with prerequisites");
177- return;
178- }
179-
180- if (strcmp(target, ".SILENT") == 0 && ndeps == 0) {
181- sflag = 1;
182- return;
183- }
184-
185- if (strcmp(target, ".IGNORE") == 0 && ndeps == 0) {
186- iflag = 1;
187- return;
188- }
189+ Target *tp = lookup(target);
190+
191+ tp->defined = 1;
192+ if (!deftarget && target[0] != '.') {
193+ deftarget = tp;
194+ return;
195+ }
196+
197+ if (strcmp(target, ".SUFFIXES") == 0 && ndeps == 0) {
198+ free(tp->deps);
199+ tp->deps = NULL;
200+ tp->ndeps = 0;
201+ return;
202+ }
203+
204+ if (strcmp(target, ".DEFAULT") == 0) {
205+ if (ndeps > 0)
206+ error("DEFAULT rule with prerequisites");
207+ return;
208+ }
209+
210+ if (strcmp(target, ".SILENT") == 0 && ndeps == 0) {
211+ sflag = 1;
212+ return;
213+ }
214+
215+ if (strcmp(target, ".IGNORE") == 0 && ndeps == 0) {
216+ iflag = 1;
217+ return;
218+ }
219+
220+ /* .PHONY */
221+ if (strcmp(target, ".PHONY") == 0) {
222+ if (ndeps == 0) {
223+ free(tp->deps);
224+ tp->deps = NULL;
225+ tp->ndeps = 0;
226+ }
227+ return;
228+ }
229 }
230
231 void
232 adddep(char *target, char *dep)
233 {
234- size_t siz;
235- Target **p, *tp = lookup(target);
236-
237- if (depends(dep, target)) {
238- warning("circular dependency %s <- %s dropped", target, dep);
239- return;
240- }
241-
242- for (p = tp->deps; p && *p; ++p) {
243- if (strcmp((*p)->name, dep) == 0)
244- return;
245- }
246-
247- tp->ndeps++;
248- siz = (tp->ndeps + 1) * sizeof(Target *);
249- tp->deps = erealloc(tp->deps, siz);
250- tp->deps[tp->ndeps-1] = lookup(dep);
251- tp->deps[tp->ndeps] = NULL;
252-
253- debug("adding dependency %s <- %s", target, dep);
254+ size_t siz;
255+ Target **p, *tp = lookup(target);
256+
257+ if (depends(dep, target)) {
258+ warning("circular dependency %s <- %s dropped", target, dep);
259+ return;
260+ }
261+
262+ for (p = tp->deps; p && *p; ++p) {
263+ if (strcmp((*p)->name, dep) == 0)
264+ return;
265+ }
266+
267+ tp->ndeps++;
268+ siz = (tp->ndeps + 1) * sizeof(Target *);
269+ tp->deps = erealloc(tp->deps, siz);
270+ tp->deps[tp->ndeps-1] = lookup(dep);
271+ tp->deps[tp->ndeps] = NULL;
272+
273+ debug("adding dependency %s <- %s", target, dep);
274 }
275
276 static void
277 freeaction(struct action *act)
278 {
279- free(act->line);
280- freeloc(&act->loc);
281+ free(act->line);
282+ freeloc(&act->loc);
283 }
284
285 void
286 addrule(char *target, struct action *acts, int n)
287 {
288- int i;
289- struct action *v;
290- Target *tp = lookup(target);
291-
292- debug("adding actions for target %s", target);
293-
294- if (tp->actions) {
295- debug("overring actions of target %s", target);
296- for (i = 0; i < tp->nactions; i++)
297- freeaction(&tp->actions[i]);
298- free(tp->actions);
299- }
300-
301- v = emalloc(n * sizeof(*v));
302- for (i = 0; i < n; i++) {
303- v[i].line = estrdup(acts[i].line);
304- v[i].loc.lineno = acts[i].loc.lineno;
305- v[i].loc.fname = estrdup(acts[i].loc.fname);
306- }
307-
308- tp->nactions = n;
309- tp->actions = v;
310+ int i;
311+ struct action *v;
312+ Target *tp = lookup(target);
313+
314+ debug("adding actions for target %s", target);
315+
316+ if (tp->actions) {
317+ debug("overring actions of target %s", target);
318+ for (i = 0; i < tp->nactions; i++)
319+ freeaction(&tp->actions[i]);
320+ free(tp->actions);
321+ }
322+
323+ v = emalloc(n * sizeof(*v));
324+ for (i = 0; i < n; i++) {
325+ v[i].line = estrdup(acts[i].line);
326+ v[i].loc.lineno = acts[i].loc.lineno;
327+ v[i].loc.fname = estrdup(acts[i].loc.fname);
328+ }
329+
330+ tp->nactions = n;
331+ tp->actions = v;
332 }
333
334 static int
335 execline(Target *tp, char *line, int ignore, int silence)
336 {
337- char *s, *t;
338- int r, at, plus, minus, l;
339-
340- (void)tp;
341-
342- debug("executing '%s'", line);
343-
344- at = plus = minus = 0;
345- for (s = line; ; s++) {
346- switch (*s) {
347- case '@':
348- at = 1;
349- break;
350- case '-':
351- minus = 1;
352- break;
353- case '+':
354- plus = 1;
355- break;
356- default:
357- goto out_loop;
358- }
359- }
360+ char *s, *t;
361+ int r, at, plus, minus, l;
362+
363+ (void)tp;
364+
365+ debug("executing '%s'", line);
366+
367+ at = plus = minus = 0;
368+ for (s = line; ; s++) {
369+ switch (*s) {
370+ case '@':
371+ at = 1;
372+ break;
373+ case '-':
374+ minus = 1;
375+ break;
376+ case '+':
377+ plus = 1;
378+ break;
379+ default:
380+ goto out_loop;
381+ }
382+ }
383
384 out_loop:
385- /* unescape $$ */
386- for (l = strlen(s)+1, t = s; *t; --l, ++t) {
387- if (t[0] == '$' && t[1] == '$') {
388- memmove(t+1, t+2, l-2);
389- l--;
390- }
391- }
392-
393- if (tflag && !plus)
394- return 0;
395-
396- if (sflag || silence || (qflag && !plus))
397- at = 1;
398- if (nflag)
399- at = 0;
400- if (!at) {
401- puts(s);
402- fflush(stdout);
403- }
404-
405- if ((nflag || qflag) && !plus) {
406- if (qflag)
407- exitstatus = 1;
408- return 0;
409- }
410-
411- if (minus || iflag || ignore)
412- ignore = 1;
413-
414- r = launch(s, ignore);
415- if (ignore)
416- return 0;
417-
418- return r;
419+ /* unescape $$ */
420+ for (l = strlen(s)+1, t = s; *t; --l, ++t) {
421+ if (t[0] == '$' && t[1] == '$') {
422+ memmove(t+1, t+2, l-2);
423+ l--;
424+ }
425+ }
426+
427+ if (tflag && !plus)
428+ return 0;
429+
430+ if (sflag || silence || (qflag && !plus))
431+ at = 1;
432+ if (nflag)
433+ at = 0;
434+ if (!at) {
435+ puts(s);
436+ fflush(stdout);
437+ }
438+
439+ if ((nflag || qflag) && !plus) {
440+ if (qflag)
441+ exitstatus = 1;
442+ return 0;
443+ }
444+
445+ if (minus || iflag || ignore)
446+ ignore = 1;
447+
448+ r = launch(s, ignore);
449+ if (ignore)
450+ return 0;
451+
452+ return r;
453 }
454
455 static int
456 touch(char *name, int ignore, int silence)
457 {
458- char *cmd;
459- int r, n;
460+ char *cmd;
461+ int r, n;
462
463- n = snprintf(NULL, 0, "touch %s", name) + 1;
464- cmd = emalloc(n);
465- snprintf(cmd, n, "touch %s", name);
466+ n = snprintf(NULL, 0, "touch %s", name) + 1;
467+ cmd = emalloc(n);
468+ snprintf(cmd, n, "touch %s", name);
469
470- if (!sflag && !silence)
471- puts(cmd);
472+ if (!sflag && !silence)
473+ puts(cmd);
474
475- r = system(cmd);
476- free(cmd);
477+ r = wsystem(cmd);
478+ free(cmd);
479
480- if (ignore || iflag)
481- return 0;
482+ if (ignore || iflag)
483+ return 0;
484
485- return r;
486+ return r;
487 }
488
489 static int
490 touchdeps(Target *tp, int ignore, int silent)
491 {
492- int r;
493- Target **p;
494-
495- if (tp->req) {
496- r = touch(tp->req, silent, ignore);
497- if (r)
498- return r;
499- }
500-
501- for (p = tp->deps; p && *p; ++p) {
502- r = touch((*p)->name, silent, ignore);
503- if (r)
504- return r;
505- }
506-
507- return 0;
508+ int r;
509+ Target **p;
510+
511+ if (tp->req) {
512+ r = touch(tp->req, silent, ignore);
513+ if (r)
514+ return r;
515+ }
516+
517+ for (p = tp->deps; p && *p; ++p) {
518+ r = touch((*p)->name, silent, ignore);
519+ if (r)
520+ return r;
521+ }
522+
523+ return 0;
524 }
525
526 static int
527 run(Target *tp)
528 {
529- int r, i, ignore, silent;
530- char *s;
531- Target *p, **q;
532-
533- silent = 0;
534- p = lookup(".SILENT");
535- for (q = p->deps; q && *q; ++q) {
536- if (strcmp((*q)->name, tp->name) == 0) {
537- debug("target %s error silent by .SILENT", tp->name);
538- silent = 1;
539- }
540- }
541-
542- ignore = 0;
543- p = lookup(".IGNORE");
544- for (q = p->deps; q && *q; ++q) {
545- if (strcmp((*q)->name, tp->name) == 0) {
546- debug("target %s error ignored by .IGNORE", tp->name);
547- ignore = 1;
548- }
549- }
550-
551- if (tflag) {
552- r = touchdeps(tp, ignore, silent);
553- if (r)
554- return r;
555- }
556-
557- for (i = 0; i < tp->nactions; i++) {
558- struct action *p;
559-
560- if (stop)
561- cleanup(tp);
562-
563- p = &tp->actions[i];
564- debug("executing action '%s'", p->line);
565- s = expandstring(p->line, tp, &p->loc);
566- r = execline(tp, s, ignore, silent);
567- free(s);
568-
569- if (r)
570- return r;
571- }
572-
573- if (tflag) {
574- r = touch(tp->target, ignore, silent);
575- if (r)
576- return r;
577- }
578-
579- return 0;
580+ int r, i, ignore, silent;
581+ char *s;
582+ Target *p, **q;
583+
584+ silent = 0;
585+ p = lookup(".SILENT");
586+ for (q = p->deps; q && *q; ++q) {
587+ if (strcmp((*q)->name, tp->name) == 0) {
588+ debug("target %s error silent by .SILENT", tp->name);
589+ silent = 1;
590+ }
591+ }
592+
593+ ignore = 0;
594+ p = lookup(".IGNORE");
595+ for (q = p->deps; q && *q; ++q) {
596+ if (strcmp((*q)->name, tp->name) == 0) {
597+ debug("target %s error ignored by .IGNORE", tp->name);
598+ ignore = 1;
599+ }
600+ }
601+
602+ if (tflag) {
603+ r = touchdeps(tp, ignore, silent);
604+ if (r)
605+ return r;
606+ }
607+
608+ for (i = 0; i < tp->nactions; i++) {
609+ struct action *p;
610+
611+ if (stop)
612+ cleanup(tp);
613+
614+ p = &tp->actions[i];
615+ debug("executing action '%s'", p->line);
616+ s = expandstring(p->line, tp, &p->loc);
617+ r = execline(tp, s, ignore, silent);
618+ free(s);
619+
620+ if (r)
621+ return r;
622+ }
623+
624+ if (tflag) {
625+ r = touch(tp->target, ignore, silent);
626+ if (r)
627+ return r;
628+ }
629+
630+ return 0;
631 }
632
633 static int
634 enabled(char *suffix)
635 {
636- Target **p, *tp = lookup(".SUFFIXES");
637+ Target **p, *tp = lookup(".SUFFIXES");
638
639- for (p = tp->deps; p && *p; ++p) {
640- if (strcmp(suffix, (*p)->name) == 0)
641- return 1;
642- }
643+ for (p = tp->deps; p && *p; ++p) {
644+ if (strcmp(suffix, (*p)->name) == 0)
645+ return 1;
646+ }
647
648- return 0;
649+ return 0;
650 }
651
652 static Target *
653 inference(Target *tp, int force)
654 {
655- time_t t;
656- int tolen, r;
657- char *to, *from;
658- Target *q, **p, *suffixes;
659- char buf[FILENAME_MAX], fname[FILENAME_MAX];
660-
661- debug("searching an inference rule for %s", tp->name);
662-
663- to = strrchr(tp->name, '.');
664- if (to && !enabled(to))
665- return NULL;
666- tolen = to ? (int)(to - tp->name) : (int)strlen(tp->name);
667-
668- if (!to)
669- to = "";
670-
671- suffixes = lookup(".SUFFIXES");
672- for (p = suffixes->deps; p && *p; ++p) {
673- from = (*p)->name;
674- debug("trying suffix %s", from);
675-
676- r = snprintf(buf,
677- sizeof(buf),
678- "%s%s",
679- from, to);
680-
681- if (r < 0 || (size_t)r >= sizeof(buf))
682- error("suffixes too long %s %s", from, to);
683-
684- q = lookup(buf);
685- if (!q->actions)
686- continue;
687-
688- r = snprintf(fname,
689- sizeof(fname),
690- "%*.*s%s",
691- tolen, tolen, tp->name, from);
692-
693- if (r < 0 || (size_t)r >= sizeof(fname)) {
694- error("prerequisite name too long %s %s",
695- tp->name, from);
696- }
697-
698- debug("\tsearching prerequisite %s", fname);
699-
700- t = stamp(fname);
701- if (t == -1) {
702- debug("\tprerequisite %s not found", fname);
703- continue;
704- }
705-
706- if (!force && t <= tp->stamp) {
707- debug("\tdiscarded because is newer");
708- debug("\t%s: %s", tp->name, ctime(&tp->stamp));
709- debug("\t%s: %s", fname, ctime(&t));
710- continue;
711- }
712-
713- free(q->req);
714- q->req = estrdup(fname);
715- q->deps = tp->deps;
716- q->target = tp->name;
717- q->stamp = tp->stamp;
718-
719- debug("using inference rule %s with %s", q->name, fname);
720- return q;
721- }
722-
723- return NULL;
724+ time_t t;
725+ int tolen, r;
726+ char *to, *from;
727+ Target *q, **p, *suffixes;
728+ char buf[FILENAME_MAX], fname[FILENAME_MAX];
729+
730+ debug("searching an inference rule for %s", tp->name);
731+
732+ to = strrchr(tp->name, '.');
733+ if (to && !enabled(to))
734+ return NULL;
735+ tolen = to ? (int)(to - tp->name) : (int)strlen(tp->name);
736+
737+ if (!to)
738+ to = "";
739+
740+ suffixes = lookup(".SUFFIXES");
741+ for (p = suffixes->deps; p && *p; ++p) {
742+ from = (*p)->name;
743+ debug("trying suffix %s", from);
744+
745+ r = snprintf(buf,
746+ sizeof(buf),
747+ "%s%s",
748+ from, to);
749+
750+ if (r < 0 || (size_t)r >= sizeof(buf))
751+ error("suffixes too long %s %s", from, to);
752+
753+ q = lookup(buf);
754+ if (!q->actions)
755+ continue;
756+
757+ r = snprintf(fname,
758+ sizeof(fname),
759+ "%*.*s%s",
760+ tolen, tolen, tp->name, from);
761+
762+ if (r < 0 || (size_t)r >= sizeof(fname)) {
763+ error("prerequisite name too long %s %s",
764+ tp->name, from);
765+ }
766+
767+ debug("\tsearching prerequisite %s", fname);
768+
769+ t = stamp(fname);
770+ if (t == -1) {
771+ debug("\tprerequisite %s not found", fname);
772+ continue;
773+ }
774+
775+ if (!force && t <= tp->stamp) {
776+ debug("\tdiscarded because is newer");
777+ debug("\t%s: %s", tp->name, ctime(&tp->stamp));
778+ debug("\t%s: %s", fname, ctime(&t));
779+ continue;
780+ }
781+
782+ free(q->req);
783+ q->req = estrdup(fname);
784+ q->deps = tp->deps;
785+ q->target = tp->name;
786+ q->stamp = tp->stamp;
787+
788+ debug("using inference rule %s with %s", q->name, fname);
789+ return q;
790+ }
791+
792+ return NULL;
793 }
794
795 static int
796 update(Target *tp)
797 {
798- Target *p;
799+ Target *p;
800
801- debug("%s needs to be updated", tp->name);
802+ debug("%s needs to be updated", tp->name);
803
804- if (tp->actions) {
805- debug("using target rule to build %s", tp->name);
806- return run(tp);
807- }
808+ if (tp->actions) {
809+ debug("using target rule to build %s", tp->name);
810+ return run(tp);
811+ }
812
813- if ((p = inference(tp, FORCE)) != NULL) {
814- debug("using inference rule %s", p->name);
815- return run(p);
816- }
817+ if ((p = inference(tp, FORCE)) != NULL) {
818+ debug("using inference rule %s", p->name);
819+ return run(p);
820+ }
821
822- p = lookup(".DEFAULT");
823- if (p->defined) {
824- debug("using default rule");
825- return run(p);
826- }
827+ p = lookup(".DEFAULT");
828+ if (p->defined) {
829+ debug("using default rule");
830+ return run(p);
831+ }
832
833- debug("not rule found to update %s", tp->name);
834+ debug("not rule found to update %s", tp->name);
835
836- if (!tp->defined)
837- error("don't know how to make %s", tp->name);
838+ if (!tp->defined)
839+ error("don't know how to make %s", tp->name);
840
841- return 0;
842+ return 0;
843 }
844
845-static int
846+static int
847+is_phony(Target *tp)
848+{
849+ Target **p, *ph = lookup(".PHONY");
850+ for (p = ph->deps; p && *p; ++p)
851+ if (strcmp((*p)->name, tp->name) == 0)
852+ return 1;
853+ return 0;
854+}
855+
856+static int
857 rebuild(Target *tp, int *buildp)
858 {
859- Target **p, *q;
860- int r, need, build, err, def;
861-
862- debug("checking rebuild of %s", tp->name);
863-
864- tp->stamp = stamp(tp->name);
865-
866- def = err = need = 0;
867- for (p = tp->deps; p && *p; ++p) {
868- if (stop)
869- cleanup(tp);
870-
871- q = *p;
872- debug("checking dependency %s", q->name);
873-
874- if (strcmp(q->name, tp->name) == 0 && q->actions)
875- def = 1;
876-
877- build = 0;
878- if (rebuild(q, &build) != 0) {
879- err = 1;
880- continue;
881- }
882-
883- if (build) {
884- debug("rebuild of %s forces rebuild of %s",
885- q->name, tp->name);
886- need = 1;
887- } else if (q->stamp > tp->stamp) {
888- debug("dependency %s is newer than %s",
889- q->name, tp->name);
890- need = 1;
891- }
892- }
893-
894- if (tp->stamp == -1) {
895- need = 1;
896- } else if (!def) {
897- debug("no action found for %s, looking a inference rule",
898- tp->name);
899- if (inference(tp, NOFORCE))
900- need = 1;
901- }
902-
903- if (err) {
904- warning("target %s not remade because of errors", tp->name);
905- return 1;
906- } else if (need) {
907- *buildp = 1;
908-
909- debug("target %s needs updating", tp->name);
910- r = update(tp);
911- if (r == 0)
912- return 0;
913-
914- if (stop)
915- cleanup(tp);
916-
917- exitstatus = 1;
918-
919- if (!kflag)
920- error("target %s: error %d", tp->name, r);
921- else
922- warning("target %s: error %d", tp->name, r);
923- return r;
924- }
925-
926- return 0;
927+ Target **p, *q;
928+ int r, need, build, err, def;
929+
930+ debug("checking rebuild of %s", tp->name);
931+
932+ if (is_phony(tp))
933+ tp->stamp = -1;
934+ else
935+ tp->stamp = stamp(tp->name);
936+
937+ def = err = need = 0;
938+ for (p = tp->deps; p && *p; ++p) {
939+ if (stop)
940+ cleanup(tp);
941+
942+ q = *p;
943+ debug("checking dependency %s", q->name);
944+
945+ if (strcmp(q->name, tp->name) == 0 && q->actions)
946+ def = 1;
947+
948+ build = 0;
949+ if (rebuild(q, &build) != 0) {
950+ err = 1;
951+ continue;
952+ }
953+
954+ if (build) {
955+ debug("rebuild of %s forces rebuild of %s",
956+ q->name, tp->name);
957+ need = 1;
958+ } else if (q->stamp > tp->stamp) {
959+ debug("dependency %s is newer than %s",
960+ q->name, tp->name);
961+ need = 1;
962+ }
963+ }
964+
965+ if (tp->stamp == -1) {
966+ need = 1;
967+ } else if (!def) {
968+ debug("no action found for %s, looking a inference rule",
969+ tp->name);
970+ if (inference(tp, NOFORCE))
971+ need = 1;
972+ }
973+
974+ if (err) {
975+ warning("target %s not remade because of errors", tp->name);
976+ return 1;
977+ } else if (need) {
978+ *buildp = 1;
979+
980+ debug("target %s needs updating", tp->name);
981+ r = update(tp);
982+ if (r == 0)
983+ return 0;
984+
985+ if (stop)
986+ cleanup(tp);
987+
988+ exitstatus = 1;
989+
990+ if (!kflag)
991+ error("target %s: error %d", tp->name, r);
992+ else
993+ warning("target %s: error %d", tp->name, r);
994+ return r;
995+ }
996+
997+ return 0;
998 }
999
1000 int
1001 build(char *name)
1002 {
1003- int build;
1004+ int build;
1005
1006- if (!name) {
1007- if (!deftarget) {
1008- printf("make: no target to make\n");
1009- return 0;
1010- }
1011- name = deftarget->name;
1012- }
1013+ if (!name) {
1014+ if (!deftarget) {
1015+ printf("make: no target to make\n");
1016+ return 0;
1017+ }
1018+ name = deftarget->name;
1019+ }
1020
1021- debug("checking target %s", name);
1022+ debug("checking target %s", name);
1023
1024- build = 0;
1025- return rebuild(lookup(name), &build);
1026+ build = 0;
1027+ return rebuild(lookup(name), &build);
1028 }
+3,
-2
1@@ -7,6 +7,7 @@
2 #include <stdlib.h>
3 #include <unistd.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 #ifndef PRIO_MIN
9@@ -54,9 +55,9 @@ main(int argc, char *argv[])
10 if (setpriority(PRIO_PROCESS, 0, val) < 0)
11 weprintf("setpriority:");
12
13- execvp(argv[0], argv);
14+ wexecvp_self(argv[0], argv);
15 savederrno = errno;
16- weprintf("execvp %s:", argv[0]);
17+ weprintf("wexecvp %s:", argv[0]);
18
19 _exit(126 + (savederrno == ENOENT));
20 }
+3,
-2
1@@ -8,6 +8,7 @@
2 #include <signal.h>
3 #include <unistd.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 static void
9@@ -45,9 +46,9 @@ main(int argc, char *argv[])
10 if (isatty(STDERR_FILENO) && dup2(STDOUT_FILENO, STDERR_FILENO) < 0)
11 enprintf(127, "dup2:");
12
13- execvp(argv[0], argv);
14+ wexecvp_self(argv[0], argv);
15 savederrno = errno;
16- weprintf("execvp %s:", argv[0]);
17+ weprintf("wexecvp %s:", argv[0]);
18
19 _exit(126 + (savederrno == ENOENT));
20 }
+2407,
-2438
1@@ -1,4 +1,6 @@
2 /* See LICENSE file for copyright and license details. */
3+#include "wexec.h"
4+#include "paths.h"
5 #include "util.h"
6
7 #include <sys/file.h>
8@@ -9,13 +11,11 @@
9
10 #include <ctype.h>
11 #include <dirent.h>
12-#include <err.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <getopt.h>
16 #include <libgen.h>
17 #include <limits.h>
18-#include <paths.h>
19 #include <stdarg.h>
20 #include <stddef.h>
21 #include <stdint.h>
22@@ -37,8 +37,8 @@
23 #define SCCSDIFF "get -p %s | diff - %s >/dev/null"
24
25 #define RCSSUFFIX ",v"
26-#define CHECKOUT "/usr/bin/co"
27-#define RCSDIFF "/usr/bin/rcsdiff"
28+#define CHECKOUT "co"
29+#define RCSDIFF "rcsdiff"
30
31 #define ORIGEXT ".orig"
32 #define REJEXT ".rej"
33@@ -59,7 +59,7 @@
34 #define NEW_CONTEXT_DIFF 4
35 #define UNI_DIFF 5
36
37-#define _PATH_ED "/bin/ed"
38+#define _PATH_ED "ed"
39
40 #define ISDIGIT(c) (isascii((unsigned char)c) && isdigit((unsigned char)c))
41
42@@ -74,16 +74,16 @@
43 typedef long LINENUM;
44
45 enum BackupType {
46- BACKUP_UNDEFINED,
47- BACKUP_NONE,
48- BACKUP_SIMPLE,
49- BACKUP_NUMBERED_EXISTING,
50- BACKUP_NUMBERED
51+ BACKUP_UNDEFINED,
52+ BACKUP_NONE,
53+ BACKUP_SIMPLE,
54+ BACKUP_NUMBERED_EXISTING,
55+ BACKUP_NUMBERED
56 };
57
58 struct FileName {
59- char *path;
60- int exists;
61+ char *path;
62+ int exists;
63 };
64
65 mode_t filemode = 0644;
66@@ -154,7 +154,6 @@ static void reinitialize_almost_everything(void);
67 static void get_some_switches(void);
68 static void reset_getopt_state(void);
69 static LINENUM locate_hunk(LINENUM);
70-static void abort_context_hunk(void);
71 static void rej_line(int, LINENUM);
72 static void abort_hunk(void);
73 static void apply_hunk(LINENUM);
74@@ -162,7 +161,6 @@ static void init_output(const char *);
75 static void init_reject(const char *);
76 static void copy_till(LINENUM, int);
77 static int spew_output(void);
78-static void dump_patch_line(LINENUM, int);
79 static void dump_input_line(LINENUM, int);
80 static int patch_match(LINENUM, LINENUM, LINENUM);
81 static int similar(const char *, const char *, ssize_t);
82@@ -268,11 +266,11 @@ static int argmatch(const char *, const char **);
83 static void invalid_arg(const char *, const char *, int);
84
85 static const char *backup_args[] = {
86- "none", "never", "simple", "nil", "existing", "t", "numbered", 0
87+ "none", "never", "simple", "nil", "existing", "t", "numbered", 0
88 };
89 static enum BackupType backup_types[] = {
90- BACKUP_NONE, BACKUP_SIMPLE, BACKUP_SIMPLE, BACKUP_NUMBERED_EXISTING,
91- BACKUP_NUMBERED_EXISTING, BACKUP_NUMBERED, BACKUP_NUMBERED
92+ BACKUP_NONE, BACKUP_SIMPLE, BACKUP_SIMPLE, BACKUP_NUMBERED_EXISTING,
93+ BACKUP_NUMBERED_EXISTING, BACKUP_NUMBERED, BACKUP_NUMBERED
94 };
95
96 /* implementation */
97@@ -281,675 +279,660 @@ static enum BackupType backup_types[] = {
98 int
99 main(int argc, char *argv[])
100 {
101- int error, hunk, failed, i, fd;
102- LINENUM where, newwhere, fuzz, mymaxfuzz;
103- const char *tmpdir;
104- char *v;
105-
106- error = 0;
107- where = 0;
108- bufsz = INITLINELEN;
109- if ((buf = malloc(bufsz)) == NULL)
110- pfatal("allocating input buffer");
111- buf[0] = '\0';
112-
113- setbuf(stderr, serrbuf);
114- for (i = 0; i < MAXFILEC; i++)
115- filearg[i] = NULL;
116-
117- if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
118- tmpdir = _PATH_TMP;
119- for (i = strlen(tmpdir) - 1; i > 0 && tmpdir[i] == '/'; i--)
120- ;
121- i++;
122- if (asprintf(&TMPOUTNAME, "%.*s/patchoXXXXXXXXXX", i, tmpdir) == -1)
123- fatal("cannot allocate memory");
124- if ((fd = mkstemp(TMPOUTNAME)) < 0)
125- pfatal("cant create %s", TMPOUTNAME);
126- close(fd);
127-
128- if (asprintf(&TMPINNAME, "%.*s/patchiXXXXXXXXXX", i, tmpdir) == -1)
129- fatal("cannot allocate memory");
130- if ((fd = mkstemp(TMPINNAME)) < 0)
131- pfatal("cant create %s", TMPINNAME);
132- close(fd);
133-
134- if (asprintf(&TMPREJNAME, "%.*s/patchrXXXXXXXXXX", i, tmpdir) == -1)
135- fatal("cannot allocate memory");
136- if ((fd = mkstemp(TMPREJNAME)) < 0)
137- pfatal("cant create %s", TMPREJNAME);
138- close(fd);
139-
140- if (asprintf(&TMPPATNAME, "%.*s/patchpXXXXXXXXXX", i, tmpdir) == -1)
141- fatal("cannot allocate memory");
142- if ((fd = mkstemp(TMPPATNAME)) < 0)
143- pfatal("cant create %s", TMPPATNAME);
144- close(fd);
145-
146- v = getenv("SIMPLE_BACKUP_SUFFIX");
147- if (v)
148- simple_backup_suffix = v;
149- else
150- simple_backup_suffix = ORIGEXT;
151-
152- if ((v = getenv("PATCH_VERSION_CONTROL")) == NULL)
153- v = getenv("VERSION_CONTROL");
154- if (v != NULL)
155- backup_type = get_version(v);
156-
157- Argc = argc;
158- Argv = argv;
159- get_some_switches();
160-
161- if (backup_type == BACKUP_UNDEFINED)
162- backup_type = posix ? BACKUP_NONE : BACKUP_NUMBERED_EXISTING;
163-
164- set_signals(0);
165-
166- for (open_patch_file(filearg[1]); there_is_another_patch(); reinitialize_almost_everything()) {
167- warn_on_invalid_line = 1;
168- if (outname == NULL)
169- outname = savestr(filearg[0]);
170-
171- if (diff_type == ED_DIFF) {
172- do_ed_script();
173- continue;
174- }
175- if (!skip_rest_of_patch)
176- init_output(TMPOUTNAME);
177-
178- init_reject(TMPREJNAME);
179-
180- if (!skip_rest_of_patch)
181- scan_input(filearg[0]);
182-
183- hunk = 0;
184- failed = 0;
185- out_of_mem = 0;
186- while (another_hunk()) {
187- hunk++;
188- fuzz = 0;
189- mymaxfuzz = pch_context();
190- if (maxfuzz < mymaxfuzz)
191- mymaxfuzz = maxfuzz;
192- if (!skip_rest_of_patch) {
193- do {
194- where = locate_hunk(fuzz);
195- if (hunk == 1 && where == 0 && !force) {
196- if (!pch_swap()) {
197- if (fuzz == 0)
198- say("Not enough memory to try swapped hunk! Assuming unswapped.\n");
199- continue;
200- }
201- reverse = !reverse;
202- where = locate_hunk(fuzz);
203- if (where == 0) {
204- if (!pch_swap())
205- fatal("lost hunk on alloc error!\n");
206- reverse = !reverse;
207- } else if (noreverse) {
208- if (!pch_swap())
209- fatal("lost hunk on alloc error!\n");
210- reverse = !reverse;
211- say("Ignoring previously applied (or reversed) patch.\n");
212- skip_rest_of_patch = 1;
213- } else if (batch) {
214- if (verbose)
215- say("%seversed (or %spreviously applied) patch detected! %s -R.",
216- reverse ? "R" : "Unr",
217- reverse ? "" : "not ",
218- reverse ? "Assuming" : "Ignoring");
219- } else {
220- ask("%seversed (or %spreviously applied) patch detected! %s -R? [y] ",
221- reverse ? "R" : "Unr",
222- reverse ? "" : "not ",
223- reverse ? "Assume" : "Ignore");
224- if (*buf == 'n') {
225- ask("Apply anyway? [n] ");
226- if (*buf != 'y')
227- skip_rest_of_patch = 1;
228- where = 0;
229- reverse = !reverse;
230- if (!pch_swap())
231- fatal("lost hunk on alloc error!\n");
232- }
233- }
234- }
235- } while (!skip_rest_of_patch && where == 0 && ++fuzz <= mymaxfuzz);
236-
237- if (skip_rest_of_patch) {
238- if (ferror(ofp) || fclose(ofp)) {
239- say("Error writing %s\n", TMPOUTNAME);
240- error = 1;
241- }
242- ofp = NULL;
243- }
244- }
245- newwhere = pch_newfirst() + last_offset;
246- if (skip_rest_of_patch) {
247- abort_hunk();
248- failed++;
249- if (verbose)
250- say("Hunk #%d ignored at %ld.\n", hunk, newwhere);
251- } else if (where == 0) {
252- abort_hunk();
253- failed++;
254- if (verbose)
255- say("Hunk #%d failed at %ld.\n", hunk, newwhere);
256- } else {
257- apply_hunk(where);
258- if (verbose) {
259- say("Hunk #%d succeeded at %ld", hunk, newwhere);
260- if (fuzz != 0)
261- say(" with fuzz %ld", fuzz);
262- if (last_offset)
263- say(" (offset %ld line%s)", last_offset, last_offset == 1L ? "" : "s");
264- say(".\n");
265- }
266- }
267- }
268-
269- if (out_of_mem && using_plan_a) {
270- Argc = Argc_last;
271- Argv = Argv_last;
272- say("\n\nRan out of memory using Plan A--trying again...\n\n");
273- if (ofp)
274- fclose(ofp);
275- ofp = NULL;
276- if (rejfp)
277- fclose(rejfp);
278- rejfp = NULL;
279- continue;
280- }
281- if (hunk == 0)
282- fatal("internal error: hunk should not be 0\n");
283-
284- if (!skip_rest_of_patch && !spew_output()) {
285- say("cant write %s\n", TMPOUTNAME);
286- error = 1;
287- }
288-
289- ignore_signals();
290- if (!skip_rest_of_patch) {
291- struct stat statbuf;
292- char *realout = outname;
293-
294- if (!check_only) {
295- enum BackupType saved = backup_type;
296- if (failed > 0 && backup_if_mismatch > 0 && backup_type == BACKUP_NONE)
297- backup_type = BACKUP_SIMPLE;
298- if (move_file(TMPOUTNAME, outname) < 0) {
299- toutkeep = 1;
300- realout = TMPOUTNAME;
301- chmod(TMPOUTNAME, filemode);
302- } else
303- chmod(outname, filemode);
304- backup_type = saved;
305-
306- if (remove_empty_files && stat(realout, &statbuf) == 0 && statbuf.st_size == 0) {
307- if (verbose)
308- say("Removing %s (empty after patching).\n", realout);
309- unlink(realout);
310- }
311- }
312- }
313- if (ferror(rejfp) || fclose(rejfp)) {
314- say("Error writing %s\n", rejname);
315- error = 1;
316- }
317- rejfp = NULL;
318- if (failed) {
319- error = 1;
320- if (*rejname == '\0') {
321- if (strlcpy(rejname, outname, sizeof(rejname)) >= sizeof(rejname))
322- fatal("filename %s is too long\n", outname);
323- if (strlcat(rejname, REJEXT, sizeof(rejname)) >= sizeof(rejname))
324- fatal("filename %s is too long\n", outname);
325- }
326- if (skip_rest_of_patch) {
327- say("%d out of %d hunks ignored--saving rejects to %s\n", failed, hunk, rejname);
328- } else {
329- say("%d out of %d hunks FAILED -- saving rejects to %s\n", failed, hunk, rejname);
330- }
331- if (!check_only && move_file(TMPREJNAME, rejname) < 0)
332- trejkeep = 1;
333- }
334- set_signals(1);
335- }
336- my_exit(error);
337+ int error, hunk, failed, i, fd;
338+ LINENUM where, newwhere, fuzz, mymaxfuzz;
339+ const char *tmpdir;
340+ char *v;
341+
342+ error = 0;
343+ where = 0;
344+ bufsz = INITLINELEN;
345+ if ((buf = malloc(bufsz)) == NULL)
346+ pfatal("allocating input buffer");
347+ buf[0] = '\0';
348+
349+ setbuf(stderr, serrbuf);
350+ for (i = 0; i < MAXFILEC; i++)
351+ filearg[i] = NULL;
352+
353+ if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
354+ tmpdir = ARUU_PATH_TMP;
355+ for (i = strlen(tmpdir) - 1; i > 0 && tmpdir[i] == '/'; i--)
356+ ;
357+ i++;
358+ if (asprintf(&TMPOUTNAME, "%.*s/patchoXXXXXXXXXX", i, tmpdir) == -1)
359+ fatal("cannot allocate memory");
360+ if ((fd = mkstemp(TMPOUTNAME)) < 0)
361+ pfatal("cant create %s", TMPOUTNAME);
362+ close(fd);
363+
364+ if (asprintf(&TMPINNAME, "%.*s/patchiXXXXXXXXXX", i, tmpdir) == -1)
365+ fatal("cannot allocate memory");
366+ if ((fd = mkstemp(TMPINNAME)) < 0)
367+ pfatal("cant create %s", TMPINNAME);
368+ close(fd);
369+
370+ if (asprintf(&TMPREJNAME, "%.*s/patchrXXXXXXXXXX", i, tmpdir) == -1)
371+ fatal("cannot allocate memory");
372+ if ((fd = mkstemp(TMPREJNAME)) < 0)
373+ pfatal("cant create %s", TMPREJNAME);
374+ close(fd);
375+
376+ if (asprintf(&TMPPATNAME, "%.*s/patchpXXXXXXXXXX", i, tmpdir) == -1)
377+ fatal("cannot allocate memory");
378+ if ((fd = mkstemp(TMPPATNAME)) < 0)
379+ pfatal("cant create %s", TMPPATNAME);
380+ close(fd);
381+
382+ v = getenv("SIMPLE_BACKUP_SUFFIX");
383+ if (v)
384+ simple_backup_suffix = v;
385+ else
386+ simple_backup_suffix = ORIGEXT;
387+
388+ if ((v = getenv("PATCH_VERSION_CONTROL")) == NULL)
389+ v = getenv("VERSION_CONTROL");
390+ if (v != NULL)
391+ backup_type = get_version(v);
392+
393+ Argc = argc;
394+ Argv = argv;
395+ get_some_switches();
396+
397+ if (backup_type == BACKUP_UNDEFINED)
398+ backup_type = posix ? BACKUP_NONE : BACKUP_NUMBERED_EXISTING;
399+
400+ set_signals(0);
401+
402+ for (open_patch_file(filearg[1]); there_is_another_patch(); reinitialize_almost_everything()) {
403+ warn_on_invalid_line = 1;
404+ if (outname == NULL)
405+ outname = savestr(filearg[0]);
406+
407+ if (diff_type == ED_DIFF) {
408+ do_ed_script();
409+ continue;
410+ }
411+ if (!skip_rest_of_patch)
412+ init_output(TMPOUTNAME);
413+
414+ init_reject(TMPREJNAME);
415+
416+ if (!skip_rest_of_patch)
417+ scan_input(filearg[0]);
418+
419+ hunk = 0;
420+ failed = 0;
421+ out_of_mem = 0;
422+ while (another_hunk()) {
423+ hunk++;
424+ fuzz = 0;
425+ mymaxfuzz = pch_context();
426+ if (maxfuzz < mymaxfuzz)
427+ mymaxfuzz = maxfuzz;
428+ if (!skip_rest_of_patch) {
429+ do {
430+ where = locate_hunk(fuzz);
431+ if (hunk == 1 && where == 0 && !force) {
432+ if (!pch_swap()) {
433+ if (fuzz == 0)
434+ say("Not enough memory to try swapped hunk! Assuming unswapped.\n");
435+ continue;
436+ }
437+ reverse = !reverse;
438+ where = locate_hunk(fuzz);
439+ if (where == 0) {
440+ if (!pch_swap())
441+ fatal("lost hunk on alloc error!\n");
442+ reverse = !reverse;
443+ } else if (noreverse) {
444+ if (!pch_swap())
445+ fatal("lost hunk on alloc error!\n");
446+ reverse = !reverse;
447+ say("Ignoring previously applied (or reversed) patch.\n");
448+ skip_rest_of_patch = 1;
449+ } else if (batch) {
450+ if (verbose)
451+ say("%seversed (or %spreviously applied) patch detected! %s -R.",
452+ reverse ? "R" : "Unr",
453+ reverse ? "" : "not ",
454+ reverse ? "Assuming" : "Ignoring");
455+ } else {
456+ ask("%seversed (or %spreviously applied) patch detected! %s -R? [y] ",
457+ reverse ? "R" : "Unr",
458+ reverse ? "" : "not ",
459+ reverse ? "Assume" : "Ignore");
460+ if (*buf == 'n') {
461+ ask("Apply anyway? [n] ");
462+ if (*buf != 'y')
463+ skip_rest_of_patch = 1;
464+ where = 0;
465+ reverse = !reverse;
466+ if (!pch_swap())
467+ fatal("lost hunk on alloc error!\n");
468+ }
469+ }
470+ }
471+ } while (!skip_rest_of_patch && where == 0 && ++fuzz <= mymaxfuzz);
472+
473+ if (skip_rest_of_patch) {
474+ if (ferror(ofp) || fclose(ofp)) {
475+ say("Error writing %s\n", TMPOUTNAME);
476+ error = 1;
477+ }
478+ ofp = NULL;
479+ }
480+ }
481+ newwhere = pch_newfirst() + last_offset;
482+ if (skip_rest_of_patch) {
483+ abort_hunk();
484+ failed++;
485+ if (verbose)
486+ say("Hunk #%d ignored at %ld.\n", hunk, newwhere);
487+ } else if (where == 0) {
488+ abort_hunk();
489+ failed++;
490+ if (verbose)
491+ say("Hunk #%d failed at %ld.\n", hunk, newwhere);
492+ } else {
493+ apply_hunk(where);
494+ if (verbose) {
495+ say("Hunk #%d succeeded at %ld", hunk, newwhere);
496+ if (fuzz != 0)
497+ say(" with fuzz %ld", fuzz);
498+ if (last_offset)
499+ say(" (offset %ld line%s)", last_offset, last_offset == 1L ? "" : "s");
500+ say(".\n");
501+ }
502+ }
503+ }
504+
505+ if (out_of_mem && using_plan_a) {
506+ Argc = Argc_last;
507+ Argv = Argv_last;
508+ say("\n\nRan out of memory using Plan A--trying again...\n\n");
509+ if (ofp)
510+ fclose(ofp);
511+ ofp = NULL;
512+ if (rejfp)
513+ fclose(rejfp);
514+ rejfp = NULL;
515+ continue;
516+ }
517+ if (hunk == 0)
518+ fatal("internal error: hunk should not be 0\n");
519+
520+ if (!skip_rest_of_patch && !spew_output()) {
521+ say("cant write %s\n", TMPOUTNAME);
522+ error = 1;
523+ }
524+
525+ ignore_signals();
526+ if (!skip_rest_of_patch) {
527+ struct stat statbuf;
528+ char *realout = outname;
529+
530+ if (!check_only) {
531+ enum BackupType saved = backup_type;
532+ if (failed > 0 && backup_if_mismatch > 0 && backup_type == BACKUP_NONE)
533+ backup_type = BACKUP_SIMPLE;
534+ if (move_file(TMPOUTNAME, outname) < 0) {
535+ toutkeep = 1;
536+ realout = TMPOUTNAME;
537+ chmod(TMPOUTNAME, filemode);
538+ } else
539+ chmod(outname, filemode);
540+ backup_type = saved;
541+
542+ if (remove_empty_files && stat(realout, &statbuf) == 0 && statbuf.st_size == 0) {
543+ if (verbose)
544+ say("Removing %s (empty after patching).\n", realout);
545+ unlink(realout);
546+ }
547+ }
548+ }
549+ if (ferror(rejfp) || fclose(rejfp)) {
550+ say("Error writing %s\n", rejname);
551+ error = 1;
552+ }
553+ rejfp = NULL;
554+ if (failed) {
555+ error = 1;
556+ if (*rejname == '\0') {
557+ if (strlcpy(rejname, outname, sizeof(rejname)) >= sizeof(rejname))
558+ fatal("filename %s is too long\n", outname);
559+ if (strlcat(rejname, REJEXT, sizeof(rejname)) >= sizeof(rejname))
560+ fatal("filename %s is too long\n", outname);
561+ }
562+ if (skip_rest_of_patch) {
563+ say("%d out of %d hunks ignored--saving rejects to %s\n", failed, hunk, rejname);
564+ } else {
565+ say("%d out of %d hunks FAILED -- saving rejects to %s\n", failed, hunk, rejname);
566+ }
567+ if (!check_only && move_file(TMPREJNAME, rejname) < 0)
568+ trejkeep = 1;
569+ }
570+ set_signals(1);
571+ }
572+ my_exit(error);
573 }
574
575 static void
576 reset_getopt_state(void)
577 {
578 #if defined(__GLIBC__) || defined(__linux__)
579- optind = 0;
580+ optind = 0;
581 #else
582- optreset = 1;
583- optind = 1;
584+ optreset = 1;
585+ optind = 1;
586 #endif
587 }
588
589 static void
590 reinitialize_almost_everything(void)
591 {
592- re_patch();
593- re_input();
594-
595- input_lines = 0;
596- last_frozen_line = 0;
597- filec = 0;
598- if (!out_of_mem) {
599- free(filearg[0]);
600- filearg[0] = NULL;
601- }
602- free(outname);
603- outname = NULL;
604- last_offset = 0;
605- diff_type = 0;
606- free(revision);
607- revision = NULL;
608- reverse = reverse_flag_specified;
609- skip_rest_of_patch = 0;
610- get_some_switches();
611+ re_patch();
612+ re_input();
613+
614+ input_lines = 0;
615+ last_frozen_line = 0;
616+ filec = 0;
617+ if (!out_of_mem) {
618+ free(filearg[0]);
619+ filearg[0] = NULL;
620+ }
621+ free(outname);
622+ outname = NULL;
623+ last_offset = 0;
624+ diff_type = 0;
625+ free(revision);
626+ revision = NULL;
627+ reverse = reverse_flag_specified;
628+ skip_rest_of_patch = 0;
629+ get_some_switches();
630 }
631
632 static void
633 get_some_switches(void)
634 {
635- const char *options = "b::B:cCd:D:eEfF:i:lnNo:p:r:RstuvV:x:z:";
636- static struct option longopts[] = {
637- {"backup", no_argument, 0, 'b'},
638- {"backup-if-mismatch", no_argument, &backup_if_mismatch, 1},
639- {"batch", no_argument, 0, 't'},
640- {"check", no_argument, 0, 'C'},
641- {"context", no_argument, 0, 'c'},
642- {"debug", required_argument, 0, 'x'},
643- {"directory", required_argument, 0, 'd'},
644- {"ed", no_argument, 0, 'e'},
645- {"force", no_argument, 0, 'f'},
646- {"forward", no_argument, 0, 'N'},
647- {"fuzz", required_argument, 0, 'F'},
648- {"ifdef", required_argument, 0, 'D'},
649- {"input", required_argument, 0, 'i'},
650- {"ignore-whitespace", no_argument, 0, 'l'},
651- {"no-backup-if-mismatch", no_argument, &backup_if_mismatch, 0},
652- {"normal", no_argument, 0, 'n'},
653- {"output", required_argument, 0, 'o'},
654- {"prefix", required_argument, 0, 'B'},
655- {"quiet", no_argument, 0, 's'},
656- {"reject-file", required_argument, 0, 'r'},
657- {"remove-empty-files", no_argument, 0, 'E'},
658- {"reverse", no_argument, 0, 'R'},
659- {"silent", no_argument, 0, 's'},
660- {"strip", required_argument, 0, 'p'},
661- {"suffix", required_argument, 0, 'z'},
662- {"unified", no_argument, 0, 'u'},
663- {"version", no_argument, 0, 'v'},
664- {"version-control", required_argument, 0, 'V'},
665- {"posix", no_argument, &posix, 1},
666- {NULL, 0, 0, 0}
667- };
668- int ch;
669-
670- rejname[0] = '\0';
671- Argc_last = Argc;
672- Argv_last = Argv;
673- if (!Argc)
674- return;
675- reset_getopt_state();
676- while ((ch = getopt_long(Argc, Argv, options, longopts, NULL)) != -1) {
677- switch (ch) {
678- case 'b':
679- if (backup_type == BACKUP_UNDEFINED)
680- backup_type = BACKUP_NUMBERED_EXISTING;
681- if (optarg == NULL)
682- break;
683- if (verbose)
684- say("Warning, the -b suffix option has been obsoleted by the -z option\n");
685- /* FALLTHROUGH */
686- case 'z':
687- simple_backup_suffix = savestr(optarg);
688- break;
689- case 'B':
690- origprae = savestr(optarg);
691- break;
692- case 'c':
693- diff_type = CONTEXT_DIFF;
694- break;
695- case 'C':
696- check_only = 1;
697- break;
698- case 'd':
699- if (chdir(optarg) < 0)
700- pfatal("cant cd to %s", optarg);
701- break;
702- case 'D':
703- do_defines = 1;
704- if (!isalpha((unsigned char)*optarg) && *optarg != '_')
705- fatal("argument to -D is not an identifier\n");
706- snprintf(if_defined, sizeof if_defined, "#ifdef %s\n", optarg);
707- snprintf(not_defined, sizeof not_defined, "#ifndef %s\n", optarg);
708- snprintf(end_defined, sizeof end_defined, "#endif /* %s */\n", optarg);
709- break;
710- case 'e':
711- diff_type = ED_DIFF;
712- break;
713- case 'E':
714- remove_empty_files = 1;
715- break;
716- case 'f':
717- force = 1;
718- break;
719- case 'F':
720- maxfuzz = strtolinenum(optarg, NULL);
721- break;
722- case 'i':
723- free(filearg[1]);
724- filearg[1] = fetchname(optarg, &warn_on_invalid_line, 0);
725- break;
726- case 'l':
727- canonicalize = 1;
728- break;
729- case 'n':
730- diff_type = NORMAL_DIFF;
731- break;
732- case 'N':
733- noreverse = 1;
734- break;
735- case 'o':
736- outname = savestr(optarg);
737- break;
738- case 'p':
739- strippath = (int)strtolinenum(optarg, NULL);
740- break;
741- case 'r':
742- if (strlcpy(rejname, optarg, sizeof(rejname)) >= sizeof(rejname))
743- fatal("reject filename %s too long\n", optarg);
744- break;
745- case 'R':
746- reverse = 1;
747- reverse_flag_specified = 1;
748- break;
749- case 's':
750- verbose = 0;
751- break;
752- case 't':
753- batch = 1;
754- break;
755- case 'u':
756- diff_type = UNI_DIFF;
757- break;
758- case 'v':
759- version();
760- break;
761- case 'V':
762- backup_type = get_version(optarg);
763- break;
764- case 'x':
765+ const char *options = "b::B:cCd:D:eEfF:i:lnNo:p:r:RstuvV:x:z:";
766+ static struct option longopts[] = {
767+ {"backup", no_argument, 0, 'b'},
768+ {"backup-if-mismatch", no_argument, &backup_if_mismatch, 1},
769+ {"batch", no_argument, 0, 't'},
770+ {"check", no_argument, 0, 'C'},
771+ {"context", no_argument, 0, 'c'},
772+ {"debug", required_argument, 0, 'x'},
773+ {"directory", required_argument, 0, 'd'},
774+ {"ed", no_argument, 0, 'e'},
775+ {"force", no_argument, 0, 'f'},
776+ {"forward", no_argument, 0, 'N'},
777+ {"fuzz", required_argument, 0, 'F'},
778+ {"ifdef", required_argument, 0, 'D'},
779+ {"input", required_argument, 0, 'i'},
780+ {"ignore-whitespace", no_argument, 0, 'l'},
781+ {"no-backup-if-mismatch", no_argument, &backup_if_mismatch, 0},
782+ {"normal", no_argument, 0, 'n'},
783+ {"output", required_argument, 0, 'o'},
784+ {"prefix", required_argument, 0, 'B'},
785+ {"quiet", no_argument, 0, 's'},
786+ {"reject-file", required_argument, 0, 'r'},
787+ {"remove-empty-files", no_argument, 0, 'E'},
788+ {"reverse", no_argument, 0, 'R'},
789+ {"silent", no_argument, 0, 's'},
790+ {"strip", required_argument, 0, 'p'},
791+ {"suffix", required_argument, 0, 'z'},
792+ {"unified", no_argument, 0, 'u'},
793+ {"version", no_argument, 0, 'v'},
794+ {"version-control", required_argument, 0, 'V'},
795+ {"posix", no_argument, &posix, 1},
796+ {NULL, 0, 0, 0}
797+ };
798+ int ch;
799+
800+ rejname[0] = '\0';
801+ Argc_last = Argc;
802+ Argv_last = Argv;
803+ if (!Argc)
804+ return;
805+ reset_getopt_state();
806+ while ((ch = getopt_long(Argc, Argv, options, longopts, NULL)) != -1) {
807+ switch (ch) {
808+ case 'b':
809+ if (backup_type == BACKUP_UNDEFINED)
810+ backup_type = BACKUP_NUMBERED_EXISTING;
811+ if (optarg == NULL)
812+ break;
813+ if (verbose)
814+ say("Warning, the -b suffix option has been obsoleted by the -z option\n");
815+ /* FALLTHROUGH */
816+ case 'z':
817+ simple_backup_suffix = savestr(optarg);
818+ break;
819+ case 'B':
820+ origprae = savestr(optarg);
821+ break;
822+ case 'c':
823+ diff_type = CONTEXT_DIFF;
824+ break;
825+ case 'C':
826+ check_only = 1;
827+ break;
828+ case 'd':
829+ if (chdir(optarg) < 0)
830+ pfatal("cant cd to %s", optarg);
831+ break;
832+ case 'D':
833+ do_defines = 1;
834+ if (!isalpha((unsigned char)*optarg) && *optarg != '_')
835+ fatal("argument to -D is not an identifier\n");
836+ snprintf(if_defined, sizeof if_defined, "#ifdef %s\n", optarg);
837+ snprintf(not_defined, sizeof not_defined, "#ifndef %s\n", optarg);
838+ snprintf(end_defined, sizeof end_defined, "#endif /* %s */\n", optarg);
839+ break;
840+ case 'e':
841+ diff_type = ED_DIFF;
842+ break;
843+ case 'E':
844+ remove_empty_files = 1;
845+ break;
846+ case 'f':
847+ force = 1;
848+ break;
849+ case 'F':
850+ maxfuzz = strtolinenum(optarg, NULL);
851+ break;
852+ case 'i':
853+ free(filearg[1]);
854+ filearg[1] = fetchname(optarg, &warn_on_invalid_line, 0);
855+ break;
856+ case 'l':
857+ canonicalize = 1;
858+ break;
859+ case 'n':
860+ diff_type = NORMAL_DIFF;
861+ break;
862+ case 'N':
863+ noreverse = 1;
864+ break;
865+ case 'o':
866+ outname = savestr(optarg);
867+ break;
868+ case 'p':
869+ strippath = (int)strtolinenum(optarg, NULL);
870+ break;
871+ case 'r':
872+ if (strlcpy(rejname, optarg, sizeof(rejname)) >= sizeof(rejname))
873+ fatal("reject filename %s too long\n", optarg);
874+ break;
875+ case 'R':
876+ reverse = 1;
877+ reverse_flag_specified = 1;
878+ break;
879+ case 's':
880+ verbose = 0;
881+ break;
882+ case 't':
883+ batch = 1;
884+ break;
885+ case 'u':
886+ diff_type = UNI_DIFF;
887+ break;
888+ case 'v':
889+ version();
890+ break;
891+ case 'V':
892+ backup_type = get_version(optarg);
893+ break;
894+ case 'x':
895 #ifdef DEBUGGING
896- debug = (int)strtolinenum(optarg, NULL);
897+ debug = (int)strtolinenum(optarg, NULL);
898 #endif
899- break;
900- default:
901- if (ch == 0)
902- break;
903- usage();
904- }
905- }
906- Argc -= optind;
907- Argv += optind;
908-
909- for (ch = 0; ch < Argc; ch++) {
910- if (filec >= MAXFILEC)
911- usage();
912- filearg[filec++] = savestr(Argv[ch]);
913- }
914+ break;
915+ default:
916+ if (ch == 0)
917+ break;
918+ usage();
919+ }
920+ }
921+ Argc -= optind;
922+ Argv += optind;
923+
924+ for (ch = 0; ch < Argc; ch++) {
925+ if (filec >= MAXFILEC)
926+ usage();
927+ filearg[filec++] = savestr(Argv[ch]);
928+ }
929 }
930
931 static void
932 usage(void)
933 {
934- fprintf(stderr, "usage: patch [-bCcEeflNnRstuv] [-B backup-prefix] [-D symbol] "
935- "[-d directory] [-F max-fuzz] [-i patchfile] [-o out-file] "
936- "[-p strip-count] [-r rej-name] [-V method] [-x number] "
937- "[-z backup-ext] [origfile [patchfile]]\n");
938- my_exit(2);
939+ fprintf(stderr, "usage: patch [-bCcEeflNnRstuv] [-B backup-prefix] [-D symbol] "
940+ "[-d directory] [-F max-fuzz] [-i patchfile] [-o out-file] "
941+ "[-p strip-count] [-r rej-name] [-V method] [-x number] "
942+ "[-z backup-ext] [origfile [patchfile]]\n");
943+ my_exit(2);
944 }
945
946 static LINENUM
947 locate_hunk(LINENUM fuzz)
948 {
949- LINENUM first_hunk_line = pch_first();
950- LINENUM count = pch_ptrn_lines();
951- LINENUM max_line = input_lines - count + 1;
952- LINENUM line;
953- LINENUM offset;
954-
955- if (!count)
956- return first_hunk_line + last_offset;
957-
958- if (first_hunk_line + last_offset <= 0)
959- offset = 1 - first_hunk_line;
960- else if (first_hunk_line + last_offset > max_line)
961- offset = max_line - first_hunk_line;
962- else
963- offset = last_offset;
964-
965- for (line = first_hunk_line + offset; line <= max_line; line++) {
966- if (patch_match(line, count, fuzz)) {
967- last_offset = line - first_hunk_line;
968- return line;
969- }
970- }
971- for (line = first_hunk_line + offset - 1; line >= 1; line--) {
972- if (patch_match(line, count, fuzz)) {
973- last_offset = line - first_hunk_line;
974- return line;
975- }
976- }
977- return 0;
978+ LINENUM first_hunk_line = pch_first();
979+ LINENUM count = pch_ptrn_lines();
980+ LINENUM max_line = input_lines - count + 1;
981+ LINENUM line;
982+ LINENUM offset;
983+
984+ if (!count)
985+ return first_hunk_line + last_offset;
986+
987+ if (first_hunk_line + last_offset <= 0)
988+ offset = 1 - first_hunk_line;
989+ else if (first_hunk_line + last_offset > max_line)
990+ offset = max_line - first_hunk_line;
991+ else
992+ offset = last_offset;
993+
994+ for (line = first_hunk_line + offset; line <= max_line; line++) {
995+ if (patch_match(line, count, fuzz)) {
996+ last_offset = line - first_hunk_line;
997+ return line;
998+ }
999+ }
1000+ for (line = first_hunk_line + offset - 1; line >= 1; line--) {
1001+ if (patch_match(line, count, fuzz)) {
1002+ last_offset = line - first_hunk_line;
1003+ return line;
1004+ }
1005+ }
1006+ return 0;
1007 }
1008
1009 static int
1010 patch_match(LINENUM line, LINENUM count, LINENUM fuzz)
1011 {
1012- LINENUM i;
1013- LINENUM pat_line;
1014- char *str;
1015- char *pat;
1016- ssize_t len;
1017-
1018- for (i = 1; i <= count; i++) {
1019- pat_line = i;
1020- if (i <= fuzz)
1021- continue;
1022- if (i > count - fuzz)
1023- continue;
1024- str = ifetch(line + i - 1 - fuzz, 0);
1025- if (str == NULL)
1026- return 0;
1027- pat = pfetch(pat_line);
1028- len = pch_line_len(pat_line);
1029- if (canonicalize) {
1030- if (!similar(str, pat, len))
1031- return 0;
1032- } else if (strncmp(str, pat, len) != 0)
1033- return 0;
1034- }
1035- return 1;
1036+ LINENUM i;
1037+ LINENUM pat_line;
1038+ char *str;
1039+ char *pat;
1040+ ssize_t len;
1041+
1042+ for (i = 1; i <= count; i++) {
1043+ pat_line = i;
1044+ if (i <= fuzz)
1045+ continue;
1046+ if (i > count - fuzz)
1047+ continue;
1048+ str = ifetch(line + i - 1 - fuzz, 0);
1049+ if (str == NULL)
1050+ return 0;
1051+ pat = pfetch(pat_line);
1052+ len = pch_line_len(pat_line);
1053+ if (canonicalize) {
1054+ if (!similar(str, pat, len))
1055+ return 0;
1056+ } else if (strncmp(str, pat, len) != 0)
1057+ return 0;
1058+ }
1059+ return 1;
1060 }
1061
1062 static int
1063 similar(const char *a, const char *b, ssize_t len)
1064 {
1065- while (len > 0) {
1066- if (isspace((unsigned char)*b)) {
1067- if (!isspace((unsigned char)*a))
1068- return 0;
1069- while (len > 0 && isspace((unsigned char)*b)) {
1070- b++;
1071- len--;
1072- }
1073- while (isspace((unsigned char)*a) && *a != '\n')
1074- a++;
1075- } else {
1076- if (*a != *b)
1077- return 0;
1078- a++;
1079- b++;
1080- len--;
1081- }
1082- }
1083- if (*a == '\n' || *a == '\r') {
1084- while (*a == '\n' || *a == '\r')
1085- a++;
1086- return *a == '\0';
1087- }
1088- return *a == '\0' || isspace((unsigned char)*a);
1089+ while (len > 0) {
1090+ if (isspace((unsigned char)*b)) {
1091+ if (!isspace((unsigned char)*a))
1092+ return 0;
1093+ while (len > 0 && isspace((unsigned char)*b)) {
1094+ b++;
1095+ len--;
1096+ }
1097+ while (isspace((unsigned char)*a) && *a != '\n')
1098+ a++;
1099+ } else {
1100+ if (*a != *b)
1101+ return 0;
1102+ a++;
1103+ b++;
1104+ len--;
1105+ }
1106+ }
1107+ if (*a == '\n' || *a == '\r') {
1108+ while (*a == '\n' || *a == '\r')
1109+ a++;
1110+ return *a == '\0';
1111+ }
1112+ return *a == '\0' || isspace((unsigned char)*a);
1113 }
1114
1115 static void
1116 abort_hunk(void)
1117 {
1118- LINENUM i;
1119- LINENUM pat_line;
1120- char *str;
1121- ssize_t len;
1122+ LINENUM i;
1123
1124- for (i = 1; i <= pch_end(); i++) {
1125- pat_line = i;
1126- str = pfetch(pat_line);
1127- len = pch_line_len(pat_line);
1128- rej_line(pat_line, i);
1129- }
1130+ for (i = 1; i <= pch_end(); i++)
1131+ rej_line(i, i);
1132 }
1133
1134 static void
1135 rej_line(int pat_line, LINENUM i)
1136 {
1137- char *str = pfetch(pat_line);
1138- char ch = pch_char(pat_line);
1139- if (rejfp != NULL) {
1140- if (ch == ' ')
1141- fprintf(rejfp, " %s", str);
1142- else
1143- fprintf(rejfp, "%c%s", ch, str);
1144- }
1145-}
1146-
1147-static void
1148-abort_context_hunk(void)
1149-{
1150- LINENUM i;
1151- for (i = 0; i <= pch_end(); i++) {
1152- rej_line(i, i);
1153- }
1154+ char *str = pfetch(pat_line);
1155+ char ch = pch_char(pat_line);
1156+ (void)i;
1157+ if (rejfp != NULL) {
1158+ if (ch == ' ')
1159+ fprintf(rejfp, " %s", str);
1160+ else
1161+ fprintf(rejfp, "%c%s", ch, str);
1162+ }
1163 }
1164
1165 static void
1166 apply_hunk(LINENUM where)
1167 {
1168- LINENUM old = 1;
1169- const LINENUM lastline = pch_ptrn_lines();
1170- LINENUM new = lastline + 1;
1171+ LINENUM old = 1;
1172+ const LINENUM lastline = pch_ptrn_lines();
1173+ LINENUM new = lastline + 1;
1174 #define OUTSIDE 0
1175 #define IN_IFNDEF 1
1176 #define IN_IFDEF 2
1177 #define IN_ELSE 3
1178- int def_state = OUTSIDE;
1179- const LINENUM pat_end = pch_end();
1180-
1181- where--;
1182- while (pch_char(new) == '=' || pch_char(new) == '\n')
1183- new++;
1184-
1185- while (old <= lastline) {
1186- if (pch_char(old) == '-') {
1187- copy_till(where + old - 1, 0);
1188- if (do_defines) {
1189- if (def_state == OUTSIDE) {
1190- fputs(not_defined, ofp);
1191- def_state = IN_IFNDEF;
1192- } else if (def_state == IN_IFDEF) {
1193- fputs(else_defined, ofp);
1194- def_state = IN_ELSE;
1195- }
1196- fputs(pfetch(old), ofp);
1197- }
1198- last_frozen_line++;
1199- old++;
1200- } else if (new > pat_end) {
1201- break;
1202- } else if (pch_char(new) == '+') {
1203- copy_till(where + old - 1, 0);
1204- if (do_defines) {
1205- if (def_state == IN_IFNDEF) {
1206- fputs(else_defined, ofp);
1207- def_state = IN_ELSE;
1208- } else if (def_state == OUTSIDE) {
1209- fputs(if_defined, ofp);
1210- def_state = IN_IFDEF;
1211- }
1212- }
1213- fputs(pfetch(new), ofp);
1214- new++;
1215- } else if (pch_char(new) != pch_char(old)) {
1216- say("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
1217- pch_hunk_beg() + old,
1218- pch_hunk_beg() + new);
1219- my_exit(2);
1220- } else if (pch_char(new) == '!') {
1221- copy_till(where + old - 1, 0);
1222- if (do_defines) {
1223- fputs(not_defined, ofp);
1224- def_state = IN_IFNDEF;
1225- }
1226- while (pch_char(old) == '!') {
1227- if (do_defines) {
1228- fputs(pfetch(old), ofp);
1229- }
1230- last_frozen_line++;
1231- old++;
1232- }
1233- if (do_defines) {
1234- fputs(else_defined, ofp);
1235- def_state = IN_ELSE;
1236- }
1237- while (pch_char(new) == '!') {
1238- fputs(pfetch(new), ofp);
1239- new++;
1240- }
1241- } else {
1242- if (pch_char(new) != ' ')
1243- fatal("Internal error: expected ' '\n");
1244- old++;
1245- new++;
1246- if (do_defines && def_state != OUTSIDE) {
1247- fputs(end_defined, ofp);
1248- def_state = OUTSIDE;
1249- }
1250- }
1251- }
1252- if (new <= pat_end && pch_char(new) == '+') {
1253- copy_till(where + old - 1, 0);
1254- if (do_defines) {
1255- if (def_state == OUTSIDE) {
1256- fputs(if_defined, ofp);
1257- def_state = IN_IFDEF;
1258- } else if (def_state == IN_IFNDEF) {
1259- fputs(else_defined, ofp);
1260- def_state = IN_ELSE;
1261- }
1262- }
1263- while (new <= pat_end && pch_char(new) == '+') {
1264- fputs(pfetch(new), ofp);
1265- new++;
1266- }
1267- }
1268- if (do_defines && def_state != OUTSIDE) {
1269- fputs(end_defined, ofp);
1270- }
1271+ int def_state = OUTSIDE;
1272+ const LINENUM pat_end = pch_end();
1273+
1274+ where--;
1275+ while (pch_char(new) == '=' || pch_char(new) == '\n')
1276+ new++;
1277+
1278+ while (old <= lastline) {
1279+ if (pch_char(old) == '-') {
1280+ copy_till(where + old - 1, 0);
1281+ if (do_defines) {
1282+ if (def_state == OUTSIDE) {
1283+ fputs(not_defined, ofp);
1284+ def_state = IN_IFNDEF;
1285+ } else if (def_state == IN_IFDEF) {
1286+ fputs(else_defined, ofp);
1287+ def_state = IN_ELSE;
1288+ }
1289+ fputs(pfetch(old), ofp);
1290+ }
1291+ last_frozen_line++;
1292+ old++;
1293+ } else if (new > pat_end) {
1294+ break;
1295+ } else if (pch_char(new) == '+') {
1296+ copy_till(where + old - 1, 0);
1297+ if (do_defines) {
1298+ if (def_state == IN_IFNDEF) {
1299+ fputs(else_defined, ofp);
1300+ def_state = IN_ELSE;
1301+ } else if (def_state == OUTSIDE) {
1302+ fputs(if_defined, ofp);
1303+ def_state = IN_IFDEF;
1304+ }
1305+ }
1306+ fputs(pfetch(new), ofp);
1307+ new++;
1308+ } else if (pch_char(new) != pch_char(old)) {
1309+ say("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
1310+ pch_hunk_beg() + old,
1311+ pch_hunk_beg() + new);
1312+ my_exit(2);
1313+ } else if (pch_char(new) == '!') {
1314+ copy_till(where + old - 1, 0);
1315+ if (do_defines) {
1316+ fputs(not_defined, ofp);
1317+ def_state = IN_IFNDEF;
1318+ }
1319+ while (pch_char(old) == '!') {
1320+ if (do_defines) {
1321+ fputs(pfetch(old), ofp);
1322+ }
1323+ last_frozen_line++;
1324+ old++;
1325+ }
1326+ if (do_defines) {
1327+ fputs(else_defined, ofp);
1328+ def_state = IN_ELSE;
1329+ }
1330+ while (pch_char(new) == '!') {
1331+ fputs(pfetch(new), ofp);
1332+ new++;
1333+ }
1334+ } else {
1335+ if (pch_char(new) != ' ')
1336+ fatal("Internal error: expected ' '\n");
1337+ old++;
1338+ new++;
1339+ if (do_defines && def_state != OUTSIDE) {
1340+ fputs(end_defined, ofp);
1341+ def_state = OUTSIDE;
1342+ }
1343+ }
1344+ }
1345+ if (new <= pat_end && pch_char(new) == '+') {
1346+ copy_till(where + old - 1, 0);
1347+ if (do_defines) {
1348+ if (def_state == OUTSIDE) {
1349+ fputs(if_defined, ofp);
1350+ def_state = IN_IFDEF;
1351+ } else if (def_state == IN_IFNDEF) {
1352+ fputs(else_defined, ofp);
1353+ def_state = IN_ELSE;
1354+ }
1355+ }
1356+ while (new <= pat_end && pch_char(new) == '+') {
1357+ fputs(pfetch(new), ofp);
1358+ new++;
1359+ }
1360+ }
1361+ if (do_defines && def_state != OUTSIDE) {
1362+ fputs(end_defined, ofp);
1363+ }
1364 #undef OUTSIDE
1365 #undef IN_IFNDEF
1366 #undef IN_IFDEF
1367@@ -959,2192 +942,2178 @@ apply_hunk(LINENUM where)
1368 static void
1369 dump_input_line(LINENUM line, int write_newline)
1370 {
1371- char *s = ifetch(line, 0);
1372- if (s == NULL)
1373- return;
1374- for (; *s != '\n' && *s != '\0'; s++)
1375- putc(*s, ofp);
1376- if (write_newline)
1377- putc('\n', ofp);
1378+ char *s = ifetch(line, 0);
1379+ if (s == NULL)
1380+ return;
1381+ for (; *s != '\n' && *s != '\0'; s++)
1382+ putc(*s, ofp);
1383+ if (write_newline)
1384+ putc('\n', ofp);
1385 }
1386
1387 static void
1388 copy_till(LINENUM line, int end)
1389 {
1390- if (last_frozen_line > line)
1391- fatal("misordered hunks! output would be garbled\n");
1392- while (last_frozen_line < line) {
1393- if (++last_frozen_line == line && end)
1394- dump_input_line(last_frozen_line, !last_line_missing_eol);
1395- else
1396- dump_input_line(last_frozen_line, 1);
1397- }
1398+ if (last_frozen_line > line)
1399+ fatal("misordered hunks! output would be garbled\n");
1400+ while (last_frozen_line < line) {
1401+ if (++last_frozen_line == line && end)
1402+ dump_input_line(last_frozen_line, !last_line_missing_eol);
1403+ else
1404+ dump_input_line(last_frozen_line, 1);
1405+ }
1406 }
1407
1408 static int
1409 spew_output(void)
1410 {
1411- if (input_lines)
1412- copy_till(input_lines, 1);
1413- if (ferror(ofp) || fclose(ofp))
1414- return 0;
1415- ofp = NULL;
1416- return 1;
1417+ if (input_lines)
1418+ copy_till(input_lines, 1);
1419+ if (ferror(ofp) || fclose(ofp))
1420+ return 0;
1421+ ofp = NULL;
1422+ return 1;
1423 }
1424
1425 static void
1426 init_output(const char *name)
1427 {
1428- ofp = fopen(name, "w");
1429- if (ofp == NULL)
1430- pfatal("cant create %s", name);
1431+ ofp = fopen(name, "w");
1432+ if (ofp == NULL)
1433+ pfatal("cant create %s", name);
1434 }
1435
1436 static void
1437 init_reject(const char *name)
1438 {
1439- rejfp = fopen(name, "w");
1440- if (rejfp == NULL)
1441- pfatal("cant create %s", name);
1442+ rejfp = fopen(name, "w");
1443+ if (rejfp == NULL)
1444+ pfatal("cant create %s", name);
1445 }
1446
1447 void
1448 re_input(void)
1449 {
1450- if (using_plan_a) {
1451- i_size = 0;
1452- free(i_ptr);
1453- i_ptr = NULL;
1454- if (i_womp != NULL) {
1455- munmap(i_womp, i_size);
1456- i_womp = NULL;
1457- }
1458- } else {
1459- using_plan_a = 1;
1460- close(tifd);
1461- tifd = -1;
1462- free(tibuf[0]);
1463- free(tibuf[1]);
1464- tibuf[0] = tibuf[1] = NULL;
1465- tiline[0] = tiline[1] = -1;
1466- tireclen = 0;
1467- }
1468+ if (using_plan_a) {
1469+ i_size = 0;
1470+ free(i_ptr);
1471+ i_ptr = NULL;
1472+ if (i_womp != NULL) {
1473+ munmap(i_womp, i_size);
1474+ i_womp = NULL;
1475+ }
1476+ } else {
1477+ using_plan_a = 1;
1478+ close(tifd);
1479+ tifd = -1;
1480+ free(tibuf[0]);
1481+ free(tibuf[1]);
1482+ tibuf[0] = tibuf[1] = NULL;
1483+ tiline[0] = tiline[1] = -1;
1484+ tireclen = 0;
1485+ }
1486 }
1487
1488 void
1489 scan_input(const char *filename)
1490 {
1491- if (!plan_a(filename))
1492- plan_b(filename);
1493- if (verbose) {
1494- say("Patching file %s using Plan %s...\n", filename, (using_plan_a ? "A" : "B"));
1495- }
1496+ if (!plan_a(filename))
1497+ plan_b(filename);
1498+ if (verbose) {
1499+ say("Patching file %s using Plan %s...\n", filename, (using_plan_a ? "A" : "B"));
1500+ }
1501 }
1502
1503 static int
1504 reallocate_lines(size_t *lines_allocated)
1505 {
1506- char **p;
1507- size_t new_size;
1508+ char **p;
1509+ size_t new_size;
1510
1511- new_size = *lines_allocated * 3 / 2;
1512- p = pch_realloc(i_ptr, new_size + 2, sizeof(char *));
1513- if (p == NULL) {
1514- munmap(i_womp, i_size);
1515- i_womp = NULL;
1516- free(i_ptr);
1517- i_ptr = NULL;
1518- *lines_allocated = 0;
1519- return 0;
1520- }
1521- *lines_allocated = new_size;
1522- i_ptr = p;
1523- return 1;
1524+ new_size = *lines_allocated * 3 / 2;
1525+ p = pch_realloc(i_ptr, new_size + 2, sizeof(char *));
1526+ if (p == NULL) {
1527+ munmap(i_womp, i_size);
1528+ i_womp = NULL;
1529+ free(i_ptr);
1530+ i_ptr = NULL;
1531+ *lines_allocated = 0;
1532+ return 0;
1533+ }
1534+ *lines_allocated = new_size;
1535+ i_ptr = p;
1536+ return 1;
1537 }
1538
1539 static int
1540 plan_a(const char *filename)
1541 {
1542- int ifd, statfailed, devnull, pstat;
1543- char *p, *s, *lbuf;
1544- struct stat filestat;
1545- off_t i;
1546- ptrdiff_t sz;
1547- size_t iline, lines_allocated, lbufsz;
1548- pid_t pid;
1549- char *argp[4] = {NULL};
1550+ int ifd, statfailed;
1551+ char *p, *s, *lbuf;
1552+ struct stat filestat;
1553+ off_t i;
1554+ ptrdiff_t sz;
1555+ size_t iline, lines_allocated, lbufsz;
1556
1557 #ifdef DEBUGGING
1558- if (debug & 8)
1559- return 0;
1560+ if (debug & 8)
1561+ return 0;
1562 #endif
1563
1564- if (filename == NULL || *filename == '\0')
1565- return 0;
1566-
1567- statfailed = stat(filename, &filestat);
1568- if (statfailed && ok_to_create_file) {
1569- if (verbose)
1570- say("(Creating file %s...)\n", filename);
1571- if (check_only)
1572- return 1;
1573- makedirs(filename, 1);
1574- close(creat(filename, 0666));
1575- statfailed = stat(filename, &filestat);
1576- }
1577- if (statfailed && check_only)
1578- fatal("%s not found, -C mode, cant probe further\n", filename);
1579-
1580- if (statfailed || (filestat.st_mode & 0222) == 0 ||
1581- ((filestat.st_mode & 0022) == 0 && filestat.st_uid != getuid())) {
1582- char *filebase, *filedir;
1583- struct stat cstat;
1584- char *tmp_filename1, *tmp_filename2;
1585-
1586- tmp_filename1 = strdup(filename);
1587- tmp_filename2 = strdup(filename);
1588- if (tmp_filename1 == NULL || tmp_filename2 == NULL)
1589- fatal("strdupping filename");
1590- filebase = basename(tmp_filename1);
1591- filedir = dirname(tmp_filename2);
1592-
1593- lbufsz = INITLINELEN;
1594- if ((lbuf = malloc(bufsz)) == NULL)
1595- pfatal("allocating line buffer");
1596- lbuf[0] = '\0';
1597+ if (filename == NULL || *filename == '\0')
1598+ return 0;
1599+
1600+ statfailed = stat(filename, &filestat);
1601+ if (statfailed && ok_to_create_file) {
1602+ if (verbose)
1603+ say("(Creating file %s...)\n", filename);
1604+ if (check_only)
1605+ return 1;
1606+ makedirs(filename, 1);
1607+ close(creat(filename, 0666));
1608+ statfailed = stat(filename, &filestat);
1609+ }
1610+ if (statfailed && check_only)
1611+ fatal("%s not found, -C mode, cant probe further\n", filename);
1612+
1613+ if (statfailed || (filestat.st_mode & 0222) == 0 ||
1614+ ((filestat.st_mode & 0022) == 0 && filestat.st_uid != getuid())) {
1615+ char *filebase, *filedir;
1616+ struct stat cstat;
1617+ char *tmp_filename1, *tmp_filename2;
1618+
1619+ tmp_filename1 = strdup(filename);
1620+ tmp_filename2 = strdup(filename);
1621+ if (tmp_filename1 == NULL || tmp_filename2 == NULL)
1622+ fatal("strdupping filename");
1623+ filebase = basename(tmp_filename1);
1624+ filedir = dirname(tmp_filename2);
1625+
1626+ lbufsz = INITLINELEN;
1627+ if ((lbuf = malloc(bufsz)) == NULL)
1628+ pfatal("allocating line buffer");
1629+ lbuf[0] = '\0';
1630
1631 #define try(f, a1, a2, a3) \
1632- (snprintf(lbuf, lbufsz, f, a1, a2, a3), stat(lbuf, &cstat) == 0)
1633-
1634- if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
1635- try("%s/RCS/%s%s", filedir, filebase, "") ||
1636- try("%s/%s%s", filedir, filebase, RCSSUFFIX)) {
1637- if (!statfailed) {
1638- if ((filestat.st_mode & 0222) != 0)
1639- fatal("file %s seems to be locked by somebody else under RCS\n", filename);
1640- if (verbose)
1641- say("Comparing file %s to default RCS version...\n", filename);
1642- switch (pid = fork()) {
1643- case -1:
1644- fatal("cant fork: %s\n", strerror(errno));
1645- case 0:
1646- devnull = open("/dev/null", O_RDONLY);
1647- if (devnull == -1)
1648- fatal("cant open /dev/null: %s", strerror(errno));
1649- dup2(devnull, STDOUT_FILENO);
1650- argp[0] = __UNCONST(RCSDIFF);
1651- argp[1] = __UNCONST(filename);
1652- execv(RCSDIFF, argp);
1653- exit(127);
1654- }
1655- pid = waitpid(pid, &pstat, 0);
1656- if (pid == -1 || WEXITSTATUS(pstat) != 0)
1657- fatal("cant check out file %s: differs from default RCS version\n", filename);
1658- }
1659- if (verbose)
1660- say("Checking out file %s from RCS...\n", filename);
1661- switch (pid = fork()) {
1662- case -1:
1663- fatal("cant fork: %s\n", strerror(errno));
1664- case 0:
1665- argp[0] = __UNCONST(CHECKOUT);
1666- argp[1] = __UNCONST("-l");
1667- argp[2] = __UNCONST(filename);
1668- execv(CHECKOUT, argp);
1669- exit(127);
1670- }
1671- pid = waitpid(pid, &pstat, 0);
1672- if (pid == -1 || WEXITSTATUS(pstat) != 0 || stat(filename, &filestat))
1673- fatal("cant check out file %s from RCS\n", filename);
1674- } else if (statfailed) {
1675- fatal("cant find %s\n", filename);
1676- }
1677+ (snprintf(lbuf, lbufsz, f, a1, a2, a3), stat(lbuf, &cstat) == 0)
1678+
1679+ if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
1680+ try("%s/RCS/%s%s", filedir, filebase, "") ||
1681+ try("%s/%s%s", filedir, filebase, RCSSUFFIX)) {
1682+ if (!statfailed) {
1683+ if ((filestat.st_mode & 0222) != 0)
1684+ fatal("file %s seems to be locked by somebody else under RCS\n", filename);
1685+ if (verbose)
1686+ say("Comparing file %s to default RCS version...\n", filename);
1687+ {
1688+ char *rcsdiff_argv[3];
1689+ rcsdiff_argv[0] = __UNCONST(RCSDIFF);
1690+ rcsdiff_argv[1] = __UNCONST(filename);
1691+ rcsdiff_argv[2] = NULL;
1692+ if (wexecvp(RCSDIFF, rcsdiff_argv) != 0)
1693+ fatal("cant check out file %s: differs from default RCS version\n", filename);
1694+ }
1695+ }
1696+ if (verbose)
1697+ say("Checking out file %s from RCS...\n", filename);
1698+ {
1699+ char *co_argv[4];
1700+ co_argv[0] = __UNCONST(CHECKOUT);
1701+ co_argv[1] = __UNCONST("-l");
1702+ co_argv[2] = __UNCONST(filename);
1703+ co_argv[3] = NULL;
1704+ if (wexecvp(CHECKOUT, co_argv) != 0 || stat(filename, &filestat))
1705+ fatal("cant check out file %s from RCS\n", filename);
1706+ }
1707+ } else if (statfailed) {
1708+ fatal("cant find %s\n", filename);
1709+ }
1710 #undef try
1711- free(lbuf);
1712- free(tmp_filename1);
1713- free(tmp_filename2);
1714- }
1715-
1716- filemode = filestat.st_mode;
1717- if (!S_ISREG(filemode))
1718- fatal("%s is not a normal file--cant patch\n", filename);
1719- i_size = filestat.st_size;
1720- if (out_of_mem) {
1721- set_hunkmax();
1722- out_of_mem = 0;
1723- return 0;
1724- }
1725- if ((uintmax_t)i_size > (uintmax_t)SIZE_MAX) {
1726- say("block too large to mmap\n");
1727- return 0;
1728- }
1729- if ((ifd = open(filename, O_RDONLY)) < 0)
1730- pfatal("cant open file %s", filename);
1731-
1732- if (i_size) {
1733- i_womp = mmap(NULL, i_size, PROT_READ, MAP_PRIVATE, ifd, 0);
1734- if (i_womp == MAP_FAILED) {
1735- perror("mmap failed");
1736- i_womp = NULL;
1737- close(ifd);
1738- return 0;
1739- }
1740- } else
1741- i_womp = NULL;
1742-
1743- close(ifd);
1744- if (i_size)
1745- madvise(i_womp, i_size, MADV_SEQUENTIAL);
1746-
1747- lines_allocated = i_size / 25;
1748- if (lines_allocated < 100)
1749- lines_allocated = 100;
1750-
1751- if (!reallocate_lines(&lines_allocated))
1752- return 0;
1753-
1754- iline = 1;
1755- i_ptr[iline] = i_womp;
1756- for (s = i_womp, i = 0; i < i_size && *s != '\0'; s++, i++) {
1757- if (*s == '\n') {
1758- if (iline == lines_allocated) {
1759- if (!reallocate_lines(&lines_allocated))
1760- return 0;
1761- }
1762- i_ptr[++iline] = s + 1;
1763- }
1764- }
1765- if (i_size > 0 && i_womp[i_size - 1] != '\n') {
1766- last_line_missing_eol = 1;
1767- sz = s - i_ptr[iline];
1768- p = malloc(sz + 1);
1769- if (p == NULL) {
1770- free(i_ptr);
1771- i_ptr = NULL;
1772- munmap(i_womp, i_size);
1773- i_womp = NULL;
1774- return 0;
1775- }
1776- memcpy(p, i_ptr[iline], sz);
1777- p[sz] = '\n';
1778- i_ptr[iline] = p;
1779- i_ptr[++iline] = empty_line;
1780- } else
1781- last_line_missing_eol = 0;
1782-
1783- input_lines = iline - 1;
1784-
1785- if (revision != NULL) {
1786- if (!rev_in_string(i_womp)) {
1787- if (force) {
1788- if (verbose)
1789- say("Warning: this file doesnt appear to be the %s version--patching anyway\n", revision);
1790- } else if (batch) {
1791- fatal("this file doesnt appear to be the %s version--aborting\n", revision);
1792- } else {
1793- ask("This file doesnt appear to be the %s version--patch anyway? [n] ", revision);
1794- if (*buf != 'y')
1795- fatal("aborted\n");
1796- }
1797- } else if (verbose)
1798- say("Good. This file appears to be the %s version.\n", revision);
1799- }
1800- return 1;
1801+ free(lbuf);
1802+ free(tmp_filename1);
1803+ free(tmp_filename2);
1804+ }
1805+
1806+ filemode = filestat.st_mode;
1807+ if (!S_ISREG(filemode))
1808+ fatal("%s is not a normal file--cant patch\n", filename);
1809+ i_size = filestat.st_size;
1810+ if (out_of_mem) {
1811+ set_hunkmax();
1812+ out_of_mem = 0;
1813+ return 0;
1814+ }
1815+ if ((uintmax_t)i_size > (uintmax_t)SIZE_MAX) {
1816+ say("block too large to mmap\n");
1817+ return 0;
1818+ }
1819+ if ((ifd = open(filename, O_RDONLY)) < 0)
1820+ pfatal("cant open file %s", filename);
1821+
1822+ if (i_size) {
1823+ i_womp = mmap(NULL, i_size, PROT_READ, MAP_PRIVATE, ifd, 0);
1824+ if (i_womp == MAP_FAILED) {
1825+ perror("mmap failed");
1826+ i_womp = NULL;
1827+ close(ifd);
1828+ return 0;
1829+ }
1830+ } else
1831+ i_womp = NULL;
1832+
1833+ close(ifd);
1834+ if (i_size)
1835+ madvise(i_womp, i_size, MADV_SEQUENTIAL);
1836+
1837+ lines_allocated = i_size / 25;
1838+ if (lines_allocated < 100)
1839+ lines_allocated = 100;
1840+
1841+ if (!reallocate_lines(&lines_allocated))
1842+ return 0;
1843+
1844+ iline = 1;
1845+ i_ptr[iline] = i_womp;
1846+ for (s = i_womp, i = 0; i < i_size && *s != '\0'; s++, i++) {
1847+ if (*s == '\n') {
1848+ if (iline == lines_allocated) {
1849+ if (!reallocate_lines(&lines_allocated))
1850+ return 0;
1851+ }
1852+ i_ptr[++iline] = s + 1;
1853+ }
1854+ }
1855+ if (i_size > 0 && i_womp[i_size - 1] != '\n') {
1856+ last_line_missing_eol = 1;
1857+ sz = s - i_ptr[iline];
1858+ p = malloc(sz + 1);
1859+ if (p == NULL) {
1860+ free(i_ptr);
1861+ i_ptr = NULL;
1862+ munmap(i_womp, i_size);
1863+ i_womp = NULL;
1864+ return 0;
1865+ }
1866+ memcpy(p, i_ptr[iline], sz);
1867+ p[sz] = '\n';
1868+ i_ptr[iline] = p;
1869+ i_ptr[++iline] = empty_line;
1870+ } else
1871+ last_line_missing_eol = 0;
1872+
1873+ input_lines = iline - 1;
1874+
1875+ if (revision != NULL) {
1876+ if (!rev_in_string(i_womp)) {
1877+ if (force) {
1878+ if (verbose)
1879+ say("Warning: this file doesnt appear to be the %s version--patching anyway\n", revision);
1880+ } else if (batch) {
1881+ fatal("this file doesnt appear to be the %s version--aborting\n", revision);
1882+ } else {
1883+ ask("This file doesnt appear to be the %s version--patch anyway? [n] ", revision);
1884+ if (*buf != 'y')
1885+ fatal("aborted\n");
1886+ }
1887+ } else if (verbose)
1888+ say("Good. This file appears to be the %s version.\n", revision);
1889+ }
1890+ return 1;
1891 }
1892
1893 static void
1894 plan_b(const char *filename)
1895 {
1896- FILE *ifp;
1897- size_t i = 0, j, maxlen = 1;
1898- char *p;
1899- int found_revision = (revision == NULL);
1900-
1901- using_plan_a = 0;
1902- if ((ifp = fopen(filename, "r")) == NULL)
1903- pfatal("cant open file %s", filename);
1904- unlink(TMPINNAME);
1905- if ((tifd = open(TMPINNAME, O_EXCL | O_CREAT | O_WRONLY, 0666)) < 0)
1906- pfatal("cant open file %s", TMPINNAME);
1907- while (getline(&buf, &bufsz, ifp) != -1) {
1908- if (revision != NULL && !found_revision && rev_in_string(buf))
1909- found_revision = 1;
1910- if ((i = strlen(buf)) > maxlen)
1911- maxlen = i;
1912- }
1913- last_line_missing_eol = i > 0 && buf[i - 1] != '\n';
1914- if (last_line_missing_eol && maxlen == i)
1915- maxlen++;
1916-
1917- if (revision != NULL) {
1918- if (!found_revision) {
1919- if (force) {
1920- if (verbose)
1921- say("Warning: this file doesnt appear to be the %s version--patching anyway\n", revision);
1922- } else if (batch) {
1923- fatal("this file doesnt appear to be the %s version--aborting\n", revision);
1924- } else {
1925- ask("This file doesnt appear to be the %s version--patch anyway? [n] ", revision);
1926- if (*buf != 'y')
1927- fatal("aborted\n");
1928- }
1929- } else if (verbose)
1930- say("Good. This file appears to be the %s version.\n", revision);
1931- }
1932- fseek(ifp, 0L, SEEK_SET);
1933- lines_per_buf = BUFFERSIZE / maxlen;
1934- tireclen = maxlen;
1935- tibuf[0] = malloc(BUFFERSIZE + 1);
1936- if (tibuf[0] == NULL)
1937- fatal("out of memory\n");
1938- tibuf[1] = malloc(BUFFERSIZE + 1);
1939- if (tibuf[1] == NULL)
1940- fatal("out of memory\n");
1941- for (i = 1;; i++) {
1942- p = tibuf[0] + maxlen * (i % lines_per_buf);
1943- if (i % lines_per_buf == 0) {
1944- if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
1945- pfatal("cant write temp file");
1946- }
1947- if (fgets(p, maxlen + 1, ifp) == NULL) {
1948- input_lines = i - 1;
1949- if (i % lines_per_buf != 0) {
1950- if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
1951- pfatal("cant write temp file");
1952- }
1953- break;
1954- }
1955- j = strlen(p);
1956- if (j == 0 || p[j - 1] != '\n')
1957- p[j] = '\n';
1958- }
1959- fclose(ifp);
1960- close(tifd);
1961- if ((tifd = open(TMPINNAME, O_RDONLY)) < 0)
1962- pfatal("cant reopen file %s", TMPINNAME);
1963+ FILE *ifp;
1964+ size_t i = 0, j, maxlen = 1;
1965+ char *p;
1966+ int found_revision = (revision == NULL);
1967+
1968+ using_plan_a = 0;
1969+ if ((ifp = fopen(filename, "r")) == NULL)
1970+ pfatal("cant open file %s", filename);
1971+ unlink(TMPINNAME);
1972+ if ((tifd = open(TMPINNAME, O_EXCL | O_CREAT | O_WRONLY, 0666)) < 0)
1973+ pfatal("cant open file %s", TMPINNAME);
1974+ while (getline(&buf, &bufsz, ifp) != -1) {
1975+ if (revision != NULL && !found_revision && rev_in_string(buf))
1976+ found_revision = 1;
1977+ if ((i = strlen(buf)) > maxlen)
1978+ maxlen = i;
1979+ }
1980+ last_line_missing_eol = i > 0 && buf[i - 1] != '\n';
1981+ if (last_line_missing_eol && maxlen == i)
1982+ maxlen++;
1983+
1984+ if (revision != NULL) {
1985+ if (!found_revision) {
1986+ if (force) {
1987+ if (verbose)
1988+ say("Warning: this file doesnt appear to be the %s version--patching anyway\n", revision);
1989+ } else if (batch) {
1990+ fatal("this file doesnt appear to be the %s version--aborting\n", revision);
1991+ } else {
1992+ ask("This file doesnt appear to be the %s version--patch anyway? [n] ", revision);
1993+ if (*buf != 'y')
1994+ fatal("aborted\n");
1995+ }
1996+ } else if (verbose)
1997+ say("Good. This file appears to be the %s version.\n", revision);
1998+ }
1999+ fseek(ifp, 0L, SEEK_SET);
2000+ lines_per_buf = BUFFERSIZE / maxlen;
2001+ tireclen = maxlen;
2002+ tibuf[0] = malloc(BUFFERSIZE + 1);
2003+ if (tibuf[0] == NULL)
2004+ fatal("out of memory\n");
2005+ tibuf[1] = malloc(BUFFERSIZE + 1);
2006+ if (tibuf[1] == NULL)
2007+ fatal("out of memory\n");
2008+ for (i = 1;; i++) {
2009+ p = tibuf[0] + maxlen * (i % lines_per_buf);
2010+ if (i % lines_per_buf == 0) {
2011+ if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
2012+ pfatal("cant write temp file");
2013+ }
2014+ if (fgets(p, maxlen + 1, ifp) == NULL) {
2015+ input_lines = i - 1;
2016+ if (i % lines_per_buf != 0) {
2017+ if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
2018+ pfatal("cant write temp file");
2019+ }
2020+ break;
2021+ }
2022+ j = strlen(p);
2023+ if (j == 0 || p[j - 1] != '\n')
2024+ p[j] = '\n';
2025+ }
2026+ fclose(ifp);
2027+ close(tifd);
2028+ if ((tifd = open(TMPINNAME, O_RDONLY)) < 0)
2029+ pfatal("cant reopen file %s", TMPINNAME);
2030 }
2031
2032 char *
2033 ifetch(LINENUM line, int whichbuf)
2034 {
2035- if (line < 1 || line > input_lines) {
2036- if (warn_on_invalid_line) {
2037- say("No such line %ld in input file, ignoring\n", line);
2038- warn_on_invalid_line = 0;
2039- }
2040- return NULL;
2041- }
2042- if (using_plan_a)
2043- return i_ptr[line];
2044- else {
2045- LINENUM offline = line % lines_per_buf;
2046- LINENUM baseline = line - offline;
2047-
2048- if (tiline[0] == baseline)
2049- whichbuf = 0;
2050- else if (tiline[1] == baseline)
2051- whichbuf = 1;
2052- else {
2053- tiline[whichbuf] = baseline;
2054- if (lseek(tifd, (off_t)(baseline / lines_per_buf * BUFFERSIZE), SEEK_SET) < 0)
2055- pfatal("cannot seek in the temporary input file");
2056- if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
2057- pfatal("error reading tmp file %s", TMPINNAME);
2058- }
2059- return tibuf[whichbuf] + (tireclen * offline);
2060- }
2061+ if (line < 1 || line > input_lines) {
2062+ if (warn_on_invalid_line) {
2063+ say("No such line %ld in input file, ignoring\n", line);
2064+ warn_on_invalid_line = 0;
2065+ }
2066+ return NULL;
2067+ }
2068+ if (using_plan_a)
2069+ return i_ptr[line];
2070+ else {
2071+ LINENUM offline = line % lines_per_buf;
2072+ LINENUM baseline = line - offline;
2073+
2074+ if (tiline[0] == baseline)
2075+ whichbuf = 0;
2076+ else if (tiline[1] == baseline)
2077+ whichbuf = 1;
2078+ else {
2079+ tiline[whichbuf] = baseline;
2080+ if (lseek(tifd, (off_t)(baseline / lines_per_buf * BUFFERSIZE), SEEK_SET) < 0)
2081+ pfatal("cannot seek in the temporary input file");
2082+ if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
2083+ pfatal("error reading tmp file %s", TMPINNAME);
2084+ }
2085+ return tibuf[whichbuf] + (tireclen * offline);
2086+ }
2087 }
2088
2089 static int
2090 rev_in_string(const char *string)
2091 {
2092- const char *s;
2093- size_t patlen;
2094+ const char *s;
2095+ size_t patlen;
2096
2097- if (revision == NULL)
2098- return 1;
2099- patlen = strlen(revision);
2100- if (strnEQ(string, revision, patlen) && isspace((unsigned char)string[patlen]))
2101- return 1;
2102- for (s = string; *s; s++) {
2103- if (isspace((unsigned char)*s) && strnEQ(s + 1, revision, patlen) &&
2104- isspace((unsigned char)s[patlen + 1]))
2105- return 1;
2106- }
2107- return 0;
2108+ if (revision == NULL)
2109+ return 1;
2110+ patlen = strlen(revision);
2111+ if (strnEQ(string, revision, patlen) && isspace((unsigned char)string[patlen]))
2112+ return 1;
2113+ for (s = string; *s; s++) {
2114+ if (isspace((unsigned char)*s) && strnEQ(s + 1, revision, patlen) &&
2115+ isspace((unsigned char)s[patlen + 1]))
2116+ return 1;
2117+ }
2118+ return 0;
2119 }
2120
2121 void
2122 re_patch(void)
2123 {
2124- p_first = 0;
2125- p_newfirst = 0;
2126- p_ptrn_lines = 0;
2127- p_repl_lines = 0;
2128- p_end = (LINENUM)-1;
2129- p_max = 0;
2130- p_indent = 0;
2131+ p_first = 0;
2132+ p_newfirst = 0;
2133+ p_ptrn_lines = 0;
2134+ p_repl_lines = 0;
2135+ p_end = (LINENUM)-1;
2136+ p_max = 0;
2137+ p_indent = 0;
2138 }
2139
2140 void
2141 open_patch_file(const char *filename)
2142 {
2143- struct stat filestat;
2144-
2145- if (filename == NULL || *filename == '\0' || strEQ(filename, "-")) {
2146- pfp = fopen(TMPPATNAME, "w");
2147- if (pfp == NULL)
2148- pfatal("cant create %s", TMPPATNAME);
2149- while (getline(&buf, &bufsz, stdin) != -1)
2150- fprintf(pfp, "%s", buf);
2151- if (ferror(pfp) || fclose(pfp))
2152- pfatal("cant write %s", TMPPATNAME);
2153- filename = TMPPATNAME;
2154- }
2155- pfp = fopen(filename, "r");
2156- if (pfp == NULL)
2157- pfatal("patch file %s not found", filename);
2158- fstat(fileno(pfp), &filestat);
2159- p_filesize = filestat.st_size;
2160- next_intuit_at(0L, 1L);
2161- set_hunkmax();
2162+ struct stat filestat;
2163+
2164+ if (filename == NULL || *filename == '\0' || strEQ(filename, "-")) {
2165+ pfp = fopen(TMPPATNAME, "w");
2166+ if (pfp == NULL)
2167+ pfatal("cant create %s", TMPPATNAME);
2168+ while (getline(&buf, &bufsz, stdin) != -1)
2169+ fprintf(pfp, "%s", buf);
2170+ if (ferror(pfp) || fclose(pfp))
2171+ pfatal("cant write %s", TMPPATNAME);
2172+ filename = TMPPATNAME;
2173+ }
2174+ pfp = fopen(filename, "r");
2175+ if (pfp == NULL)
2176+ pfatal("patch file %s not found", filename);
2177+ fstat(fileno(pfp), &filestat);
2178+ p_filesize = filestat.st_size;
2179+ next_intuit_at(0L, 1L);
2180+ set_hunkmax();
2181 }
2182
2183 void
2184 set_hunkmax(void)
2185 {
2186- if (p_line == NULL)
2187- p_line = calloc((size_t)hunkmax, sizeof(char *));
2188- if (p_len == NULL)
2189- p_len = calloc((size_t)hunkmax, sizeof(ssize_t));
2190- if (p_char == NULL)
2191- p_char = calloc((size_t)hunkmax, sizeof(char));
2192+ if (p_line == NULL)
2193+ p_line = calloc((size_t)hunkmax, sizeof(char *));
2194+ if (p_len == NULL)
2195+ p_len = calloc((size_t)hunkmax, sizeof(ssize_t));
2196+ if (p_char == NULL)
2197+ p_char = calloc((size_t)hunkmax, sizeof(char));
2198 }
2199
2200 static void
2201 grow_hunkmax(void)
2202 {
2203- int new_hunkmax;
2204- char **new_p_line;
2205- ssize_t *new_p_len;
2206- char *new_p_char;
2207+ int new_hunkmax;
2208+ char **new_p_line;
2209+ ssize_t *new_p_len;
2210+ char *new_p_char;
2211
2212- new_hunkmax = hunkmax * 2;
2213- if (p_line == NULL || p_len == NULL || p_char == NULL)
2214- fatal("Internal memory allocation error\n");
2215+ new_hunkmax = hunkmax * 2;
2216+ if (p_line == NULL || p_len == NULL || p_char == NULL)
2217+ fatal("Internal memory allocation error\n");
2218
2219- new_p_line = pch_realloc(p_line, new_hunkmax, sizeof(char *));
2220- if (new_p_line == NULL)
2221- free(p_line);
2222- new_p_len = pch_realloc(p_len, new_hunkmax, sizeof(ssize_t));
2223- if (new_p_len == NULL)
2224- free(p_len);
2225- new_p_char = pch_realloc(p_char, new_hunkmax, sizeof(char));
2226- if (new_p_char == NULL)
2227- free(p_char);
2228+ new_p_line = pch_realloc(p_line, new_hunkmax, sizeof(char *));
2229+ if (new_p_line == NULL)
2230+ free(p_line);
2231+ new_p_len = pch_realloc(p_len, new_hunkmax, sizeof(ssize_t));
2232+ if (new_p_len == NULL)
2233+ free(p_len);
2234+ new_p_char = pch_realloc(p_char, new_hunkmax, sizeof(char));
2235+ if (new_p_char == NULL)
2236+ free(p_char);
2237
2238- p_char = new_p_char;
2239- p_len = new_p_len;
2240- p_line = new_p_line;
2241+ p_char = new_p_char;
2242+ p_len = new_p_len;
2243+ p_line = new_p_line;
2244
2245- if (p_line != NULL && p_len != NULL && p_char != NULL) {
2246- hunkmax = new_hunkmax;
2247- return;
2248- }
2249+ if (p_line != NULL && p_len != NULL && p_char != NULL) {
2250+ hunkmax = new_hunkmax;
2251+ return;
2252+ }
2253
2254- if (!using_plan_a)
2255- fatal("out of memory\n");
2256- out_of_mem = 1;
2257+ if (!using_plan_a)
2258+ fatal("out of memory\n");
2259+ out_of_mem = 1;
2260 }
2261
2262 int
2263 there_is_another_patch(void)
2264 {
2265- int exists = 0;
2266-
2267- if (p_base != 0L && p_base >= p_filesize) {
2268- if (verbose)
2269- say("done\n");
2270- return 0;
2271- }
2272- if (verbose)
2273- say("Hmm...");
2274- diff_type = intuit_diff_type();
2275- if (!diff_type) {
2276- if (p_base != 0L) {
2277- if (verbose)
2278- say(" Ignoring the trailing garbage.\ndone\n");
2279- } else
2280- say(" I cant seem to find a patch in there anywhere\n");
2281- return 0;
2282- }
2283- if (verbose) {
2284- say(" %sooks like %s to me...\n",
2285- (p_base == 0L ? "L" : "The next patch l"),
2286- diff_type == UNI_DIFF ? "a unified diff" :
2287- diff_type == CONTEXT_DIFF ? "a context diff" :
2288- diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
2289- diff_type == NORMAL_DIFF ? "a normal diff" : "an ed script");
2290- }
2291- if (p_indent && verbose)
2292- say("(Patch is indented %d space%s.)\n", p_indent, p_indent == 1 ? "" : "s");
2293- skip_to(p_start, p_sline);
2294- while (filearg[0] == NULL) {
2295- if (force || batch) {
2296- say("No file to patch. Skipping...\n");
2297- filearg[0] = savestr(bestguess);
2298- skip_rest_of_patch = 1;
2299- return 1;
2300- }
2301- ask("File to patch: ");
2302- if (*buf != '\n') {
2303- free(bestguess);
2304- bestguess = savestr(buf);
2305- filearg[0] = fetchname(buf, &exists, 0);
2306- }
2307- if (!exists) {
2308- ask("No file found--skip this patch? [n] ");
2309- if (*buf != 'y')
2310- continue;
2311- if (verbose)
2312- say("Skipping patch...\n");
2313- free(filearg[0]);
2314- filearg[0] = fetchname(bestguess, &exists, 0);
2315- skip_rest_of_patch = 1;
2316- return 1;
2317- }
2318- }
2319- return 1;
2320+ int exists = 0;
2321+
2322+ if (p_base != 0L && p_base >= p_filesize) {
2323+ if (verbose)
2324+ say("done\n");
2325+ return 0;
2326+ }
2327+ if (verbose)
2328+ say("Hmm...");
2329+ diff_type = intuit_diff_type();
2330+ if (!diff_type) {
2331+ if (p_base != 0L) {
2332+ if (verbose)
2333+ say(" Ignoring the trailing garbage.\ndone\n");
2334+ } else
2335+ say(" I cant seem to find a patch in there anywhere\n");
2336+ return 0;
2337+ }
2338+ if (verbose) {
2339+ say(" %sooks like %s to me...\n",
2340+ (p_base == 0L ? "L" : "The next patch l"),
2341+ diff_type == UNI_DIFF ? "a unified diff" :
2342+ diff_type == CONTEXT_DIFF ? "a context diff" :
2343+ diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
2344+ diff_type == NORMAL_DIFF ? "a normal diff" : "an ed script");
2345+ }
2346+ if (p_indent && verbose)
2347+ say("(Patch is indented %d space%s.)\n", p_indent, p_indent == 1 ? "" : "s");
2348+ skip_to(p_start, p_sline);
2349+ while (filearg[0] == NULL) {
2350+ if (force || batch) {
2351+ say("No file to patch. Skipping...\n");
2352+ filearg[0] = savestr(bestguess);
2353+ skip_rest_of_patch = 1;
2354+ return 1;
2355+ }
2356+ ask("File to patch: ");
2357+ if (*buf != '\n') {
2358+ free(bestguess);
2359+ bestguess = savestr(buf);
2360+ filearg[0] = fetchname(buf, &exists, 0);
2361+ }
2362+ if (!exists) {
2363+ ask("No file found--skip this patch? [n] ");
2364+ if (*buf != 'y')
2365+ continue;
2366+ if (verbose)
2367+ say("Skipping patch...\n");
2368+ free(filearg[0]);
2369+ filearg[0] = fetchname(bestguess, &exists, 0);
2370+ skip_rest_of_patch = 1;
2371+ return 1;
2372+ }
2373+ }
2374+ return 1;
2375 }
2376
2377 static int
2378 intuit_diff_type(void)
2379 {
2380- long this_line = 0, previous_line;
2381- long first_command_line = -1;
2382- LINENUM fcl_line = -1;
2383- int last_line_was_command = 0, this_is_a_command = 0;
2384- int stars_last_line = 0, stars_this_line = 0;
2385- char *s, *t;
2386- int indent, retval;
2387- struct FileName names[MAX_FILE];
2388-
2389- memset(names, 0, sizeof(names));
2390- ok_to_create_file = 0;
2391- fseek(pfp, p_base, SEEK_SET);
2392- p_input_line = p_bline - 1;
2393- for (;;) {
2394- previous_line = this_line;
2395- last_line_was_command = this_is_a_command;
2396- stars_last_line = stars_this_line;
2397- this_line = ftell(pfp);
2398- indent = 0;
2399- p_input_line++;
2400- if (getline(&buf, &bufsz, pfp) == -1) {
2401- if (first_command_line >= 0L) {
2402- p_start = first_command_line;
2403- p_sline = fcl_line;
2404- retval = ED_DIFF;
2405- goto scan_exit;
2406- } else {
2407- p_start = this_line;
2408- p_sline = p_input_line;
2409- retval = 0;
2410- goto scan_exit;
2411- }
2412- }
2413- for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
2414- if (*s == '\t')
2415- indent += 8 - (indent % 8);
2416- else
2417- indent++;
2418- }
2419- for (t = s; isdigit((unsigned char)*t) || *t == ','; t++)
2420- ;
2421- this_is_a_command = (isdigit((unsigned char)*s) && (*t == 'd' || *t == 'c' || *t == 'a'));
2422- if (first_command_line < 0L && this_is_a_command) {
2423- first_command_line = this_line;
2424- fcl_line = p_input_line;
2425- p_indent = indent;
2426- }
2427- if (!stars_last_line && strnEQ(s, "*** ", 4)) {
2428- names[OLD_FILE].path = fetchname(s + 4, &names[OLD_FILE].exists, strippath);
2429- } else if (strnEQ(s, "--- ", 4)) {
2430- names[NEW_FILE].path = fetchname(s + 4, &names[NEW_FILE].exists, strippath);
2431- } else if (strnEQ(s, "+++ ", 4)) {
2432- names[OLD_FILE].path = fetchname(s + 4, &names[OLD_FILE].exists, strippath);
2433- } else if (strnEQ(s, "Index:", 6)) {
2434- names[INDEX_FILE].path = fetchname(s + 6, &names[INDEX_FILE].exists, strippath);
2435- } else if (strnEQ(s, "Prereq:", 7)) {
2436- for (t = s + 7; isspace((unsigned char)*t); t++)
2437- ;
2438- revision = savestr(t);
2439- for (t = revision; *t && !isspace((unsigned char)*t); t++)
2440- ;
2441- *t = '\0';
2442- if (*revision == '\0') {
2443- free(revision);
2444- revision = NULL;
2445- }
2446- }
2447- if ((!diff_type || diff_type == ED_DIFF) && first_command_line >= 0L && strEQ(s, ".\n")) {
2448- p_indent = indent;
2449- p_start = first_command_line;
2450- p_sline = fcl_line;
2451- retval = ED_DIFF;
2452- goto scan_exit;
2453- }
2454- if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) {
2455- if (strnEQ(s + 4, "0,0", 3))
2456- ok_to_create_file = 1;
2457- p_indent = indent;
2458- p_start = this_line;
2459- p_sline = p_input_line;
2460- retval = UNI_DIFF;
2461- goto scan_exit;
2462- }
2463- stars_this_line = strnEQ(s, "********", 8);
2464- if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line && strnEQ(s, "*** ", 4)) {
2465- if (atol(s + 4) == 0)
2466- ok_to_create_file = 1;
2467- while (*s != '\n')
2468- s++;
2469- p_indent = indent;
2470- p_start = previous_line;
2471- p_sline = p_input_line - 1;
2472- retval = (*(s - 1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
2473- goto scan_exit;
2474- }
2475- if ((!diff_type || diff_type == NORMAL_DIFF) && last_line_was_command &&
2476- (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2))) {
2477- p_start = previous_line;
2478- p_sline = p_input_line - 1;
2479- p_indent = indent;
2480- retval = NORMAL_DIFF;
2481- goto scan_exit;
2482- }
2483- }
2484+ long this_line = 0, previous_line;
2485+ long first_command_line = -1;
2486+ LINENUM fcl_line = -1;
2487+ int last_line_was_command = 0, this_is_a_command = 0;
2488+ int stars_last_line = 0, stars_this_line = 0;
2489+ char *s, *t;
2490+ int indent, retval;
2491+ struct FileName names[MAX_FILE];
2492+
2493+ memset(names, 0, sizeof(names));
2494+ ok_to_create_file = 0;
2495+ fseek(pfp, p_base, SEEK_SET);
2496+ p_input_line = p_bline - 1;
2497+ for (;;) {
2498+ previous_line = this_line;
2499+ last_line_was_command = this_is_a_command;
2500+ stars_last_line = stars_this_line;
2501+ this_line = ftell(pfp);
2502+ indent = 0;
2503+ p_input_line++;
2504+ if (getline(&buf, &bufsz, pfp) == -1) {
2505+ if (first_command_line >= 0L) {
2506+ p_start = first_command_line;
2507+ p_sline = fcl_line;
2508+ retval = ED_DIFF;
2509+ goto scan_exit;
2510+ } else {
2511+ p_start = this_line;
2512+ p_sline = p_input_line;
2513+ retval = 0;
2514+ goto scan_exit;
2515+ }
2516+ }
2517+ for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
2518+ if (*s == '\t')
2519+ indent += 8 - (indent % 8);
2520+ else
2521+ indent++;
2522+ }
2523+ for (t = s; isdigit((unsigned char)*t) || *t == ','; t++)
2524+ ;
2525+ this_is_a_command = (isdigit((unsigned char)*s) && (*t == 'd' || *t == 'c' || *t == 'a'));
2526+ if (first_command_line < 0L && this_is_a_command) {
2527+ first_command_line = this_line;
2528+ fcl_line = p_input_line;
2529+ p_indent = indent;
2530+ }
2531+ if (!stars_last_line && strnEQ(s, "*** ", 4)) {
2532+ names[OLD_FILE].path = fetchname(s + 4, &names[OLD_FILE].exists, strippath);
2533+ } else if (strnEQ(s, "--- ", 4)) {
2534+ names[NEW_FILE].path = fetchname(s + 4, &names[NEW_FILE].exists, strippath);
2535+ } else if (strnEQ(s, "+++ ", 4)) {
2536+ names[OLD_FILE].path = fetchname(s + 4, &names[OLD_FILE].exists, strippath);
2537+ } else if (strnEQ(s, "Index:", 6)) {
2538+ names[INDEX_FILE].path = fetchname(s + 6, &names[INDEX_FILE].exists, strippath);
2539+ } else if (strnEQ(s, "Prereq:", 7)) {
2540+ for (t = s + 7; isspace((unsigned char)*t); t++)
2541+ ;
2542+ revision = savestr(t);
2543+ for (t = revision; *t && !isspace((unsigned char)*t); t++)
2544+ ;
2545+ *t = '\0';
2546+ if (*revision == '\0') {
2547+ free(revision);
2548+ revision = NULL;
2549+ }
2550+ }
2551+ if ((!diff_type || diff_type == ED_DIFF) && first_command_line >= 0L && strEQ(s, ".\n")) {
2552+ p_indent = indent;
2553+ p_start = first_command_line;
2554+ p_sline = fcl_line;
2555+ retval = ED_DIFF;
2556+ goto scan_exit;
2557+ }
2558+ if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) {
2559+ if (strnEQ(s + 4, "0,0", 3))
2560+ ok_to_create_file = 1;
2561+ p_indent = indent;
2562+ p_start = this_line;
2563+ p_sline = p_input_line;
2564+ retval = UNI_DIFF;
2565+ goto scan_exit;
2566+ }
2567+ stars_this_line = strnEQ(s, "********", 8);
2568+ if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line && strnEQ(s, "*** ", 4)) {
2569+ if (atol(s + 4) == 0)
2570+ ok_to_create_file = 1;
2571+ while (*s != '\n')
2572+ s++;
2573+ p_indent = indent;
2574+ p_start = previous_line;
2575+ p_sline = p_input_line - 1;
2576+ retval = (*(s - 1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
2577+ goto scan_exit;
2578+ }
2579+ if ((!diff_type || diff_type == NORMAL_DIFF) && last_line_was_command &&
2580+ (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2))) {
2581+ p_start = previous_line;
2582+ p_sline = p_input_line - 1;
2583+ p_indent = indent;
2584+ retval = NORMAL_DIFF;
2585+ goto scan_exit;
2586+ }
2587+ }
2588 scan_exit:
2589- if (retval == UNI_DIFF) {
2590- struct FileName tmp = names[OLD_FILE];
2591- names[OLD_FILE] = names[NEW_FILE];
2592- names[NEW_FILE] = tmp;
2593- }
2594- if (filearg[0] == NULL) {
2595- if (posix)
2596- filearg[0] = posix_name(names, ok_to_create_file);
2597- else {
2598- if (names[OLD_FILE].path != NULL || names[NEW_FILE].path != NULL) {
2599- free(names[INDEX_FILE].path);
2600- names[INDEX_FILE].path = NULL;
2601- }
2602- filearg[0] = best_name(names, ok_to_create_file);
2603- }
2604- }
2605- free(bestguess);
2606- bestguess = NULL;
2607- if (filearg[0] != NULL)
2608- bestguess = savestr(filearg[0]);
2609- else if (!ok_to_create_file) {
2610- if (posix)
2611- bestguess = posix_name(names, 1);
2612- else
2613- bestguess = best_name(names, 1);
2614- }
2615- free(names[OLD_FILE].path);
2616- free(names[NEW_FILE].path);
2617- free(names[INDEX_FILE].path);
2618- return retval;
2619+ if (retval == UNI_DIFF) {
2620+ struct FileName tmp = names[OLD_FILE];
2621+ names[OLD_FILE] = names[NEW_FILE];
2622+ names[NEW_FILE] = tmp;
2623+ }
2624+ if (filearg[0] == NULL) {
2625+ if (posix)
2626+ filearg[0] = posix_name(names, ok_to_create_file);
2627+ else {
2628+ if (names[OLD_FILE].path != NULL || names[NEW_FILE].path != NULL) {
2629+ free(names[INDEX_FILE].path);
2630+ names[INDEX_FILE].path = NULL;
2631+ }
2632+ filearg[0] = best_name(names, ok_to_create_file);
2633+ }
2634+ }
2635+ free(bestguess);
2636+ bestguess = NULL;
2637+ if (filearg[0] != NULL)
2638+ bestguess = savestr(filearg[0]);
2639+ else if (!ok_to_create_file) {
2640+ if (posix)
2641+ bestguess = posix_name(names, 1);
2642+ else
2643+ bestguess = best_name(names, 1);
2644+ }
2645+ free(names[OLD_FILE].path);
2646+ free(names[NEW_FILE].path);
2647+ free(names[INDEX_FILE].path);
2648+ return retval;
2649 }
2650
2651 static void
2652 next_intuit_at(LINENUM file_pos, LINENUM file_line)
2653 {
2654- p_base = file_pos;
2655- p_bline = file_line;
2656+ p_base = file_pos;
2657+ p_bline = file_line;
2658 }
2659
2660 static void
2661 skip_to(LINENUM file_pos, LINENUM file_line)
2662 {
2663- int ret;
2664-
2665- if (p_base > file_pos)
2666- fatal("Internal error: seek %ld>%ld\n", p_base, file_pos);
2667- if (verbose && p_base < file_pos) {
2668- fseek(pfp, p_base, SEEK_SET);
2669- say("The text leading up to this was:\n--------------------------\n");
2670- while (ftell(pfp) < file_pos) {
2671- ret = getline(&buf, &bufsz, pfp);
2672- if (ret == -1)
2673- fatal("Unexpected end of file\n");
2674- say("|%s", buf);
2675- }
2676- say("--------------------------\n");
2677- } else
2678- fseek(pfp, file_pos, SEEK_SET);
2679- p_input_line = file_line - 1;
2680+ int ret;
2681+
2682+ if (p_base > file_pos)
2683+ fatal("Internal error: seek %ld>%ld\n", p_base, file_pos);
2684+ if (verbose && p_base < file_pos) {
2685+ fseek(pfp, p_base, SEEK_SET);
2686+ say("The text leading up to this was:\n--------------------------\n");
2687+ while (ftell(pfp) < file_pos) {
2688+ ret = getline(&buf, &bufsz, pfp);
2689+ if (ret == -1)
2690+ fatal("Unexpected end of file\n");
2691+ say("|%s", buf);
2692+ }
2693+ say("--------------------------\n");
2694+ } else
2695+ fseek(pfp, file_pos, SEEK_SET);
2696+ p_input_line = file_line - 1;
2697 }
2698
2699 __dead static void
2700 malformed(void)
2701 {
2702- fatal("malformed patch at line %ld: %s", p_input_line, buf);
2703+ fatal("malformed patch at line %ld: %s", p_input_line, buf);
2704 }
2705
2706 static LINENUM
2707 getlinenum(const char *s)
2708 {
2709- LINENUM l = (LINENUM)atol(s);
2710- if (l < 0) {
2711- l = 0;
2712- malformed();
2713- }
2714- return l;
2715+ LINENUM l = (LINENUM)atol(s);
2716+ if (l < 0) {
2717+ l = 0;
2718+ malformed();
2719+ }
2720+ return l;
2721 }
2722
2723 static LINENUM
2724 getskiplinenum(char **p)
2725 {
2726- char *s = *p;
2727- LINENUM l = getlinenum(s);
2728- while (isdigit((unsigned char)*s))
2729- s++;
2730- *p = s;
2731- return l;
2732+ char *s = *p;
2733+ LINENUM l = getlinenum(s);
2734+ while (isdigit((unsigned char)*s))
2735+ s++;
2736+ *p = s;
2737+ return l;
2738 }
2739
2740 static int
2741 remove_special_line(void)
2742 {
2743- int c;
2744+ int c;
2745
2746- c = fgetc(pfp);
2747- if (c == '\\') {
2748- do {
2749- c = fgetc(pfp);
2750- } while (c != EOF && c != '\n');
2751- return 1;
2752- }
2753- if (c != EOF)
2754- fseek(pfp, -1L, SEEK_CUR);
2755- return 0;
2756+ c = fgetc(pfp);
2757+ if (c == '\\') {
2758+ do {
2759+ c = fgetc(pfp);
2760+ } while (c != EOF && c != '\n');
2761+ return 1;
2762+ }
2763+ if (c != EOF)
2764+ fseek(pfp, -1L, SEEK_CUR);
2765+ return 0;
2766 }
2767
2768 int
2769 another_hunk(void)
2770 {
2771- long line_beginning;
2772- LINENUM repl_beginning;
2773- LINENUM fillcnt;
2774- LINENUM fillsrc;
2775- LINENUM filldst;
2776- int ptrn_spaces_eaten;
2777- int repl_could_be_missing;
2778- int repl_missing;
2779- long repl_backtrack_position;
2780- LINENUM repl_patch_line;
2781- LINENUM ptrn_copiable;
2782- char *s;
2783- int context = 0;
2784- int ret;
2785-
2786- while (p_end >= 0) {
2787- if (p_end == p_efake)
2788- p_end = p_bfake;
2789- else
2790- free(p_line[p_end]);
2791- p_end--;
2792- }
2793- p_efake = -1;
2794- p_max = hunkmax;
2795-
2796- if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
2797- line_beginning = ftell(pfp);
2798- repl_beginning = 0;
2799- fillcnt = 0;
2800- fillsrc = 0;
2801- filldst = 0;
2802- ptrn_spaces_eaten = 0;
2803- repl_could_be_missing = 1;
2804- repl_missing = 0;
2805- repl_backtrack_position = 0;
2806- repl_patch_line = 0;
2807- ptrn_copiable = 0;
2808-
2809- ret = pgetline(&buf, &bufsz, pfp);
2810- p_input_line++;
2811- if (ret == -1 || strnNE(buf, "********", 8)) {
2812- next_intuit_at(line_beginning, p_input_line);
2813- return 0;
2814- }
2815- p_context = 100;
2816- p_hunk_beg = p_input_line + 1;
2817- while (p_end < p_max) {
2818- ret = pgetline(&buf, &bufsz, pfp);
2819- p_input_line++;
2820- if (ret == -1) {
2821- if (repl_beginning && repl_could_be_missing) {
2822- repl_missing = 1;
2823- goto hunk_done;
2824- }
2825- fatal("unexpected end of file in patch\n");
2826- }
2827- p_end++;
2828- if (p_end >= hunkmax)
2829- fatal("Internal error: hunk larger than hunk buffer size");
2830- p_char[p_end] = *buf;
2831- p_line[p_end] = NULL;
2832- switch (*buf) {
2833- case '*':
2834- if (strnEQ(buf, "********", 8)) {
2835- if (repl_beginning && repl_could_be_missing) {
2836- repl_missing = 1;
2837- goto hunk_done;
2838- } else
2839- fatal("unexpected end of hunk at line %ld\n", p_input_line);
2840- }
2841- if (p_end != 0) {
2842- if (repl_beginning && repl_could_be_missing) {
2843- repl_missing = 1;
2844- goto hunk_done;
2845- }
2846- fatal("unexpected *** at line %ld: %s", p_input_line, buf);
2847- }
2848- context = 0;
2849- p_line[p_end] = savestr(buf);
2850- if (out_of_mem) {
2851- p_end--;
2852- return 0;
2853- }
2854- for (s = buf; *s && !isdigit((unsigned char)*s); s++)
2855- ;
2856- if (!*s)
2857- malformed();
2858- if (strnEQ(s, "0,0", 3))
2859- memmove(s, s + 2, strlen(s + 2) + 1);
2860- p_first = getskiplinenum(&s);
2861- if (*s == ',') {
2862- for (; *s && !isdigit((unsigned char)*s); s++)
2863- ;
2864- if (!*s)
2865- malformed();
2866- p_ptrn_lines = (getlinenum(s)) - p_first + 1;
2867- if (p_ptrn_lines < 0)
2868- malformed();
2869- } else if (p_first)
2870- p_ptrn_lines = 1;
2871- else {
2872- p_ptrn_lines = 0;
2873- p_first = 1;
2874- }
2875- if (p_first >= LINENUM_MAX - p_ptrn_lines || p_ptrn_lines >= LINENUM_MAX - 6)
2876- malformed();
2877- p_max = p_ptrn_lines + 6;
2878- while (p_max >= hunkmax)
2879- grow_hunkmax();
2880- p_max = hunkmax;
2881- break;
2882- case '-':
2883- if (buf[1] == '-') {
2884- if (repl_beginning || (p_end != p_ptrn_lines + 1 + (p_char[p_end - 1] == '\n'))) {
2885- if (p_end == 1) {
2886- p_end = p_ptrn_lines + 1;
2887- fillsrc = p_end + 1;
2888- filldst = 1;
2889- fillcnt = p_ptrn_lines;
2890- } else {
2891- if (repl_beginning) {
2892- if (repl_could_be_missing) {
2893- repl_missing = 1;
2894- goto hunk_done;
2895- }
2896- fatal("duplicate \"---\" at line %ld\n", p_input_line);
2897- } else {
2898- fatal("premature/overdue \"---\" at line %ld\n", p_input_line);
2899- }
2900- }
2901- }
2902- repl_beginning = p_end;
2903- repl_backtrack_position = ftell(pfp);
2904- repl_patch_line = p_input_line;
2905- p_line[p_end] = savestr(buf);
2906- if (out_of_mem) {
2907- p_end--;
2908- return 0;
2909- }
2910- p_char[p_end] = '=';
2911- for (s = buf; *s && !isdigit((unsigned char)*s); s++)
2912- ;
2913- if (!*s)
2914- malformed();
2915- p_newfirst = getskiplinenum(&s);
2916- if (*s == ',') {
2917- for (; *s && !isdigit((unsigned char)*s); s++)
2918- ;
2919- if (!*s)
2920- malformed();
2921- p_repl_lines = (getlinenum(s)) - p_newfirst + 1;
2922- if (p_repl_lines < 0)
2923- malformed();
2924- } else if (p_newfirst)
2925- p_repl_lines = 1;
2926- else {
2927- p_repl_lines = 0;
2928- p_newfirst = 1;
2929- }
2930- if (p_newfirst >= LINENUM_MAX - p_repl_lines || p_repl_lines >= LINENUM_MAX - p_end)
2931- malformed();
2932- p_max = p_repl_lines + p_end;
2933- if (p_max > MAXHUNKSIZE)
2934- fatal("hunk too large at line %ld\n", p_input_line);
2935- while (p_max >= hunkmax)
2936- grow_hunkmax();
2937- if (p_repl_lines != ptrn_copiable && (p_context != 0 || p_repl_lines != 1))
2938- repl_could_be_missing = 0;
2939- break;
2940- }
2941- goto change_line;
2942- case '+':
2943- case '!':
2944- repl_could_be_missing = 0;
2945- change_line:
2946- if (buf[1] == '\n' && canonicalize)
2947- strlcpy(buf + 1, " \n", bufsz - 1);
2948- if (!isspace((unsigned char)buf[1]) && buf[1] != '>' && buf[1] != '<' &&
2949- repl_beginning && repl_could_be_missing) {
2950- repl_missing = 1;
2951- goto hunk_done;
2952- }
2953- if (context >= 0) {
2954- if (context < p_context)
2955- p_context = context;
2956- context = -1000;
2957- }
2958- p_line[p_end] = savestr(buf + 2);
2959- if (out_of_mem) {
2960- p_end--;
2961- return 0;
2962- }
2963- if (p_end == p_ptrn_lines) {
2964- if (remove_special_line()) {
2965- int length = strlen(p_line[p_end]) - 1;
2966- (p_line[p_end])[length] = 0;
2967- }
2968- }
2969- break;
2970- case '\t':
2971- case '\n':
2972- if (repl_beginning && repl_could_be_missing &&
2973- (!ptrn_spaces_eaten || diff_type == NEW_CONTEXT_DIFF)) {
2974- repl_missing = 1;
2975- goto hunk_done;
2976- }
2977- p_line[p_end] = savestr(buf);
2978- if (out_of_mem) {
2979- p_end--;
2980- return 0;
2981- }
2982- if (p_end != p_ptrn_lines + 1) {
2983- ptrn_spaces_eaten |= (repl_beginning != 0);
2984- context++;
2985- if (!repl_beginning)
2986- ptrn_copiable++;
2987- p_char[p_end] = ' ';
2988- }
2989- break;
2990- case ' ':
2991- if (!isspace((unsigned char)buf[1]) && repl_beginning && repl_could_be_missing) {
2992- repl_missing = 1;
2993- goto hunk_done;
2994- }
2995- context++;
2996- if (!repl_beginning)
2997- ptrn_copiable++;
2998- p_line[p_end] = savestr(buf + 2);
2999- if (out_of_mem) {
3000- p_end--;
3001- return 0;
3002- }
3003- break;
3004- default:
3005- if (repl_beginning && repl_could_be_missing) {
3006- repl_missing = 1;
3007- goto hunk_done;
3008- }
3009- malformed();
3010- }
3011- if (p_line[p_end])
3012- p_len[p_end] = strlen(p_line[p_end]);
3013- else
3014- p_len[p_end] = 0;
3015- }
3016+ long line_beginning;
3017+ LINENUM repl_beginning;
3018+ LINENUM fillcnt;
3019+ LINENUM fillsrc;
3020+ LINENUM filldst;
3021+ int ptrn_spaces_eaten;
3022+ int repl_could_be_missing;
3023+ int repl_missing;
3024+ long repl_backtrack_position;
3025+ LINENUM repl_patch_line;
3026+ LINENUM ptrn_copiable;
3027+ char *s;
3028+ int context = 0;
3029+ int ret;
3030+
3031+ while (p_end >= 0) {
3032+ if (p_end == p_efake)
3033+ p_end = p_bfake;
3034+ else
3035+ free(p_line[p_end]);
3036+ p_end--;
3037+ }
3038+ p_efake = -1;
3039+ p_max = hunkmax;
3040+
3041+ if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
3042+ line_beginning = ftell(pfp);
3043+ repl_beginning = 0;
3044+ fillcnt = 0;
3045+ fillsrc = 0;
3046+ filldst = 0;
3047+ ptrn_spaces_eaten = 0;
3048+ repl_could_be_missing = 1;
3049+ repl_missing = 0;
3050+ repl_backtrack_position = 0;
3051+ repl_patch_line = 0;
3052+ ptrn_copiable = 0;
3053+
3054+ ret = pgetline(&buf, &bufsz, pfp);
3055+ p_input_line++;
3056+ if (ret == -1 || strnNE(buf, "********", 8)) {
3057+ next_intuit_at(line_beginning, p_input_line);
3058+ return 0;
3059+ }
3060+ p_context = 100;
3061+ p_hunk_beg = p_input_line + 1;
3062+ while (p_end < p_max) {
3063+ ret = pgetline(&buf, &bufsz, pfp);
3064+ p_input_line++;
3065+ if (ret == -1) {
3066+ if (repl_beginning && repl_could_be_missing) {
3067+ repl_missing = 1;
3068+ goto hunk_done;
3069+ }
3070+ fatal("unexpected end of file in patch\n");
3071+ }
3072+ p_end++;
3073+ if (p_end >= hunkmax)
3074+ fatal("Internal error: hunk larger than hunk buffer size");
3075+ p_char[p_end] = *buf;
3076+ p_line[p_end] = NULL;
3077+ switch (*buf) {
3078+ case '*':
3079+ if (strnEQ(buf, "********", 8)) {
3080+ if (repl_beginning && repl_could_be_missing) {
3081+ repl_missing = 1;
3082+ goto hunk_done;
3083+ } else
3084+ fatal("unexpected end of hunk at line %ld\n", p_input_line);
3085+ }
3086+ if (p_end != 0) {
3087+ if (repl_beginning && repl_could_be_missing) {
3088+ repl_missing = 1;
3089+ goto hunk_done;
3090+ }
3091+ fatal("unexpected *** at line %ld: %s", p_input_line, buf);
3092+ }
3093+ context = 0;
3094+ p_line[p_end] = savestr(buf);
3095+ if (out_of_mem) {
3096+ p_end--;
3097+ return 0;
3098+ }
3099+ for (s = buf; *s && !isdigit((unsigned char)*s); s++)
3100+ ;
3101+ if (!*s)
3102+ malformed();
3103+ if (strnEQ(s, "0,0", 3))
3104+ memmove(s, s + 2, strlen(s + 2) + 1);
3105+ p_first = getskiplinenum(&s);
3106+ if (*s == ',') {
3107+ for (; *s && !isdigit((unsigned char)*s); s++)
3108+ ;
3109+ if (!*s)
3110+ malformed();
3111+ p_ptrn_lines = (getlinenum(s)) - p_first + 1;
3112+ if (p_ptrn_lines < 0)
3113+ malformed();
3114+ } else if (p_first)
3115+ p_ptrn_lines = 1;
3116+ else {
3117+ p_ptrn_lines = 0;
3118+ p_first = 1;
3119+ }
3120+ if (p_first >= LINENUM_MAX - p_ptrn_lines || p_ptrn_lines >= LINENUM_MAX - 6)
3121+ malformed();
3122+ p_max = p_ptrn_lines + 6;
3123+ while (p_max >= hunkmax)
3124+ grow_hunkmax();
3125+ p_max = hunkmax;
3126+ break;
3127+ case '-':
3128+ if (buf[1] == '-') {
3129+ if (repl_beginning || (p_end != p_ptrn_lines + 1 + (p_char[p_end - 1] == '\n'))) {
3130+ if (p_end == 1) {
3131+ p_end = p_ptrn_lines + 1;
3132+ fillsrc = p_end + 1;
3133+ filldst = 1;
3134+ fillcnt = p_ptrn_lines;
3135+ } else {
3136+ if (repl_beginning) {
3137+ if (repl_could_be_missing) {
3138+ repl_missing = 1;
3139+ goto hunk_done;
3140+ }
3141+ fatal("duplicate \"---\" at line %ld\n", p_input_line);
3142+ } else {
3143+ fatal("premature/overdue \"---\" at line %ld\n", p_input_line);
3144+ }
3145+ }
3146+ }
3147+ repl_beginning = p_end;
3148+ repl_backtrack_position = ftell(pfp);
3149+ repl_patch_line = p_input_line;
3150+ p_line[p_end] = savestr(buf);
3151+ if (out_of_mem) {
3152+ p_end--;
3153+ return 0;
3154+ }
3155+ p_char[p_end] = '=';
3156+ for (s = buf; *s && !isdigit((unsigned char)*s); s++)
3157+ ;
3158+ if (!*s)
3159+ malformed();
3160+ p_newfirst = getskiplinenum(&s);
3161+ if (*s == ',') {
3162+ for (; *s && !isdigit((unsigned char)*s); s++)
3163+ ;
3164+ if (!*s)
3165+ malformed();
3166+ p_repl_lines = (getlinenum(s)) - p_newfirst + 1;
3167+ if (p_repl_lines < 0)
3168+ malformed();
3169+ } else if (p_newfirst)
3170+ p_repl_lines = 1;
3171+ else {
3172+ p_repl_lines = 0;
3173+ p_newfirst = 1;
3174+ }
3175+ if (p_newfirst >= LINENUM_MAX - p_repl_lines || p_repl_lines >= LINENUM_MAX - p_end)
3176+ malformed();
3177+ p_max = p_repl_lines + p_end;
3178+ if (p_max > MAXHUNKSIZE)
3179+ fatal("hunk too large at line %ld\n", p_input_line);
3180+ while (p_max >= hunkmax)
3181+ grow_hunkmax();
3182+ if (p_repl_lines != ptrn_copiable && (p_context != 0 || p_repl_lines != 1))
3183+ repl_could_be_missing = 0;
3184+ break;
3185+ }
3186+ goto change_line;
3187+ case '+':
3188+ case '!':
3189+ repl_could_be_missing = 0;
3190+ change_line:
3191+ if (buf[1] == '\n' && canonicalize)
3192+ strlcpy(buf + 1, " \n", bufsz - 1);
3193+ if (!isspace((unsigned char)buf[1]) && buf[1] != '>' && buf[1] != '<' &&
3194+ repl_beginning && repl_could_be_missing) {
3195+ repl_missing = 1;
3196+ goto hunk_done;
3197+ }
3198+ if (context >= 0) {
3199+ if (context < p_context)
3200+ p_context = context;
3201+ context = -1000;
3202+ }
3203+ p_line[p_end] = savestr(buf + 2);
3204+ if (out_of_mem) {
3205+ p_end--;
3206+ return 0;
3207+ }
3208+ if (p_end == p_ptrn_lines) {
3209+ if (remove_special_line()) {
3210+ int length = strlen(p_line[p_end]) - 1;
3211+ (p_line[p_end])[length] = 0;
3212+ }
3213+ }
3214+ break;
3215+ case '\t':
3216+ case '\n':
3217+ if (repl_beginning && repl_could_be_missing &&
3218+ (!ptrn_spaces_eaten || diff_type == NEW_CONTEXT_DIFF)) {
3219+ repl_missing = 1;
3220+ goto hunk_done;
3221+ }
3222+ p_line[p_end] = savestr(buf);
3223+ if (out_of_mem) {
3224+ p_end--;
3225+ return 0;
3226+ }
3227+ if (p_end != p_ptrn_lines + 1) {
3228+ ptrn_spaces_eaten |= (repl_beginning != 0);
3229+ context++;
3230+ if (!repl_beginning)
3231+ ptrn_copiable++;
3232+ p_char[p_end] = ' ';
3233+ }
3234+ break;
3235+ case ' ':
3236+ if (!isspace((unsigned char)buf[1]) && repl_beginning && repl_could_be_missing) {
3237+ repl_missing = 1;
3238+ goto hunk_done;
3239+ }
3240+ context++;
3241+ if (!repl_beginning)
3242+ ptrn_copiable++;
3243+ p_line[p_end] = savestr(buf + 2);
3244+ if (out_of_mem) {
3245+ p_end--;
3246+ return 0;
3247+ }
3248+ break;
3249+ default:
3250+ if (repl_beginning && repl_could_be_missing) {
3251+ repl_missing = 1;
3252+ goto hunk_done;
3253+ }
3254+ malformed();
3255+ }
3256+ if (p_line[p_end])
3257+ p_len[p_end] = strlen(p_line[p_end]);
3258+ else
3259+ p_len[p_end] = 0;
3260+ }
3261
3262 hunk_done:
3263- if (p_end >= 0 && !repl_beginning)
3264- fatal("no --- found in patch at line %ld\n", pch_hunk_beg());
3265-
3266- if (repl_missing) {
3267- p_input_line = repl_patch_line;
3268- for (p_end--; p_end > repl_beginning; p_end--)
3269- free(p_line[p_end]);
3270- fseek(pfp, repl_backtrack_position, SEEK_SET);
3271-
3272- if (!p_context && p_repl_lines == 1) {
3273- p_repl_lines = 0;
3274- p_max--;
3275- }
3276- fillsrc = 1;
3277- filldst = repl_beginning + 1;
3278- fillcnt = p_repl_lines;
3279- p_end = p_max;
3280- } else if (!p_context && fillcnt == 1) {
3281- while (filldst < p_end) {
3282- p_line[filldst] = p_line[filldst + 1];
3283- p_char[filldst] = p_char[filldst + 1];
3284- p_len[filldst] = p_len[filldst + 1];
3285- filldst++;
3286- }
3287- p_end--;
3288- p_first++;
3289- fillcnt = 0;
3290- p_ptrn_lines = 0;
3291- }
3292- if (diff_type == CONTEXT_DIFF && (fillcnt || (p_first > 1 && ptrn_copiable > 2 * p_context))) {
3293- diff_type = NEW_CONTEXT_DIFF;
3294- }
3295- if (fillcnt) {
3296- p_bfake = filldst;
3297- p_efake = filldst + fillcnt - 1;
3298- while (fillcnt-- > 0) {
3299- while (fillsrc <= p_end && p_char[fillsrc] != ' ')
3300- fillsrc++;
3301- if (fillsrc > p_end)
3302- fatal("replacement text mangled in hunk at line %ld\n", p_hunk_beg);
3303- p_line[filldst] = p_line[fillsrc];
3304- p_char[filldst] = p_char[fillsrc];
3305- p_len[filldst] = p_len[fillsrc];
3306- fillsrc++;
3307- filldst++;
3308- }
3309- while (fillsrc <= p_end && fillsrc != repl_beginning && p_char[fillsrc] != ' ')
3310- fillsrc++;
3311- if (fillsrc != p_end + 1 && fillsrc != repl_beginning)
3312- malformed();
3313- if (filldst != p_end + 1 && filldst != repl_beginning)
3314- malformed();
3315- }
3316- if (p_line[p_end] != NULL) {
3317- if (remove_special_line()) {
3318- p_len[p_end] -= 1;
3319- (p_line[p_end])[p_len[p_end]] = 0;
3320- }
3321- }
3322- } else if (diff_type == UNI_DIFF) {
3323- LINENUM fillold;
3324- LINENUM fillnew;
3325- char ch;
3326-
3327- line_beginning = ftell(pfp);
3328- ret = pgetline(&buf, &bufsz, pfp);
3329- p_input_line++;
3330- if (ret == -1 || strnNE(buf, "@@ -", 4)) {
3331- next_intuit_at(line_beginning, p_input_line);
3332- return 0;
3333- }
3334- s = buf + 4;
3335- if (!*s)
3336- malformed();
3337- p_first = getskiplinenum(&s);
3338- if (*s == ',') {
3339- s++;
3340- p_ptrn_lines = getskiplinenum(&s);
3341- } else
3342- p_ptrn_lines = 1;
3343- if (p_first >= LINENUM_MAX - p_ptrn_lines)
3344- malformed();
3345- if (*s == ' ')
3346- s++;
3347- if (*s != '+' || !*++s)
3348- malformed();
3349- p_newfirst = getskiplinenum(&s);
3350- if (*s == ',') {
3351- s++;
3352- p_repl_lines = getskiplinenum(&s);
3353- } else
3354- p_repl_lines = 1;
3355- if (*s == ' ')
3356- s++;
3357- if (*s != '@')
3358- malformed();
3359- if (p_first >= LINENUM_MAX - p_ptrn_lines ||
3360- p_newfirst > LINENUM_MAX - p_repl_lines ||
3361- p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
3362- malformed();
3363- if (!p_ptrn_lines)
3364- p_first++;
3365- p_max = p_ptrn_lines + p_repl_lines + 1;
3366- while (p_max >= hunkmax)
3367- grow_hunkmax();
3368- fillold = 1;
3369- fillnew = fillold + p_ptrn_lines;
3370- p_end = fillnew + p_repl_lines;
3371- snprintf(buf, bufsz, "*** %ld,%ld ****\n", p_first, p_first + p_ptrn_lines - 1);
3372- p_line[0] = savestr(buf);
3373- if (out_of_mem) {
3374- p_end = -1;
3375- return 0;
3376- }
3377- p_char[0] = '*';
3378- snprintf(buf, bufsz, "--- %ld,%ld ----\n", p_newfirst, p_newfirst + p_repl_lines - 1);
3379- p_line[fillnew] = savestr(buf);
3380- if (out_of_mem) {
3381- p_end = 0;
3382- return 0;
3383- }
3384- p_char[fillnew++] = '=';
3385- p_context = 100;
3386- context = 0;
3387- p_hunk_beg = p_input_line + 1;
3388- while (fillold <= p_ptrn_lines || fillnew <= p_end) {
3389- ret = pgetline(&buf, &bufsz, pfp);
3390- p_input_line++;
3391- if (ret == -1) {
3392- if (p_max - fillnew < 3)
3393- strlcpy(buf, " \n", bufsz);
3394- else
3395- fatal("unexpected end of file in patch\n");
3396- }
3397- if (*buf == '\t' || *buf == '\n') {
3398- ch = ' ';
3399- s = savestr(buf);
3400- } else {
3401- ch = *buf;
3402- s = savestr(buf + 1);
3403- }
3404- if (out_of_mem) {
3405- while (--fillnew > p_ptrn_lines)
3406- free(p_line[fillnew]);
3407- p_end = fillold - 1;
3408- return 0;
3409- }
3410- switch (ch) {
3411- case '-':
3412- if (fillold > p_ptrn_lines) {
3413- free(s);
3414- p_end = fillnew - 1;
3415- malformed();
3416- }
3417- p_char[fillold] = ch;
3418- p_line[fillold] = s;
3419- p_len[fillold++] = strlen(s);
3420- if (fillold > p_ptrn_lines) {
3421- if (remove_special_line()) {
3422- p_len[fillold - 1] -= 1;
3423- s[p_len[fillold - 1]] = 0;
3424- }
3425- }
3426- break;
3427- case '=':
3428- ch = ' ';
3429- /* FALL THROUGH */
3430- case ' ':
3431- if (fillold > p_ptrn_lines) {
3432- free(s);
3433- while (--fillnew > p_ptrn_lines)
3434- free(p_line[fillnew]);
3435- p_end = fillold - 1;
3436- malformed();
3437- }
3438- context++;
3439- p_char[fillold] = ch;
3440- p_line[fillold] = s;
3441- p_len[fillold++] = strlen(s);
3442- s = savestr(s);
3443- if (out_of_mem) {
3444- while (--fillnew > p_ptrn_lines)
3445- free(p_line[fillnew]);
3446- p_end = fillold - 1;
3447- return 0;
3448- }
3449- if (fillold > p_ptrn_lines) {
3450- if (remove_special_line()) {
3451- p_len[fillold - 1] -= 1;
3452- s[p_len[fillold - 1]] = 0;
3453- }
3454- }
3455- /* FALL THROUGH */
3456- case '+':
3457- if (fillnew > p_end) {
3458- free(s);
3459- while (--fillnew > p_ptrn_lines)
3460- free(p_line[fillnew]);
3461- p_end = fillold - 1;
3462- malformed();
3463- }
3464- p_char[fillnew] = ch;
3465- p_line[fillnew] = s;
3466- p_len[fillnew++] = strlen(s);
3467- if (fillold > p_ptrn_lines) {
3468- if (remove_special_line()) {
3469- p_len[fillnew - 1] -= 1;
3470- s[p_len[fillnew - 1]] = 0;
3471- }
3472- }
3473- break;
3474- default:
3475- p_end = fillnew;
3476- malformed();
3477- }
3478- if (ch != ' ' && context > 0) {
3479- if (context < p_context)
3480- p_context = context;
3481- context = -1000;
3482- }
3483- }
3484- } else {
3485- char hunk_type;
3486- int i;
3487- LINENUM min, max;
3488-
3489- line_beginning = ftell(pfp);
3490- p_context = 0;
3491- ret = pgetline(&buf, &bufsz, pfp);
3492- p_input_line++;
3493- if (ret == -1 || !isdigit((unsigned char)*buf)) {
3494- next_intuit_at(line_beginning, p_input_line);
3495- return 0;
3496- }
3497- s = buf;
3498- p_first = getskiplinenum(&s);
3499- if (*s == ',') {
3500- s++;
3501- p_ptrn_lines = getskiplinenum(&s) - p_first + 1;
3502- } else
3503- p_ptrn_lines = (*s != 'a');
3504- if (p_first >= LINENUM_MAX - p_ptrn_lines)
3505- malformed();
3506- hunk_type = *s++;
3507- if (hunk_type == 'a')
3508- p_first++;
3509- min = getskiplinenum(&s);
3510- if (*s == ',')
3511- max = getlinenum(++s);
3512- else
3513- max = min;
3514- if (min < 0 || min > max || max - min == LINENUM_MAX)
3515- malformed();
3516- if (hunk_type == 'd')
3517- min++;
3518- p_end = p_ptrn_lines + p_repl_lines + 1;
3519- p_newfirst = min;
3520- p_repl_lines = max - min + 1;
3521- if (p_newfirst > LINENUM_MAX - p_repl_lines || p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
3522- malformed();
3523- p_end = p_ptrn_lines + p_repl_lines + 1;
3524- if (p_end > MAXHUNKSIZE)
3525- fatal("hunk too large at line %ld\n", p_input_line);
3526- while (p_end >= hunkmax)
3527- grow_hunkmax();
3528- snprintf(buf, bufsz, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1);
3529- p_line[0] = savestr(buf);
3530- if (out_of_mem) {
3531- p_end = -1;
3532- return 0;
3533- }
3534- p_char[0] = '*';
3535- for (i = 1; i <= p_ptrn_lines; i++) {
3536- ret = pgetline(&buf, &bufsz, pfp);
3537- p_input_line++;
3538- if (ret == -1)
3539- fatal("unexpected end of file in patch at line %ld\n", p_input_line);
3540- if (*buf != '<')
3541- fatal("< expected at line %ld of patch\n", p_input_line);
3542- p_line[i] = savestr(buf + 2);
3543- if (out_of_mem) {
3544- p_end = i - 1;
3545- return 0;
3546- }
3547- p_len[i] = strlen(p_line[i]);
3548- p_char[i] = '-';
3549- }
3550- if (remove_special_line()) {
3551- p_len[i - 1] -= 1;
3552- (p_line[i - 1])[p_len[i - 1]] = 0;
3553- }
3554- if (hunk_type == 'c') {
3555- ret = pgetline(&buf, &bufsz, pfp);
3556- p_input_line++;
3557- if (ret == -1)
3558- fatal("unexpected end of file in patch at line %ld\n", p_input_line);
3559- if (*buf != '-')
3560- fatal("--- expected at line %ld of patch\n", p_input_line);
3561- }
3562- snprintf(buf, bufsz, "--- %ld,%ld\n", min, max);
3563- p_line[i] = savestr(buf);
3564- if (out_of_mem) {
3565- p_end = i - 1;
3566- return 0;
3567- }
3568- p_char[i] = '=';
3569- for (i++; i <= p_end; i++) {
3570- ret = pgetline(&buf, &bufsz, pfp);
3571- p_input_line++;
3572- if (ret == -1)
3573- fatal("unexpected end of file in patch at line %ld\n", p_input_line);
3574- if (*buf != '>')
3575- fatal("> expected at line %ld of patch\n", p_input_line);
3576- p_line[i] = savestr(buf + 2);
3577- if (out_of_mem) {
3578- p_end = i - 1;
3579- return 0;
3580- }
3581- p_len[i] = strlen(p_line[i]);
3582- p_char[i] = '+';
3583- }
3584- if (remove_special_line()) {
3585- p_len[i - 1] -= 1;
3586- (p_line[i - 1])[p_len[i - 1]] = 0;
3587- }
3588- }
3589- if (reverse) {
3590- if (!pch_swap())
3591- say("Not enough memory to swap next hunk!\n");
3592- }
3593- if (p_end + 1 < hunkmax)
3594- p_char[p_end + 1] = '^';
3595- return 1;
3596+ if (p_end >= 0 && !repl_beginning)
3597+ fatal("no --- found in patch at line %ld\n", pch_hunk_beg());
3598+
3599+ if (repl_missing) {
3600+ p_input_line = repl_patch_line;
3601+ for (p_end--; p_end > repl_beginning; p_end--)
3602+ free(p_line[p_end]);
3603+ fseek(pfp, repl_backtrack_position, SEEK_SET);
3604+
3605+ if (!p_context && p_repl_lines == 1) {
3606+ p_repl_lines = 0;
3607+ p_max--;
3608+ }
3609+ fillsrc = 1;
3610+ filldst = repl_beginning + 1;
3611+ fillcnt = p_repl_lines;
3612+ p_end = p_max;
3613+ } else if (!p_context && fillcnt == 1) {
3614+ while (filldst < p_end) {
3615+ p_line[filldst] = p_line[filldst + 1];
3616+ p_char[filldst] = p_char[filldst + 1];
3617+ p_len[filldst] = p_len[filldst + 1];
3618+ filldst++;
3619+ }
3620+ p_end--;
3621+ p_first++;
3622+ fillcnt = 0;
3623+ p_ptrn_lines = 0;
3624+ }
3625+ if (diff_type == CONTEXT_DIFF && (fillcnt || (p_first > 1 && ptrn_copiable > 2 * p_context))) {
3626+ diff_type = NEW_CONTEXT_DIFF;
3627+ }
3628+ if (fillcnt) {
3629+ p_bfake = filldst;
3630+ p_efake = filldst + fillcnt - 1;
3631+ while (fillcnt-- > 0) {
3632+ while (fillsrc <= p_end && p_char[fillsrc] != ' ')
3633+ fillsrc++;
3634+ if (fillsrc > p_end)
3635+ fatal("replacement text mangled in hunk at line %ld\n", p_hunk_beg);
3636+ p_line[filldst] = p_line[fillsrc];
3637+ p_char[filldst] = p_char[fillsrc];
3638+ p_len[filldst] = p_len[fillsrc];
3639+ fillsrc++;
3640+ filldst++;
3641+ }
3642+ while (fillsrc <= p_end && fillsrc != repl_beginning && p_char[fillsrc] != ' ')
3643+ fillsrc++;
3644+ if (fillsrc != p_end + 1 && fillsrc != repl_beginning)
3645+ malformed();
3646+ if (filldst != p_end + 1 && filldst != repl_beginning)
3647+ malformed();
3648+ }
3649+ if (p_line[p_end] != NULL) {
3650+ if (remove_special_line()) {
3651+ p_len[p_end] -= 1;
3652+ (p_line[p_end])[p_len[p_end]] = 0;
3653+ }
3654+ }
3655+ } else if (diff_type == UNI_DIFF) {
3656+ LINENUM fillold;
3657+ LINENUM fillnew;
3658+ char ch;
3659+
3660+ line_beginning = ftell(pfp);
3661+ ret = pgetline(&buf, &bufsz, pfp);
3662+ p_input_line++;
3663+ if (ret == -1 || strnNE(buf, "@@ -", 4)) {
3664+ next_intuit_at(line_beginning, p_input_line);
3665+ return 0;
3666+ }
3667+ s = buf + 4;
3668+ if (!*s)
3669+ malformed();
3670+ p_first = getskiplinenum(&s);
3671+ if (*s == ',') {
3672+ s++;
3673+ p_ptrn_lines = getskiplinenum(&s);
3674+ } else
3675+ p_ptrn_lines = 1;
3676+ if (p_first >= LINENUM_MAX - p_ptrn_lines)
3677+ malformed();
3678+ if (*s == ' ')
3679+ s++;
3680+ if (*s != '+' || !*++s)
3681+ malformed();
3682+ p_newfirst = getskiplinenum(&s);
3683+ if (*s == ',') {
3684+ s++;
3685+ p_repl_lines = getskiplinenum(&s);
3686+ } else
3687+ p_repl_lines = 1;
3688+ if (*s == ' ')
3689+ s++;
3690+ if (*s != '@')
3691+ malformed();
3692+ if (p_first >= LINENUM_MAX - p_ptrn_lines ||
3693+ p_newfirst > LINENUM_MAX - p_repl_lines ||
3694+ p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
3695+ malformed();
3696+ if (!p_ptrn_lines)
3697+ p_first++;
3698+ p_max = p_ptrn_lines + p_repl_lines + 1;
3699+ while (p_max >= hunkmax)
3700+ grow_hunkmax();
3701+ fillold = 1;
3702+ fillnew = fillold + p_ptrn_lines;
3703+ p_end = fillnew + p_repl_lines;
3704+ snprintf(buf, bufsz, "*** %ld,%ld ****\n", p_first, p_first + p_ptrn_lines - 1);
3705+ p_line[0] = savestr(buf);
3706+ if (out_of_mem) {
3707+ p_end = -1;
3708+ return 0;
3709+ }
3710+ p_char[0] = '*';
3711+ snprintf(buf, bufsz, "--- %ld,%ld ----\n", p_newfirst, p_newfirst + p_repl_lines - 1);
3712+ p_line[fillnew] = savestr(buf);
3713+ if (out_of_mem) {
3714+ p_end = 0;
3715+ return 0;
3716+ }
3717+ p_char[fillnew++] = '=';
3718+ p_context = 100;
3719+ context = 0;
3720+ p_hunk_beg = p_input_line + 1;
3721+ while (fillold <= p_ptrn_lines || fillnew <= p_end) {
3722+ ret = pgetline(&buf, &bufsz, pfp);
3723+ p_input_line++;
3724+ if (ret == -1) {
3725+ if (p_max - fillnew < 3)
3726+ strlcpy(buf, " \n", bufsz);
3727+ else
3728+ fatal("unexpected end of file in patch\n");
3729+ }
3730+ if (*buf == '\t' || *buf == '\n') {
3731+ ch = ' ';
3732+ s = savestr(buf);
3733+ } else {
3734+ ch = *buf;
3735+ s = savestr(buf + 1);
3736+ }
3737+ if (out_of_mem) {
3738+ while (--fillnew > p_ptrn_lines)
3739+ free(p_line[fillnew]);
3740+ p_end = fillold - 1;
3741+ return 0;
3742+ }
3743+ switch (ch) {
3744+ case '-':
3745+ if (fillold > p_ptrn_lines) {
3746+ free(s);
3747+ p_end = fillnew - 1;
3748+ malformed();
3749+ }
3750+ p_char[fillold] = ch;
3751+ p_line[fillold] = s;
3752+ p_len[fillold++] = strlen(s);
3753+ if (fillold > p_ptrn_lines) {
3754+ if (remove_special_line()) {
3755+ p_len[fillold - 1] -= 1;
3756+ s[p_len[fillold - 1]] = 0;
3757+ }
3758+ }
3759+ break;
3760+ case '=':
3761+ ch = ' ';
3762+ /* FALL THROUGH */
3763+ case ' ':
3764+ if (fillold > p_ptrn_lines) {
3765+ free(s);
3766+ while (--fillnew > p_ptrn_lines)
3767+ free(p_line[fillnew]);
3768+ p_end = fillold - 1;
3769+ malformed();
3770+ }
3771+ context++;
3772+ p_char[fillold] = ch;
3773+ p_line[fillold] = s;
3774+ p_len[fillold++] = strlen(s);
3775+ s = savestr(s);
3776+ if (out_of_mem) {
3777+ while (--fillnew > p_ptrn_lines)
3778+ free(p_line[fillnew]);
3779+ p_end = fillold - 1;
3780+ return 0;
3781+ }
3782+ if (fillold > p_ptrn_lines) {
3783+ if (remove_special_line()) {
3784+ p_len[fillold - 1] -= 1;
3785+ s[p_len[fillold - 1]] = 0;
3786+ }
3787+ }
3788+ /* FALL THROUGH */
3789+ case '+':
3790+ if (fillnew > p_end) {
3791+ free(s);
3792+ while (--fillnew > p_ptrn_lines)
3793+ free(p_line[fillnew]);
3794+ p_end = fillold - 1;
3795+ malformed();
3796+ }
3797+ p_char[fillnew] = ch;
3798+ p_line[fillnew] = s;
3799+ p_len[fillnew++] = strlen(s);
3800+ if (fillold > p_ptrn_lines) {
3801+ if (remove_special_line()) {
3802+ p_len[fillnew - 1] -= 1;
3803+ s[p_len[fillnew - 1]] = 0;
3804+ }
3805+ }
3806+ break;
3807+ default:
3808+ p_end = fillnew;
3809+ malformed();
3810+ }
3811+ if (ch != ' ' && context > 0) {
3812+ if (context < p_context)
3813+ p_context = context;
3814+ context = -1000;
3815+ }
3816+ }
3817+ } else {
3818+ char hunk_type;
3819+ int i;
3820+ LINENUM min, max;
3821+
3822+ line_beginning = ftell(pfp);
3823+ p_context = 0;
3824+ ret = pgetline(&buf, &bufsz, pfp);
3825+ p_input_line++;
3826+ if (ret == -1 || !isdigit((unsigned char)*buf)) {
3827+ next_intuit_at(line_beginning, p_input_line);
3828+ return 0;
3829+ }
3830+ s = buf;
3831+ p_first = getskiplinenum(&s);
3832+ if (*s == ',') {
3833+ s++;
3834+ p_ptrn_lines = getskiplinenum(&s) - p_first + 1;
3835+ } else
3836+ p_ptrn_lines = (*s != 'a');
3837+ if (p_first >= LINENUM_MAX - p_ptrn_lines)
3838+ malformed();
3839+ hunk_type = *s++;
3840+ if (hunk_type == 'a')
3841+ p_first++;
3842+ min = getskiplinenum(&s);
3843+ if (*s == ',')
3844+ max = getlinenum(++s);
3845+ else
3846+ max = min;
3847+ if (min < 0 || min > max || max - min == LINENUM_MAX)
3848+ malformed();
3849+ if (hunk_type == 'd')
3850+ min++;
3851+ p_end = p_ptrn_lines + p_repl_lines + 1;
3852+ p_newfirst = min;
3853+ p_repl_lines = max - min + 1;
3854+ if (p_newfirst > LINENUM_MAX - p_repl_lines || p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
3855+ malformed();
3856+ p_end = p_ptrn_lines + p_repl_lines + 1;
3857+ if (p_end > MAXHUNKSIZE)
3858+ fatal("hunk too large at line %ld\n", p_input_line);
3859+ while (p_end >= hunkmax)
3860+ grow_hunkmax();
3861+ snprintf(buf, bufsz, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1);
3862+ p_line[0] = savestr(buf);
3863+ if (out_of_mem) {
3864+ p_end = -1;
3865+ return 0;
3866+ }
3867+ p_char[0] = '*';
3868+ for (i = 1; i <= p_ptrn_lines; i++) {
3869+ ret = pgetline(&buf, &bufsz, pfp);
3870+ p_input_line++;
3871+ if (ret == -1)
3872+ fatal("unexpected end of file in patch at line %ld\n", p_input_line);
3873+ if (*buf != '<')
3874+ fatal("< expected at line %ld of patch\n", p_input_line);
3875+ p_line[i] = savestr(buf + 2);
3876+ if (out_of_mem) {
3877+ p_end = i - 1;
3878+ return 0;
3879+ }
3880+ p_len[i] = strlen(p_line[i]);
3881+ p_char[i] = '-';
3882+ }
3883+ if (remove_special_line()) {
3884+ p_len[i - 1] -= 1;
3885+ (p_line[i - 1])[p_len[i - 1]] = 0;
3886+ }
3887+ if (hunk_type == 'c') {
3888+ ret = pgetline(&buf, &bufsz, pfp);
3889+ p_input_line++;
3890+ if (ret == -1)
3891+ fatal("unexpected end of file in patch at line %ld\n", p_input_line);
3892+ if (*buf != '-')
3893+ fatal("--- expected at line %ld of patch\n", p_input_line);
3894+ }
3895+ snprintf(buf, bufsz, "--- %ld,%ld\n", min, max);
3896+ p_line[i] = savestr(buf);
3897+ if (out_of_mem) {
3898+ p_end = i - 1;
3899+ return 0;
3900+ }
3901+ p_char[i] = '=';
3902+ for (i++; i <= p_end; i++) {
3903+ ret = pgetline(&buf, &bufsz, pfp);
3904+ p_input_line++;
3905+ if (ret == -1)
3906+ fatal("unexpected end of file in patch at line %ld\n", p_input_line);
3907+ if (*buf != '>')
3908+ fatal("> expected at line %ld of patch\n", p_input_line);
3909+ p_line[i] = savestr(buf + 2);
3910+ if (out_of_mem) {
3911+ p_end = i - 1;
3912+ return 0;
3913+ }
3914+ p_len[i] = strlen(p_line[i]);
3915+ p_char[i] = '+';
3916+ }
3917+ if (remove_special_line()) {
3918+ p_len[i - 1] -= 1;
3919+ (p_line[i - 1])[p_len[i - 1]] = 0;
3920+ }
3921+ }
3922+ if (reverse) {
3923+ if (!pch_swap())
3924+ say("Not enough memory to swap next hunk!\n");
3925+ }
3926+ if (p_end + 1 < hunkmax)
3927+ p_char[p_end + 1] = '^';
3928+ return 1;
3929 }
3930
3931 int
3932 pgetline(char **bf, size_t *sz, FILE *fp)
3933 {
3934- char *s;
3935- int indent = 0;
3936- int ret;
3937+ char *s;
3938+ int indent = 0;
3939+ int ret;
3940
3941- ret = getline(bf, sz, fp);
3942- if (p_indent && ret != -1) {
3943- for (s = buf; indent < p_indent && (*s == ' ' || *s == '\t' || *s == 'X'); s++) {
3944- if (*s == '\t')
3945- indent += 8 - (indent % 7);
3946- else
3947- indent++;
3948- }
3949- if (buf != s && strlcpy(buf, s, bufsz) >= bufsz)
3950- fatal("buffer too small in pgetline()\n");
3951- }
3952- return ret;
3953+ ret = getline(bf, sz, fp);
3954+ if (p_indent && ret != -1) {
3955+ for (s = buf; indent < p_indent && (*s == ' ' || *s == '\t' || *s == 'X'); s++) {
3956+ if (*s == '\t')
3957+ indent += 8 - (indent % 7);
3958+ else
3959+ indent++;
3960+ }
3961+ if (buf != s && strlcpy(buf, s, bufsz) >= bufsz)
3962+ fatal("buffer too small in pgetline()\n");
3963+ }
3964+ return ret;
3965 }
3966
3967 int
3968 pch_swap(void)
3969 {
3970- char **tp_line;
3971- ssize_t *tp_len;
3972- char *tp_char;
3973- LINENUM i;
3974- LINENUM n;
3975- int blankline = 0;
3976- char *s;
3977-
3978- i = p_first;
3979- p_first = p_newfirst;
3980- p_newfirst = i;
3981-
3982- tp_line = p_line;
3983- tp_len = p_len;
3984- tp_char = p_char;
3985- p_line = NULL;
3986- p_len = NULL;
3987- p_char = NULL;
3988- set_hunkmax();
3989- if (p_line == NULL || p_len == NULL || p_char == NULL) {
3990- free(p_line);
3991- p_line = tp_line;
3992- free(p_len);
3993- p_len = tp_len;
3994- free(p_char);
3995- p_char = tp_char;
3996- return 0;
3997- }
3998-
3999- i = p_ptrn_lines + 1;
4000- if (tp_char[i] == '\n') {
4001- blankline = 1;
4002- i++;
4003- }
4004- if (p_efake >= 0) {
4005- if (p_efake <= i)
4006- n = p_end - i + 1;
4007- else
4008- n = -i;
4009- p_efake += n;
4010- p_bfake += n;
4011- }
4012- for (n = 0; i <= p_end; i++, n++) {
4013- p_line[n] = tp_line[i];
4014- p_char[n] = tp_char[i];
4015- if (p_char[n] == '+')
4016- p_char[n] = '-';
4017- p_len[n] = tp_len[i];
4018- }
4019- if (blankline) {
4020- i = p_ptrn_lines + 1;
4021- p_line[n] = tp_line[i];
4022- p_char[n] = tp_char[i];
4023- p_len[n] = tp_len[i];
4024- n++;
4025- }
4026- if (p_char[0] != '=')
4027- fatal("expected '=' found '%c'\n", p_char[0]);
4028- p_char[0] = '*';
4029- for (s = p_line[0]; *s; s++)
4030- if (*s == '-')
4031- *s = '*';
4032-
4033- if (p_char[0] != '*')
4034- fatal("expected '*' found '%c'\n", p_char[0]);
4035- tp_char[0] = '=';
4036- for (s = tp_line[0]; *s; s++)
4037- if (*s == '*')
4038- *s = '-';
4039- for (i = 0; n <= p_end; i++, n++) {
4040- p_line[n] = tp_line[i];
4041- p_char[n] = tp_char[i];
4042- if (p_char[n] == '-')
4043- p_char[n] = '+';
4044- p_len[n] = tp_len[i];
4045- }
4046- if (i != p_ptrn_lines + 1)
4047- fatal("expected %ld lines, got %ld\n", p_ptrn_lines + 1, i);
4048-
4049- i = p_ptrn_lines;
4050- p_ptrn_lines = p_repl_lines;
4051- p_repl_lines = i;
4052-
4053- free(tp_line);
4054- free(tp_len);
4055- free(tp_char);
4056- return 1;
4057+ char **tp_line;
4058+ ssize_t *tp_len;
4059+ char *tp_char;
4060+ LINENUM i;
4061+ LINENUM n;
4062+ int blankline = 0;
4063+ char *s;
4064+
4065+ i = p_first;
4066+ p_first = p_newfirst;
4067+ p_newfirst = i;
4068+
4069+ tp_line = p_line;
4070+ tp_len = p_len;
4071+ tp_char = p_char;
4072+ p_line = NULL;
4073+ p_len = NULL;
4074+ p_char = NULL;
4075+ set_hunkmax();
4076+ if (p_line == NULL || p_len == NULL || p_char == NULL) {
4077+ free(p_line);
4078+ p_line = tp_line;
4079+ free(p_len);
4080+ p_len = tp_len;
4081+ free(p_char);
4082+ p_char = tp_char;
4083+ return 0;
4084+ }
4085+
4086+ i = p_ptrn_lines + 1;
4087+ if (tp_char[i] == '\n') {
4088+ blankline = 1;
4089+ i++;
4090+ }
4091+ if (p_efake >= 0) {
4092+ if (p_efake <= i)
4093+ n = p_end - i + 1;
4094+ else
4095+ n = -i;
4096+ p_efake += n;
4097+ p_bfake += n;
4098+ }
4099+ for (n = 0; i <= p_end; i++, n++) {
4100+ p_line[n] = tp_line[i];
4101+ p_char[n] = tp_char[i];
4102+ if (p_char[n] == '+')
4103+ p_char[n] = '-';
4104+ p_len[n] = tp_len[i];
4105+ }
4106+ if (blankline) {
4107+ i = p_ptrn_lines + 1;
4108+ p_line[n] = tp_line[i];
4109+ p_char[n] = tp_char[i];
4110+ p_len[n] = tp_len[i];
4111+ n++;
4112+ }
4113+ if (p_char[0] != '=')
4114+ fatal("expected '=' found '%c'\n", p_char[0]);
4115+ p_char[0] = '*';
4116+ for (s = p_line[0]; *s; s++)
4117+ if (*s == '-')
4118+ *s = '*';
4119+
4120+ if (p_char[0] != '*')
4121+ fatal("expected '*' found '%c'\n", p_char[0]);
4122+ tp_char[0] = '=';
4123+ for (s = tp_line[0]; *s; s++)
4124+ if (*s == '*')
4125+ *s = '-';
4126+ for (i = 0; n <= p_end; i++, n++) {
4127+ p_line[n] = tp_line[i];
4128+ p_char[n] = tp_char[i];
4129+ if (p_char[n] == '-')
4130+ p_char[n] = '+';
4131+ p_len[n] = tp_len[i];
4132+ }
4133+ if (i != p_ptrn_lines + 1)
4134+ fatal("expected %ld lines, got %ld\n", p_ptrn_lines + 1, i);
4135+
4136+ i = p_ptrn_lines;
4137+ p_ptrn_lines = p_repl_lines;
4138+ p_repl_lines = i;
4139+
4140+ free(tp_line);
4141+ free(tp_len);
4142+ free(tp_char);
4143+ return 1;
4144 }
4145
4146 LINENUM
4147 pch_first(void)
4148 {
4149- return p_first;
4150+ return p_first;
4151 }
4152
4153 LINENUM
4154 pch_ptrn_lines(void)
4155 {
4156- return p_ptrn_lines;
4157+ return p_ptrn_lines;
4158 }
4159
4160 LINENUM
4161 pch_newfirst(void)
4162 {
4163- return p_newfirst;
4164+ return p_newfirst;
4165 }
4166
4167 LINENUM
4168 pch_repl_lines(void)
4169 {
4170- return p_repl_lines;
4171+ return p_repl_lines;
4172 }
4173
4174 LINENUM
4175 pch_end(void)
4176 {
4177- return p_end;
4178+ return p_end;
4179 }
4180
4181 LINENUM
4182 pch_context(void)
4183 {
4184- return p_context;
4185+ return p_context;
4186 }
4187
4188 ssize_t
4189 pch_line_len(LINENUM line)
4190 {
4191- return p_len[line];
4192+ return p_len[line];
4193 }
4194
4195 char
4196 pch_char(LINENUM line)
4197 {
4198- return p_char[line];
4199+ return p_char[line];
4200 }
4201
4202 char *
4203 pfetch(LINENUM line)
4204 {
4205- return p_line[line];
4206+ return p_line[line];
4207 }
4208
4209 LINENUM
4210 pch_hunk_beg(void)
4211 {
4212- return p_hunk_beg;
4213+ return p_hunk_beg;
4214 }
4215
4216 void
4217 do_ed_script(void)
4218 {
4219- char *t;
4220- long beginning_of_this_line;
4221- FILE *pipefp = NULL;
4222- int continuation;
4223-
4224- if (!skip_rest_of_patch) {
4225- if (copy_file(filearg[0], TMPOUTNAME) < 0) {
4226- unlink(TMPOUTNAME);
4227- fatal("cant create temp file %s", TMPOUTNAME);
4228- }
4229- snprintf(buf, bufsz, "%s -S%s %s", _PATH_ED, verbose ? "" : "s", TMPOUTNAME);
4230- pipefp = popen(buf, "w");
4231- }
4232- for (;;) {
4233- beginning_of_this_line = ftell(pfp);
4234- if (pgetline(&buf, &bufsz, pfp) == -1) {
4235- next_intuit_at(beginning_of_this_line, p_input_line);
4236- break;
4237- }
4238- p_input_line++;
4239- for (t = buf; isdigit((unsigned char)*t) || *t == ','; t++)
4240- ;
4241- if (isdigit((unsigned char)*buf) && (*t == 'a' || *t == 'c' || *t == 'd' || *t == 'i' || *t == 's')) {
4242- if (pipefp != NULL)
4243- fprintf(pipefp, "%s", buf);
4244- if (*t == 's') {
4245- for (;;) {
4246- continuation = 0;
4247- t = strchr(buf, '\0') - 1;
4248- while (--t >= buf && *t == '\\')
4249- continuation = !continuation;
4250- if (!continuation || pgetline(&buf, &bufsz, pfp) == -1)
4251- break;
4252- if (pipefp != NULL)
4253- fprintf(pipefp, "%s", buf);
4254- }
4255- } else if (*t != 'd') {
4256- while (pgetline(&buf, &bufsz, pfp) != -1) {
4257- p_input_line++;
4258- if (pipefp != NULL)
4259- fprintf(pipefp, "%s", buf);
4260- if (strEQ(buf, ".\n"))
4261- break;
4262- }
4263- }
4264- } else {
4265- next_intuit_at(beginning_of_this_line, p_input_line);
4266- break;
4267- }
4268- }
4269- if (pipefp == NULL)
4270- return;
4271- fprintf(pipefp, "w\n");
4272- fprintf(pipefp, "q\n");
4273- fflush(pipefp);
4274- pclose(pipefp);
4275- ignore_signals();
4276- if (!check_only) {
4277- if (move_file(TMPOUTNAME, outname) < 0) {
4278- toutkeep = 1;
4279- chmod(TMPOUTNAME, filemode);
4280- } else
4281- chmod(outname, filemode);
4282- }
4283- set_signals(1);
4284+ char *t;
4285+ long beginning_of_this_line;
4286+ FILE *pipefp = NULL;
4287+ int continuation;
4288+
4289+ if (!skip_rest_of_patch) {
4290+ if (copy_file(filearg[0], TMPOUTNAME) < 0) {
4291+ unlink(TMPOUTNAME);
4292+ fatal("cant create temp file %s", TMPOUTNAME);
4293+ }
4294+ snprintf(buf, bufsz, "%s -S%s %s", _PATH_ED, verbose ? "" : "s", TMPOUTNAME);
4295+ pipefp = wpopen(buf, NULL, "w");
4296+ }
4297+ for (;;) {
4298+ beginning_of_this_line = ftell(pfp);
4299+ if (pgetline(&buf, &bufsz, pfp) == -1) {
4300+ next_intuit_at(beginning_of_this_line, p_input_line);
4301+ break;
4302+ }
4303+ p_input_line++;
4304+ for (t = buf; isdigit((unsigned char)*t) || *t == ','; t++)
4305+ ;
4306+ if (isdigit((unsigned char)*buf) && (*t == 'a' || *t == 'c' || *t == 'd' || *t == 'i' || *t == 's')) {
4307+ if (pipefp != NULL)
4308+ fprintf(pipefp, "%s", buf);
4309+ if (*t == 's') {
4310+ for (;;) {
4311+ continuation = 0;
4312+ t = strchr(buf, '\0') - 1;
4313+ while (--t >= buf && *t == '\\')
4314+ continuation = !continuation;
4315+ if (!continuation || pgetline(&buf, &bufsz, pfp) == -1)
4316+ break;
4317+ if (pipefp != NULL)
4318+ fprintf(pipefp, "%s", buf);
4319+ }
4320+ } else if (*t != 'd') {
4321+ while (pgetline(&buf, &bufsz, pfp) != -1) {
4322+ p_input_line++;
4323+ if (pipefp != NULL)
4324+ fprintf(pipefp, "%s", buf);
4325+ if (strEQ(buf, ".\n"))
4326+ break;
4327+ }
4328+ }
4329+ } else {
4330+ next_intuit_at(beginning_of_this_line, p_input_line);
4331+ break;
4332+ }
4333+ }
4334+ if (pipefp == NULL)
4335+ return;
4336+ fprintf(pipefp, "w\n");
4337+ fprintf(pipefp, "q\n");
4338+ fflush(pipefp);
4339+ wpclose(pipefp);
4340+ ignore_signals();
4341+ if (!check_only) {
4342+ if (move_file(TMPOUTNAME, outname) < 0) {
4343+ toutkeep = 1;
4344+ chmod(TMPOUTNAME, filemode);
4345+ } else
4346+ chmod(outname, filemode);
4347+ }
4348+ set_signals(1);
4349 }
4350
4351 static char *
4352 posix_name(const struct FileName *names, int assume_exists)
4353 {
4354- char *path = NULL;
4355- int i;
4356-
4357- for (i = 0; i < MAX_FILE; i++) {
4358- if (names[i].path != NULL && names[i].exists) {
4359- path = names[i].path;
4360- break;
4361- }
4362- }
4363- if (path == NULL && !assume_exists) {
4364- for (i = 0; i < MAX_FILE; i++) {
4365- if (names[i].path != NULL && (path = checked_in(names[i].path)) != NULL)
4366- break;
4367- }
4368- if (path == NULL && ok_to_create_file && names[NEW_FILE].path != NULL)
4369- path = names[NEW_FILE].path;
4370- }
4371- return path ? savestr(path) : NULL;
4372+ char *path = NULL;
4373+ int i;
4374+
4375+ for (i = 0; i < MAX_FILE; i++) {
4376+ if (names[i].path != NULL && names[i].exists) {
4377+ path = names[i].path;
4378+ break;
4379+ }
4380+ }
4381+ if (path == NULL && !assume_exists) {
4382+ for (i = 0; i < MAX_FILE; i++) {
4383+ if (names[i].path != NULL && (path = checked_in(names[i].path)) != NULL)
4384+ break;
4385+ }
4386+ if (path == NULL && ok_to_create_file && names[NEW_FILE].path != NULL)
4387+ path = names[NEW_FILE].path;
4388+ }
4389+ return path ? savestr(path) : NULL;
4390 }
4391
4392 static char *
4393 best_name(const struct FileName *names, int assume_exists)
4394 {
4395- size_t min_components, min_baselen, min_len, tmp;
4396- char *best = NULL;
4397- int i;
4398-
4399- min_components = min_baselen = min_len = SIZE_MAX;
4400- for (i = INDEX_FILE; i >= OLD_FILE; i--) {
4401- if (names[i].path == NULL || (!names[i].exists && !assume_exists))
4402- continue;
4403- if ((tmp = num_components(names[i].path)) > min_components)
4404- continue;
4405- min_components = tmp;
4406- if ((tmp = strlen(basename(names[i].path))) > min_baselen)
4407- continue;
4408- min_baselen = tmp;
4409- if ((tmp = strlen(names[i].path)) > min_len)
4410- continue;
4411- min_len = tmp;
4412- best = names[i].path;
4413- }
4414- if (best == NULL) {
4415- min_components = min_baselen = min_len = SIZE_MAX;
4416- for (i = INDEX_FILE; i >= OLD_FILE; i--) {
4417- if (names[i].path == NULL || checked_in(names[i].path) == NULL)
4418- continue;
4419- if ((tmp = num_components(names[i].path)) > min_components)
4420- continue;
4421- min_components = tmp;
4422- if ((tmp = strlen(basename(names[i].path))) > min_baselen)
4423- continue;
4424- min_baselen = tmp;
4425- if ((tmp = strlen(names[i].path)) > min_len)
4426- continue;
4427- min_len = tmp;
4428- best = names[i].path;
4429- }
4430- if (best == NULL && ok_to_create_file && names[NEW_FILE].path != NULL)
4431- best = names[NEW_FILE].path;
4432- }
4433- return best ? savestr(best) : NULL;
4434+ size_t min_components, min_baselen, min_len, tmp;
4435+ char *best = NULL;
4436+ int i;
4437+
4438+ min_components = min_baselen = min_len = SIZE_MAX;
4439+ for (i = INDEX_FILE; i >= OLD_FILE; i--) {
4440+ if (names[i].path == NULL || (!names[i].exists && !assume_exists))
4441+ continue;
4442+ if ((tmp = num_components(names[i].path)) > min_components)
4443+ continue;
4444+ min_components = tmp;
4445+ if ((tmp = strlen(basename(names[i].path))) > min_baselen)
4446+ continue;
4447+ min_baselen = tmp;
4448+ if ((tmp = strlen(names[i].path)) > min_len)
4449+ continue;
4450+ min_len = tmp;
4451+ best = names[i].path;
4452+ }
4453+ if (best == NULL) {
4454+ min_components = min_baselen = min_len = SIZE_MAX;
4455+ for (i = INDEX_FILE; i >= OLD_FILE; i--) {
4456+ if (names[i].path == NULL || checked_in(names[i].path) == NULL)
4457+ continue;
4458+ if ((tmp = num_components(names[i].path)) > min_components)
4459+ continue;
4460+ min_components = tmp;
4461+ if ((tmp = strlen(basename(names[i].path))) > min_baselen)
4462+ continue;
4463+ min_baselen = tmp;
4464+ if ((tmp = strlen(names[i].path)) > min_len)
4465+ continue;
4466+ min_len = tmp;
4467+ best = names[i].path;
4468+ }
4469+ if (best == NULL && ok_to_create_file && names[NEW_FILE].path != NULL)
4470+ best = names[NEW_FILE].path;
4471+ }
4472+ return best ? savestr(best) : NULL;
4473 }
4474
4475 static size_t
4476 num_components(const char *path)
4477 {
4478- size_t n;
4479- const char *cp;
4480+ size_t n;
4481+ const char *cp;
4482
4483- for (n = 0, cp = path; (cp = strchr(cp, '/')) != NULL; n++, cp++) {
4484- while (*cp == '/')
4485- cp++;
4486- }
4487- return n;
4488+ for (n = 0, cp = path; (cp = strchr(cp, '/')) != NULL; n++, cp++) {
4489+ while (*cp == '/')
4490+ cp++;
4491+ }
4492+ return n;
4493 }
4494
4495 LINENUM
4496 strtolinenum(char *nptr, char **endptr)
4497 {
4498- LINENUM rv;
4499- char c;
4500- char *p;
4501- const char *errstr;
4502+ LINENUM rv;
4503+ char c;
4504+ char *p;
4505+ const char *errstr;
4506
4507- for (p = nptr; isdigit((unsigned char)*p); p++)
4508- ;
4509+ for (p = nptr; isdigit((unsigned char)*p); p++)
4510+ ;
4511
4512- if (p == nptr)
4513- malformed();
4514+ if (p == nptr)
4515+ malformed();
4516
4517- c = *p;
4518- *p = '\0';
4519+ c = *p;
4520+ *p = '\0';
4521
4522- rv = strtonum(nptr, 0, LINENUM_MAX, &errstr);
4523- if (errstr != NULL)
4524- fatal("invalid line number at line %ld: `%s' is %s\n",
4525- p_input_line, nptr, errstr);
4526+ rv = strtonum(nptr, 0, LINENUM_MAX, &errstr);
4527+ if (errstr != NULL)
4528+ fatal("invalid line number at line %ld: `%s' is %s\n",
4529+ p_input_line, nptr, errstr);
4530
4531- *p = c;
4532- *endptr = p;
4533+ *p = c;
4534+ *endptr = p;
4535
4536- return rv;
4537+ return rv;
4538 }
4539
4540 int
4541 move_file(const char *from, const char *to)
4542 {
4543- int fromfd;
4544- ssize_t i;
4545-
4546- if (strEQ(to, "-")) {
4547- fromfd = open(from, O_RDONLY);
4548- if (fromfd < 0)
4549- pfatal("internal error, cant reopen %s", from);
4550- while ((i = read(fromfd, buf, bufsz)) > 0) {
4551- if (write(STDOUT_FILENO, buf, i) != i)
4552- pfatal("write failed");
4553- }
4554- close(fromfd);
4555- return 0;
4556- }
4557- if (backup_file(to) < 0) {
4558- say("Cant backup %s, output is in %s: %s\n", to, from, strerror(errno));
4559- return -1;
4560- }
4561- if (rename(from, to) < 0) {
4562- if (errno != EXDEV || copy_file(from, to) < 0) {
4563- say("Cant create %s, output is in %s: %s\n", to, from, strerror(errno));
4564- return -1;
4565- }
4566- }
4567- return 0;
4568+ int fromfd;
4569+ ssize_t i;
4570+
4571+ if (strEQ(to, "-")) {
4572+ fromfd = open(from, O_RDONLY);
4573+ if (fromfd < 0)
4574+ pfatal("internal error, cant reopen %s", from);
4575+ while ((i = read(fromfd, buf, bufsz)) > 0) {
4576+ if (write(STDOUT_FILENO, buf, i) != i)
4577+ pfatal("write failed");
4578+ }
4579+ close(fromfd);
4580+ return 0;
4581+ }
4582+ if (backup_file(to) < 0) {
4583+ say("Cant backup %s, output is in %s: %s\n", to, from, strerror(errno));
4584+ return -1;
4585+ }
4586+ if (rename(from, to) < 0) {
4587+ if (errno != EXDEV || copy_file(from, to) < 0) {
4588+ say("Cant create %s, output is in %s: %s\n", to, from, strerror(errno));
4589+ return -1;
4590+ }
4591+ }
4592+ return 0;
4593 }
4594
4595 int
4596 backup_file(const char *orig)
4597 {
4598- struct stat filestat;
4599- char bakname[PATH_MAX], *s, *simplename;
4600- dev_t orig_device;
4601- ino_t orig_inode;
4602-
4603- if (backup_type == BACKUP_NONE || stat(orig, &filestat) != 0)
4604- return 0;
4605- if ((origprae && *origprae == 0) || *simple_backup_suffix == 0) {
4606- unlink(orig);
4607- return 0;
4608- }
4609- orig_device = filestat.st_dev;
4610- orig_inode = filestat.st_ino;
4611-
4612- if (origprae) {
4613- if (strlcpy(bakname, origprae, sizeof(bakname)) >= sizeof(bakname) ||
4614- strlcat(bakname, orig, sizeof(bakname)) >= sizeof(bakname))
4615- fatal("filename too long\n");
4616- } else {
4617- if ((s = find_backup_file_name(orig)) == NULL)
4618- fatal("out of memory\n");
4619- if (strlcpy(bakname, s, sizeof(bakname)) >= sizeof(bakname))
4620- fatal("filename too long\n");
4621- free(s);
4622- }
4623-
4624- if ((simplename = strrchr(bakname, '/')) != NULL)
4625- simplename = simplename + 1;
4626- else
4627- simplename = bakname;
4628-
4629- while (stat(bakname, &filestat) == 0 && orig_device == filestat.st_dev && orig_inode == filestat.st_ino) {
4630- for (s = simplename; *s && !islower((unsigned char)*s); s++)
4631- ;
4632- if (*s)
4633- *s = toupper((unsigned char)*s);
4634- else
4635- memmove(simplename, simplename + 1, strlen(simplename + 1) + 1);
4636- }
4637- if (rename(orig, bakname) < 0) {
4638- if (errno != EXDEV || copy_file(orig, bakname) < 0)
4639- return -1;
4640- }
4641- return 0;
4642+ struct stat filestat;
4643+ char bakname[PATH_MAX], *s, *simplename;
4644+ dev_t orig_device;
4645+ ino_t orig_inode;
4646+
4647+ if (backup_type == BACKUP_NONE || stat(orig, &filestat) != 0)
4648+ return 0;
4649+ if ((origprae && *origprae == 0) || *simple_backup_suffix == 0) {
4650+ unlink(orig);
4651+ return 0;
4652+ }
4653+ orig_device = filestat.st_dev;
4654+ orig_inode = filestat.st_ino;
4655+
4656+ if (origprae) {
4657+ if (strlcpy(bakname, origprae, sizeof(bakname)) >= sizeof(bakname) ||
4658+ strlcat(bakname, orig, sizeof(bakname)) >= sizeof(bakname))
4659+ fatal("filename too long\n");
4660+ } else {
4661+ if ((s = find_backup_file_name(orig)) == NULL)
4662+ fatal("out of memory\n");
4663+ if (strlcpy(bakname, s, sizeof(bakname)) >= sizeof(bakname))
4664+ fatal("filename too long\n");
4665+ free(s);
4666+ }
4667+
4668+ if ((simplename = strrchr(bakname, '/')) != NULL)
4669+ simplename = simplename + 1;
4670+ else
4671+ simplename = bakname;
4672+
4673+ while (stat(bakname, &filestat) == 0 && orig_device == filestat.st_dev && orig_inode == filestat.st_ino) {
4674+ for (s = simplename; *s && !islower((unsigned char)*s); s++)
4675+ ;
4676+ if (*s)
4677+ *s = toupper((unsigned char)*s);
4678+ else
4679+ memmove(simplename, simplename + 1, strlen(simplename + 1) + 1);
4680+ }
4681+ if (rename(orig, bakname) < 0) {
4682+ if (errno != EXDEV || copy_file(orig, bakname) < 0)
4683+ return -1;
4684+ }
4685+ return 0;
4686 }
4687
4688 int
4689 copy_file(const char *from, const char *to)
4690 {
4691- int tofd, fromfd;
4692- ssize_t i;
4693+ int tofd, fromfd;
4694+ ssize_t i;
4695
4696- tofd = open(to, O_CREAT|O_TRUNC|O_WRONLY, 0666);
4697- if (tofd < 0)
4698- return -1;
4699- fromfd = open(from, O_RDONLY, 0);
4700- if (fromfd < 0)
4701- pfatal("internal error, cant reopen %s", from);
4702- while ((i = read(fromfd, buf, bufsz)) > 0) {
4703- if (write(tofd, buf, i) != i)
4704- pfatal("write to %s failed", to);
4705- }
4706- close(fromfd);
4707- close(tofd);
4708- return 0;
4709+ tofd = open(to, O_CREAT|O_TRUNC|O_WRONLY, 0666);
4710+ if (tofd < 0)
4711+ return -1;
4712+ fromfd = open(from, O_RDONLY, 0);
4713+ if (fromfd < 0)
4714+ pfatal("internal error, cant reopen %s", from);
4715+ while ((i = read(fromfd, buf, bufsz)) > 0) {
4716+ if (write(tofd, buf, i) != i)
4717+ pfatal("write to %s failed", to);
4718+ }
4719+ close(fromfd);
4720+ close(tofd);
4721+ return 0;
4722 }
4723
4724 char *
4725 savestr(const char *s)
4726 {
4727- char *rv;
4728+ char *rv;
4729
4730- if (!s)
4731- s = "Oops";
4732- rv = strdup(s);
4733- if (rv == NULL) {
4734- if (using_plan_a)
4735- out_of_mem = 1;
4736- else
4737- fatal("out of memory\n");
4738- }
4739- return rv;
4740+ if (!s)
4741+ s = "Oops";
4742+ rv = strdup(s);
4743+ if (rv == NULL) {
4744+ if (using_plan_a)
4745+ out_of_mem = 1;
4746+ else
4747+ fatal("out of memory\n");
4748+ }
4749+ return rv;
4750 }
4751
4752 void
4753 say(const char *fmt, ...)
4754 {
4755- va_list ap;
4756+ va_list ap;
4757
4758- va_start(ap, fmt);
4759- vfprintf(stderr, fmt, ap);
4760- va_end(ap);
4761- fflush(stderr);
4762+ va_start(ap, fmt);
4763+ vfprintf(stderr, fmt, ap);
4764+ va_end(ap);
4765+ fflush(stderr);
4766 }
4767
4768 __dead void
4769 fatal(const char *fmt, ...)
4770 {
4771- va_list ap;
4772+ va_list ap;
4773
4774- va_start(ap, fmt);
4775- fprintf(stderr, "patch: **** ");
4776- vfprintf(stderr, fmt, ap);
4777- va_end(ap);
4778- my_exit(2);
4779+ va_start(ap, fmt);
4780+ fprintf(stderr, "patch: **** ");
4781+ vfprintf(stderr, fmt, ap);
4782+ va_end(ap);
4783+ my_exit(2);
4784 }
4785
4786 __dead void
4787 pfatal(const char *fmt, ...)
4788 {
4789- va_list ap;
4790- int errnum = errno;
4791+ va_list ap;
4792+ int errnum = errno;
4793
4794- fprintf(stderr, "patch: **** ");
4795- va_start(ap, fmt);
4796- vfprintf(stderr, fmt, ap);
4797- va_end(ap);
4798- fprintf(stderr, ": %s\n", strerror(errnum));
4799- my_exit(2);
4800+ fprintf(stderr, "patch: **** ");
4801+ va_start(ap, fmt);
4802+ vfprintf(stderr, fmt, ap);
4803+ va_end(ap);
4804+ fprintf(stderr, ": %s\n", strerror(errnum));
4805+ my_exit(2);
4806 }
4807
4808 void
4809 ask(const char *fmt, ...)
4810 {
4811- va_list ap;
4812- ssize_t nr = 0;
4813- static int ttyfd = -1;
4814-
4815- va_start(ap, fmt);
4816- vfprintf(stdout, fmt, ap);
4817- va_end(ap);
4818- fflush(stdout);
4819- if (ttyfd < 0)
4820- ttyfd = open(_PATH_TTY, O_RDONLY);
4821- if (ttyfd >= 0) {
4822- if ((nr = read(ttyfd, buf, bufsz)) > 0 && buf[nr - 1] == '\n')
4823- buf[nr - 1] = '\0';
4824- }
4825- if (ttyfd < 0 || nr <= 0) {
4826- putchar('\n');
4827- buf[0] = '\0';
4828- }
4829+ va_list ap;
4830+ ssize_t nr = 0;
4831+ static int ttyfd = -1;
4832+
4833+ va_start(ap, fmt);
4834+ vfprintf(stdout, fmt, ap);
4835+ va_end(ap);
4836+ fflush(stdout);
4837+ if (ttyfd < 0)
4838+ ttyfd = open(ARUU_PATH_DEVTTY, O_RDONLY);
4839+ if (ttyfd >= 0) {
4840+ if ((nr = read(ttyfd, buf, bufsz)) > 0 && buf[nr - 1] == '\n')
4841+ buf[nr - 1] = '\0';
4842+ }
4843+ if (ttyfd < 0 || nr <= 0) {
4844+ putchar('\n');
4845+ buf[0] = '\0';
4846+ }
4847 }
4848
4849 void
4850 set_signals(int reset)
4851 {
4852- static sig_t hupval, intval;
4853+ static sig_t hupval, intval;
4854
4855- if (!reset) {
4856- hupval = signal(SIGHUP, SIG_IGN);
4857- if (hupval != SIG_IGN)
4858- hupval = (sig_t)my_exit;
4859- intval = signal(SIGINT, SIG_IGN);
4860- if (intval != SIG_IGN)
4861- intval = (sig_t)my_exit;
4862- }
4863- signal(SIGHUP, hupval);
4864- signal(SIGINT, intval);
4865+ if (!reset) {
4866+ hupval = signal(SIGHUP, SIG_IGN);
4867+ if (hupval != SIG_IGN)
4868+ hupval = (sig_t)my_exit;
4869+ intval = signal(SIGINT, SIG_IGN);
4870+ if (intval != SIG_IGN)
4871+ intval = (sig_t)my_exit;
4872+ }
4873+ signal(SIGHUP, hupval);
4874+ signal(SIGINT, intval);
4875 }
4876
4877 void
4878 ignore_signals(void)
4879 {
4880- signal(SIGHUP, SIG_IGN);
4881- signal(SIGINT, SIG_IGN);
4882+ signal(SIGHUP, SIG_IGN);
4883+ signal(SIGINT, SIG_IGN);
4884 }
4885
4886 void
4887 makedirs(const char *filename, int striplast)
4888 {
4889- char *tmpbuf;
4890+ char *tmpbuf;
4891
4892- if ((tmpbuf = strdup(filename)) == NULL)
4893- fatal("out of memory\n");
4894+ if ((tmpbuf = strdup(filename)) == NULL)
4895+ fatal("out of memory\n");
4896
4897- if (striplast) {
4898- char *s = strrchr(tmpbuf, '/');
4899- if (s == NULL) {
4900- free(tmpbuf);
4901- return;
4902- }
4903- *s = '\0';
4904- }
4905- if (mkpath(tmpbuf) != 0)
4906- pfatal("creation of %s failed", tmpbuf);
4907- free(tmpbuf);
4908+ if (striplast) {
4909+ char *s = strrchr(tmpbuf, '/');
4910+ if (s == NULL) {
4911+ free(tmpbuf);
4912+ return;
4913+ }
4914+ *s = '\0';
4915+ }
4916+ if (mkpath(tmpbuf) != 0)
4917+ pfatal("creation of %s failed", tmpbuf);
4918+ free(tmpbuf);
4919 }
4920
4921 char *
4922 fetchname(const char *at, int *exists, int strip_leading)
4923 {
4924- char *fullname, *name, *t;
4925- int sleading, tab;
4926- struct stat filestat;
4927-
4928- if (at == NULL || *at == '\0')
4929- return NULL;
4930- while (isspace((unsigned char)*at))
4931- at++;
4932- if (strnEQ(at, _PATH_DEVNULL, sizeof(_PATH_DEVNULL) - 1))
4933- return NULL;
4934- name = fullname = t = savestr(at);
4935- tab = strchr(t, '\t') != NULL;
4936- for (sleading = strip_leading; *t != '\0' && ((tab && *t != '\t') || !isspace((unsigned char)*t)); t++) {
4937- if (t[0] == '/' && t[1] != '/' && t[1] != '\0') {
4938- if (--sleading >= 0)
4939- name = t + 1;
4940- }
4941- }
4942- *t = '\0';
4943-
4944- if (strip_leading == 957 && name != fullname && *fullname != '/') {
4945- name[-1] = '\0';
4946- if (stat(fullname, &filestat) == 0 && S_ISDIR(filestat.st_mode)) {
4947- name[-1] = '/';
4948- name = fullname;
4949- }
4950- }
4951- name = savestr(name);
4952- free(fullname);
4953-
4954- *exists = stat(name, &filestat) == 0;
4955- return name;
4956+ char *fullname, *name, *t;
4957+ int sleading, tab;
4958+ struct stat filestat;
4959+
4960+ if (at == NULL || *at == '\0')
4961+ return NULL;
4962+ while (isspace((unsigned char)*at))
4963+ at++;
4964+ if (strnEQ(at, ARUU_PATH_DEVNULL, sizeof(ARUU_PATH_DEVNULL) - 1))
4965+ return NULL;
4966+ name = fullname = t = savestr(at);
4967+ tab = strchr(t, '\t') != NULL;
4968+ for (sleading = strip_leading; *t != '\0' && ((tab && *t != '\t') || !isspace((unsigned char)*t)); t++) {
4969+ if (t[0] == '/' && t[1] != '/' && t[1] != '\0') {
4970+ if (--sleading >= 0)
4971+ name = t + 1;
4972+ }
4973+ }
4974+ *t = '\0';
4975+
4976+ if (strip_leading == 957 && name != fullname && *fullname != '/') {
4977+ name[-1] = '\0';
4978+ if (stat(fullname, &filestat) == 0 && S_ISDIR(filestat.st_mode)) {
4979+ name[-1] = '/';
4980+ name = fullname;
4981+ }
4982+ }
4983+ name = savestr(name);
4984+ free(fullname);
4985+
4986+ *exists = stat(name, &filestat) == 0;
4987+ return name;
4988 }
4989
4990 char *
4991 checked_in(char *file)
4992 {
4993- char *filebase, *filedir, tmpbuf[PATH_MAX];
4994- struct stat filestat;
4995+ char *filebase, *filedir, tmpbuf[PATH_MAX];
4996+ struct stat filestat;
4997
4998- filebase = basename(file);
4999- filedir = dirname(file);
5000+ filebase = basename(file);
5001+ filedir = dirname(file);
5002
5003 #define try(f, a1, a2, a3) \
5004 (snprintf(tmpbuf, sizeof tmpbuf, f, a1, a2, a3), stat(tmpbuf, &filestat) == 0)
5005
5006- if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
5007- try("%s/RCS/%s%s", filedir, filebase, "") ||
5008- try("%s/%s%s", filedir, filebase, RCSSUFFIX) ||
5009- try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) ||
5010- try("%s/%s%s", filedir, SCCSPREFIX, filebase))
5011- return file;
5012+ if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
5013+ try("%s/RCS/%s%s", filedir, filebase, "") ||
5014+ try("%s/%s%s", filedir, filebase, RCSSUFFIX) ||
5015+ try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) ||
5016+ try("%s/%s%s", filedir, SCCSPREFIX, filebase))
5017+ return file;
5018
5019- return NULL;
5020+ return NULL;
5021 }
5022
5023 __dead void
5024 version(void)
5025 {
5026- printf("Patch version 2.0-12u9-NetBSD\n");
5027- my_exit(EXIT_SUCCESS);
5028+ printf("Patch version 2.0-12u9-NetBSD\n");
5029+ my_exit(EXIT_SUCCESS);
5030 }
5031
5032 __dead void
5033 my_exit(int status)
5034 {
5035- unlink(TMPINNAME);
5036- if (!toutkeep)
5037- unlink(TMPOUTNAME);
5038- if (!trejkeep)
5039- unlink(TMPREJNAME);
5040- unlink(TMPPATNAME);
5041- exit(status);
5042+ unlink(TMPINNAME);
5043+ if (!toutkeep)
5044+ unlink(TMPOUTNAME);
5045+ if (!trejkeep)
5046+ unlink(TMPREJNAME);
5047+ unlink(TMPPATNAME);
5048+ exit(status);
5049 }
5050
5051 static void *
5052 pch_realloc(void *ptr, size_t number, size_t size)
5053 {
5054- if (number > SIZE_MAX / size) {
5055- errno = EOVERFLOW;
5056- return NULL;
5057- }
5058- return realloc(ptr, number * size);
5059+ if (number > SIZE_MAX / size) {
5060+ errno = EOVERFLOW;
5061+ return NULL;
5062+ }
5063+ return realloc(ptr, number * size);
5064 }
5065
5066 int
5067 mkpath(char *path)
5068 {
5069- struct stat sb;
5070- char *slash;
5071- int done = 0;
5072-
5073- slash = path;
5074- while (!done) {
5075- slash += strspn(slash, "/");
5076- slash += strcspn(slash, "/");
5077- done = (*slash == '\0');
5078- *slash = '\0';
5079- if (stat(path, &sb)) {
5080- if (errno != ENOENT || (mkdir(path, 0777) && errno != EEXIST)) {
5081- warn("%s", path);
5082- return -1;
5083- }
5084- } else if (!S_ISDIR(sb.st_mode)) {
5085- warnx("%s: %s", path, strerror(ENOTDIR));
5086- return -1;
5087- }
5088- *slash = '/';
5089- }
5090- return 0;
5091+ struct stat sb;
5092+ char *slash;
5093+ int done = 0;
5094+
5095+ slash = path;
5096+ while (!done) {
5097+ slash += strspn(slash, "/");
5098+ slash += strcspn(slash, "/");
5099+ done = (*slash == '\0');
5100+ *slash = '\0';
5101+ if (stat(path, &sb)) {
5102+ if (errno != ENOENT || (mkdir(path, 0777) && errno != EEXIST)) {
5103+ weprintf("%s", path);
5104+ return -1;
5105+ }
5106+ } else if (!S_ISDIR(sb.st_mode)) {
5107+ weprintf("%s: %s", path, strerror(ENOTDIR));
5108+ return -1;
5109+ }
5110+ *slash = '/';
5111+ }
5112+ return 0;
5113 }
5114
5115 char *
5116 find_backup_file_name(const char *file)
5117 {
5118- char *dir, *base_versions, *tmp_file;
5119- int highest_backup;
5120-
5121- if (backup_type == BACKUP_SIMPLE)
5122- return patch_concat(file, simple_backup_suffix);
5123- tmp_file = strdup(file);
5124- if (tmp_file == NULL)
5125- return NULL;
5126- base_versions = patch_concat(basename(tmp_file), ".~");
5127- free(tmp_file);
5128- if (base_versions == NULL)
5129- return NULL;
5130- tmp_file = strdup(file);
5131- if (tmp_file == NULL) {
5132- free(base_versions);
5133- return NULL;
5134- }
5135- dir = dirname(tmp_file);
5136- if (dir == NULL) {
5137- free(base_versions);
5138- free(tmp_file);
5139- return NULL;
5140- }
5141- highest_backup = max_backup_version(base_versions, dir);
5142- free(base_versions);
5143- free(tmp_file);
5144- if (backup_type == BACKUP_NUMBERED_EXISTING && highest_backup == 0)
5145- return patch_concat(file, simple_backup_suffix);
5146- return make_version_name(file, highest_backup + 1);
5147+ char *dir, *base_versions, *tmp_file;
5148+ int highest_backup;
5149+
5150+ if (backup_type == BACKUP_SIMPLE)
5151+ return patch_concat(file, simple_backup_suffix);
5152+ tmp_file = strdup(file);
5153+ if (tmp_file == NULL)
5154+ return NULL;
5155+ base_versions = patch_concat(basename(tmp_file), ".~");
5156+ free(tmp_file);
5157+ if (base_versions == NULL)
5158+ return NULL;
5159+ tmp_file = strdup(file);
5160+ if (tmp_file == NULL) {
5161+ free(base_versions);
5162+ return NULL;
5163+ }
5164+ dir = dirname(tmp_file);
5165+ if (dir == NULL) {
5166+ free(base_versions);
5167+ free(tmp_file);
5168+ return NULL;
5169+ }
5170+ highest_backup = max_backup_version(base_versions, dir);
5171+ free(base_versions);
5172+ free(tmp_file);
5173+ if (backup_type == BACKUP_NUMBERED_EXISTING && highest_backup == 0)
5174+ return patch_concat(file, simple_backup_suffix);
5175+ return make_version_name(file, highest_backup + 1);
5176 }
5177
5178 static int
5179 max_backup_version(const char *file, const char *dir)
5180 {
5181- DIR *dirp;
5182- struct dirent *dp;
5183- int highest_version, this_version;
5184- size_t file_name_length;
5185+ DIR *dirp;
5186+ struct dirent *dp;
5187+ int highest_version, this_version;
5188+ size_t file_name_length;
5189
5190- dirp = opendir(dir);
5191- if (dirp == NULL)
5192- return 0;
5193+ dirp = opendir(dir);
5194+ if (dirp == NULL)
5195+ return 0;
5196
5197- highest_version = 0;
5198- file_name_length = strlen(file);
5199- while ((dp = readdir(dirp)) != NULL) {
5200- if (strlen(dp->d_name) <= file_name_length)
5201- continue;
5202- this_version = version_number(file, dp->d_name, file_name_length);
5203- if (this_version > highest_version)
5204- highest_version = this_version;
5205- }
5206- closedir(dirp);
5207- return highest_version;
5208+ highest_version = 0;
5209+ file_name_length = strlen(file);
5210+ while ((dp = readdir(dirp)) != NULL) {
5211+ if (strlen(dp->d_name) <= file_name_length)
5212+ continue;
5213+ this_version = version_number(file, dp->d_name, file_name_length);
5214+ if (this_version > highest_version)
5215+ highest_version = this_version;
5216+ }
5217+ closedir(dirp);
5218+ return highest_version;
5219 }
5220
5221 static char *
5222 make_version_name(const char *file, int version_num)
5223 {
5224- char *backup_name;
5225+ char *backup_name;
5226
5227- if (asprintf(&backup_name, "%s.~%d~", file, version_num) == -1)
5228- return NULL;
5229- return backup_name;
5230+ if (asprintf(&backup_name, "%s.~%d~", file, version_num) == -1)
5231+ return NULL;
5232+ return backup_name;
5233 }
5234
5235 static int
5236 version_number(const char *base, const char *backup, size_t base_length)
5237 {
5238- int version_num;
5239- const char *p;
5240+ int version_num;
5241+ const char *p;
5242
5243- version_num = 0;
5244- if (!strncmp(base, backup, base_length) && ISDIGIT(backup[base_length])) {
5245- for (p = &backup[base_length]; ISDIGIT(*p); ++p)
5246- version_num = version_num * 10 + *p - '0';
5247- if (p[0] != '~' || p[1])
5248- version_num = 0;
5249- }
5250- return version_num;
5251+ version_num = 0;
5252+ if (!strncmp(base, backup, base_length) && ISDIGIT(backup[base_length])) {
5253+ for (p = &backup[base_length]; ISDIGIT(*p); ++p)
5254+ version_num = version_num * 10 + *p - '0';
5255+ if (p[0] != '~' || p[1])
5256+ version_num = 0;
5257+ }
5258+ return version_num;
5259 }
5260
5261 static char *
5262 patch_concat(const char *str1, const char *str2)
5263 {
5264- char *newstr;
5265+ char *newstr;
5266
5267- if (asprintf(&newstr, "%s%s", str1, str2) == -1)
5268- return NULL;
5269- return newstr;
5270+ if (asprintf(&newstr, "%s%s", str1, str2) == -1)
5271+ return NULL;
5272+ return newstr;
5273 }
5274
5275 static int
5276 argmatch(const char *arg, const char **optlist)
5277 {
5278- int i;
5279- size_t arglen;
5280- int matchind = -1;
5281- int ambiguous = 0;
5282-
5283- arglen = strlen(arg);
5284- for (i = 0; optlist[i]; i++) {
5285- if (!strncmp(optlist[i], arg, arglen)) {
5286- if (strlen(optlist[i]) == arglen)
5287- return i;
5288- else if (matchind == -1)
5289- matchind = i;
5290- else
5291- ambiguous = 1;
5292- }
5293- }
5294- if (ambiguous)
5295- return -2;
5296- else
5297- return matchind;
5298+ int i;
5299+ size_t arglen;
5300+ int matchind = -1;
5301+ int ambiguous = 0;
5302+
5303+ arglen = strlen(arg);
5304+ for (i = 0; optlist[i]; i++) {
5305+ if (!strncmp(optlist[i], arg, arglen)) {
5306+ if (strlen(optlist[i]) == arglen)
5307+ return i;
5308+ else if (matchind == -1)
5309+ matchind = i;
5310+ else
5311+ ambiguous = 1;
5312+ }
5313+ }
5314+ if (ambiguous)
5315+ return -2;
5316+ else
5317+ return matchind;
5318 }
5319
5320 static void
5321 invalid_arg(const char *kind, const char *value, int problem)
5322 {
5323- fprintf(stderr, "patch: ");
5324- if (problem == -1)
5325- fprintf(stderr, "invalid");
5326- else
5327- fprintf(stderr, "ambiguous");
5328- fprintf(stderr, " %s `%s'\n", kind, value);
5329+ fprintf(stderr, "patch: ");
5330+ if (problem == -1)
5331+ fprintf(stderr, "invalid");
5332+ else
5333+ fprintf(stderr, "ambiguous");
5334+ fprintf(stderr, " %s `%s'\n", kind, value);
5335 }
5336
5337 enum BackupType
5338 get_version(const char *version_str)
5339 {
5340- int i;
5341+ int i;
5342
5343- if (version_str == NULL || *version_str == '\0')
5344- return BACKUP_NUMBERED_EXISTING;
5345- i = argmatch(version_str, backup_args);
5346- if (i >= 0)
5347- return backup_types[i];
5348- invalid_arg("version control type", version_str, i);
5349- exit(2);
5350+ if (version_str == NULL || *version_str == '\0')
5351+ return BACKUP_NUMBERED_EXISTING;
5352+ i = argmatch(version_str, backup_args);
5353+ if (i >= 0)
5354+ return backup_types[i];
5355+ invalid_arg("version control type", version_str, i);
5356+ exit(2);
5357 }
+3,
-3
1@@ -32,7 +32,6 @@
2 * SUCH DAMAGE.
3 */
4
5-#include <paths.h>
6 #include <signal.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9@@ -43,6 +42,7 @@
10 * Evaluate a command.
11 */
12
13+#include "../../../shared/paths.h"
14 #include "shell.h"
15 #include "nodes.h"
16 #include "syntax.h"
17@@ -989,7 +989,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
18 argv += 2;
19 argc -= 2;
20 }
21- path = _PATH_STDPATH;
22+ path = ARUU_PATH_STDPATH;
23 clearcmdentry();
24 do_clearcmdentry = 1;
25 } else if (!strcmp(argv[1], "--")) {
26@@ -1318,7 +1318,7 @@ commandcmd(int argc __unused, char **argv __unused)
27 while ((ch = nextopt("pvV")) != '\0') {
28 switch (ch) {
29 case 'p':
30- path = _PATH_STDPATH;
31+ path = ARUU_PATH_STDPATH;
32 break;
33 case 'v':
34 cmd = TYPECMD_SMALLV;
+3,
-3
1@@ -37,7 +37,6 @@
2 #include <unistd.h>
3 #include <fcntl.h>
4 #include <errno.h>
5-#include <paths.h>
6 #include <stdlib.h>
7
8 /*
9@@ -49,6 +48,7 @@
10 * would make the command name "hash" a misnomer.
11 */
12
13+#include "../../../shared/paths.h"
14 #include "shell.h"
15 #include "main.h"
16 #include "nodes.h"
17@@ -186,8 +186,8 @@ tryexec(char *cmd, char **argv, char **envp)
18 }
19 }
20 *argv = cmd;
21- *--argv = __DECONST(char *, _PATH_BSHELL);
22- execve(_PATH_BSHELL, argv, envp);
23+ *--argv = __DECONST(char *, ARUU_PATH_BSHELL);
24+ execve(ARUU_PATH_BSHELL, argv, envp);
25 }
26 errno = e;
27 }
+6,
-6
1@@ -39,12 +39,12 @@
2 #include <sys/wait.h>
3 #include <errno.h>
4 #include <fcntl.h>
5-#include <paths.h>
6 #include <signal.h>
7 #include <stddef.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10
11+#include "../../../shared/paths.h"
12 #include "shell.h"
13 #if JOBS
14 #include <termios.h>
15@@ -179,7 +179,7 @@ setjobctl(int on)
16 if (on) {
17 if (ttyfd != -1)
18 close(ttyfd);
19- if ((ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC)) < 0) {
20+ if ((ttyfd = open(ARUU_PATH_DEVTTY, O_RDWR | O_CLOEXEC)) < 0) {
21 i = 0;
22 while (i <= 2 && !isatty(i))
23 i++;
24@@ -942,9 +942,9 @@ forkshell(struct job *jp, union node *n, int mode)
25 if ((jp == NULL || jp->nprocs == 0) &&
26 ! fd0_redirected_p ()) {
27 close(0);
28- if (open(_PATH_DEVNULL, O_RDONLY) != 0)
29+ if (open(ARUU_PATH_DEVNULL, O_RDONLY) != 0)
30 error("cannot open %s: %s",
31- _PATH_DEVNULL, strerror(errno));
32+ ARUU_PATH_DEVNULL, strerror(errno));
33 }
34 }
35 #else
36@@ -954,9 +954,9 @@ forkshell(struct job *jp, union node *n, int mode)
37 if ((jp == NULL || jp->nprocs == 0) &&
38 ! fd0_redirected_p ()) {
39 close(0);
40- if (open(_PATH_DEVNULL, O_RDONLY) != 0)
41+ if (open(ARUU_PATH_DEVNULL, O_RDONLY) != 0)
42 error("cannot open %s: %s",
43- _PATH_DEVNULL, strerror(errno));
44+ ARUU_PATH_DEVNULL, strerror(errno));
45 }
46 }
47 #endif
+2,
-2
1@@ -39,6 +39,7 @@
2 #endif
3
4 #include "util.h"
5+#include "../../../shared/paths.h"
6 #include "shell.h"
7 #include "alias.h"
8 #include "builtins.h"
9@@ -63,7 +64,6 @@
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <limits.h>
13-#include <paths.h>
14 #include <pwd.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17@@ -693,7 +693,7 @@ operands:
18 if (editor) {
19 int fd;
20 INTOFF;
21- sprintf(editfilestr, "%s/_shXXXXXX", _PATH_TMP);
22+ sprintf(editfilestr, "%s/_shXXXXXX", ARUU_PATH_TMP);
23 if ((fd = mkstemp(editfilestr)) < 0)
24 error("can't create temporary file %s", editfile);
25 editfile = editfilestr;
+2,
-2
1@@ -40,9 +40,9 @@
2 #include <locale.h>
3 #include <errno.h>
4 #include <termios.h>
5-#include <paths.h>
6 #include <unistd.h>
7
8+#include "../../../shared/paths.h"
9 #include "shell.h"
10 #include "main.h"
11 #include "mail.h"
12@@ -134,7 +134,7 @@ main(int argc, char *argv[])
13 * file descriptors 0, 1, and 2 on /dev/console.
14 */
15 if (fcntl(STDIN_FILENO, F_GETFL, NULL) == -1 && errno == EBADF) {
16- (void)open(_PATH_CONSOLE, O_RDWR);
17+ (void)open(ARUU_PATH_DEVCONSOLE, O_RDWR);
18 (void)setsid();
19 (void)tcsetsid(STDIN_FILENO, rootpid);
20 }
+2,
-2
1@@ -32,6 +32,7 @@
2 * SUCH DAMAGE.
3 */
4
5+#include "../../../shared/paths.h"
6 #include "shell.h"
7 #include "output.h"
8 #include "expand.h"
9@@ -53,7 +54,6 @@
10
11 #include <langinfo.h>
12 #include <locale.h>
13-#include <paths.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16
17@@ -102,7 +102,7 @@ static const struct varinit varinit[] = {
18 NULL },
19 { &vmpath, VUNSET, "MAILPATH=",
20 NULL },
21- { &vpath, 0, "PATH=" _PATH_DEFPATH,
22+ { &vpath, 0, "PATH=" ARUU_PATH_DEFPATH,
23 changepath },
24 /*
25 * vps1 depends on uid
+3,
-2
1@@ -8,6 +8,7 @@
2 #include <stdio.h>
3 #include <unistd.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 static void
9@@ -50,9 +51,9 @@ main(int argc, char *argv[])
10 eprintf("fork:");
11 /* fallthrough */
12 case 0:
13- execvp(argv[0], argv);
14+ wexecvp_self(argv[0], argv);
15 savederrno = errno;
16- weprintf("execvp %s:", argv[0]);
17+ weprintf("wexecvp %s:", argv[0]);
18 _exit(126 + (savederrno == ENOENT));
19 default:
20 break;
+3,
-2
1@@ -11,6 +11,7 @@
2 #include <string.h>
3 #include <unistd.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 #define NARGS 10000
9@@ -245,9 +246,9 @@ dospawn:
10 eprintf("fork:");
11 /* fallthrough */
12 case 0:
13- execvp(*cmd, cmd);
14+ wexecvp_self(*cmd, cmd);
15 savederrno = errno;
16- weprintf("execvp %s:", *cmd);
17+ weprintf("wexecvp %s:", *cmd);
18 _exit(126 + (savederrno == ENOENT));
19 }
20 curprocs++;
+4,
-3
1@@ -5,6 +5,7 @@
2 #include <stdlib.h>
3 #include <unistd.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 static void
9@@ -41,14 +42,14 @@ main(int argc, char *argv[])
10
11 if (argc == 1) {
12 cmd = *shell;
13- execvp(cmd, shell);
14+ wexecvp_self(cmd, shell);
15 } else {
16 cmd = argv[1];
17- execvp(cmd, argv + 1);
18+ wexecvp_self(cmd, argv + 1);
19 }
20
21 savederrno = errno;
22- weprintf("execvp %s:", cmd);
23+ weprintf("wexecvp %s:", cmd);
24
25 _exit(126 + (savederrno == ENOENT));
26 }
+3,
-1
1@@ -17,6 +17,8 @@
2 #include <unistd.h>
3
4 #include "queue.h"
5+#include "paths.h"
6+#include "wexec.h"
7 #include "util.h"
8
9 struct field {
10@@ -121,7 +123,7 @@ runjob(char *cmd)
11 setsid();
12 loginfo("run: %s pid: %d at %s",
13 cmd, getpid(), ctime(&t));
14- execl("/bin/sh", "/bin/sh", "-c", cmd, (char *)NULL);
15+ wexecv_self(ARUU_PATH_BIN "/sh", (char *const[]){"sh", "-c", cmd, NULL});
16 logerr("error: failed to execute job: %s time: %s",
17 cmd, ctime(&t));
18 _exit(1);
+3,
-2
1@@ -9,6 +9,7 @@
2 #include <stdio.h>
3 #include <unistd.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 static void
9@@ -71,9 +72,9 @@ main(int argc, char *argv[])
10 if (oflag && close(fd) < 0)
11 eprintf("close:");
12 argv++;
13- execvp(*argv, argv);
14+ wexecvp_self(*argv, argv);
15 savederrno = errno;
16- weprintf("execvp %s:", *argv);
17+ weprintf("wexecvp %s:", *argv);
18 _exit(126 + (savederrno == ENOENT));
19 default:
20 break;
+117,
-114
1@@ -15,6 +15,7 @@
2 #include <utmp.h>
3
4 #include "config.h"
5+#include "wexec.h"
6 #include "util.h"
7
8 static char *tty = "/dev/tty1";
9@@ -23,7 +24,7 @@ static char *defaultterm = "linux";
10 static void
11 usage(void)
12 {
13- eprintf("usage: %s [tty] [term] [cmd] [args...]\n", argv0);
14+ eprintf("usage: %s [tty] [term] [cmd] [args...]\n", argv0);
15 }
16
17 // ?man getty: set terminal mode
18@@ -32,117 +33,119 @@ usage(void)
19 int
20 main(int argc, char *argv[])
21 {
22- char term[128], logname[LOGIN_NAME_MAX], c;
23- char hostname[HOST_NAME_MAX + 1];
24- char ut_line_buf[UT_LINESIZE + 1];
25- struct utmp usr;
26- struct sigaction sa;
27- FILE *fp;
28- int fd;
29- unsigned int i = 0;
30- ssize_t n;
31- long pos;
32-
33- ARGBEGIN {
34- default:
35- usage();
36- } ARGEND;
37-
38- strlcpy(term, defaultterm, sizeof(term));
39- if (argc > 0) {
40- tty = argv[0];
41- if (argc > 1)
42- strlcpy(term, argv[1], sizeof(term));
43- }
44-
45- sa.sa_handler = SIG_IGN;
46- sa.sa_flags = 0;
47- sigemptyset(&sa.sa_mask);
48- sigaction(SIGHUP, &sa, NULL);
49-
50- setenv("TERM", term, 1);
51-
52- setsid();
53-
54- fd = open(tty, O_RDWR);
55- if (fd < 0)
56- eprintf("open %s:", tty);
57- if (isatty(fd) == 0)
58- eprintf("%s is not a tty\n", tty);
59-
60- /* steal the controlling terminal if necessary */
61- if (ioctl(fd, TIOCSCTTY, (void *)1) != 0)
62- weprintf("TIOCSCTTY: could not set controlling tty\n");
63- vhangup();
64- close(fd);
65-
66- fd = open(tty, O_RDWR);
67- if (fd < 0)
68- eprintf("open %s:", tty);
69- dup2(fd, 0);
70- dup2(fd, 1);
71- dup2(fd, 2);
72- if (fchown(fd, 0, 0) < 0)
73- weprintf("fchown %s:", tty);
74- if (fchmod(fd, 0600) < 0)
75- weprintf("fchmod %s:", tty);
76- if (fd > 2)
77- close(fd);
78-
79- sa.sa_handler = SIG_DFL;
80- sa.sa_flags = 0;
81- sigemptyset(&sa.sa_mask);
82- sigaction(SIGHUP, &sa, NULL);
83-
84- /* Clear all utmp entries for this tty */
85- fp = fopen(UTMP_PATH, "r+");
86- if (fp) {
87- do {
88- pos = ftell(fp);
89- if (fread(&usr, sizeof(usr), 1, fp) != 1)
90- break;
91- if (usr.ut_line[0] == '\0')
92- continue;
93- memcpy(ut_line_buf, usr.ut_line, UT_LINESIZE);
94- ut_line_buf[UT_LINESIZE] = '\0';
95- if (strcmp(ut_line_buf, tty) != 0)
96- continue;
97- memset(&usr, 0, sizeof(usr));
98- fseek(fp, pos, SEEK_SET);
99- if (fwrite(&usr, sizeof(usr), 1, fp) != 1)
100- break;
101- } while (1);
102- if (ferror(fp))
103- weprintf("%s: I/O error:", UTMP_PATH);
104- fclose(fp);
105- }
106-
107- if (argc > 2)
108- return execvp(argv[2], argv + 2);
109-
110- if (gethostname(hostname, sizeof(hostname)) == 0)
111- printf("%s ", hostname);
112- printf("login: ");
113- fflush(stdout);
114-
115- /* Flush pending input */
116- ioctl(0, TCFLSH, (void *)0);
117- memset(logname, 0, sizeof(logname));
118- while (1) {
119- n = read(0, &c, 1);
120- if (n < 0)
121- eprintf("read:");
122- if (n == 0)
123- return 1;
124- if (i >= sizeof(logname) - 1)
125- eprintf("login name too long\n");
126- if (c == '\n' || c == '\r')
127- break;
128- logname[i++] = c;
129- }
130- if (logname[0] == '-')
131- eprintf("login name cannot start with '-'\n");
132- if (logname[0] == '\0')
133- return 1;
134- return execlp("/bin/login", "login", "-p", logname, NULL);
135+ char term[128], logname[LOGIN_NAME_MAX], c;
136+ char hostname[HOST_NAME_MAX + 1];
137+ char ut_line_buf[UT_LINESIZE + 1];
138+ struct utmp usr;
139+ struct sigaction sa;
140+ FILE *fp;
141+ int fd;
142+ unsigned int i = 0;
143+ ssize_t n;
144+ long pos;
145+
146+ ARGBEGIN {
147+ default:
148+ usage();
149+ } ARGEND;
150+
151+ strlcpy(term, defaultterm, sizeof(term));
152+ if (argc > 0) {
153+ tty = argv[0];
154+ if (argc > 1)
155+ strlcpy(term, argv[1], sizeof(term));
156+ }
157+
158+ sa.sa_handler = SIG_IGN;
159+ sa.sa_flags = 0;
160+ sigemptyset(&sa.sa_mask);
161+ sigaction(SIGHUP, &sa, NULL);
162+
163+ setenv("TERM", term, 1);
164+
165+ setsid();
166+
167+ fd = open(tty, O_RDWR);
168+ if (fd < 0)
169+ eprintf("open %s:", tty);
170+ if (isatty(fd) == 0)
171+ eprintf("%s is not a tty\n", tty);
172+
173+ /* steal the controlling terminal if necessary */
174+ if (ioctl(fd, TIOCSCTTY, (void *)1) != 0)
175+ weprintf("TIOCSCTTY: could not set controlling tty\n");
176+ vhangup();
177+ close(fd);
178+
179+ fd = open(tty, O_RDWR);
180+ if (fd < 0)
181+ eprintf("open %s:", tty);
182+ dup2(fd, 0);
183+ dup2(fd, 1);
184+ dup2(fd, 2);
185+ if (fchown(fd, 0, 0) < 0)
186+ weprintf("fchown %s:", tty);
187+ if (fchmod(fd, 0600) < 0)
188+ weprintf("fchmod %s:", tty);
189+ if (fd > 2)
190+ close(fd);
191+
192+ sa.sa_handler = SIG_DFL;
193+ sa.sa_flags = 0;
194+ sigemptyset(&sa.sa_mask);
195+ sigaction(SIGHUP, &sa, NULL);
196+
197+ /* Clear all utmp entries for this tty */
198+ fp = fopen(UTMP_PATH, "r+");
199+ if (fp) {
200+ do {
201+ pos = ftell(fp);
202+ if (fread(&usr, sizeof(usr), 1, fp) != 1)
203+ break;
204+ if (usr.ut_line[0] == '\0')
205+ continue;
206+ memcpy(ut_line_buf, usr.ut_line, UT_LINESIZE);
207+ ut_line_buf[UT_LINESIZE] = '\0';
208+ if (strcmp(ut_line_buf, tty) != 0)
209+ continue;
210+ memset(&usr, 0, sizeof(usr));
211+ fseek(fp, pos, SEEK_SET);
212+ if (fwrite(&usr, sizeof(usr), 1, fp) != 1)
213+ break;
214+ } while (1);
215+ if (ferror(fp))
216+ weprintf("%s: I/O error:", UTMP_PATH);
217+ fclose(fp);
218+ }
219+
220+ if (argc > 2) {
221+ wexecvp_self(argv[2], argv + 2);
222+ return 0;
223+ }
224+
225+ if (gethostname(hostname, sizeof(hostname)) == 0)
226+ printf("%s ", hostname);
227+ printf("login: ");
228+ fflush(stdout);
229+
230+ /* Flush pending input */
231+ ioctl(0, TCFLSH, (void *)0);
232+ memset(logname, 0, sizeof(logname));
233+ while (1) {
234+ n = read(0, &c, 1);
235+ if (n < 0)
236+ eprintf("read:");
237+ if (n == 0)
238+ return 1;
239+ if (i >= sizeof(logname) - 1)
240+ eprintf("login name too long\n");
241+ if (c == '\n' || c == '\r')
242+ break;
243+ logname[i++] = c;
244+ }
245+ if (logname[0] == '-')
246+ eprintf("login name cannot start with '-'\n");
247+ if (logname[0] == '\0')
248+ return 1;
249+ wexecvp_self("login", (char *const[]){"login", "-p", logname, NULL}); return 0;
250 }
+1,
-1
1@@ -3,7 +3,6 @@
2
3 #include <errno.h>
4 #include <libgen.h>
5-#include <paths.h>
6 #include <pwd.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9@@ -13,6 +12,7 @@
10 #include <unistd.h>
11
12 #include "config.h"
13+#include "paths.h"
14 #include "util.h"
15
16 static void
+5,
-5
1@@ -2,7 +2,6 @@
2
3
4 #include <errno.h>
5-#include <paths.h>
6 #include <pwd.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9@@ -11,6 +10,7 @@
10 #include <utmp.h>
11
12 #include "text.h"
13+#include "paths.h"
14 #include "util.h"
15
16 #define PASSWD "/etc/passwd"
17@@ -37,7 +37,7 @@ lastlog(char *user)
18 fread(&ll, sizeof(struct lastlog), 1, last);
19
20 if (ferror(last))
21- eprintf("%s: read error:", _PATH_LASTLOG);
22+ eprintf("%s: read error:", ARUU_PATH_LASTLOG);
23
24 /* on glibc `ll_time' can be an int32_t with compat32
25 * avoid compiler warning when calling ctime() */
26@@ -55,8 +55,8 @@ main(int argc, char **argv)
27 char *line = NULL, *p;
28 size_t sz = 0;
29
30- if ((last = fopen(_PATH_LASTLOG, "r")) == NULL)
31- eprintf("fopen %s:", _PATH_LASTLOG);
32+ if ((last = fopen(ARUU_PATH_LASTLOG, "r")) == NULL)
33+ eprintf("fopen %s:", ARUU_PATH_LASTLOG);
34
35 if (argc > 1) {
36 while (*++argv)
37@@ -76,7 +76,7 @@ main(int argc, char **argv)
38 }
39
40 if (fclose(last))
41- eprintf("fclose %s:", _PATH_LASTLOG);
42+ eprintf("fclose %s:", ARUU_PATH_LASTLOG);
43
44 return 0;
45 }
+3,
-2
1@@ -16,6 +16,7 @@
2
3 #include "config.h"
4 #include "passwd.h"
5+#include "wexec.h"
6 #include "util.h"
7
8 /* Write utmp entry */
9@@ -58,8 +59,8 @@ dologin(struct passwd *pw, int preserve)
10 setenv("PATH", ENV_PATH, 1);
11 if (chdir(pw->pw_dir) < 0)
12 eprintf("chdir %s:", pw->pw_dir);
13- execlp(shell, shell, "-l", NULL);
14- weprintf("execlp %s:", shell);
15+ wexecvp_self(shell, (char *const[]){shell, "-l", NULL});
16+ weprintf("wexecvp %s:", shell);
17 return (errno == ENOENT) ? 127 : 126;
18 }
19
+115,
-143
1@@ -1,8 +1,9 @@
2 /* See LICENSE file for copyright and license details. */
3+#include "passwd.h"
4+#include "paths.h"
5 #include "util.h"
6
7 #include <ctype.h>
8-#include <fcntl.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12@@ -11,7 +12,7 @@
13 static void
14 usage(void)
15 {
16- eprintf("usage: %s [-P fd] [-m type] [-S salt] [password] [salt]\n", argv0);
17+ eprintf("usage: %s [-P fd] [-m type] [-S salt] [password] [salt]\n", argv0);
18 }
19
20 // ?man mkpasswd: encrypt the given password using salt
21@@ -20,145 +21,116 @@ usage(void)
22 int
23 main(int argc, char *argv[])
24 {
25- char *mflag;
26- char *sflag;
27- char *parg;
28- char *password;
29- char *cryptpass;
30- int pfd;
31- int fd;
32- int r;
33- int i;
34- int len;
35- int id;
36- char salt[128];
37- char rand_bytes[32];
38- char passbuf[1024];
39- static const char saltchars[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
40-
41- mflag = NULL;
42- sflag = NULL;
43- parg = NULL;
44- password = NULL;
45- cryptpass = NULL;
46- pfd = -1;
47-
48- ARGBEGIN {
49- // ?man -P:fd: read password from file descriptor
50- case 'P':
51- parg = EARGF(usage());
52- pfd = estrtonum(parg, 0, INT_MAX);
53- break;
54- // ?man -m:type: encryption method (des, md5, sha256, sha512)
55- case 'm':
56- mflag = EARGF(usage());
57- break;
58- // ?man -S:salt: salt to use
59- case 'S':
60- sflag = EARGF(usage());
61- break;
62- default:
63- usage();
64- } ARGEND
65-
66- if (argc > 2)
67- usage();
68-
69- if (argc == 2) {
70- if (sflag)
71- eprintf("duplicate salt\n");
72- sflag = argv[1];
73- }
74-
75- if (argc >= 1)
76- password = argv[0];
77-
78- /* default type is des */
79- if (!mflag)
80- mflag = "des";
81-
82- if (strcasecmp(mflag, "des") == 0) {
83- id = 0;
84- len = 2;
85- } else if (strcasecmp(mflag, "md5") == 0) {
86- id = 1;
87- len = 8;
88- } else if (strcasecmp(mflag, "sha256") == 0) {
89- id = 5;
90- len = 16;
91- } else if (strcasecmp(mflag, "sha512") == 0) {
92- id = 6;
93- len = 16;
94- } else {
95- eprintf("bad method: %s\n", mflag);
96- }
97-
98- if (sflag) {
99- /* validate provided salt */
100- char *s = sflag;
101- while (*s) {
102- if (!isalnum((unsigned char)*s) && *s != '.' && *s != '/')
103- eprintf("bad SALT (need [a-zA-Z0-9./])\n");
104- s++;
105- }
106- if (id > 0)
107- snprintf(salt, sizeof(salt), "$%d$%s", id, sflag);
108- else
109- estrlcpy(salt, sflag, sizeof(salt));
110- } else {
111- /* generate random salt */
112- fd = open("/dev/urandom", O_RDONLY);
113- if (fd < 0)
114- eprintf("open /dev/urandom:");
115- r = read(fd, rand_bytes, len);
116- if (r < len)
117- eprintf("read /dev/urandom:");
118- close(fd);
119-
120- if (id > 0) {
121- snprintf(salt, sizeof(salt), "$%d$", id);
122- for (i = 0; i < len; i++)
123- salt[3 + i] = saltchars[(unsigned char)rand_bytes[i] % 64];
124- salt[3 + len] = '\0';
125- } else {
126- for (i = 0; i < len; i++)
127- salt[i] = saltchars[(unsigned char)rand_bytes[i] % 64];
128- salt[len] = '\0';
129- }
130- }
131-
132- if (pfd >= 0) {
133- if (dup2(pfd, 0) == -1)
134- eprintf("dup2:");
135- close(pfd);
136- }
137-
138- if (!password) {
139- if (isatty(0)) {
140- char *p = getpass("Password: ");
141- if (!p)
142- eprintf("getpass failed\n");
143- estrlcpy(passbuf, p, sizeof(passbuf));
144- password = passbuf;
145- } else {
146- /* read from stdin */
147- int bytes = read(0, passbuf, sizeof(passbuf) - 1);
148- if (bytes < 0)
149- eprintf("read stdin:");
150- /* strip trailing newline or cr */
151- while (bytes > 0 && (passbuf[bytes - 1] == '\n' || passbuf[bytes - 1] == '\r'))
152- bytes--;
153- passbuf[bytes] = '\0';
154- password = passbuf;
155- }
156- }
157-
158- cryptpass = crypt(password, salt);
159- if (!cryptpass)
160- eprintf("crypt:");
161- printf("%s\n", cryptpass);
162-
163- if (fshut(stdout, "<stdout>"))
164- return 2;
165- return 0;
166+ char *mflag, *sflag, *parg, *password, *cryptpass;
167+ char *prefix;
168+ char salt[128];
169+ char passbuf[1024];
170+ int pfd, len;
171+
172+ mflag = NULL;
173+ sflag = NULL;
174+ parg = NULL;
175+ password = NULL;
176+ cryptpass = NULL;
177+ pfd = -1;
178+ len = 2;
179+ prefix = NULL;
180+
181+ ARGBEGIN {
182+ case 'P':
183+ // ?man -P:fd: read password from file descriptor
184+ parg = EARGF(usage());
185+ pfd = estrtonum(parg, 0, INT_MAX);
186+ break;
187+ case 'm':
188+ // ?man -m:type: encryption method (des, md5, sha256, sha512)
189+ mflag = EARGF(usage());
190+ break;
191+ case 'S':
192+ // ?man -S:salt: salt to use
193+ sflag = EARGF(usage());
194+ break;
195+ default:
196+ usage();
197+ } ARGEND
198+
199+ if (argc > 2)
200+ usage();
201+
202+ if (argc == 2) {
203+ if (sflag)
204+ eprintf("duplicate salt\n");
205+ sflag = argv[1];
206+ }
207+
208+ if (argc >= 1)
209+ password = argv[0];
210+
211+ if (!mflag)
212+ mflag = "des";
213+
214+ if (strcasecmp(mflag, "des") == 0) {
215+ len = 2;
216+ prefix = NULL;
217+ } else if (strcasecmp(mflag, "md5") == 0) {
218+ len = 8;
219+ prefix = "$1$";
220+ } else if (strcasecmp(mflag, "sha256") == 0) {
221+ len = 16;
222+ prefix = "$5$";
223+ } else if (strcasecmp(mflag, "sha512") == 0) {
224+ len = 16;
225+ prefix = "$6$";
226+ } else {
227+ eprintf("bad method: %s\n", mflag);
228+ }
229+
230+ if (sflag) {
231+ char *s = sflag;
232+ while (*s) {
233+ if (!isalnum((unsigned char)*s) && *s != '.' && *s != '/')
234+ eprintf("bad SALT (need [a-zA-Z0-9./])\n");
235+ s++;
236+ }
237+ if (prefix)
238+ snprintf(salt, sizeof(salt), "%s%s", prefix, sflag);
239+ else
240+ estrlcpy(salt, sflag, sizeof(salt));
241+ } else {
242+ if (pw_gensalt_cipher(salt, sizeof(salt), prefix, len) < 0)
243+ eprintf("pw_gensalt_cipher:");
244+ }
245+
246+ if (pfd >= 0) {
247+ if (dup2(pfd, 0) == -1)
248+ eprintf("dup2:");
249+ close(pfd);
250+ }
251+
252+ if (!password) {
253+ if (isatty(0)) {
254+ char *p = getpass("Password: ");
255+ if (!p)
256+ eprintf("getpass failed\n");
257+ estrlcpy(passbuf, p, sizeof(passbuf));
258+ password = passbuf;
259+ } else {
260+ int bytes = read(0, passbuf, sizeof(passbuf) - 1);
261+ if (bytes < 0)
262+ eprintf("read stdin:");
263+ while (bytes > 0 && (passbuf[bytes - 1] == '\n' || passbuf[bytes - 1] == '\r'))
264+ bytes--;
265+ passbuf[bytes] = '\0';
266+ password = passbuf;
267+ }
268+ }
269+
270+ cryptpass = crypt(password, salt);
271+ if (!cryptpass)
272+ eprintf("crypt:");
273+ printf("%s\n", cryptpass);
274+
275+ if (fshut(stdout, "<stdout>"))
276+ return 2;
277+ return 0;
278 }
+3,
-2
1@@ -14,6 +14,7 @@
2 #include <stdlib.h>
3 #include <unistd.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 static void
9@@ -103,9 +104,9 @@ main(int argc, char *argv[])
10 eprintf("fork:");
11 switch (pid) {
12 case 0:
13- execvp(argv[0], argv);
14+ wexecvp_self(argv[0], argv);
15 savederrno = errno;
16- weprintf("execvp %s:", argv[0]);
17+ weprintf("wexecvp %s:", argv[0]);
18 _exit(savederrno == ENOENT ? 127 : 126);
19 break;
20 default:
+3,
-2
1@@ -4,6 +4,7 @@
2 #include <errno.h>
3 #include <unistd.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 static int fflag = 0;
9@@ -46,9 +47,9 @@ main(int argc, char *argv[])
10 }
11 if (setsid() < 0)
12 eprintf("setsid:");
13- execvp(argv[0], argv);
14+ wexecvp_self(argv[0], argv);
15 savederrno = errno;
16- weprintf("execvp %s:", argv[0]);
17+ weprintf("wexecvp %s:", argv[0]);
18
19 _exit(126 + (savederrno == ENOENT));
20 }
+778,
-765
1@@ -3,6 +3,7 @@
2 #include "config.h"
3 #include "fs.h"
4 #include "utf.h"
5+#include "wexec.h"
6 #include "util.h"
7
8 #include <assert.h>
9@@ -25,27 +26,27 @@
10 static void
11 safe_puts(const char *s)
12 {
13- Rune r;
14- int n;
15-
16- if (isatty(1)) {
17- while (*s) {
18- n = chartorune(&r, s);
19- if (r == Runeerror) {
20- putchar('?');
21- s++;
22- } else if (isprintrune(r)) {
23- fputrune(&r, stdout);
24- s += n;
25- } else {
26- putchar('?');
27- s += n;
28- }
29- }
30- putchar('\n');
31- } else {
32- puts(s);
33- }
34+ Rune r;
35+ int n;
36+
37+ if (isatty(1)) {
38+ while (*s) {
39+ n = chartorune(&r, s);
40+ if (r == Runeerror) {
41+ putchar('?');
42+ s++;
43+ } else if (isprintrune(r)) {
44+ fputrune(&r, stdout);
45+ s += n;
46+ } else {
47+ putchar('?');
48+ s += n;
49+ }
50+ }
51+ putchar('\n');
52+ } else {
53+ puts(s);
54+ }
55 }
56 #else
57 #define safe_puts(s) puts(s)
58@@ -54,40 +55,40 @@ safe_puts(const char *s)
59 #define BLKSIZ (sizeof (struct header)) /* must equal 512 bytes */
60
61 enum Type {
62- REG = '0',
63- AREG = '\0',
64- HARDLINK = '1',
65- SYMLINK = '2',
66- CHARDEV = '3',
67- BLOCKDEV = '4',
68- DIRECTORY = '5',
69- FIFO = '6',
70- RESERVED = '7'
71+ REG = '0',
72+ AREG = '\0',
73+ HARDLINK = '1',
74+ SYMLINK = '2',
75+ CHARDEV = '3',
76+ BLOCKDEV = '4',
77+ DIRECTORY = '5',
78+ FIFO = '6',
79+ RESERVED = '7'
80 };
81
82 struct header {
83- char name[100];
84- char mode[8];
85- char uid[8];
86- char gid[8];
87- char size[12];
88- char mtime[12];
89- char chksum[8];
90- char type;
91- char linkname[100];
92- char magic[6];
93- char version[2];
94- char uname[32];
95- char gname[32];
96- char major[8];
97- char minor[8];
98- char prefix[155];
99- char padding[12];
100+ char name[100];
101+ char mode[8];
102+ char uid[8];
103+ char gid[8];
104+ char size[12];
105+ char mtime[12];
106+ char chksum[8];
107+ char type;
108+ char linkname[100];
109+ char magic[6];
110+ char version[2];
111+ char uname[32];
112+ char gname[32];
113+ char major[8];
114+ char minor[8];
115+ char prefix[155];
116+ char padding[12];
117 };
118
119 static struct dirtime {
120- char *name;
121- time_t mtime;
122+ char *name;
123+ time_t mtime;
124 } *dirtimes;
125
126 static size_t dirtimeslen;
127@@ -106,33 +107,33 @@ static size_t excludes_cnt = 0;
128 static void
129 add_exclude(const char *pattern)
130 {
131- excludes = ereallocarray(excludes, excludes_cnt + 1, sizeof(*excludes));
132- excludes[excludes_cnt++] = estrdup(pattern);
133+ excludes = ereallocarray(excludes, excludes_cnt + 1, sizeof(*excludes));
134+ excludes[excludes_cnt++] = estrdup(pattern);
135 }
136
137 static int
138 is_excluded(const char *path)
139 {
140- size_t i;
141- const char *base = strrchr(path, '/');
142- base = base ? base + 1 : path;
143-
144- for (i = 0; i < excludes_cnt; i++) {
145- if (fnmatch(excludes[i], path, 0) == 0 ||
146- fnmatch(excludes[i], base, 0) == 0)
147- return 1;
148- }
149- return 0;
150+ size_t i;
151+ const char *base = strrchr(path, '/');
152+ base = base ? base + 1 : path;
153+
154+ for (i = 0; i < excludes_cnt; i++) {
155+ if (fnmatch(excludes[i], path, 0) == 0 ||
156+ fnmatch(excludes[i], base, 0) == 0)
157+ return 1;
158+ }
159+ return 0;
160 }
161 #endif
162 static const char *filtertool;
163
164 static const char *filtertools[] = {
165- ['J'] = "xz",
166- ['Z'] = "compress",
167- ['a'] = "lzma",
168- ['j'] = "bzip2",
169- ['z'] = "gzip",
170+ ['J'] = "xz",
171+ ['Z'] = "compress",
172+ ['a'] = "lzma",
173+ ['j'] = "bzip2",
174+ ['z'] = "gzip",
175 };
176
177 #if FEATURE_TAR_TO_STDOUT
178@@ -153,17 +154,17 @@ static int strip_components_count = 0;
179 static char *
180 strip_components(char *path, int count)
181 {
182- char *p = path;
183- int i;
184-
185- for (i = 0; i < count; i++) {
186- p = strchr(p, '/');
187- if (!p)
188- return NULL;
189- while (*p == '/')
190- p++;
191- }
192- return p;
193+ char *p = path;
194+ int i;
195+
196+ for (i = 0; i < count; i++) {
197+ p = strchr(p, '/');
198+ if (!p)
199+ return NULL;
200+ while (*p == '/')
201+ p++;
202+ }
203+ return p;
204 }
205 #else
206 #define strip_components_count 0
207@@ -176,27 +177,27 @@ static size_t files_from_cnt = 0;
208 static void
209 add_files_from(const char *path)
210 {
211- files_from = ereallocarray(files_from, files_from_cnt + 1, sizeof(*files_from));
212- files_from[files_from_cnt++] = estrdup(path);
213+ files_from = ereallocarray(files_from, files_from_cnt + 1, sizeof(*files_from));
214+ files_from[files_from_cnt++] = estrdup(path);
215 }
216
217 static void
218 load_files_from_file(const char *path)
219 {
220- FILE *fp = fopen(path, "r");
221- char line[PATH_MAX];
222-
223- if (!fp)
224- eprintf("open %s:", path);
225- while (fgets(line, sizeof(line), fp)) {
226- size_t len = strlen(line);
227- while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
228- len--;
229- line[len] = '\0';
230- if (len > 0)
231- add_files_from(line);
232- }
233- fclose(fp);
234+ FILE *fp = fopen(path, "r");
235+ char line[PATH_MAX];
236+
237+ if (!fp)
238+ eprintf("open %s:", path);
239+ while (fgets(line, sizeof(line), fp)) {
240+ size_t len = strlen(line);
241+ while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
242+ len--;
243+ line[len] = '\0';
244+ if (len > 0)
245+ add_files_from(line);
246+ }
247+ fclose(fp);
248 }
249 #else
250 #define files_from_cnt 0
251@@ -206,581 +207,593 @@ load_files_from_file(const char *path)
252 static void
253 load_excludes_from_file(const char *path)
254 {
255- FILE *fp = fopen(path, "r");
256- char line[PATH_MAX];
257-
258- if (!fp)
259- eprintf("open %s:", path);
260- while (fgets(line, sizeof(line), fp)) {
261- size_t len = strlen(line);
262- while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
263- len--;
264- line[len] = '\0';
265- if (len > 0) {
266+ FILE *fp = fopen(path, "r");
267+ char line[PATH_MAX];
268+
269+ if (!fp)
270+ eprintf("open %s:", path);
271+ while (fgets(line, sizeof(line), fp)) {
272+ size_t len = strlen(line);
273+ while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
274+ len--;
275+ line[len] = '\0';
276+ if (len > 0) {
277 #if FEATURE_TAR_EXCLUDE
278- add_exclude(line);
279+ add_exclude(line);
280 #else
281- (void)line;
282+ (void)line;
283 #endif
284- }
285- }
286- fclose(fp);
287+ }
288+ }
289+ fclose(fp);
290 }
291 #endif
292
293 static void
294 pushdirtime(char *name, time_t mtime)
295 {
296- dirtimes = ereallocarray(dirtimes, dirtimeslen + 1, sizeof(*dirtimes));
297- dirtimes[dirtimeslen].name = estrdup(name);
298- dirtimes[dirtimeslen].mtime = mtime;
299- dirtimeslen++;
300+ dirtimes = ereallocarray(dirtimes, dirtimeslen + 1, sizeof(*dirtimes));
301+ dirtimes[dirtimeslen].name = estrdup(name);
302+ dirtimes[dirtimeslen].mtime = mtime;
303+ dirtimeslen++;
304 }
305
306 static struct dirtime *
307 popdirtime(void)
308 {
309- if (dirtimeslen) {
310- dirtimeslen--;
311- return &dirtimes[dirtimeslen];
312- }
313- return NULL;
314+ if (dirtimeslen) {
315+ dirtimeslen--;
316+ return &dirtimes[dirtimeslen];
317+ }
318+ return NULL;
319 }
320
321 static int
322 comp(int fd, const char *tool, const char *flags)
323 {
324- int fds[2];
325-
326- if (pipe(fds) < 0)
327- eprintf("pipe:");
328-
329- switch (fork()) {
330- case -1:
331- eprintf("fork:");
332- /* fallthrough */
333- case 0:
334- dup2(fd, 1);
335- dup2(fds[0], 0);
336- close(fds[0]);
337- close(fds[1]);
338-
339- execlp(tool, tool, flags, NULL);
340- weprintf("execlp %s:", tool);
341- _exit(1);
342- }
343- close(fds[0]);
344- return fds[1];
345+ int fds[2];
346+
347+ if (pipe(fds) < 0)
348+ eprintf("pipe:");
349+
350+ switch (fork()) {
351+ case -1:
352+ eprintf("fork:");
353+ /* fallthrough */
354+ case 0:
355+ dup2(fd, 1);
356+ dup2(fds[0], 0);
357+ close(fds[0]);
358+ close(fds[1]);
359+
360+ {
361+ char *tar_argv[3];
362+ tar_argv[0] = (char *)tool;
363+ tar_argv[1] = (char *)flags;
364+ tar_argv[2] = NULL;
365+ wexecvp_self(tool, tar_argv);
366+ }
367+ weprintf("wexecvp %s:", tool);
368+ _exit(1);
369+ }
370+ close(fds[0]);
371+ return fds[1];
372 }
373
374 static int
375 decomp(int fd, const char *tool, const char *flags)
376 {
377- int fds[2];
378-
379- if (pipe(fds) < 0)
380- eprintf("pipe:");
381-
382- switch (fork()) {
383- case -1:
384- eprintf("fork:");
385- /* fallthrough */
386- case 0:
387- dup2(fd, 0);
388- dup2(fds[1], 1);
389- close(fds[0]);
390- close(fds[1]);
391-
392- execlp(tool, tool, flags, NULL);
393- weprintf("execlp %s:", tool);
394- _exit(1);
395- }
396- close(fds[1]);
397- return fds[0];
398+ int fds[2];
399+
400+ if (pipe(fds) < 0)
401+ eprintf("pipe:");
402+
403+ switch (fork()) {
404+ case -1:
405+ eprintf("fork:");
406+ /* fallthrough */
407+ case 0:
408+ dup2(fd, 0);
409+ dup2(fds[1], 1);
410+ close(fds[0]);
411+ close(fds[1]);
412+
413+ {
414+ char *tar_argv[3];
415+ tar_argv[0] = (char *)tool;
416+ tar_argv[1] = (char *)flags;
417+ tar_argv[2] = NULL;
418+ wexecvp_self(tool, tar_argv);
419+ }
420+ weprintf("wexecvp %s:", tool);
421+ _exit(1);
422+ }
423+ close(fds[1]);
424+ return fds[0];
425 }
426
427 static ssize_t
428 eread(int fd, void *buf, size_t n)
429 {
430- ssize_t r;
431+ ssize_t r;
432
433 again:
434- r = read(fd, buf, n);
435- if (r < 0) {
436- if (errno == EINTR)
437- goto again;
438- eprintf("read:");
439- }
440- return r;
441+ r = read(fd, buf, n);
442+ if (r < 0) {
443+ if (errno == EINTR)
444+ goto again;
445+ eprintf("read:");
446+ }
447+ return r;
448 }
449
450 static ssize_t
451 ewrite(int fd, const void *buf, size_t n)
452 {
453- ssize_t r;
454+ ssize_t r;
455
456- if ((r = write(fd, buf, n)) < 0 || (size_t)r != n)
457- eprintf("write:");
458- return r;
459+ if ((r = write(fd, buf, n)) < 0 || (size_t)r != n)
460+ eprintf("write:");
461+ return r;
462 }
463
464 static unsigned
465 chksum(struct header *h)
466 {
467- unsigned sum, i;
468+ unsigned sum, i;
469
470- memset(h->chksum, ' ', sizeof(h->chksum));
471- for (i = 0, sum = 0, assert(BLKSIZ == 512); i < BLKSIZ; i++)
472- sum += *((unsigned char *)h + i);
473- return sum;
474+ memset(h->chksum, ' ', sizeof(h->chksum));
475+ for (i = 0, sum = 0, assert(BLKSIZ == 512); i < BLKSIZ; i++)
476+ sum += *((unsigned char *)h + i);
477+ return sum;
478 }
479
480 #if FEATURE_TAR_CREATE
481 static void
482 putoctal(char *dst, unsigned num, int size)
483 {
484- if (snprintf(dst, size, "%.*o", size - 1, num) >= size)
485- eprintf("putoctal: input number '%o' too large\n", num);
486+ if (snprintf(dst, size, "%.*o", size - 1, num) >= size)
487+ eprintf("putoctal: input number '%o' too large\n", num);
488 }
489
490 static int
491 archive(const char *path)
492 {
493- static const struct header blank = {
494- .name = "././@LongLink",
495- .mode = "0000600",
496- .uid = "0000000",
497- .gid = "0000000",
498- .size = "00000000000",
499- .mtime = "00000000000",
500- .chksum = " ",
501- .type = AREG,
502- .linkname = "",
503- .magic = "ustar",
504- .version = { '0', '0' }
505- };
506- char b[BLKSIZ + BLKSIZ], *p;
507- struct header *h = (struct header *)b;
508- struct group *gr;
509- struct passwd *pw;
510- struct stat st;
511- ssize_t l, n, r;
512- int fd = -1;
513-
514- if (lstat(path, &st) < 0) {
515- weprintf("lstat %s:", path);
516- return 0;
517- } else if (st.st_ino == tarinode && st.st_dev == tardev) {
518- weprintf("ignoring %s\n", path);
519- return 0;
520- }
521- pw = getpwuid(st.st_uid);
522- gr = getgrgid(st.st_gid);
523-
524- *h = blank;
525- n = strlcpy(h->name, path, sizeof(h->name));
526- if ((size_t)n >= sizeof(h->name)) {
527- *++h = blank;
528- h->type = 'L';
529- putoctal(h->size, n, sizeof(h->size));
530- putoctal(h->chksum, chksum(h), sizeof(h->chksum));
531- ewrite(tarfd, (char *)h, BLKSIZ);
532-
533- for (p = (char *)path; n > 0; n -= BLKSIZ, p += BLKSIZ) {
534- if ((size_t)n < BLKSIZ) {
535- p = memcpy(h--, p, n);
536- memset(p + n, 0, BLKSIZ - (size_t)n);
537- }
538- ewrite(tarfd, p, BLKSIZ);
539- }
540- }
541-
542- putoctal(h->mode, (unsigned)st.st_mode & 0777, sizeof(h->mode));
543- putoctal(h->uid, (unsigned)st.st_uid, sizeof(h->uid));
544- putoctal(h->gid, (unsigned)st.st_gid, sizeof(h->gid));
545- putoctal(h->mtime, (unsigned)st.st_mtime, sizeof(h->mtime));
546- estrlcpy(h->uname, pw ? pw->pw_name : "", sizeof(h->uname));
547- estrlcpy(h->gname, gr ? gr->gr_name : "", sizeof(h->gname));
548-
549- if (S_ISREG(st.st_mode)) {
550- h->type = REG;
551- putoctal(h->size, st.st_size, sizeof(h->size));
552- fd = open(path, O_RDONLY);
553- if (fd < 0)
554- eprintf("open %s:", path);
555- } else if (S_ISDIR(st.st_mode)) {
556- h->type = DIRECTORY;
557- } else if (S_ISLNK(st.st_mode)) {
558- h->type = SYMLINK;
559- if ((r = readlink(path, h->linkname, sizeof(h->linkname) - 1)) < 0)
560- eprintf("readlink %s:", path);
561- h->linkname[r] = '\0';
562- } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
563- h->type = S_ISCHR(st.st_mode) ? CHARDEV : BLOCKDEV;
564- putoctal(h->major, (unsigned)major(st.st_dev), sizeof(h->major));
565- putoctal(h->minor, (unsigned)minor(st.st_dev), sizeof(h->minor));
566- } else if (S_ISFIFO(st.st_mode)) {
567- h->type = FIFO;
568- }
569-
570- putoctal(h->chksum, chksum(h), sizeof(h->chksum));
571- ewrite(tarfd, b, BLKSIZ);
572-
573- if (fd != -1) {
574- while ((l = eread(fd, b, BLKSIZ)) > 0) {
575- if ((size_t)l < BLKSIZ)
576- memset(b + l, 0, BLKSIZ - (size_t)l);
577- ewrite(tarfd, b, BLKSIZ);
578- }
579- close(fd);
580- }
581-
582- return 0;
583+ static const struct header blank = {
584+ .name = "././@LongLink",
585+ .mode = "0000600",
586+ .uid = "0000000",
587+ .gid = "0000000",
588+ .size = "00000000000",
589+ .mtime = "00000000000",
590+ .chksum = " ",
591+ .type = AREG,
592+ .linkname = "",
593+ .magic = "ustar",
594+ .version = { '0', '0' }
595+ };
596+ char b[BLKSIZ + BLKSIZ], *p;
597+ struct header *h = (struct header *)b;
598+ struct group *gr;
599+ struct passwd *pw;
600+ struct stat st;
601+ ssize_t l, n, r;
602+ int fd = -1;
603+
604+ if (lstat(path, &st) < 0) {
605+ weprintf("lstat %s:", path);
606+ return 0;
607+ } else if (st.st_ino == tarinode && st.st_dev == tardev) {
608+ weprintf("ignoring %s\n", path);
609+ return 0;
610+ }
611+ pw = getpwuid(st.st_uid);
612+ gr = getgrgid(st.st_gid);
613+
614+ *h = blank;
615+ n = strlcpy(h->name, path, sizeof(h->name));
616+ if ((size_t)n >= sizeof(h->name)) {
617+ *++h = blank;
618+ h->type = 'L';
619+ putoctal(h->size, n, sizeof(h->size));
620+ putoctal(h->chksum, chksum(h), sizeof(h->chksum));
621+ ewrite(tarfd, (char *)h, BLKSIZ);
622+
623+ for (p = (char *)path; n > 0; n -= BLKSIZ, p += BLKSIZ) {
624+ if ((size_t)n < BLKSIZ) {
625+ p = memcpy(h--, p, n);
626+ memset(p + n, 0, BLKSIZ - (size_t)n);
627+ }
628+ ewrite(tarfd, p, BLKSIZ);
629+ }
630+ }
631+
632+ putoctal(h->mode, (unsigned)st.st_mode & 0777, sizeof(h->mode));
633+ putoctal(h->uid, (unsigned)st.st_uid, sizeof(h->uid));
634+ putoctal(h->gid, (unsigned)st.st_gid, sizeof(h->gid));
635+ putoctal(h->mtime, (unsigned)st.st_mtime, sizeof(h->mtime));
636+ estrlcpy(h->uname, pw ? pw->pw_name : "", sizeof(h->uname));
637+ estrlcpy(h->gname, gr ? gr->gr_name : "", sizeof(h->gname));
638+
639+ if (S_ISREG(st.st_mode)) {
640+ h->type = REG;
641+ putoctal(h->size, st.st_size, sizeof(h->size));
642+ fd = open(path, O_RDONLY);
643+ if (fd < 0)
644+ eprintf("open %s:", path);
645+ } else if (S_ISDIR(st.st_mode)) {
646+ h->type = DIRECTORY;
647+ } else if (S_ISLNK(st.st_mode)) {
648+ h->type = SYMLINK;
649+ if ((r = readlink(path, h->linkname, sizeof(h->linkname) - 1)) < 0)
650+ eprintf("readlink %s:", path);
651+ h->linkname[r] = '\0';
652+ } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
653+ h->type = S_ISCHR(st.st_mode) ? CHARDEV : BLOCKDEV;
654+ putoctal(h->major, (unsigned)major(st.st_dev), sizeof(h->major));
655+ putoctal(h->minor, (unsigned)minor(st.st_dev), sizeof(h->minor));
656+ } else if (S_ISFIFO(st.st_mode)) {
657+ h->type = FIFO;
658+ }
659+
660+ putoctal(h->chksum, chksum(h), sizeof(h->chksum));
661+ ewrite(tarfd, b, BLKSIZ);
662+
663+ if (fd != -1) {
664+ while ((l = eread(fd, b, BLKSIZ)) > 0) {
665+ if ((size_t)l < BLKSIZ)
666+ memset(b + l, 0, BLKSIZ - (size_t)l);
667+ ewrite(tarfd, b, BLKSIZ);
668+ }
669+ close(fd);
670+ }
671+
672+ return 0;
673 }
674 #endif
675
676 static void
677 skipblk(ssize_t l)
678 {
679- char b[BLKSIZ];
680+ char b[BLKSIZ];
681
682- for (; l > 0; l -= BLKSIZ)
683- if (!eread(tarfd, b, BLKSIZ))
684- break;
685+ for (; l > 0; l -= BLKSIZ)
686+ if (!eread(tarfd, b, BLKSIZ))
687+ break;
688 }
689
690 static int
691 unarchive(char *fname, ssize_t l, char b[BLKSIZ])
692 {
693- struct header *h = (struct header *)b;
694- struct timespec times[2];
695- struct stat st;
696- char lname[101], *tmp, *p;
697- long mode, major, minor, type, mtime, uid, gid;
698- int fd = -1, lnk = h->type == SYMLINK;
699-
700- if (kflag_keep && !Oflag_stdout) {
701- if (lstat(fname, &st) == 0) {
702- skipblk(l);
703- return 0;
704- }
705- }
706-
707- if (!mflag && ((mtime = strtol(h->mtime, &p, 8)) < 0 || *p != '\0'))
708- eprintf("strtol %s: invalid mtime\n", h->mtime);
709-
710- if (Oflag_stdout) {
711- if (h->type == REG || h->type == AREG || h->type == RESERVED) {
712- fd = 1;
713- } else {
714- return 0;
715- }
716- } else {
717- if (strcmp(fname, ".") && strcmp(fname, "./") && remove(fname) < 0)
718- if (errno != ENOENT) weprintf("remove %s:", fname);
719-
720- tmp = estrdup(fname);
721- mkdirp(dirname(tmp), 0777, 0777);
722- free(tmp);
723-
724- switch (h->type) {
725- case REG:
726- case AREG:
727- case RESERVED:
728- if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0')
729- eprintf("strtol %s: invalid mode\n", h->mode);
730+ struct header *h = (struct header *)b;
731+ struct timespec times[2];
732+ struct stat st;
733+ char lname[101], *tmp, *p;
734+ long mode, major, minor, type, mtime, uid, gid;
735+ int fd = -1, lnk = h->type == SYMLINK;
736+
737+ if (kflag_keep && !Oflag_stdout) {
738+ if (lstat(fname, &st) == 0) {
739+ skipblk(l);
740+ return 0;
741+ }
742+ }
743+
744+ if (!mflag && ((mtime = strtol(h->mtime, &p, 8)) < 0 || *p != '\0'))
745+ eprintf("strtol %s: invalid mtime\n", h->mtime);
746+
747+ if (Oflag_stdout) {
748+ if (h->type == REG || h->type == AREG || h->type == RESERVED) {
749+ fd = 1;
750+ } else {
751+ return 0;
752+ }
753+ } else {
754+ if (strcmp(fname, ".") && strcmp(fname, "./") && remove(fname) < 0)
755+ if (errno != ENOENT) weprintf("remove %s:", fname);
756+
757+ tmp = estrdup(fname);
758+ mkdirp(dirname(tmp), 0777, 0777);
759+ free(tmp);
760+
761+ switch (h->type) {
762+ case REG:
763+ case AREG:
764+ case RESERVED:
765+ if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0')
766+ eprintf("strtol %s: invalid mode\n", h->mode);
767 #if FEATURE_TAR_NOFOLLOW
768- fd = open(fname, O_WRONLY | O_TRUNC | O_CREAT | O_NOFOLLOW, 0600);
769+ fd = open(fname, O_WRONLY | O_TRUNC | O_CREAT | O_NOFOLLOW, 0600);
770 #else
771- fd = open(fname, O_WRONLY | O_TRUNC | O_CREAT, 0600);
772+ fd = open(fname, O_WRONLY | O_TRUNC | O_CREAT, 0600);
773 #endif
774- if (fd < 0)
775- eprintf("open %s:", fname);
776- break;
777- case HARDLINK:
778- case SYMLINK:
779- snprintf(lname, sizeof(lname), "%.*s", (int)sizeof(h->linkname),
780- h->linkname);
781- if ((lnk ? symlink:link)(lname, fname) < 0)
782- eprintf("%s %s -> %s:", lnk ? "symlink":"link", fname, lname);
783- lnk++;
784- break;
785- case DIRECTORY:
786- if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0')
787- eprintf("strtol %s: invalid mode\n", h->mode);
788- if (mkdir(fname, (mode_t)mode) < 0 && errno != EEXIST)
789- eprintf("mkdir %s:", fname);
790- pushdirtime(fname, mtime);
791- break;
792- case CHARDEV:
793- case BLOCKDEV:
794- if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0')
795- eprintf("strtol %s: invalid mode\n", h->mode);
796- if ((major = strtol(h->major, &p, 8)) < 0 || *p != '\0')
797- eprintf("strtol %s: invalid major device\n", h->major);
798- if ((minor = strtol(h->minor, &p, 8)) < 0 || *p != '\0')
799- eprintf("strtol %s: invalid minor device\n", h->minor);
800- type = (h->type == CHARDEV) ? S_IFCHR : S_IFBLK;
801- if (mknod(fname, type | mode, makedev(major, minor)) < 0)
802- eprintf("mknod %s:", fname);
803- break;
804- case FIFO:
805- if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0')
806- eprintf("strtol %s: invalid mode\n", h->mode);
807- if (mknod(fname, S_IFIFO | mode, 0) < 0)
808- eprintf("mknod %s:", fname);
809- break;
810- default:
811- eprintf("unsupported tar-filetype %c\n", h->type);
812- }
813- }
814-
815- if (!Oflag_stdout) {
816- if ((uid = strtol(h->uid, &p, 8)) < 0 || *p != '\0')
817- eprintf("strtol %s: invalid uid\n", h->uid);
818- if ((gid = strtol(h->gid, &p, 8)) < 0 || *p != '\0')
819- eprintf("strtol %s: invalid gid\n", h->gid);
820- }
821-
822- if (fd != -1) {
823- for (; l > 0; l -= BLKSIZ)
824- if (eread(tarfd, b, BLKSIZ) > 0)
825- ewrite(fd, b, MIN(l, (ssize_t)BLKSIZ));
826- if (fd != 1)
827- close(fd);
828- }
829-
830- if (Oflag_stdout)
831- return 0;
832-
833- if (lnk == 1)
834- return 0;
835-
836- times[0].tv_sec = times[1].tv_sec = mtime;
837- times[0].tv_nsec = times[1].tv_nsec = 0;
838- if (!mflag && utimensat(AT_FDCWD, fname, times, AT_SYMLINK_NOFOLLOW) < 0)
839- weprintf("utimensat %s:", fname);
840- if (lnk) {
841- if (!getuid() && lchown(fname, uid, gid))
842- weprintf("lchown %s:", fname);
843- } else {
844- if (!getuid() && chown(fname, uid, gid))
845- weprintf("chown %s:", fname);
846- if (chmod(fname, mode) < 0)
847- eprintf("fchmod %s:", fname);
848- }
849-
850- return 0;
851+ if (fd < 0)
852+ eprintf("open %s:", fname);
853+ break;
854+ case HARDLINK:
855+ case SYMLINK:
856+ snprintf(lname, sizeof(lname), "%.*s", (int)sizeof(h->linkname),
857+ h->linkname);
858+ if ((lnk ? symlink:link)(lname, fname) < 0)
859+ eprintf("%s %s -> %s:", lnk ? "symlink":"link", fname, lname);
860+ lnk++;
861+ break;
862+ case DIRECTORY:
863+ if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0')
864+ eprintf("strtol %s: invalid mode\n", h->mode);
865+ if (mkdir(fname, (mode_t)mode) < 0 && errno != EEXIST)
866+ eprintf("mkdir %s:", fname);
867+ pushdirtime(fname, mtime);
868+ break;
869+ case CHARDEV:
870+ case BLOCKDEV:
871+ if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0')
872+ eprintf("strtol %s: invalid mode\n", h->mode);
873+ if ((major = strtol(h->major, &p, 8)) < 0 || *p != '\0')
874+ eprintf("strtol %s: invalid major device\n", h->major);
875+ if ((minor = strtol(h->minor, &p, 8)) < 0 || *p != '\0')
876+ eprintf("strtol %s: invalid minor device\n", h->minor);
877+ type = (h->type == CHARDEV) ? S_IFCHR : S_IFBLK;
878+ if (mknod(fname, type | mode, makedev(major, minor)) < 0)
879+ eprintf("mknod %s:", fname);
880+ break;
881+ case FIFO:
882+ if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0')
883+ eprintf("strtol %s: invalid mode\n", h->mode);
884+ if (mknod(fname, S_IFIFO | mode, 0) < 0)
885+ eprintf("mknod %s:", fname);
886+ break;
887+ default:
888+ eprintf("unsupported tar-filetype %c\n", h->type);
889+ }
890+ }
891+
892+ if (!Oflag_stdout) {
893+ if ((uid = strtol(h->uid, &p, 8)) < 0 || *p != '\0')
894+ eprintf("strtol %s: invalid uid\n", h->uid);
895+ if ((gid = strtol(h->gid, &p, 8)) < 0 || *p != '\0')
896+ eprintf("strtol %s: invalid gid\n", h->gid);
897+ }
898+
899+ if (fd != -1) {
900+ for (; l > 0; l -= BLKSIZ)
901+ if (eread(tarfd, b, BLKSIZ) > 0)
902+ ewrite(fd, b, MIN(l, (ssize_t)BLKSIZ));
903+ if (fd != 1)
904+ close(fd);
905+ }
906+
907+ if (Oflag_stdout)
908+ return 0;
909+
910+ if (lnk == 1)
911+ return 0;
912+
913+ times[0].tv_sec = times[1].tv_sec = mtime;
914+ times[0].tv_nsec = times[1].tv_nsec = 0;
915+ if (!mflag && utimensat(AT_FDCWD, fname, times, AT_SYMLINK_NOFOLLOW) < 0)
916+ weprintf("utimensat %s:", fname);
917+ if (lnk) {
918+ if (!getuid() && lchown(fname, uid, gid))
919+ weprintf("lchown %s:", fname);
920+ } else {
921+ if (!getuid() && chown(fname, uid, gid))
922+ weprintf("chown %s:", fname);
923+ if (chmod(fname, mode) < 0)
924+ eprintf("fchmod %s:", fname);
925+ }
926+
927+ return 0;
928 }
929
930
931 static int
932 print(char *fname, ssize_t l, char b[BLKSIZ])
933 {
934- (void)b;
935- safe_puts(fname);
936- skipblk(l);
937- return 0;
938+ (void)b;
939+ safe_puts(fname);
940+ skipblk(l);
941+ return 0;
942 }
943
944 #if FEATURE_TAR_CREATE
945 static void
946 c(int dirfd, const char *name, struct stat *st, void *data, struct recursor *r)
947 {
948- (void)data;
949+ (void)data;
950 #if FEATURE_TAR_EXCLUDE
951- if (is_excluded(r->path))
952- return;
953+ if (is_excluded(r->path))
954+ return;
955 #endif
956- archive(r->path);
957- if (vflag)
958- safe_puts(r->path);
959+ archive(r->path);
960+ if (vflag)
961+ safe_puts(r->path);
962
963- if (S_ISDIR(st->st_mode))
964- recurse(dirfd, name, NULL, r);
965+ if (S_ISDIR(st->st_mode))
966+ recurse(dirfd, name, NULL, r);
967 }
968 #endif
969
970 static void
971 sanitize(struct header *h)
972 {
973- size_t i, j, l;
974- struct {
975- char *f;
976- size_t l;
977- } fields[] = {
978- { h->mode, sizeof(h->mode) },
979- { h->uid, sizeof(h->uid) },
980- { h->gid, sizeof(h->gid) },
981- { h->size, sizeof(h->size) },
982- { h->mtime, sizeof(h->mtime) },
983- { h->chksum, sizeof(h->chksum) },
984- { h->major, sizeof(h->major) },
985- { h->minor, sizeof(h->minor) }
986- };
987-
988- /* Numeric fields can be terminated with spaces instead of
989- * NULs as per the ustar specification. Patch all of them to
990- * use NULs so we can perform string operations on them. */
991- for (i = 0; i < LEN(fields); i++){
992- j = 0, l = fields[i].l - 1;
993- for (; j < l && fields[i].f[j] == ' '; j++);
994- for (; j <= l; j++)
995- if (fields[i].f[j] == ' ')
996- fields[i].f[j] = '\0';
997- if (fields[i].f[l])
998- eprintf("numeric field #%d (%.*s) is not null or space terminated\n",
999- i, l+1, fields[i].f);
1000- }
1001+ size_t i, j, l;
1002+ struct {
1003+ char *f;
1004+ size_t l;
1005+ } fields[] = {
1006+ { h->mode, sizeof(h->mode) },
1007+ { h->uid, sizeof(h->uid) },
1008+ { h->gid, sizeof(h->gid) },
1009+ { h->size, sizeof(h->size) },
1010+ { h->mtime, sizeof(h->mtime) },
1011+ { h->chksum, sizeof(h->chksum) },
1012+ { h->major, sizeof(h->major) },
1013+ { h->minor, sizeof(h->minor) }
1014+ };
1015+
1016+ /* Numeric fields can be terminated with spaces instead of
1017+ * NULs as per the ustar specification. Patch all of them to
1018+ * use NULs so we can perform string operations on them. */
1019+ for (i = 0; i < LEN(fields); i++){
1020+ j = 0, l = fields[i].l - 1;
1021+ for (; j < l && fields[i].f[j] == ' '; j++);
1022+ for (; j <= l; j++)
1023+ if (fields[i].f[j] == ' ')
1024+ fields[i].f[j] = '\0';
1025+ if (fields[i].f[l])
1026+ eprintf("numeric field #%d (%.*s) is not null or space terminated\n",
1027+ i, l+1, fields[i].f);
1028+ }
1029 }
1030
1031 static void
1032 chktar(struct header *h)
1033 {
1034- const char *reason;
1035- char tmp[sizeof h->chksum], *err;
1036- long sum, i;
1037-
1038- if (h->prefix[0] == '\0' && h->name[0] == '\0') {
1039- reason = "empty filename";
1040- goto bad;
1041- }
1042- if (h->magic[0] && strncmp("ustar", h->magic, 5)) {
1043- reason = "not ustar format";
1044- goto bad;
1045- }
1046- memcpy(tmp, h->chksum, sizeof(tmp));
1047- for (i = sizeof(tmp)-1; i > 0 && tmp[i] == ' '; i--) {
1048- tmp[i] = '\0';
1049- }
1050- sum = strtol(tmp, &err, 8);
1051- if (sum < 0 || sum >= (long)(BLKSIZ*256) || *err != '\0') {
1052- reason = "invalid checksum";
1053- goto bad;
1054- }
1055- if (sum != chksum(h)) {
1056- reason = "incorrect checksum";
1057- goto bad;
1058- }
1059- memcpy(h->chksum, tmp, sizeof(tmp));
1060- return;
1061+ const char *reason;
1062+ char tmp[sizeof h->chksum], *err;
1063+ long sum, i;
1064+
1065+ if (h->prefix[0] == '\0' && h->name[0] == '\0') {
1066+ reason = "empty filename";
1067+ goto bad;
1068+ }
1069+ if (h->magic[0] && strncmp("ustar", h->magic, 5)) {
1070+ reason = "not ustar format";
1071+ goto bad;
1072+ }
1073+ memcpy(tmp, h->chksum, sizeof(tmp));
1074+ for (i = sizeof(tmp)-1; i > 0 && tmp[i] == ' '; i--) {
1075+ tmp[i] = '\0';
1076+ }
1077+ sum = strtol(tmp, &err, 8);
1078+ if (sum < 0 || sum >= (long)(BLKSIZ*256) || *err != '\0') {
1079+ reason = "invalid checksum";
1080+ goto bad;
1081+ }
1082+ if (sum != chksum(h)) {
1083+ reason = "incorrect checksum";
1084+ goto bad;
1085+ }
1086+ memcpy(h->chksum, tmp, sizeof(tmp));
1087+ return;
1088 bad:
1089- eprintf("malformed tar archive: %s\n", reason);
1090+ eprintf("malformed tar archive: %s\n", reason);
1091 }
1092
1093 static void
1094 xt(int argc, char *argv[], int mode)
1095 {
1096- long size;
1097- char b[BLKSIZ], fname[PATH_MAX + 1], *p, *q = NULL, *stripped;
1098- int i, m, n, match;
1099- int (*fn)(char *, ssize_t, char[BLKSIZ]) = (mode == 'x') ? unarchive : print;
1100- struct timespec times[2];
1101- struct header *h = (struct header *)b;
1102- struct dirtime *dirtime;
1103+ long size;
1104+ char b[BLKSIZ], fname[PATH_MAX + 1], *p, *q = NULL, *stripped;
1105+ int i, m, n, match;
1106+ int (*fn)(char *, ssize_t, char[BLKSIZ]) = (mode == 'x') ? unarchive : print;
1107+ struct timespec times[2];
1108+ struct header *h = (struct header *)b;
1109+ struct dirtime *dirtime;
1110 #if FEATURE_TAR_FILES_FROM
1111- size_t idx;
1112+ size_t idx;
1113 #endif
1114
1115- while (eread(tarfd, b, BLKSIZ) > 0 && (h->name[0] || h->prefix[0])) {
1116- chktar(h);
1117- sanitize(h);
1118-
1119- if ((size = strtol(h->size, &p, 8)) < 0 || *p != '\0')
1120- eprintf("strtol %s: invalid size\n", h->size);
1121-
1122- /* Long file path is read directly into fname*/
1123- if (h->type == 'L' || h->type == 'x' || h->type == 'g') {
1124-
1125- /* Read header only up to size of fname buffer */
1126- for (q = fname; q < fname+size; q += BLKSIZ) {
1127- if (q + BLKSIZ >= fname + sizeof fname)
1128- eprintf("name exceeds buffer: %.*s\n", q-fname, fname);
1129- eread(tarfd, q, BLKSIZ);
1130- }
1131-
1132- /* Convert pax x header with 'path=' field into L header */
1133- if (h->type == 'x') for (q = fname; q < fname+size-16; q += n) {
1134- if ((n = strtol(q, &p, 10)) < 0 || *p != ' ')
1135- eprintf("strtol %.*s: invalid number\n", p+1-q, q);
1136- if (n && strncmp(p+1, "path=", 5) == 0) {
1137- memmove(fname, p+6, size = q+n - p-6 - 1);
1138- h->type = 'L';
1139- break;
1140- }
1141- }
1142- fname[size] = '\0';
1143-
1144- /* Non L-like header (eg. pax 'g') is skipped by setting q=null */
1145- if (h->type != 'L')
1146- q = NULL;
1147- continue;
1148- }
1149-
1150- /* Ustar path is copied into fname if no L header (ie: q is NULL) */
1151- if (!q) {
1152- m = sizeof h->prefix, n = sizeof h->name;
1153- p = "/" + !h->prefix[0];
1154- snprintf(fname, sizeof fname, "%.*s%s%.*s", m, h->prefix, p, n, h->name);
1155- }
1156- q = NULL;
1157-
1158- /* If argc > 0 or files_from_cnt > 0 then only extract the matching files/dirs */
1159- if (argc || files_from_cnt) {
1160- match = 0;
1161- for (i = 0; i < argc; i++) {
1162- if (strncmp(argv[i], fname, n = strlen(argv[i])) == 0) {
1163- if (strchr("/", fname[n]) || argv[i][n-1] == '/') {
1164- match = 1;
1165- break;
1166- }
1167- }
1168- }
1169+ while (eread(tarfd, b, BLKSIZ) > 0 && (h->name[0] || h->prefix[0])) {
1170+ chktar(h);
1171+ sanitize(h);
1172+
1173+ if ((size = strtol(h->size, &p, 8)) < 0 || *p != '\0')
1174+ eprintf("strtol %s: invalid size\n", h->size);
1175+
1176+ /* Long file path is read directly into fname*/
1177+ if (h->type == 'L' || h->type == 'x' || h->type == 'g') {
1178+
1179+ /* Read header only up to size of fname buffer */
1180+ for (q = fname; q < fname+size; q += BLKSIZ) {
1181+ if (q + BLKSIZ >= fname + sizeof fname)
1182+ eprintf("name exceeds buffer: %.*s\n", q-fname, fname);
1183+ eread(tarfd, q, BLKSIZ);
1184+ }
1185+
1186+ /* Convert pax x header with 'path=' field into L header */
1187+ if (h->type == 'x') for (q = fname; q < fname+size-16; q += n) {
1188+ if ((n = strtol(q, &p, 10)) < 0 || *p != ' ')
1189+ eprintf("strtol %.*s: invalid number\n", p+1-q, q);
1190+ if (n && strncmp(p+1, "path=", 5) == 0) {
1191+ memmove(fname, p+6, size = q+n - p-6 - 1);
1192+ h->type = 'L';
1193+ break;
1194+ }
1195+ }
1196+ fname[size] = '\0';
1197+
1198+ /* Non L-like header (eg. pax 'g') is skipped by setting q=null */
1199+ if (h->type != 'L')
1200+ q = NULL;
1201+ continue;
1202+ }
1203+
1204+ /* Ustar path is copied into fname if no L header (ie: q is NULL) */
1205+ if (!q) {
1206+ m = sizeof h->prefix, n = sizeof h->name;
1207+ p = "/" + !h->prefix[0];
1208+ snprintf(fname, sizeof fname, "%.*s%s%.*s", m, h->prefix, p, n, h->name);
1209+ }
1210+ q = NULL;
1211+
1212+ /* If argc > 0 or files_from_cnt > 0 then only extract the matching files/dirs */
1213+ if (argc || files_from_cnt) {
1214+ match = 0;
1215+ for (i = 0; i < argc; i++) {
1216+ if (strncmp(argv[i], fname, n = strlen(argv[i])) == 0) {
1217+ if (strchr("/", fname[n]) || argv[i][n-1] == '/') {
1218+ match = 1;
1219+ break;
1220+ }
1221+ }
1222+ }
1223 #if FEATURE_TAR_FILES_FROM
1224- if (!match) {
1225- for (idx = 0; idx < files_from_cnt; idx++) {
1226- if (strncmp(files_from[idx], fname, n = strlen(files_from[idx])) == 0) {
1227- if (strchr("/", fname[n]) || files_from[idx][n-1] == '/') {
1228- match = 1;
1229- break;
1230- }
1231- }
1232- }
1233- }
1234+ if (!match) {
1235+ for (idx = 0; idx < files_from_cnt; idx++) {
1236+ if (strncmp(files_from[idx], fname, n = strlen(files_from[idx])) == 0) {
1237+ if (strchr("/", fname[n]) || files_from[idx][n-1] == '/') {
1238+ match = 1;
1239+ break;
1240+ }
1241+ }
1242+ }
1243+ }
1244 #endif
1245- if (!match) {
1246- skipblk(size);
1247- continue;
1248- }
1249- }
1250+ if (!match) {
1251+ skipblk(size);
1252+ continue;
1253+ }
1254+ }
1255
1256- stripped = fname;
1257+ stripped = fname;
1258 #if FEATURE_TAR_STRIP_COMPONENTS
1259- if (mode == 'x' && strip_components_count > 0) {
1260- stripped = strip_components(fname, strip_components_count);
1261- if (!stripped || *stripped == '\0') {
1262- skipblk(size);
1263- continue;
1264- }
1265- }
1266+ if (mode == 'x' && strip_components_count > 0) {
1267+ stripped = strip_components(fname, strip_components_count);
1268+ if (!stripped || *stripped == '\0') {
1269+ skipblk(size);
1270+ continue;
1271+ }
1272+ }
1273 #endif
1274
1275- fn(stripped, size, b);
1276- if (vflag && mode != 't')
1277- safe_puts(fname);
1278- }
1279-
1280- if (mode == 'x' && !mflag) {
1281- while ((dirtime = popdirtime())) {
1282- times[0].tv_sec = times[1].tv_sec = dirtime->mtime;
1283- times[0].tv_nsec = times[1].tv_nsec = 0;
1284- if (utimensat(AT_FDCWD, dirtime->name, times, 0) < 0)
1285- eprintf("utimensat %s:", fname);
1286- free(dirtime->name);
1287- }
1288- free(dirtimes);
1289- dirtimes = NULL;
1290- }
1291+ fn(stripped, size, b);
1292+ if (vflag && mode != 't')
1293+ safe_puts(fname);
1294+ }
1295+
1296+ if (mode == 'x' && !mflag) {
1297+ while ((dirtime = popdirtime())) {
1298+ times[0].tv_sec = times[1].tv_sec = dirtime->mtime;
1299+ times[0].tv_nsec = times[1].tv_nsec = 0;
1300+ if (utimensat(AT_FDCWD, dirtime->name, times, 0) < 0)
1301+ eprintf("utimensat %s:", fname);
1302+ free(dirtime->name);
1303+ }
1304+ free(dirtimes);
1305+ dirtimes = NULL;
1306+ }
1307 }
1308
1309 char **args;
1310@@ -790,13 +803,13 @@ static void
1311 usage(void)
1312 {
1313 #if FEATURE_TAR_CREATE
1314- eprintf("usage: %s [x | t | -x | -t] [-C dir] [-J | -Z | -a | -j | -z] [-m] [-p] "
1315- "[-f file] [file ...]\n"
1316- " %s [c | -c] [-C dir] [-J | -Z | -a | -j | -z] [-h] path ... "
1317- "[-f file]\n", argv0, argv0);
1318+ eprintf("usage: %s [x | t | -x | -t] [-C dir] [-J | -Z | -a | -j | -z] [-m] [-p] "
1319+ "[-f file] [file ...]\n"
1320+ " %s [c | -c] [-C dir] [-J | -Z | -a | -j | -z] [-h] path ... "
1321+ "[-f file]\n", argv0, argv0);
1322 #else
1323- eprintf("usage: %s [x | t | -x | -t] [-C dir] [-J | -Z | -a | -j | -z] [-m] [-p] "
1324- "[-f file] [file ...]\n", argv0);
1325+ eprintf("usage: %s [x | t | -x | -t] [-C dir] [-J | -Z | -a | -j | -z] [-m] [-p] "
1326+ "[-f file] [file ...]\n", argv0);
1327 #endif
1328 }
1329
1330@@ -808,247 +821,247 @@ int
1331 main(int argc, char *argv[])
1332 {
1333 #if FEATURE_TAR_CREATE
1334- struct recursor r = { .fn = c, .follow = 'P', .flags = DIRFIRST };
1335+ struct recursor r = { .fn = c, .follow = 'P', .flags = DIRFIRST };
1336 #endif
1337- struct stat st;
1338- char *file = NULL, *dir = ".", mode = '\0';
1339- int fd;
1340- size_t i;
1341+ struct stat st;
1342+ char *file = NULL, *dir = ".", mode = '\0';
1343+ int fd;
1344+ size_t i;
1345
1346- argv0 = argv[0];
1347+ argv0 = argv[0];
1348 #if FEATURE_TAR_CREATE
1349- if (argc > 1 && strchr("cxt", mode = *argv[1]))
1350+ if (argc > 1 && strchr("cxt", mode = *argv[1]))
1351 #else
1352- if (argc > 1 && strchr("xt", mode = *argv[1]))
1353+ if (argc > 1 && strchr("xt", mode = *argv[1]))
1354 #endif
1355- *(argv[1]+1) ? *argv[1] = '-' : (*++argv = argv0, --argc);
1356+ *(argv[1]+1) ? *argv[1] = '-' : (*++argv = argv0, --argc);
1357
1358- ARGBEGIN {
1359- // ?man -x: extract files from an archive
1360- case 'x':
1361+ ARGBEGIN {
1362+ // ?man -x: extract files from an archive
1363+ case 'x':
1364 #if FEATURE_TAR_CREATE
1365- // ?man -c: create a new archive
1366- case 'c':
1367+ // ?man -c: create a new archive
1368+ case 'c':
1369 #endif
1370- // ?man -t: list the contents of an archive
1371- case 't':
1372- mode = ARGC();
1373- break;
1374- // ?man -C:dir: specify option flag
1375- case 'C':
1376- dir = EARGF(usage());
1377- break;
1378- // ?man -f:file: specify archive file
1379- case 'f':
1380- file = EARGF(usage());
1381- break;
1382- // ?man -m: specify mode or limit
1383- case 'm':
1384- mflag = 1;
1385- break;
1386- // ?man -J: specify option flag
1387- case 'J':
1388- // ?man -Z: specify option flag
1389- case 'Z':
1390- // ?man -a: print or show all entries
1391- case 'a':
1392- // ?man -j: specify option flag
1393- case 'j':
1394- // ?man -z: specify option flag
1395- case 'z':
1396- filtermode = ARGC();
1397- filtertool = filtertools[filtermode];
1398- break;
1399- // ?man -h: suppress headers or print help
1400- case 'h':
1401+ // ?man -t: list the contents of an archive
1402+ case 't':
1403+ mode = ARGC();
1404+ break;
1405+ // ?man -C:dir: specify option flag
1406+ case 'C':
1407+ dir = EARGF(usage());
1408+ break;
1409+ // ?man -f:file: specify archive file
1410+ case 'f':
1411+ file = EARGF(usage());
1412+ break;
1413+ // ?man -m: specify mode or limit
1414+ case 'm':
1415+ mflag = 1;
1416+ break;
1417+ // ?man -J: specify option flag
1418+ case 'J':
1419+ // ?man -Z: specify option flag
1420+ case 'Z':
1421+ // ?man -a: print or show all entries
1422+ case 'a':
1423+ // ?man -j: specify option flag
1424+ case 'j':
1425+ // ?man -z: specify option flag
1426+ case 'z':
1427+ filtermode = ARGC();
1428+ filtertool = filtertools[filtermode];
1429+ break;
1430+ // ?man -h: suppress headers or print help
1431+ case 'h':
1432 #if FEATURE_TAR_CREATE
1433- r.follow = 'L';
1434+ r.follow = 'L';
1435 #endif
1436- break;
1437- // ?man -v: verbosely list files processed
1438- case 'v':
1439- vflag = 1;
1440- break;
1441- // ?man -p: preserve file attributes
1442- case 'p':
1443- break; /* do nothing as already default behaviour */
1444+ break;
1445+ // ?man -v: verbosely list files processed
1446+ case 'v':
1447+ vflag = 1;
1448+ break;
1449+ // ?man -p: preserve file attributes
1450+ case 'p':
1451+ break; /* do nothing as already default behaviour */
1452 #if FEATURE_TAR_TO_STDOUT
1453- // ?man -O: extract files to stdout
1454- case 'O':
1455- Oflag_stdout = 1;
1456- break;
1457+ // ?man -O: extract files to stdout
1458+ case 'O':
1459+ Oflag_stdout = 1;
1460+ break;
1461 #endif
1462 #if FEATURE_TAR_KEEP_OLD
1463- // ?man -k: keep existing files, do not overwrite
1464- case 'k':
1465- kflag_keep = 1;
1466- break;
1467+ // ?man -k: keep existing files, do not overwrite
1468+ case 'k':
1469+ kflag_keep = 1;
1470+ break;
1471 #endif
1472 #if FEATURE_TAR_FILES_FROM
1473- // ?man -T:file: -T file: read filenames from file
1474- case 'T':
1475- load_files_from_file(EARGF(usage()));
1476- break;
1477+ // ?man -T:file: -T file: read filenames from file
1478+ case 'T':
1479+ load_files_from_file(EARGF(usage()));
1480+ break;
1481 #endif
1482 #if FEATURE_TAR_EXCLUDE_FROM
1483- // ?man -X:file: -X file: exclude patterns in file
1484- case 'X':
1485- load_excludes_from_file(EARGF(usage()));
1486- break;
1487+ // ?man -X:file: -X file: exclude patterns in file
1488+ case 'X':
1489+ load_excludes_from_file(EARGF(usage()));
1490+ break;
1491 #endif
1492 #if FEATURE_TAR_STRIP_COMPONENTS
1493- // ?man -s:num: -strip-components num: strip num components
1494- case 's':
1495- if (strcmp(argv[0], "strip-components") == 0) {
1496- argv[0] = "s";
1497- strip_components_count = estrtonum(EARGF(usage()), 0, INT_MAX);
1498- brk_ = 1;
1499- } else if (strncmp(argv[0], "strip-components=", 17) == 0) {
1500- strip_components_count = estrtonum(argv[0] + 17, 0, INT_MAX);
1501- brk_ = 1;
1502- } else {
1503- usage();
1504- }
1505- break;
1506+ // ?man -s:num: -strip-components num: strip num components
1507+ case 's':
1508+ if (strcmp(argv[0], "strip-components") == 0) {
1509+ argv[0] = "s";
1510+ strip_components_count = estrtonum(EARGF(usage()), 0, INT_MAX);
1511+ brk_ = 1;
1512+ } else if (strncmp(argv[0], "strip-components=", 17) == 0) {
1513+ strip_components_count = estrtonum(argv[0] + 17, 0, INT_MAX);
1514+ brk_ = 1;
1515+ } else {
1516+ usage();
1517+ }
1518+ break;
1519 #endif
1520- // ?man --:num: specify - option
1521- case '-':
1522+ // ?man --:num: specify - option
1523+ case '-':
1524 #if FEATURE_TAR_EXCLUDE
1525- if (strncmp(argv[0], "-exclude=", 9) == 0) {
1526- add_exclude(argv[0] + 9);
1527- brk_ = 1;
1528- break;
1529- } else if (strcmp(argv[0], "-exclude") == 0) {
1530- argv[0] = "-";
1531- add_exclude(EARGF(usage()));
1532- brk_ = 1;
1533- break;
1534- }
1535+ if (strncmp(argv[0], "-exclude=", 9) == 0) {
1536+ add_exclude(argv[0] + 9);
1537+ brk_ = 1;
1538+ break;
1539+ } else if (strcmp(argv[0], "-exclude") == 0) {
1540+ argv[0] = "-";
1541+ add_exclude(EARGF(usage()));
1542+ brk_ = 1;
1543+ break;
1544+ }
1545 #endif
1546 #if FEATURE_TAR_EXCLUDE_FROM
1547- if (strncmp(argv[0], "-exclude-from=", 14) == 0) {
1548- load_excludes_from_file(argv[0] + 14);
1549- brk_ = 1;
1550- break;
1551- } else if (strcmp(argv[0], "-exclude-from") == 0) {
1552- argv[0] = "-";
1553- load_excludes_from_file(EARGF(usage()));
1554- brk_ = 1;
1555- break;
1556- }
1557+ if (strncmp(argv[0], "-exclude-from=", 14) == 0) {
1558+ load_excludes_from_file(argv[0] + 14);
1559+ brk_ = 1;
1560+ break;
1561+ } else if (strcmp(argv[0], "-exclude-from") == 0) {
1562+ argv[0] = "-";
1563+ load_excludes_from_file(EARGF(usage()));
1564+ brk_ = 1;
1565+ break;
1566+ }
1567 #endif
1568 #if FEATURE_TAR_TO_STDOUT
1569- if (strcmp(argv[0], "-to-stdout") == 0) {
1570- Oflag_stdout = 1;
1571- brk_ = 1;
1572- break;
1573- }
1574+ if (strcmp(argv[0], "-to-stdout") == 0) {
1575+ Oflag_stdout = 1;
1576+ brk_ = 1;
1577+ break;
1578+ }
1579 #endif
1580 #if FEATURE_TAR_KEEP_OLD
1581- if (strcmp(argv[0], "-keep-old-files") == 0) {
1582- kflag_keep = 1;
1583- brk_ = 1;
1584- break;
1585- }
1586+ if (strcmp(argv[0], "-keep-old-files") == 0) {
1587+ kflag_keep = 1;
1588+ brk_ = 1;
1589+ break;
1590+ }
1591 #endif
1592 #if FEATURE_TAR_STRIP_COMPONENTS
1593- if (strncmp(argv[0], "-strip-components=", 18) == 0) {
1594- strip_components_count = estrtonum(argv[0] + 18, 0, INT_MAX);
1595- brk_ = 1;
1596- break;
1597- } else if (strcmp(argv[0], "-strip-components") == 0) {
1598- argv[0] = "-";
1599- strip_components_count = estrtonum(EARGF(usage()), 0, INT_MAX);
1600- brk_ = 1;
1601- break;
1602- }
1603+ if (strncmp(argv[0], "-strip-components=", 18) == 0) {
1604+ strip_components_count = estrtonum(argv[0] + 18, 0, INT_MAX);
1605+ brk_ = 1;
1606+ break;
1607+ } else if (strcmp(argv[0], "-strip-components") == 0) {
1608+ argv[0] = "-";
1609+ strip_components_count = estrtonum(EARGF(usage()), 0, INT_MAX);
1610+ brk_ = 1;
1611+ break;
1612+ }
1613 #endif
1614 #if FEATURE_TAR_FILES_FROM
1615- if (strncmp(argv[0], "-files-from=", 12) == 0) {
1616- load_files_from_file(argv[0] + 12);
1617- brk_ = 1;
1618- break;
1619- } else if (strcmp(argv[0], "-files-from") == 0) {
1620- argv[0] = "-";
1621- load_files_from_file(EARGF(usage()));
1622- brk_ = 1;
1623- break;
1624- }
1625+ if (strncmp(argv[0], "-files-from=", 12) == 0) {
1626+ load_files_from_file(argv[0] + 12);
1627+ brk_ = 1;
1628+ break;
1629+ } else if (strcmp(argv[0], "-files-from") == 0) {
1630+ argv[0] = "-";
1631+ load_files_from_file(EARGF(usage()));
1632+ brk_ = 1;
1633+ break;
1634+ }
1635 #endif
1636- usage();
1637- break;
1638- default:
1639- usage();
1640- } ARGEND
1641+ usage();
1642+ break;
1643+ default:
1644+ usage();
1645+ } ARGEND
1646
1647- switch (mode) {
1648+ switch (mode) {
1649 #if FEATURE_TAR_CREATE
1650- // ?man -c: create a new archive
1651- case 'c':
1652- if (!argc && !files_from_cnt)
1653- usage();
1654- tarfd = 1;
1655- if (file && *file != '-') {
1656- tarfd = open(file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
1657- if (tarfd < 0)
1658- eprintf("open %s:", file);
1659- if (lstat(file, &st) < 0)
1660- eprintf("lstat %s:", file);
1661- tarinode = st.st_ino;
1662- tardev = st.st_dev;
1663- }
1664-
1665- if (filtertool)
1666- tarfd = comp(tarfd, filtertool, "-cf");
1667-
1668- if (chdir(dir) < 0)
1669- eprintf("chdir %s:", dir);
1670- for (; *argv; argc--, argv++)
1671- recurse(AT_FDCWD, *argv, NULL, &r);
1672+ // ?man -c: create a new archive
1673+ case 'c':
1674+ if (!argc && !files_from_cnt)
1675+ usage();
1676+ tarfd = 1;
1677+ if (file && *file != '-') {
1678+ tarfd = open(file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
1679+ if (tarfd < 0)
1680+ eprintf("open %s:", file);
1681+ if (lstat(file, &st) < 0)
1682+ eprintf("lstat %s:", file);
1683+ tarinode = st.st_ino;
1684+ tardev = st.st_dev;
1685+ }
1686+
1687+ if (filtertool)
1688+ tarfd = comp(tarfd, filtertool, "-cf");
1689+
1690+ if (chdir(dir) < 0)
1691+ eprintf("chdir %s:", dir);
1692+ for (; *argv; argc--, argv++)
1693+ recurse(AT_FDCWD, *argv, NULL, &r);
1694 #if FEATURE_TAR_FILES_FROM
1695- for (i = 0; i < files_from_cnt; i++)
1696- recurse(AT_FDCWD, files_from[i], NULL, &r);
1697+ for (i = 0; i < files_from_cnt; i++)
1698+ recurse(AT_FDCWD, files_from[i], NULL, &r);
1699 #endif
1700- break;
1701+ break;
1702 #endif
1703- // ?man -t: list the contents of an archive
1704- case 't':
1705- // ?man -x: extract files from an archive
1706- case 'x':
1707- tarfd = 0;
1708- if (file && *file != '-') {
1709- tarfd = open(file, O_RDONLY);
1710- if (tarfd < 0)
1711- eprintf("open %s:", file);
1712- }
1713-
1714- if (filtertool) {
1715- fd = tarfd;
1716- tarfd = decomp(tarfd, filtertool, "-cdf");
1717- close(fd);
1718- }
1719-
1720- if (chdir(dir) < 0)
1721- eprintf("chdir %s:", dir);
1722- xt(argc, argv, mode);
1723- break;
1724- default:
1725- usage();
1726- }
1727+ // ?man -t: list the contents of an archive
1728+ case 't':
1729+ // ?man -x: extract files from an archive
1730+ case 'x':
1731+ tarfd = 0;
1732+ if (file && *file != '-') {
1733+ tarfd = open(file, O_RDONLY);
1734+ if (tarfd < 0)
1735+ eprintf("open %s:", file);
1736+ }
1737+
1738+ if (filtertool) {
1739+ fd = tarfd;
1740+ tarfd = decomp(tarfd, filtertool, "-cdf");
1741+ close(fd);
1742+ }
1743+
1744+ if (chdir(dir) < 0)
1745+ eprintf("chdir %s:", dir);
1746+ xt(argc, argv, mode);
1747+ break;
1748+ default:
1749+ usage();
1750+ }
1751
1752 #if FEATURE_TAR_EXCLUDE
1753- if (excludes) {
1754- for (i = 0; i < excludes_cnt; i++)
1755- free(excludes[i]);
1756- free(excludes);
1757- }
1758+ if (excludes) {
1759+ for (i = 0; i < excludes_cnt; i++)
1760+ free(excludes[i]);
1761+ free(excludes);
1762+ }
1763 #endif
1764 #if FEATURE_TAR_FILES_FROM
1765- if (files_from) {
1766- for (i = 0; i < files_from_cnt; i++)
1767- free(files_from[i]);
1768- free(files_from);
1769- }
1770+ if (files_from) {
1771+ for (i = 0; i < files_from_cnt; i++)
1772+ free(files_from[i]);
1773+ free(files_from);
1774+ }
1775 #endif
1776- return recurse_status;
1777+ return recurse_status;
1778 }
+2,
-1
1@@ -6,6 +6,7 @@
2 #include <stdlib.h>
3 #include <unistd.h>
4
5+#include "wexec.h"
6 #include "util.h"
7
8 static void
9@@ -58,7 +59,7 @@ main(int argc, char *argv[])
10 for (;;) {
11 printf("\x1b[2J\x1b[H"); /* clear */
12 fflush(NULL);
13- system(cmd);
14+ wsystem(cmd);
15 usleep(interval);
16 }
17 return 0;
+13,
-14
1@@ -1,13 +1,7 @@
2 /* See LICENSE file for copyright and license details. */
3-
4-
5 #include <sys/stat.h>
6 #include <sys/types.h>
7-#ifndef makedev
8-#include <sys/sysmacros.h>
9-#endif
10
11-#include <fcntl.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15@@ -15,17 +9,21 @@
16
17 #include "util.h"
18
19+#ifndef makedev
20+#include <sys/sysmacros.h>
21+#endif
22+
23 static void
24 usage(void)
25 {
26 eprintf("usage: %s [-m mode] name b|c|u major minor\n"
27- " %s [-m mode] name p\n",
28- argv0, argv0);
29+ " %s [-m mode] name p\n",
30+ argv0, argv0);
31 }
32
33 // ?man mknod: create special files
34-// ?man arguments: name b|c|u major minor
35-// ?man create block or character special files
36+// ?man arguments: name type [major minor]
37+// ?man create a block special, character special, or fifo file
38 int
39 main(int argc, char *argv[])
40 {
41@@ -33,13 +31,13 @@ main(int argc, char *argv[])
42 dev_t dev;
43
44 ARGBEGIN {
45-// ?man -m:mode: specify mode or limit
46-case 'm':
47+ case 'm':
48+ // ?man -m:mode: set the file mode bits of the created node
49 mode = parsemode(EARGF(usage()), mode, umask(0));
50 break;
51 default:
52 usage();
53- } ARGEND;
54+ } ARGEND
55
56 if (argc < 2)
57 usage();
58@@ -69,7 +67,8 @@ case 'm':
59 } else {
60 if (argc != 4)
61 usage();
62- dev = makedev(estrtonum(argv[2], 0, LLONG_MAX), estrtonum(argv[3], 0, LLONG_MAX));
63+ dev = makedev(estrtonum(argv[2], 0, LLONG_MAX),
64+ estrtonum(argv[3], 0, LLONG_MAX));
65 }
66
67 if (mknod(argv[0], mode, dev) == -1)
+51,
-228
1@@ -1,185 +1,43 @@
2 /* See LICENSE file for copyright and license details. */
3-
4-
5-#include <sys/ioctl.h>
6-#include <sys/stat.h>
7-#include <sys/types.h>
8-#include <sys/syscall.h>
9+#include "config.h"
10+#include "passwd.h"
11+#include "text.h"
12+#include "util.h"
13
14 #include <errno.h>
15-#include <fcntl.h>
16-#include <limits.h>
17 #include <pwd.h>
18-#include <shadow.h>
19-#include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23+#include <sys/stat.h>
24 #include <unistd.h>
25
26-#include "config.h"
27-#include "passwd.h"
28-#include "text.h"
29-#include "util.h"
30-
31-static FILE *
32-spw_get_file(const char *user)
33-{
34- FILE *fp = NULL;
35- char file[PATH_MAX];
36- int r;
37-
38- r = snprintf(file, sizeof(file), "/etc/tcb/%s/shadow", user);
39- if (r < 0 || (size_t)r >= sizeof(file))
40- eprintf("snprintf:");
41- fp = fopen(file, "r+");
42- if (!fp)
43- fp = fopen("/etc/shadow", "r+");
44- return fp;
45-}
46-
47-static int
48-spw_write_file(FILE *fp, const struct spwd *spw, char *pwhash)
49-{
50- struct spwd *spwent;
51- int r = -1, w = 0;
52- FILE *tfp = NULL;
53-
54- /* write to temporary file. */
55- tfp = tmpfile();
56- if (!tfp) {
57- weprintf("tmpfile:");
58- goto cleanup;
59- }
60- while ((spwent = fgetspent(fp))) {
61- /* update entry on name match */
62- if (strcmp(spwent->sp_namp, spw->sp_namp) == 0) {
63- spwent->sp_pwdp = pwhash;
64- w++;
65- }
66- errno = 0;
67- if (putspent(spwent, tfp) == -1) {
68- weprintf("putspent:");
69- goto cleanup;
70- }
71- }
72- if (!w) {
73- weprintf("shadow: no matching entry to write to\n");
74- goto cleanup;
75- }
76- fflush(tfp);
77-
78- if (fseek(fp, 0, SEEK_SET) == -1 || fseek(tfp, 0, SEEK_SET) == -1) {
79- weprintf("fseek:");
80- goto cleanup;
81- }
82-
83- /* write temporary file to (tcb) shadow file */
84- fconcat(tfp, "tmpfile", fp, "shadow");
85- ftruncate(fileno(fp), ftell(tfp));
86-
87- r = 0; /* success */
88-cleanup:
89- if (tfp)
90- fclose(tfp);
91- return r;
92-}
93-
94-static int
95-pw_write_file(FILE *fp, const struct passwd *pw, char *pwhash) {
96- struct passwd *pwent;
97- int r = -1, w = 0;
98- FILE *tfp = NULL;
99-
100- /* write to temporary file. */
101- tfp = tmpfile();
102- if (!tfp) {
103- weprintf("tmpfile:");
104- goto cleanup;
105- }
106- while ((pwent = fgetpwent(fp))) {
107- /* update entry on name match */
108- if (strcmp(pwent->pw_name, pw->pw_name) == 0) {
109- pwent->pw_passwd = pwhash;
110- w++;
111- }
112- errno = 0;
113- if (putpwent(pwent, tfp) == -1) {
114- weprintf("putpwent:");
115- goto cleanup;
116- }
117- }
118- if (!w) {
119- weprintf("passwd: no matching entry to write to\n");
120- goto cleanup;
121- }
122- fflush(tfp);
123-
124- if (fseek(fp, 0, SEEK_SET) == -1 || fseek(tfp, 0, SEEK_SET) == -1) {
125- weprintf("fseek:");
126- goto cleanup;
127- }
128-
129- /* write to passwd file. */
130- fconcat(tfp, "tmpfile", fp, "passwd");
131- ftruncate(fileno(fp), ftell(tfp));
132-
133- r = 0; /* success */
134-cleanup:
135- if (tfp)
136- fclose(tfp);
137- return r;
138-}
139-
140-/* generates a random base64-encoded salt string of length 16 */
141-static void
142-gensalt(char *s)
143-{
144- static const char b64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
145- uint8_t buf[12];
146- uint32_t n;
147- int i;
148-
149- if (syscall(SYS_getrandom, buf, sizeof(buf), 0) < 0)
150- eprintf("getrandom:");
151- for (i = 0; i < 12; i += 3) {
152- n = buf[i] << 16 | buf[i+1] << 8 | buf[i+2];
153- *s++ = b64[n%64]; n /= 64;
154- *s++ = b64[n%64]; n /= 64;
155- *s++ = b64[n%64]; n /= 64;
156- *s++ = b64[n];
157- }
158- *s++ = '\0';
159-}
160-
161 static void
162 usage(void)
163 {
164 eprintf("usage: %s [username]\n", argv0);
165 }
166
167-// ?man passwd: change user password
168-// ?man arguments: username
169-// ?man update a user authentication password
170+// ?man passwd: change a user password
171+// ?man arguments: [username]
172+// ?man change the password associated with the calling user or with username
173 int
174 main(int argc, char *argv[])
175 {
176- char *cryptpass1 = NULL, *cryptpass2 = NULL, *cryptpass3 = NULL;
177- char *inpass, *p, *prevhash = NULL, salt[sizeof(PW_CIPHER) + 16] = PW_CIPHER;
178+ struct pwdb_entry ent;
179 struct passwd *pw;
180- struct spwd *spw = NULL;
181- FILE *fp = NULL;
182- int r = -1, status = 1;
183+ char *inpass, *prevhash = NULL, *newhash = NULL, salt[PW_SALT_MAX];
184+ char *c1, *c2;
185+ int status = 1;
186
187 ARGBEGIN {
188 default:
189 usage();
190- } ARGEND;
191+ } ARGEND
192
193 pw_init();
194 umask(077);
195
196- errno = 0;
197 if (argc == 0)
198 pw = getpwuid(getuid());
199 else
200@@ -191,103 +49,68 @@ main(int argc, char *argv[])
201 eprintf("who are you?\n");
202 }
203
204- /* is using shadow entry ? */
205- if (pw->pw_passwd[0] == 'x' && pw->pw_passwd[1] == '\0') {
206- errno = 0;
207- spw = getspnam(pw->pw_name);
208- if (!spw) {
209- if (errno)
210- eprintf("getspnam: %s:", pw->pw_name);
211- else
212- eprintf("who are you?\n");
213- }
214- }
215+ if (pwdb_lookup(&ent, pw->pw_name) < 0)
216+ return 1;
217+ prevhash = ent.hash;
218
219- /* Flush pending input */
220- ioctl(0, TCFLSH, (void *)0);
221-
222- if (getuid() == 0) {
223- goto newpass;
224- } else {
225- if (pw->pw_passwd[0] == '!' ||
226- pw->pw_passwd[0] == '*')
227+ if (getuid() != 0) {
228+ if (prevhash[0] == '!' || prevhash[0] == '*')
229 eprintf("denied\n");
230- if (pw->pw_passwd[0] == '\0') {
231- goto newpass;
232+ if (prevhash[0] == '\0') {
233+ /* no password set */
234+ } else {
235+ printf("Changing password for %s\n", pw->pw_name);
236+ inpass = getpass("Old password: ");
237+ if (!inpass)
238+ eprintf("getpass:");
239+ if (inpass[0] == '\0')
240+ eprintf("no password supplied\n");
241+ c1 = crypt(inpass, prevhash);
242+ if (!c1)
243+ eprintf("crypt:");
244+ if (strcmp(c1, prevhash) != 0)
245+ eprintf("incorrect password\n");
246+ explicit_bzero(inpass, strlen(inpass));
247 }
248- if (pw->pw_passwd[0] == 'x' &&
249- pw->pw_passwd[1] == '\0')
250- prevhash = spw->sp_pwdp;
251- else
252- prevhash = pw->pw_passwd;
253 }
254
255- printf("Changing password for %s\n", pw->pw_name);
256- inpass = getpass("Old password: ");
257- if (!inpass)
258- eprintf("getpass:");
259- if (inpass[0] == '\0')
260- eprintf("no password supplied\n");
261- p = crypt(inpass, prevhash);
262- if (!p)
263- eprintf("crypt:");
264- cryptpass1 = estrdup(p);
265- if (strcmp(cryptpass1, prevhash) != 0)
266- eprintf("incorrect password\n");
267-
268-newpass:
269 inpass = getpass("Enter new password: ");
270 if (!inpass)
271 eprintf("getpass:");
272 if (inpass[0] == '\0')
273 eprintf("no password supplied\n");
274
275- if(prevhash) {
276- p = crypt(inpass, prevhash);
277- if (!p)
278- eprintf("crypt:");
279- if (cryptpass1 && strcmp(cryptpass1, p) == 0)
280+ if (prevhash && prevhash[0] != '\0') {
281+ c1 = crypt(inpass, prevhash);
282+ if (c1 && strcmp(c1, prevhash) == 0)
283 eprintf("password left unchanged\n");
284 }
285- gensalt(salt + strlen(salt));
286- p = crypt(inpass, salt);
287- if (!p)
288- eprintf("crypt:");
289- cryptpass2 = estrdup(p);
290
291- /* Flush pending input */
292- ioctl(0, TCFLSH, (void *)0);
293+ if (pw_gensalt(salt, sizeof(salt)) < 0)
294+ eprintf("pw_gensalt:");
295+ c1 = crypt(inpass, salt);
296+ if (!c1)
297+ eprintf("crypt:");
298+ newhash = estrdup(c1);
299+ explicit_bzero(inpass, strlen(inpass));
300
301 inpass = getpass("Retype new password: ");
302 if (!inpass)
303 eprintf("getpass:");
304 if (inpass[0] == '\0')
305 eprintf("no password supplied\n");
306- p = crypt(inpass, salt);
307- if (!p)
308+ c2 = crypt(inpass, salt);
309+ if (!c2)
310 eprintf("crypt:");
311- cryptpass3 = estrdup(p);
312- if (strcmp(cryptpass2, cryptpass3) != 0)
313+ if (strcmp(c2, newhash) != 0)
314 eprintf("passwords don't match\n");
315+ explicit_bzero(inpass, strlen(inpass));
316
317- fp = spw_get_file(pw->pw_name);
318- if (fp) {
319- r = spw_write_file(fp, spw, cryptpass3);
320- } else {
321- fp = fopen("/etc/passwd", "r+");
322- if (fp)
323- r = pw_write_file(fp, pw, cryptpass3);
324- else
325- weprintf("fopen:");
326- }
327- if (!r)
328+ if (pwdb_update(pw->pw_name, newhash) == 0)
329 status = 0;
330
331- if (fp)
332- fclose(fp);
333- free(cryptpass3);
334- free(cryptpass2);
335- free(cryptpass1);
336-
337+ free(newhash);
338+ free(ent.name);
339+ free(ent.hash);
340 return status;
341 }
+18,
-14
1@@ -1,7 +1,7 @@
2 /* See LICENSE file for copyright and license details. */
3-
4-
5-#include <sys/types.h>
6+#include "config.h"
7+#include "passwd.h"
8+#include "util.h"
9
10 #include <errno.h>
11 #include <grp.h>
12@@ -9,13 +9,15 @@
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16+#include <sys/types.h>
17 #include <unistd.h>
18
19-#include "passwd.h"
20-#include "util.h"
21-
22 extern char **environ;
23
24+#ifndef ENV_PATH_SHELL
25+#define ENV_PATH_SHELL "/bin/sh"
26+#endif
27+
28 static int lflag = 0;
29 static int pflag = 0;
30
31@@ -25,9 +27,9 @@ usage(void)
32 eprintf("usage: %s [-lp] [username]\n", argv0);
33 }
34
35-// ?man su: run command with substitute user id
36-// ?man arguments: username
37-// ?man run a shell or command with another user id
38+// ?man su: run a command with substitute user and group id
39+// ?man arguments: [username]
40+// ?man run a shell or command as the named user. defaults to root
41 int
42 main(int argc, char *argv[])
43 {
44@@ -38,17 +40,17 @@ main(int argc, char *argv[])
45 uid_t uid;
46
47 ARGBEGIN {
48- // ?man -l: list in long format
49 case 'l':
50+ // ?man -l: make the shell a login shell
51 lflag = 1;
52 break;
53- // ?man -p: preserve file attributes
54 case 'p':
55+ // ?man -p: preserve the current environment
56 pflag = 1;
57 break;
58 default:
59 usage();
60- } ARGEND;
61+ } ARGEND
62
63 if (argc > 1)
64 usage();
65@@ -70,6 +72,7 @@ main(int argc, char *argv[])
66 eprintf("getpass:");
67 if (pw_check(pw, pass) <= 0)
68 exit(1);
69+ explicit_bzero(pass, strlen(pass));
70 }
71
72 if (initgroups(usr, pw->pw_gid) < 0)
73@@ -79,7 +82,7 @@ main(int argc, char *argv[])
74 if (setuid(pw->pw_uid) < 0)
75 eprintf("setuid:");
76
77- shell = pw->pw_shell[0] == '\0' ? "/bin/sh" : pw->pw_shell;
78+ shell = pw->pw_shell[0] == '\0' ? ENV_PATH_SHELL : pw->pw_shell;
79 if (lflag) {
80 term = getenv("TERM");
81 clearenv();
82@@ -87,7 +90,8 @@ main(int argc, char *argv[])
83 setenv("SHELL", shell, 1);
84 setenv("USER", pw->pw_name, 1);
85 setenv("LOGNAME", pw->pw_name, 1);
86- setenv("TERM", term ? term : "linux", 1);
87+ setenv("TERM", term ? term : "dumb", 1);
88+ setenv("PATH", ENV_PATH, 1);
89 if (chdir(pw->pw_dir) < 0)
90 eprintf("chdir %s:", pw->pw_dir);
91 newargv[0] = shell;
+84,
-62
1@@ -232,6 +232,17 @@ FEATURE_SH_WORDEXP = 1
2 FEATURE_CAL_EXT = 1
3 FEATURE_SED_PRESERVE_NEWLINE = 1
4 FEATURE_LS_COLOR = 1
5+FEATURE_DIFF3_MERGE = 1
6+FEATURE_DIFF3_EDSCRIPT = 1
7+FEATURE_DIFF_CONTEXT = 1
8+FEATURE_DIFF_UNIFIED = 1
9+FEATURE_DIFF_ED = 1
10+FEATURE_DIFF_BRIEF = 1
11+FEATURE_DIFF_SIDEBYSIDE = 1
12+FEATURE_PATCH_BACKUP = 1
13+FEATURE_PATCH_FUZZ = 1
14+FEATURE_PATCH_STRIP_CR = 1
15+FEATURE_INPROC_EXEC = 0
16 FEATURE_MODPROBE_SHOW_DEPENDS = 1
17 FEATURE_MODPROBE_BLACKLIST = 1
18 FEATURE_MODPROBE_SYSLOG = 1
19@@ -255,68 +266,79 @@ FEATURE_IP_LINK_SET = 1
20 FEATURE_IP_ADDR_FLUSH = 1
21
22 CPPFLAGS =\
23- -Ishared\
24- -DPREFIX=\"\$(PREFIX)\"\
25- -D_DEFAULT_SOURCE\
26- -D_GNU_SOURCE\
27- -D_NETBSD_SOURCE\
28- -D_BSD_SOURCE\
29- -D_XOPEN_SOURCE=700\
30- -D_FILE_OFFSET_BITS=64\
31- -DFEATURE_FIND_DELETE=$(FEATURE_FIND_DELETE)\
32- -DFEATURE_FIND_QUIT=$(FEATURE_FIND_QUIT)\
33- -DFEATURE_FIND_EMPTY=$(FEATURE_FIND_EMPTY)\
34- -DFEATURE_FIND_INUM=$(FEATURE_FIND_INUM)\
35- -DFEATURE_FIND_SAMEFILE=$(FEATURE_FIND_SAMEFILE)\
36- -DFEATURE_FIND_MAXDEPTH=$(FEATURE_FIND_MAXDEPTH)\
37- -DFEATURE_FIND_MINDEPTH=$(FEATURE_FIND_MINDEPTH)\
38- -DFEATURE_FIND_MMIN=$(FEATURE_FIND_MMIN)\
39- -DFEATURE_FIND_AMIN=$(FEATURE_FIND_AMIN)\
40- -DFEATURE_FIND_CMIN=$(FEATURE_FIND_CMIN)\
41- -DFEATURE_FIND_INAME=$(FEATURE_FIND_INAME)\
42- -DFEATURE_FIND_IPATH=$(FEATURE_FIND_IPATH)\
43- -DFEATURE_FIND_REGEX=$(FEATURE_FIND_REGEX)\
44- -DFEATURE_FIND_PRINT0=$(FEATURE_FIND_PRINT0)\
45- -DFEATURE_SED_INPLACE=$(FEATURE_SED_INPLACE)\
46- -DFEATURE_GREP_CONTEXT=$(FEATURE_GREP_CONTEXT)\
47- -DFEATURE_GREP_MAX_COUNT=$(FEATURE_GREP_MAX_COUNT)\
48- -DFEATURE_TAR_CREATE=$(FEATURE_TAR_CREATE)\
49- -DFEATURE_TAR_EXCLUDE=$(FEATURE_TAR_EXCLUDE)\
50- -DFEATURE_STAT_FILESYSTEM=$(FEATURE_STAT_FILESYSTEM)\
51- -DFEATURE_STAT_FORMAT=$(FEATURE_STAT_FORMAT)\
52- -DFEATURE_SORT_BIG=$(FEATURE_SORT_BIG)\
53- -DFEATURE_SORT_STABLE=$(FEATURE_SORT_STABLE)\
54- -DFEATURE_OD_ENDIAN=$(FEATURE_OD_ENDIAN)\
55- -DFEATURE_SH_HISTEDIT=$(FEATURE_SH_HISTEDIT)\
56- -DFEATURE_SH_LOCAL=$(FEATURE_SH_LOCAL)\
57- -DFEATURE_SH_LET=$(FEATURE_SH_LET)\
58- -DFEATURE_SH_ULIMIT=$(FEATURE_SH_ULIMIT)\
59- -DFEATURE_SH_SETVAR=$(FEATURE_SH_SETVAR)\
60- -DFEATURE_SH_WORDEXP=$(FEATURE_SH_WORDEXP)\
61- -DFEATURE_CAL_EXT=$(FEATURE_CAL_EXT)\
62- -DFEATURE_SED_PRESERVE_NEWLINE=$(FEATURE_SED_PRESERVE_NEWLINE)\
63- -DFEATURE_LS_COLOR=$(FEATURE_LS_COLOR)\
64- -DFEATURE_MODPROBE_SHOW_DEPENDS=$(FEATURE_MODPROBE_SHOW_DEPENDS)\
65- -DFEATURE_MODPROBE_BLACKLIST=$(FEATURE_MODPROBE_BLACKLIST)\
66- -DFEATURE_MODPROBE_SYSLOG=$(FEATURE_MODPROBE_SYSLOG)\
67- -DFEATURE_MODPROBE_DIR_OVERRIDE=$(FEATURE_MODPROBE_DIR_OVERRIDE)\
68- -DFEATURE_DEPMOD_ALIAS=$(FEATURE_DEPMOD_ALIAS)\
69- -DFEATURE_DEPMOD_SYMBOLS=$(FEATURE_DEPMOD_SYMBOLS)\
70- -DFEATURE_USE_LIBRESSL=$(FEATURE_USE_LIBRESSL)\
71- -DFEATURE_USE_BEARSSL=$(FEATURE_USE_BEARSSL)\
72- -DFEATURE_USE_OPENSSL=$(FEATURE_USE_OPENSSL)\
73- -DFEATURE_TAR_TTY_SAFE=$(FEATURE_TAR_TTY_SAFE)\
74- -DFEATURE_TAR_NOFOLLOW=$(FEATURE_TAR_NOFOLLOW)\
75- -DFEATURE_READLINK_REALPATH=$(FEATURE_READLINK_REALPATH)\
76- -DFEATURE_UMOUNT_OPTIONS=$(FEATURE_UMOUNT_OPTIONS)\
77- -DFEATURE_TAR_TO_STDOUT=$(FEATURE_TAR_TO_STDOUT)\
78- -DFEATURE_TAR_KEEP_OLD=$(FEATURE_TAR_KEEP_OLD)\
79- -DFEATURE_TAR_STRIP_COMPONENTS=$(FEATURE_TAR_STRIP_COMPONENTS)\
80- -DFEATURE_TAR_FILES_FROM=$(FEATURE_TAR_FILES_FROM)\
81- -DFEATURE_TAR_EXCLUDE_FROM=$(FEATURE_TAR_EXCLUDE_FROM)\
82- -DFEATURE_IP_ROUTE_ADD_DEL=$(FEATURE_IP_ROUTE_ADD_DEL)\
83- -DFEATURE_IP_LINK_SET=$(FEATURE_IP_LINK_SET)\
84- -DFEATURE_IP_ADDR_FLUSH=$(FEATURE_IP_ADDR_FLUSH) $(CPPFLAGS_TLS)
85+ -Ishared\
86+ -DPREFIX=\"\$(PREFIX)\"\
87+ -D_DEFAULT_SOURCE\
88+ -D_GNU_SOURCE\
89+ -D_NETBSD_SOURCE\
90+ -D_BSD_SOURCE\
91+ -D_XOPEN_SOURCE=700\
92+ -D_FILE_OFFSET_BITS=64\
93+ -DFEATURE_FIND_DELETE=$(FEATURE_FIND_DELETE)\
94+ -DFEATURE_FIND_QUIT=$(FEATURE_FIND_QUIT)\
95+ -DFEATURE_FIND_EMPTY=$(FEATURE_FIND_EMPTY)\
96+ -DFEATURE_FIND_INUM=$(FEATURE_FIND_INUM)\
97+ -DFEATURE_FIND_SAMEFILE=$(FEATURE_FIND_SAMEFILE)\
98+ -DFEATURE_FIND_MAXDEPTH=$(FEATURE_FIND_MAXDEPTH)\
99+ -DFEATURE_FIND_MINDEPTH=$(FEATURE_FIND_MINDEPTH)\
100+ -DFEATURE_FIND_MMIN=$(FEATURE_FIND_MMIN)\
101+ -DFEATURE_FIND_AMIN=$(FEATURE_FIND_AMIN)\
102+ -DFEATURE_FIND_CMIN=$(FEATURE_FIND_CMIN)\
103+ -DFEATURE_FIND_INAME=$(FEATURE_FIND_INAME)\
104+ -DFEATURE_FIND_IPATH=$(FEATURE_FIND_IPATH)\
105+ -DFEATURE_FIND_REGEX=$(FEATURE_FIND_REGEX)\
106+ -DFEATURE_FIND_PRINT0=$(FEATURE_FIND_PRINT0)\
107+ -DFEATURE_SED_INPLACE=$(FEATURE_SED_INPLACE)\
108+ -DFEATURE_GREP_CONTEXT=$(FEATURE_GREP_CONTEXT)\
109+ -DFEATURE_GREP_MAX_COUNT=$(FEATURE_GREP_MAX_COUNT)\
110+ -DFEATURE_TAR_CREATE=$(FEATURE_TAR_CREATE)\
111+ -DFEATURE_TAR_EXCLUDE=$(FEATURE_TAR_EXCLUDE)\
112+ -DFEATURE_STAT_FILESYSTEM=$(FEATURE_STAT_FILESYSTEM)\
113+ -DFEATURE_STAT_FORMAT=$(FEATURE_STAT_FORMAT)\
114+ -DFEATURE_SORT_BIG=$(FEATURE_SORT_BIG)\
115+ -DFEATURE_SORT_STABLE=$(FEATURE_SORT_STABLE)\
116+ -DFEATURE_OD_ENDIAN=$(FEATURE_OD_ENDIAN)\
117+ -DFEATURE_SH_HISTEDIT=$(FEATURE_SH_HISTEDIT)\
118+ -DFEATURE_SH_LOCAL=$(FEATURE_SH_LOCAL)\
119+ -DFEATURE_SH_LET=$(FEATURE_SH_LET)\
120+ -DFEATURE_SH_ULIMIT=$(FEATURE_SH_ULIMIT)\
121+ -DFEATURE_SH_SETVAR=$(FEATURE_SH_SETVAR)\
122+ -DFEATURE_SH_WORDEXP=$(FEATURE_SH_WORDEXP)\
123+ -DFEATURE_CAL_EXT=$(FEATURE_CAL_EXT)\
124+ -DFEATURE_SED_PRESERVE_NEWLINE=$(FEATURE_SED_PRESERVE_NEWLINE)\
125+ -DFEATURE_LS_COLOR=$(FEATURE_LS_COLOR)\
126+ -DFEATURE_DIFF3_MERGE=$(FEATURE_DIFF3_MERGE)\
127+ -DFEATURE_DIFF3_EDSCRIPT=$(FEATURE_DIFF3_EDSCRIPT)\
128+ -DFEATURE_DIFF_CONTEXT=$(FEATURE_DIFF_CONTEXT)\
129+ -DFEATURE_DIFF_UNIFIED=$(FEATURE_DIFF_UNIFIED)\
130+ -DFEATURE_DIFF_ED=$(FEATURE_DIFF_ED)\
131+ -DFEATURE_DIFF_BRIEF=$(FEATURE_DIFF_BRIEF)\
132+ -DFEATURE_DIFF_SIDEBYSIDE=$(FEATURE_DIFF_SIDEBYSIDE)\
133+ -DFEATURE_PATCH_BACKUP=$(FEATURE_PATCH_BACKUP)\
134+ -DFEATURE_PATCH_FUZZ=$(FEATURE_PATCH_FUZZ)\
135+ -DFEATURE_PATCH_STRIP_CR=$(FEATURE_PATCH_STRIP_CR)\
136+ -DFEATURE_INPROC_EXEC=$(FEATURE_INPROC_EXEC)\
137+ -DFEATURE_MODPROBE_SHOW_DEPENDS=$(FEATURE_MODPROBE_SHOW_DEPENDS)\
138+ -DFEATURE_MODPROBE_BLACKLIST=$(FEATURE_MODPROBE_BLACKLIST)\
139+ -DFEATURE_MODPROBE_SYSLOG=$(FEATURE_MODPROBE_SYSLOG)\
140+ -DFEATURE_MODPROBE_DIR_OVERRIDE=$(FEATURE_MODPROBE_DIR_OVERRIDE)\
141+ -DFEATURE_DEPMOD_ALIAS=$(FEATURE_DEPMOD_ALIAS)\
142+ -DFEATURE_DEPMOD_SYMBOLS=$(FEATURE_DEPMOD_SYMBOLS)\
143+ -DFEATURE_USE_LIBRESSL=$(FEATURE_USE_LIBRESSL)\
144+ -DFEATURE_USE_BEARSSL=$(FEATURE_USE_BEARSSL)\
145+ -DFEATURE_USE_OPENSSL=$(FEATURE_USE_OPENSSL)\
146+ -DFEATURE_TAR_TTY_SAFE=$(FEATURE_TAR_TTY_SAFE)\
147+ -DFEATURE_TAR_NOFOLLOW=$(FEATURE_TAR_NOFOLLOW)\
148+ -DFEATURE_READLINK_REALPATH=$(FEATURE_READLINK_REALPATH)\
149+ -DFEATURE_UMOUNT_OPTIONS=$(FEATURE_UMOUNT_OPTIONS)\
150+ -DFEATURE_TAR_TO_STDOUT=$(FEATURE_TAR_TO_STDOUT)\
151+ -DFEATURE_TAR_KEEP_OLD=$(FEATURE_TAR_KEEP_OLD)\
152+ -DFEATURE_TAR_STRIP_COMPONENTS=$(FEATURE_TAR_STRIP_COMPONENTS)\
153+ -DFEATURE_TAR_FILES_FROM=$(FEATURE_TAR_FILES_FROM)\
154+ -DFEATURE_TAR_EXCLUDE_FROM=$(FEATURE_TAR_EXCLUDE_FROM)\
155+ -DFEATURE_IP_ROUTE_ADD_DEL=$(FEATURE_IP_ROUTE_ADD_DEL)\
156+ -DFEATURE_IP_LINK_SET=$(FEATURE_IP_LINK_SET)\
157+ -DFEATURE_IP_ADDR_FLUSH=$(FEATURE_IP_ADDR_FLUSH) $(CPPFLAGS_TLS)
158
159 CC = cc
160 CFLAGS =
M
deps.mk
+985,
-1267
1@@ -1,75 +1,71 @@
2
3 #AUTOGENERATED
4-cmd/extra/b3sum.o: cmd/extra/b3sum.c
5-cmd/extra/b3sum.o: shared/util.h
6-cmd/extra/b3sum.o: shared/arg.h
7-cmd/extra/b3sum.o: shared/compat.h
8-cmd/extra/b3sum.o: shared/arg.h
9-cmd/extra/blkid.o: cmd/extra/blkid.c
10-cmd/extra/blkid.o: shared/util.h
11-cmd/extra/blkid.o: shared/arg.h
12-cmd/extra/blkid.o: shared/compat.h
13-cmd/extra/blkid.o: shared/diskutil.h
14-cmd/extra/fdisk.o: cmd/extra/fdisk.c
15-cmd/extra/fdisk.o: shared/util.h
16-cmd/extra/fdisk.o: shared/arg.h
17-cmd/extra/fdisk.o: shared/compat.h
18-cmd/extra/fdisk.o: shared/diskutil.h
19-cmd/extra/lsblk.o: cmd/extra/lsblk.c
20-cmd/extra/lsblk.o: shared/util.h
21-cmd/extra/lsblk.o: shared/arg.h
22-cmd/extra/lsblk.o: shared/compat.h
23-cmd/extra/lsblk.o: shared/diskutil.h
24-cmd/extra/sync.o: cmd/extra/sync.c
25-cmd/extra/sync.o: shared/arg.h
26-cmd/extra/sync.o: shared/util.h
27-cmd/extra/sync.o: shared/arg.h
28-cmd/extra/sync.o: shared/compat.h
29-cmd/linux/blkdiscard.o: cmd/linux/blkdiscard.c
30-cmd/linux/blkdiscard.o: shared/util.h
31-cmd/linux/blkdiscard.o: shared/arg.h
32-cmd/linux/blkdiscard.o: shared/compat.h
33-cmd/linux/chvt.o: cmd/linux/chvt.c
34-cmd/linux/chvt.o: shared/util.h
35-cmd/linux/chvt.o: shared/arg.h
36-cmd/linux/chvt.o: shared/compat.h
37-cmd/linux/ctrlaltdel.o: cmd/linux/ctrlaltdel.c
38-cmd/linux/ctrlaltdel.o: shared/reboot.h
39-cmd/linux/ctrlaltdel.o: shared/util.h
40-cmd/linux/ctrlaltdel.o: shared/arg.h
41-cmd/linux/ctrlaltdel.o: shared/compat.h
42-cmd/linux/depmod.o: cmd/linux/depmod.c
43-cmd/linux/depmod.o: shared/fs.h
44-cmd/linux/depmod.o: shared/util.h
45-cmd/linux/depmod.o: shared/arg.h
46-cmd/linux/depmod.o: shared/compat.h
47-cmd/linux/eject.o: cmd/linux/eject.c
48-cmd/linux/eject.o: shared/util.h
49-cmd/linux/eject.o: shared/arg.h
50-cmd/linux/eject.o: shared/compat.h
51-cmd/linux/freeramdisk.o: cmd/linux/freeramdisk.c
52-cmd/linux/freeramdisk.o: shared/util.h
53-cmd/linux/freeramdisk.o: shared/arg.h
54-cmd/linux/freeramdisk.o: shared/compat.h
55-cmd/linux/fsfreeze.o: cmd/linux/fsfreeze.c
56-cmd/linux/fsfreeze.o: shared/util.h
57-cmd/linux/fsfreeze.o: shared/arg.h
58-cmd/linux/fsfreeze.o: shared/compat.h
59+cmd/linux/switch_root.o: cmd/linux/switch_root.c
60+cmd/linux/switch_root.o: shared/util.h
61+cmd/linux/switch_root.o: shared/arg.h
62+cmd/linux/switch_root.o: shared/compat.h
63+cmd/linux/unshare.o: cmd/linux/unshare.c
64+cmd/linux/unshare.o: shared/wexec.h
65+cmd/linux/unshare.o: shared/util.h
66+cmd/linux/unshare.o: shared/arg.h
67+cmd/linux/unshare.o: shared/compat.h
68+cmd/linux/mount.o: cmd/linux/mount.c
69+cmd/linux/mount.o: shared/text.h
70+cmd/linux/mount.o: shared/wexec.h
71+cmd/linux/mount.o: shared/util.h
72+cmd/linux/mount.o: shared/arg.h
73+cmd/linux/mount.o: shared/compat.h
74+cmd/linux/pivot_root.o: cmd/linux/pivot_root.c
75+cmd/linux/pivot_root.o: shared/util.h
76+cmd/linux/pivot_root.o: shared/arg.h
77+cmd/linux/pivot_root.o: shared/compat.h
78+cmd/linux/umount.o: cmd/linux/umount.c
79+cmd/linux/umount.o: shared/util.h
80+cmd/linux/umount.o: shared/arg.h
81+cmd/linux/umount.o: shared/compat.h
82+cmd/linux/rmmod.o: cmd/linux/rmmod.c
83+cmd/linux/rmmod.o: shared/util.h
84+cmd/linux/rmmod.o: shared/arg.h
85+cmd/linux/rmmod.o: shared/compat.h
86 cmd/linux/hwclock.o: cmd/linux/hwclock.c
87 cmd/linux/hwclock.o: shared/rtc.h
88+cmd/linux/hwclock.o: shared/paths.h
89 cmd/linux/hwclock.o: shared/util.h
90 cmd/linux/hwclock.o: shared/arg.h
91 cmd/linux/hwclock.o: shared/compat.h
92-cmd/linux/lsmod.o: cmd/linux/lsmod.c
93-cmd/linux/lsmod.o: shared/text.h
94-cmd/linux/lsmod.o: shared/util.h
95-cmd/linux/lsmod.o: shared/arg.h
96-cmd/linux/lsmod.o: shared/compat.h
97+cmd/linux/sysctl.o: cmd/linux/sysctl.c
98+cmd/linux/sysctl.o: shared/text.h
99+cmd/linux/sysctl.o: shared/paths.h
100+cmd/linux/sysctl.o: shared/util.h
101+cmd/linux/sysctl.o: shared/arg.h
102+cmd/linux/sysctl.o: shared/compat.h
103+cmd/linux/tunctl.o: cmd/linux/tunctl.c
104+cmd/linux/tunctl.o: shared/paths.h
105+cmd/linux/tunctl.o: shared/util.h
106+cmd/linux/tunctl.o: shared/arg.h
107+cmd/linux/tunctl.o: shared/compat.h
108+cmd/linux/fsfreeze.o: cmd/linux/fsfreeze.c
109+cmd/linux/fsfreeze.o: shared/util.h
110+cmd/linux/fsfreeze.o: shared/arg.h
111+cmd/linux/fsfreeze.o: shared/compat.h
112+cmd/linux/blkdiscard.o: cmd/linux/blkdiscard.c
113+cmd/linux/blkdiscard.o: shared/util.h
114+cmd/linux/blkdiscard.o: shared/arg.h
115+cmd/linux/blkdiscard.o: shared/compat.h
116+cmd/linux/swaplabel.o: cmd/linux/swaplabel.c
117+cmd/linux/swaplabel.o: shared/util.h
118+cmd/linux/swaplabel.o: shared/arg.h
119+cmd/linux/swaplabel.o: shared/compat.h
120 cmd/linux/lsusb.o: cmd/linux/lsusb.c
121 cmd/linux/lsusb.o: shared/text.h
122+cmd/linux/lsusb.o: shared/paths.h
123 cmd/linux/lsusb.o: shared/util.h
124 cmd/linux/lsusb.o: shared/arg.h
125 cmd/linux/lsusb.o: shared/compat.h
126+cmd/linux/readahead.o: cmd/linux/readahead.c
127+cmd/linux/readahead.o: shared/util.h
128+cmd/linux/readahead.o: shared/arg.h
129+cmd/linux/readahead.o: shared/compat.h
130 cmd/linux/mkswap.o: cmd/linux/mkswap.c
131 cmd/linux/mkswap.o: shared/util.h
132 cmd/linux/mkswap.o: shared/arg.h
133@@ -78,952 +74,171 @@ cmd/linux/mountpoint.o: cmd/linux/mountpoint.c
134 cmd/linux/mountpoint.o: shared/util.h
135 cmd/linux/mountpoint.o: shared/arg.h
136 cmd/linux/mountpoint.o: shared/compat.h
137-cmd/linux/pivot_root.o: cmd/linux/pivot_root.c
138-cmd/linux/pivot_root.o: shared/util.h
139-cmd/linux/pivot_root.o: shared/arg.h
140-cmd/linux/pivot_root.o: shared/compat.h
141-cmd/linux/readahead.o: cmd/linux/readahead.c
142-cmd/linux/readahead.o: shared/util.h
143-cmd/linux/readahead.o: shared/arg.h
144-cmd/linux/readahead.o: shared/compat.h
145-cmd/linux/rmmod.o: cmd/linux/rmmod.c
146-cmd/linux/rmmod.o: shared/util.h
147-cmd/linux/rmmod.o: shared/arg.h
148-cmd/linux/rmmod.o: shared/compat.h
149-cmd/linux/swaplabel.o: cmd/linux/swaplabel.c
150-cmd/linux/swaplabel.o: shared/util.h
151-cmd/linux/swaplabel.o: shared/arg.h
152-cmd/linux/swaplabel.o: shared/compat.h
153+cmd/linux/lsmod.o: cmd/linux/lsmod.c
154+cmd/linux/lsmod.o: shared/text.h
155+cmd/linux/lsmod.o: shared/paths.h
156+cmd/linux/lsmod.o: shared/util.h
157+cmd/linux/lsmod.o: shared/arg.h
158+cmd/linux/lsmod.o: shared/compat.h
159+cmd/linux/chvt.o: cmd/linux/chvt.c
160+cmd/linux/chvt.o: shared/paths.h
161+cmd/linux/chvt.o: shared/util.h
162+cmd/linux/chvt.o: shared/arg.h
163+cmd/linux/chvt.o: shared/compat.h
164 cmd/linux/swapoff.o: cmd/linux/swapoff.c
165 cmd/linux/swapoff.o: shared/util.h
166 cmd/linux/swapoff.o: shared/arg.h
167 cmd/linux/swapoff.o: shared/compat.h
168-cmd/linux/swapon.o: cmd/linux/swapon.c
169-cmd/linux/swapon.o: shared/util.h
170-cmd/linux/swapon.o: shared/arg.h
171-cmd/linux/swapon.o: shared/compat.h
172-cmd/linux/sysctl.o: cmd/linux/sysctl.c
173-cmd/linux/sysctl.o: shared/text.h
174-cmd/linux/sysctl.o: shared/util.h
175-cmd/linux/sysctl.o: shared/arg.h
176-cmd/linux/sysctl.o: shared/compat.h
177-cmd/linux/tunctl.o: cmd/linux/tunctl.c
178-cmd/linux/tunctl.o: shared/util.h
179-cmd/linux/tunctl.o: shared/arg.h
180-cmd/linux/tunctl.o: shared/compat.h
181-cmd/linux/umount.o: cmd/linux/umount.c
182-cmd/linux/umount.o: shared/util.h
183-cmd/linux/umount.o: shared/arg.h
184-cmd/linux/umount.o: shared/compat.h
185+cmd/linux/eject.o: cmd/linux/eject.c
186+cmd/linux/eject.o: shared/paths.h
187+cmd/linux/eject.o: shared/util.h
188+cmd/linux/eject.o: shared/arg.h
189+cmd/linux/eject.o: shared/compat.h
190+cmd/linux/depmod.o: cmd/linux/depmod.c
191+cmd/linux/depmod.o: shared/fs.h
192+cmd/linux/depmod.o: shared/wexec.h
193+cmd/linux/depmod.o: shared/util.h
194+cmd/linux/depmod.o: shared/arg.h
195+cmd/linux/depmod.o: shared/compat.h
196 cmd/linux/vtallow.o: cmd/linux/vtallow.c
197+cmd/linux/vtallow.o: shared/paths.h
198 cmd/linux/vtallow.o: shared/util.h
199 cmd/linux/vtallow.o: shared/arg.h
200 cmd/linux/vtallow.o: shared/compat.h
201-cmd/linux/insmod.o: cmd/linux/insmod.c
202-cmd/linux/insmod.o: shared/util.h
203-cmd/linux/insmod.o: shared/arg.h
204-cmd/linux/insmod.o: shared/compat.h
205+cmd/linux/freeramdisk.o: cmd/linux/freeramdisk.c
206+cmd/linux/freeramdisk.o: shared/paths.h
207+cmd/linux/freeramdisk.o: shared/util.h
208+cmd/linux/freeramdisk.o: shared/arg.h
209+cmd/linux/freeramdisk.o: shared/compat.h
210+cmd/linux/swapon.o: cmd/linux/swapon.c
211+cmd/linux/swapon.o: shared/util.h
212+cmd/linux/swapon.o: shared/arg.h
213+cmd/linux/swapon.o: shared/compat.h
214+cmd/linux/ctrlaltdel.o: cmd/linux/ctrlaltdel.c
215+cmd/linux/ctrlaltdel.o: shared/reboot.h
216+cmd/linux/ctrlaltdel.o: shared/util.h
217+cmd/linux/ctrlaltdel.o: shared/arg.h
218+cmd/linux/ctrlaltdel.o: shared/compat.h
219 cmd/linux/modprobe.o: cmd/linux/modprobe.c
220 cmd/linux/modprobe.o: shared/arg.h
221 cmd/linux/modprobe.o: shared/fs.h
222+cmd/linux/modprobe.o: shared/paths.h
223 cmd/linux/modprobe.o: shared/util.h
224 cmd/linux/modprobe.o: shared/arg.h
225 cmd/linux/modprobe.o: shared/compat.h
226-cmd/linux/mount.o: cmd/linux/mount.c
227-cmd/linux/mount.o: shared/text.h
228-cmd/linux/mount.o: shared/util.h
229-cmd/linux/mount.o: shared/arg.h
230-cmd/linux/mount.o: shared/compat.h
231-cmd/linux/switch_root.o: cmd/linux/switch_root.c
232-cmd/linux/switch_root.o: shared/util.h
233-cmd/linux/switch_root.o: shared/arg.h
234-cmd/linux/switch_root.o: shared/compat.h
235-cmd/linux/unshare.o: cmd/linux/unshare.c
236-cmd/linux/unshare.o: shared/util.h
237-cmd/linux/unshare.o: shared/arg.h
238-cmd/linux/unshare.o: shared/compat.h
239-cmd/net/httpd.o: cmd/net/httpd.c
240-cmd/net/httpd.o: shared/util.h
241-cmd/net/httpd.o: shared/arg.h
242-cmd/net/httpd.o: shared/compat.h
243-cmd/net/httpd.o: shared/arg.h
244-cmd/net/ping.o: cmd/net/ping.c
245-cmd/net/ping.o: shared/util.h
246-cmd/net/ping.o: shared/arg.h
247-cmd/net/ping.o: shared/compat.h
248-cmd/net/ping.o: shared/arg.h
249-cmd/net/sdhcp.o: cmd/net/sdhcp.c
250-cmd/net/sdhcp.o: shared/arg.h
251-cmd/net/sdhcp.o: shared/util.h
252-cmd/net/sdhcp.o: shared/arg.h
253-cmd/net/sdhcp.o: shared/compat.h
254-cmd/net/tftp.o: cmd/net/tftp.c
255-cmd/net/tftp.o: shared/util.h
256-cmd/net/tftp.o: shared/arg.h
257-cmd/net/tftp.o: shared/compat.h
258-cmd/net/wget.o: cmd/net/wget.c
259-cmd/net/wget.o: shared/util.h
260-cmd/net/wget.o: shared/arg.h
261-cmd/net/wget.o: shared/compat.h
262-cmd/net/wget.o: shared/arg.h
263-cmd/net/wget.o: shared/tls.h
264-cmd/net/host.o: cmd/net/host.c
265-cmd/net/host.o: shared/util.h
266-cmd/net/host.o: shared/arg.h
267-cmd/net/host.o: shared/compat.h
268-cmd/net/host.o: shared/arg.h
269-cmd/net/ifconfig.o: cmd/net/ifconfig.c
270-cmd/net/ifconfig.o: shared/util.h
271-cmd/net/ifconfig.o: shared/arg.h
272-cmd/net/ifconfig.o: shared/compat.h
273-cmd/net/ip.o: cmd/net/ip.c
274-cmd/net/ip.o: shared/util.h
275-cmd/net/ip.o: shared/arg.h
276-cmd/net/ip.o: shared/compat.h
277-cmd/net/netcat.o: cmd/net/netcat.c
278-cmd/net/netcat.o: shared/util.h
279-cmd/net/netcat.o: shared/arg.h
280-cmd/net/netcat.o: shared/compat.h
281-cmd/posix/awk/b.o: cmd/posix/awk/b.c
282-cmd/posix/awk/b.o: cmd/posix/awk/awk.h
283-cmd/posix/awk/b.o: cmd/posix/awk/proto.h
284-cmd/posix/awk/b.o: cmd/posix/awk/awkgram.tab.h
285-cmd/posix/awk/lex.o: cmd/posix/awk/lex.c
286-cmd/posix/awk/lex.o: cmd/posix/awk/awk.h
287-cmd/posix/awk/lex.o: cmd/posix/awk/proto.h
288-cmd/posix/awk/lex.o: cmd/posix/awk/awkgram.tab.h
289-cmd/posix/awk/lib.o: cmd/posix/awk/lib.c
290-cmd/posix/awk/lib.o: cmd/posix/awk/awk.h
291-cmd/posix/awk/lib.o: cmd/posix/awk/proto.h
292-cmd/posix/awk/main.o: cmd/posix/awk/main.c
293-cmd/posix/awk/main.o: cmd/posix/awk/awk.h
294-cmd/posix/awk/main.o: cmd/posix/awk/proto.h
295-cmd/posix/awk/maketab.o: cmd/posix/awk/maketab.c
296-cmd/posix/awk/maketab.o: cmd/posix/awk/awk.h
297-cmd/posix/awk/maketab.o: cmd/posix/awk/proto.h
298-cmd/posix/awk/maketab.o: cmd/posix/awk/awkgram.tab.h
299-cmd/posix/awk/math.o: cmd/posix/awk/math.c
300-cmd/posix/awk/math.o: cmd/posix/awk/awk.h
301-cmd/posix/awk/math.o: cmd/posix/awk/proto.h
302-cmd/posix/awk/parse.o: cmd/posix/awk/parse.c
303-cmd/posix/awk/parse.o: cmd/posix/awk/awk.h
304-cmd/posix/awk/parse.o: cmd/posix/awk/proto.h
305-cmd/posix/awk/parse.o: cmd/posix/awk/awkgram.tab.h
306-cmd/posix/awk/run.o: cmd/posix/awk/run.c
307-cmd/posix/awk/run.o: cmd/posix/awk/awk.h
308-cmd/posix/awk/run.o: cmd/posix/awk/proto.h
309-cmd/posix/awk/run.o: cmd/posix/awk/awkgram.tab.h
310-cmd/posix/awk/tran.o: cmd/posix/awk/tran.c
311-cmd/posix/awk/tran.o: cmd/posix/awk/awk.h
312-cmd/posix/awk/tran.o: cmd/posix/awk/proto.h
313-cmd/posix/awk/awkgram.tab.o: cmd/posix/awk/awkgram.tab.c
314-cmd/posix/awk/awkgram.tab.o: cmd/posix/awk/awk.h
315-cmd/posix/awk/awkgram.tab.o: cmd/posix/awk/proto.h
316-cmd/posix/awk/awkgram.tab.o: cmd/posix/awk/awkgram.tab.h
317-cmd/posix/awk/proctab.o: cmd/posix/awk/proctab.c
318-cmd/posix/awk/proctab.o: cmd/posix/awk/awk.h
319-cmd/posix/awk/proctab.o: cmd/posix/awk/proto.h
320-cmd/posix/awk/proctab.o: cmd/posix/awk/awkgram.tab.h
321-cmd/posix/cal.o: cmd/posix/cal.c
322-cmd/posix/cal.o: shared/util.h
323-cmd/posix/cal.o: shared/arg.h
324-cmd/posix/cal.o: shared/compat.h
325-cmd/posix/cat.o: cmd/posix/cat.c
326-cmd/posix/cat.o: shared/util.h
327-cmd/posix/cat.o: shared/arg.h
328-cmd/posix/cat.o: shared/compat.h
329-cmd/posix/chgrp.o: cmd/posix/chgrp.c
330-cmd/posix/chgrp.o: shared/fs.h
331-cmd/posix/chgrp.o: shared/util.h
332-cmd/posix/chgrp.o: shared/arg.h
333-cmd/posix/chgrp.o: shared/compat.h
334-cmd/posix/chmod.o: cmd/posix/chmod.c
335-cmd/posix/chmod.o: shared/fs.h
336-cmd/posix/chmod.o: shared/util.h
337-cmd/posix/chmod.o: shared/arg.h
338-cmd/posix/chmod.o: shared/compat.h
339-cmd/posix/chown.o: cmd/posix/chown.c
340-cmd/posix/chown.o: shared/fs.h
341-cmd/posix/chown.o: shared/util.h
342-cmd/posix/chown.o: shared/arg.h
343-cmd/posix/chown.o: shared/compat.h
344-cmd/posix/cksum.o: cmd/posix/cksum.c
345-cmd/posix/cksum.o: shared/util.h
346-cmd/posix/cksum.o: shared/arg.h
347-cmd/posix/cksum.o: shared/compat.h
348-cmd/posix/cmp.o: cmd/posix/cmp.c
349-cmd/posix/cmp.o: shared/util.h
350-cmd/posix/cmp.o: shared/arg.h
351-cmd/posix/cmp.o: shared/compat.h
352-cmd/posix/comm.o: cmd/posix/comm.c
353-cmd/posix/comm.o: shared/text.h
354-cmd/posix/comm.o: shared/util.h
355-cmd/posix/comm.o: shared/arg.h
356-cmd/posix/comm.o: shared/compat.h
357-cmd/posix/cp.o: cmd/posix/cp.c
358-cmd/posix/cp.o: shared/fs.h
359-cmd/posix/cp.o: shared/util.h
360-cmd/posix/cp.o: shared/arg.h
361-cmd/posix/cp.o: shared/compat.h
362-cmd/posix/dd.o: cmd/posix/dd.c
363-cmd/posix/dd.o: shared/util.h
364-cmd/posix/dd.o: shared/arg.h
365-cmd/posix/dd.o: shared/compat.h
366-cmd/posix/df.o: cmd/posix/df.c
367-cmd/posix/df.o: shared/util.h
368-cmd/posix/df.o: shared/arg.h
369-cmd/posix/df.o: shared/compat.h
370-cmd/posix/dirname.o: cmd/posix/dirname.c
371-cmd/posix/dirname.o: shared/util.h
372-cmd/posix/dirname.o: shared/arg.h
373-cmd/posix/dirname.o: shared/compat.h
374-cmd/posix/du.o: cmd/posix/du.c
375-cmd/posix/du.o: shared/fs.h
376-cmd/posix/du.o: shared/util.h
377-cmd/posix/du.o: shared/arg.h
378-cmd/posix/du.o: shared/compat.h
379-cmd/posix/echo.o: cmd/posix/echo.c
380-cmd/posix/echo.o: shared/util.h
381-cmd/posix/echo.o: shared/arg.h
382-cmd/posix/echo.o: shared/compat.h
383-cmd/posix/ed.o: cmd/posix/ed.c
384-cmd/posix/ed.o: shared/util.h
385-cmd/posix/ed.o: shared/arg.h
386-cmd/posix/ed.o: shared/compat.h
387-cmd/posix/expand.o: cmd/posix/expand.c
388-cmd/posix/expand.o: shared/utf.h
389-cmd/posix/expand.o: shared/util.h
390-cmd/posix/expand.o: shared/arg.h
391-cmd/posix/expand.o: shared/compat.h
392-cmd/posix/expr.o: cmd/posix/expr.c
393-cmd/posix/expr.o: shared/utf.h
394-cmd/posix/expr.o: shared/util.h
395-cmd/posix/expr.o: shared/arg.h
396-cmd/posix/expr.o: shared/compat.h
397-cmd/posix/false.o: cmd/posix/false.c
398-cmd/posix/fold.o: cmd/posix/fold.c
399-cmd/posix/fold.o: shared/text.h
400-cmd/posix/fold.o: shared/util.h
401-cmd/posix/fold.o: shared/arg.h
402-cmd/posix/fold.o: shared/compat.h
403-cmd/posix/fold.o: shared/utf.h
404-cmd/posix/head.o: cmd/posix/head.c
405-cmd/posix/head.o: shared/util.h
406-cmd/posix/head.o: shared/arg.h
407-cmd/posix/head.o: shared/compat.h
408-cmd/posix/id.o: cmd/posix/id.c
409-cmd/posix/id.o: shared/util.h
410-cmd/posix/id.o: shared/arg.h
411-cmd/posix/id.o: shared/compat.h
412-cmd/posix/join.o: cmd/posix/join.c
413-cmd/posix/join.o: shared/text.h
414-cmd/posix/join.o: shared/utf.h
415-cmd/posix/join.o: shared/util.h
416-cmd/posix/join.o: shared/arg.h
417-cmd/posix/join.o: shared/compat.h
418-cmd/posix/kill.o: cmd/posix/kill.c
419-cmd/posix/kill.o: shared/sig.h
420-cmd/posix/kill.o: shared/util.h
421-cmd/posix/kill.o: shared/arg.h
422-cmd/posix/kill.o: shared/compat.h
423-cmd/posix/link.o: cmd/posix/link.c
424-cmd/posix/link.o: shared/util.h
425-cmd/posix/link.o: shared/arg.h
426-cmd/posix/link.o: shared/compat.h
427-cmd/posix/logger.o: cmd/posix/logger.c
428-cmd/posix/logger.o: shared/util.h
429-cmd/posix/logger.o: shared/arg.h
430-cmd/posix/logger.o: shared/compat.h
431-cmd/posix/logname.o: cmd/posix/logname.c
432-cmd/posix/logname.o: shared/util.h
433-cmd/posix/logname.o: shared/arg.h
434-cmd/posix/logname.o: shared/compat.h
435-cmd/posix/make/defaults.o: cmd/posix/make/defaults.c
436-cmd/posix/make/main.o: cmd/posix/make/main.c
437-cmd/posix/make/main.o: cmd/posix/make/make.h
438-cmd/posix/make/parser.o: cmd/posix/make/parser.c
439-cmd/posix/make/parser.o: cmd/posix/make/make.h
440-cmd/posix/make/posix.o: cmd/posix/make/posix.c
441-cmd/posix/make/posix.o: cmd/posix/make/make.h
442-cmd/posix/make/rules.o: cmd/posix/make/rules.c
443-cmd/posix/make/rules.o: cmd/posix/make/make.h
444-cmd/posix/mesg.o: cmd/posix/mesg.c
445-cmd/posix/mesg.o: shared/util.h
446-cmd/posix/mesg.o: shared/arg.h
447-cmd/posix/mesg.o: shared/compat.h
448-cmd/posix/mkdir.o: cmd/posix/mkdir.c
449-cmd/posix/mkdir.o: shared/util.h
450-cmd/posix/mkdir.o: shared/arg.h
451-cmd/posix/mkdir.o: shared/compat.h
452-cmd/posix/mkfifo.o: cmd/posix/mkfifo.c
453-cmd/posix/mkfifo.o: shared/util.h
454-cmd/posix/mkfifo.o: shared/arg.h
455-cmd/posix/mkfifo.o: shared/compat.h
456-cmd/posix/mv.o: cmd/posix/mv.c
457-cmd/posix/mv.o: shared/fs.h
458-cmd/posix/mv.o: shared/util.h
459-cmd/posix/mv.o: shared/arg.h
460-cmd/posix/mv.o: shared/compat.h
461-cmd/posix/nl.o: cmd/posix/nl.c
462-cmd/posix/nl.o: shared/text.h
463-cmd/posix/nl.o: shared/utf.h
464-cmd/posix/nl.o: shared/util.h
465-cmd/posix/nl.o: shared/arg.h
466-cmd/posix/nl.o: shared/compat.h
467-cmd/posix/od.o: cmd/posix/od.c
468-cmd/posix/od.o: shared/queue.h
469-cmd/posix/od.o: shared/util.h
470-cmd/posix/od.o: shared/arg.h
471-cmd/posix/od.o: shared/compat.h
472-cmd/posix/paste.o: cmd/posix/paste.c
473-cmd/posix/paste.o: shared/utf.h
474-cmd/posix/paste.o: shared/util.h
475-cmd/posix/paste.o: shared/arg.h
476-cmd/posix/paste.o: shared/compat.h
477-cmd/posix/pathchk.o: cmd/posix/pathchk.c
478-cmd/posix/pathchk.o: shared/util.h
479-cmd/posix/pathchk.o: shared/arg.h
480-cmd/posix/pathchk.o: shared/compat.h
481-cmd/posix/pax.o: cmd/posix/pax.c
482-cmd/posix/pax.o: shared/arg.h
483-cmd/posix/ps.o: cmd/posix/ps.c
484-cmd/posix/ps.o: shared/proc.h
485-cmd/posix/ps.o: shared/util.h
486-cmd/posix/ps.o: shared/arg.h
487-cmd/posix/ps.o: shared/compat.h
488-cmd/posix/pwd.o: cmd/posix/pwd.c
489-cmd/posix/pwd.o: shared/util.h
490-cmd/posix/pwd.o: shared/arg.h
491-cmd/posix/pwd.o: shared/compat.h
492-cmd/posix/readlink.o: cmd/posix/readlink.c
493-cmd/posix/readlink.o: shared/util.h
494-cmd/posix/readlink.o: shared/arg.h
495-cmd/posix/readlink.o: shared/compat.h
496-cmd/posix/renice.o: cmd/posix/renice.c
497-cmd/posix/renice.o: shared/util.h
498-cmd/posix/renice.o: shared/arg.h
499-cmd/posix/renice.o: shared/compat.h
500-cmd/posix/rm.o: cmd/posix/rm.c
501-cmd/posix/rm.o: shared/fs.h
502-cmd/posix/rm.o: shared/util.h
503-cmd/posix/rm.o: shared/arg.h
504-cmd/posix/rm.o: shared/compat.h
505-cmd/posix/rmdir.o: cmd/posix/rmdir.c
506-cmd/posix/rmdir.o: shared/util.h
507-cmd/posix/rmdir.o: shared/arg.h
508-cmd/posix/rmdir.o: shared/compat.h
509-cmd/posix/sh/alias.o: cmd/posix/sh/alias.c
510-cmd/posix/sh/alias.o: cmd/posix/sh/shell.h
511-cmd/posix/sh/alias.o: shared/sig.h
512-cmd/posix/sh/alias.o: cmd/posix/sh/output.h
513-cmd/posix/sh/alias.o: cmd/posix/sh/error.h
514-cmd/posix/sh/alias.o: cmd/posix/sh/memalloc.h
515-cmd/posix/sh/alias.o: cmd/posix/sh/mystring.h
516-cmd/posix/sh/alias.o: cmd/posix/sh/alias.h
517-cmd/posix/sh/alias.o: cmd/posix/sh/options.h
518-cmd/posix/sh/alias.o: cmd/posix/sh/builtins.h
519-cmd/posix/sh/arith_yacc.o: cmd/posix/sh/arith_yacc.c
520-cmd/posix/sh/arith_yacc.o: cmd/posix/sh/arith.h
521-cmd/posix/sh/arith_yacc.o: cmd/posix/sh/shell.h
522-cmd/posix/sh/arith_yacc.o: shared/sig.h
523-cmd/posix/sh/arith_yacc.o: cmd/posix/sh/arith_yacc.h
524-cmd/posix/sh/arith_yacc.o: cmd/posix/sh/expand.h
525-cmd/posix/sh/arith_yacc.o: cmd/posix/sh/error.h
526-cmd/posix/sh/arith_yacc.o: cmd/posix/sh/memalloc.h
527-cmd/posix/sh/arith_yacc.o: cmd/posix/sh/output.h
528-cmd/posix/sh/arith_yacc.o: cmd/posix/sh/options.h
529-cmd/posix/sh/arith_yacc.o: cmd/posix/sh/var.h
530-cmd/posix/sh/arith_yylex.o: cmd/posix/sh/arith_yylex.c
531-cmd/posix/sh/arith_yylex.o: cmd/posix/sh/shell.h
532-cmd/posix/sh/arith_yylex.o: shared/sig.h
533-cmd/posix/sh/arith_yylex.o: cmd/posix/sh/arith_yacc.h
534-cmd/posix/sh/arith_yylex.o: cmd/posix/sh/expand.h
535-cmd/posix/sh/arith_yylex.o: cmd/posix/sh/error.h
536-cmd/posix/sh/arith_yylex.o: cmd/posix/sh/memalloc.h
537-cmd/posix/sh/arith_yylex.o: cmd/posix/sh/parser.h
538-cmd/posix/sh/arith_yylex.o: cmd/posix/sh/syntax.h
539-cmd/posix/sh/cd.o: cmd/posix/sh/cd.c
540-cmd/posix/sh/cd.o: cmd/posix/sh/shell.h
541-cmd/posix/sh/cd.o: shared/sig.h
542-cmd/posix/sh/cd.o: cmd/posix/sh/var.h
543-cmd/posix/sh/cd.o: cmd/posix/sh/nodes.h
544-cmd/posix/sh/cd.o: cmd/posix/sh/jobs.h
545-cmd/posix/sh/cd.o: cmd/posix/sh/options.h
546-cmd/posix/sh/cd.o: cmd/posix/sh/output.h
547-cmd/posix/sh/cd.o: cmd/posix/sh/memalloc.h
548-cmd/posix/sh/cd.o: cmd/posix/sh/error.h
549-cmd/posix/sh/cd.o: cmd/posix/sh/exec.h
550-cmd/posix/sh/cd.o: cmd/posix/sh/redir.h
551-cmd/posix/sh/cd.o: cmd/posix/sh/mystring.h
552-cmd/posix/sh/cd.o: cmd/posix/sh/show.h
553-cmd/posix/sh/cd.o: cmd/posix/sh/cd.h
554-cmd/posix/sh/cd.o: cmd/posix/sh/builtins.h
555-cmd/posix/sh/echo.o: cmd/posix/sh/echo.c
556-cmd/posix/sh/echo.o: cmd/posix/sh/bltin.h
557-cmd/posix/sh/echo.o: cmd/posix/sh/shell.h
558-cmd/posix/sh/echo.o: shared/sig.h
559-cmd/posix/sh/echo.o: cmd/posix/sh/mystring.h
560-cmd/posix/sh/error.o: cmd/posix/sh/error.c
561-cmd/posix/sh/error.o: cmd/posix/sh/shell.h
562-cmd/posix/sh/error.o: shared/sig.h
563-cmd/posix/sh/error.o: cmd/posix/sh/eval.h
564-cmd/posix/sh/error.o: cmd/posix/sh/main.h
565-cmd/posix/sh/error.o: cmd/posix/sh/options.h
566-cmd/posix/sh/error.o: cmd/posix/sh/output.h
567-cmd/posix/sh/error.o: cmd/posix/sh/error.h
568-cmd/posix/sh/error.o: cmd/posix/sh/nodes.h
569-cmd/posix/sh/error.o: cmd/posix/sh/show.h
570-cmd/posix/sh/error.o: cmd/posix/sh/trap.h
571-cmd/posix/sh/eval.o: cmd/posix/sh/eval.c
572-cmd/posix/sh/eval.o: cmd/posix/sh/shell.h
573-cmd/posix/sh/eval.o: shared/sig.h
574-cmd/posix/sh/eval.o: cmd/posix/sh/nodes.h
575-cmd/posix/sh/eval.o: cmd/posix/sh/syntax.h
576-cmd/posix/sh/eval.o: cmd/posix/sh/expand.h
577-cmd/posix/sh/eval.o: cmd/posix/sh/parser.h
578-cmd/posix/sh/eval.o: cmd/posix/sh/jobs.h
579-cmd/posix/sh/eval.o: cmd/posix/sh/eval.h
580-cmd/posix/sh/eval.o: cmd/posix/sh/builtins.h
581-cmd/posix/sh/eval.o: cmd/posix/sh/options.h
582-cmd/posix/sh/eval.o: cmd/posix/sh/exec.h
583-cmd/posix/sh/eval.o: cmd/posix/sh/redir.h
584-cmd/posix/sh/eval.o: cmd/posix/sh/input.h
585-cmd/posix/sh/eval.o: cmd/posix/sh/output.h
586-cmd/posix/sh/eval.o: cmd/posix/sh/trap.h
587-cmd/posix/sh/eval.o: cmd/posix/sh/var.h
588-cmd/posix/sh/eval.o: cmd/posix/sh/memalloc.h
589-cmd/posix/sh/eval.o: cmd/posix/sh/error.h
590-cmd/posix/sh/eval.o: cmd/posix/sh/show.h
591-cmd/posix/sh/eval.o: cmd/posix/sh/mystring.h
592-cmd/posix/sh/exec.o: cmd/posix/sh/exec.c
593-cmd/posix/sh/exec.o: cmd/posix/sh/shell.h
594-cmd/posix/sh/exec.o: shared/sig.h
595-cmd/posix/sh/exec.o: cmd/posix/sh/main.h
596-cmd/posix/sh/exec.o: cmd/posix/sh/nodes.h
597-cmd/posix/sh/exec.o: cmd/posix/sh/parser.h
598-cmd/posix/sh/exec.o: cmd/posix/sh/redir.h
599-cmd/posix/sh/exec.o: cmd/posix/sh/eval.h
600-cmd/posix/sh/exec.o: cmd/posix/sh/exec.h
601-cmd/posix/sh/exec.o: cmd/posix/sh/builtins.h
602-cmd/posix/sh/exec.o: cmd/posix/sh/var.h
603-cmd/posix/sh/exec.o: cmd/posix/sh/options.h
604-cmd/posix/sh/exec.o: cmd/posix/sh/input.h
605-cmd/posix/sh/exec.o: cmd/posix/sh/output.h
606-cmd/posix/sh/exec.o: cmd/posix/sh/syntax.h
607-cmd/posix/sh/exec.o: cmd/posix/sh/memalloc.h
608-cmd/posix/sh/exec.o: cmd/posix/sh/error.h
609-cmd/posix/sh/exec.o: cmd/posix/sh/mystring.h
610-cmd/posix/sh/exec.o: cmd/posix/sh/show.h
611-cmd/posix/sh/exec.o: cmd/posix/sh/jobs.h
612-cmd/posix/sh/exec.o: cmd/posix/sh/alias.h
613-cmd/posix/sh/expand.o: cmd/posix/sh/expand.c
614-cmd/posix/sh/expand.o: cmd/posix/sh/shell.h
615-cmd/posix/sh/expand.o: shared/sig.h
616-cmd/posix/sh/expand.o: cmd/posix/sh/main.h
617-cmd/posix/sh/expand.o: cmd/posix/sh/nodes.h
618-cmd/posix/sh/expand.o: cmd/posix/sh/eval.h
619-cmd/posix/sh/expand.o: cmd/posix/sh/expand.h
620-cmd/posix/sh/expand.o: cmd/posix/sh/syntax.h
621-cmd/posix/sh/expand.o: cmd/posix/sh/parser.h
622-cmd/posix/sh/expand.o: cmd/posix/sh/jobs.h
623-cmd/posix/sh/expand.o: cmd/posix/sh/options.h
624-cmd/posix/sh/expand.o: cmd/posix/sh/var.h
625-cmd/posix/sh/expand.o: cmd/posix/sh/input.h
626-cmd/posix/sh/expand.o: cmd/posix/sh/output.h
627-cmd/posix/sh/expand.o: cmd/posix/sh/memalloc.h
628-cmd/posix/sh/expand.o: cmd/posix/sh/error.h
629-cmd/posix/sh/expand.o: cmd/posix/sh/mystring.h
630-cmd/posix/sh/expand.o: cmd/posix/sh/arith.h
631-cmd/posix/sh/expand.o: cmd/posix/sh/show.h
632-cmd/posix/sh/expand.o: cmd/posix/sh/builtins.h
633-cmd/posix/sh/input.o: cmd/posix/sh/input.c
634-cmd/posix/sh/input.o: cmd/posix/sh/shell.h
635-cmd/posix/sh/input.o: shared/sig.h
636-cmd/posix/sh/input.o: cmd/posix/sh/redir.h
637-cmd/posix/sh/input.o: cmd/posix/sh/syntax.h
638-cmd/posix/sh/input.o: cmd/posix/sh/input.h
639-cmd/posix/sh/input.o: cmd/posix/sh/output.h
640-cmd/posix/sh/input.o: cmd/posix/sh/options.h
641-cmd/posix/sh/input.o: cmd/posix/sh/memalloc.h
642-cmd/posix/sh/input.o: cmd/posix/sh/error.h
643-cmd/posix/sh/input.o: cmd/posix/sh/alias.h
644-cmd/posix/sh/input.o: cmd/posix/sh/parser.h
645-cmd/posix/sh/input.o: cmd/posix/sh/trap.h
646-cmd/posix/sh/jobs.o: cmd/posix/sh/jobs.c
647-cmd/posix/sh/jobs.o: cmd/posix/sh/shell.h
648-cmd/posix/sh/jobs.o: shared/sig.h
649-cmd/posix/sh/jobs.o: cmd/posix/sh/redir.h
650-cmd/posix/sh/jobs.o: cmd/posix/sh/exec.h
651-cmd/posix/sh/jobs.o: cmd/posix/sh/show.h
652-cmd/posix/sh/jobs.o: cmd/posix/sh/main.h
653-cmd/posix/sh/jobs.o: cmd/posix/sh/parser.h
654-cmd/posix/sh/jobs.o: cmd/posix/sh/nodes.h
655-cmd/posix/sh/jobs.o: cmd/posix/sh/jobs.h
656-cmd/posix/sh/jobs.o: cmd/posix/sh/options.h
657-cmd/posix/sh/jobs.o: cmd/posix/sh/trap.h
658-cmd/posix/sh/jobs.o: cmd/posix/sh/syntax.h
659-cmd/posix/sh/jobs.o: cmd/posix/sh/input.h
660-cmd/posix/sh/jobs.o: cmd/posix/sh/output.h
661-cmd/posix/sh/jobs.o: cmd/posix/sh/memalloc.h
662-cmd/posix/sh/jobs.o: cmd/posix/sh/error.h
663-cmd/posix/sh/jobs.o: cmd/posix/sh/mystring.h
664-cmd/posix/sh/jobs.o: cmd/posix/sh/var.h
665-cmd/posix/sh/jobs.o: cmd/posix/sh/builtins.h
666-cmd/posix/sh/jobs.o: cmd/posix/sh/eval.h
667-cmd/posix/sh/kill.o: cmd/posix/sh/kill.c
668-cmd/posix/sh/kill.o: shared/sig.h
669-cmd/posix/sh/lineedit.o: cmd/posix/sh/lineedit.c
670-cmd/posix/sh/lineedit.o: shared/util.h
671-cmd/posix/sh/lineedit.o: shared/arg.h
672-cmd/posix/sh/lineedit.o: shared/compat.h
673-cmd/posix/sh/lineedit.o: cmd/posix/sh/shell.h
674-cmd/posix/sh/lineedit.o: shared/sig.h
675-cmd/posix/sh/lineedit.o: cmd/posix/sh/alias.h
676-cmd/posix/sh/lineedit.o: cmd/posix/sh/builtins.h
677-cmd/posix/sh/lineedit.o: cmd/posix/sh/error.h
678-cmd/posix/sh/lineedit.o: cmd/posix/sh/eval.h
679-cmd/posix/sh/lineedit.o: cmd/posix/sh/exec.h
680-cmd/posix/sh/lineedit.o: cmd/posix/sh/main.h
681-cmd/posix/sh/lineedit.o: cmd/posix/sh/memalloc.h
682-cmd/posix/sh/lineedit.o: cmd/posix/sh/mystring.h
683-cmd/posix/sh/lineedit.o: cmd/posix/sh/options.h
684-cmd/posix/sh/lineedit.o: cmd/posix/sh/output.h
685-cmd/posix/sh/lineedit.o: cmd/posix/sh/parser.h
686-cmd/posix/sh/lineedit.o: cmd/posix/sh/var.h
687-cmd/posix/sh/mail.o: cmd/posix/sh/mail.c
688-cmd/posix/sh/mail.o: cmd/posix/sh/shell.h
689-cmd/posix/sh/mail.o: shared/sig.h
690-cmd/posix/sh/mail.o: cmd/posix/sh/mail.h
691-cmd/posix/sh/mail.o: cmd/posix/sh/var.h
692-cmd/posix/sh/mail.o: cmd/posix/sh/output.h
693-cmd/posix/sh/mail.o: cmd/posix/sh/memalloc.h
694-cmd/posix/sh/mail.o: cmd/posix/sh/error.h
695-cmd/posix/sh/main.o: cmd/posix/sh/main.c
696-cmd/posix/sh/main.o: cmd/posix/sh/shell.h
697-cmd/posix/sh/main.o: shared/sig.h
698-cmd/posix/sh/main.o: cmd/posix/sh/main.h
699-cmd/posix/sh/main.o: cmd/posix/sh/mail.h
700-cmd/posix/sh/main.o: cmd/posix/sh/options.h
701-cmd/posix/sh/main.o: cmd/posix/sh/output.h
702-cmd/posix/sh/main.o: cmd/posix/sh/parser.h
703-cmd/posix/sh/main.o: cmd/posix/sh/nodes.h
704-cmd/posix/sh/main.o: cmd/posix/sh/expand.h
705-cmd/posix/sh/main.o: cmd/posix/sh/eval.h
706-cmd/posix/sh/main.o: cmd/posix/sh/jobs.h
707-cmd/posix/sh/main.o: cmd/posix/sh/input.h
708-cmd/posix/sh/main.o: cmd/posix/sh/trap.h
709-cmd/posix/sh/main.o: cmd/posix/sh/var.h
710-cmd/posix/sh/main.o: cmd/posix/sh/show.h
711-cmd/posix/sh/main.o: cmd/posix/sh/memalloc.h
712-cmd/posix/sh/main.o: cmd/posix/sh/error.h
713-cmd/posix/sh/main.o: cmd/posix/sh/mystring.h
714-cmd/posix/sh/main.o: cmd/posix/sh/exec.h
715-cmd/posix/sh/main.o: cmd/posix/sh/cd.h
716-cmd/posix/sh/main.o: cmd/posix/sh/redir.h
717-cmd/posix/sh/main.o: cmd/posix/sh/builtins.h
718-cmd/posix/sh/memalloc.o: cmd/posix/sh/memalloc.c
719-cmd/posix/sh/memalloc.o: cmd/posix/sh/shell.h
720-cmd/posix/sh/memalloc.o: shared/sig.h
721-cmd/posix/sh/memalloc.o: cmd/posix/sh/output.h
722-cmd/posix/sh/memalloc.o: cmd/posix/sh/memalloc.h
723-cmd/posix/sh/memalloc.o: cmd/posix/sh/error.h
724-cmd/posix/sh/memalloc.o: cmd/posix/sh/mystring.h
725-cmd/posix/sh/memalloc.o: cmd/posix/sh/expand.h
726-cmd/posix/sh/miscbltin.o: cmd/posix/sh/miscbltin.c
727-cmd/posix/sh/miscbltin.o: cmd/posix/sh/shell.h
728-cmd/posix/sh/miscbltin.o: shared/sig.h
729-cmd/posix/sh/miscbltin.o: shared/redline.h
730-cmd/posix/sh/miscbltin.o: cmd/posix/sh/options.h
731-cmd/posix/sh/miscbltin.o: cmd/posix/sh/var.h
732-cmd/posix/sh/miscbltin.o: cmd/posix/sh/output.h
733-cmd/posix/sh/miscbltin.o: cmd/posix/sh/memalloc.h
734-cmd/posix/sh/miscbltin.o: cmd/posix/sh/error.h
735-cmd/posix/sh/miscbltin.o: cmd/posix/sh/mystring.h
736-cmd/posix/sh/miscbltin.o: cmd/posix/sh/syntax.h
737-cmd/posix/sh/miscbltin.o: cmd/posix/sh/trap.h
738-cmd/posix/sh/mknodes.o: cmd/posix/sh/mknodes.c
739-cmd/posix/sh/mksyntax.o: cmd/posix/sh/mksyntax.c
740-cmd/posix/sh/mksyntax.o: cmd/posix/sh/parser.h
741-cmd/posix/sh/mystring.o: cmd/posix/sh/mystring.c
742-cmd/posix/sh/mystring.o: cmd/posix/sh/shell.h
743-cmd/posix/sh/mystring.o: shared/sig.h
744-cmd/posix/sh/mystring.o: cmd/posix/sh/syntax.h
745-cmd/posix/sh/mystring.o: cmd/posix/sh/error.h
746-cmd/posix/sh/mystring.o: cmd/posix/sh/mystring.h
747-cmd/posix/sh/options.o: cmd/posix/sh/options.c
748-cmd/posix/sh/options.o: cmd/posix/sh/shell.h
749-cmd/posix/sh/options.o: shared/sig.h
750-cmd/posix/sh/options.o: cmd/posix/sh/options.h
751-cmd/posix/sh/options.o: cmd/posix/sh/nodes.h
752-cmd/posix/sh/options.o: cmd/posix/sh/eval.h
753-cmd/posix/sh/options.o: cmd/posix/sh/jobs.h
754-cmd/posix/sh/options.o: cmd/posix/sh/input.h
755-cmd/posix/sh/options.o: cmd/posix/sh/output.h
756-cmd/posix/sh/options.o: cmd/posix/sh/trap.h
757-cmd/posix/sh/options.o: cmd/posix/sh/var.h
758-cmd/posix/sh/options.o: cmd/posix/sh/memalloc.h
759-cmd/posix/sh/options.o: cmd/posix/sh/error.h
760-cmd/posix/sh/options.o: cmd/posix/sh/mystring.h
761-cmd/posix/sh/options.o: cmd/posix/sh/builtins.h
762-cmd/posix/sh/output.o: cmd/posix/sh/output.c
763-cmd/posix/sh/output.o: cmd/posix/sh/shell.h
764-cmd/posix/sh/output.o: shared/sig.h
765-cmd/posix/sh/output.o: cmd/posix/sh/syntax.h
766-cmd/posix/sh/output.o: cmd/posix/sh/output.h
767-cmd/posix/sh/output.o: cmd/posix/sh/memalloc.h
768-cmd/posix/sh/output.o: cmd/posix/sh/error.h
769-cmd/posix/sh/output.o: cmd/posix/sh/var.h
770-cmd/posix/sh/parser.o: cmd/posix/sh/parser.c
771-cmd/posix/sh/parser.o: cmd/posix/sh/shell.h
772-cmd/posix/sh/parser.o: shared/sig.h
773-cmd/posix/sh/parser.o: cmd/posix/sh/parser.h
774-cmd/posix/sh/parser.o: cmd/posix/sh/nodes.h
775-cmd/posix/sh/parser.o: cmd/posix/sh/expand.h
776-cmd/posix/sh/parser.o: cmd/posix/sh/syntax.h
777-cmd/posix/sh/parser.o: cmd/posix/sh/options.h
778-cmd/posix/sh/parser.o: cmd/posix/sh/input.h
779-cmd/posix/sh/parser.o: cmd/posix/sh/output.h
780-cmd/posix/sh/parser.o: cmd/posix/sh/var.h
781-cmd/posix/sh/parser.o: cmd/posix/sh/error.h
782-cmd/posix/sh/parser.o: cmd/posix/sh/memalloc.h
783-cmd/posix/sh/parser.o: cmd/posix/sh/mystring.h
784-cmd/posix/sh/parser.o: cmd/posix/sh/alias.h
785-cmd/posix/sh/parser.o: cmd/posix/sh/show.h
786-cmd/posix/sh/parser.o: cmd/posix/sh/eval.h
787-cmd/posix/sh/parser.o: cmd/posix/sh/exec.h
788-cmd/posix/sh/parser.o: cmd/posix/sh/main.h
789-cmd/posix/sh/parser.o: cmd/posix/sh/jobs.h
790-cmd/posix/sh/parser.o: cmd/posix/sh/token.h
791-cmd/posix/sh/printf.o: cmd/posix/sh/printf.c
792-cmd/posix/sh/redir.o: cmd/posix/sh/redir.c
793-cmd/posix/sh/redir.o: cmd/posix/sh/shell.h
794-cmd/posix/sh/redir.o: shared/sig.h
795-cmd/posix/sh/redir.o: cmd/posix/sh/nodes.h
796-cmd/posix/sh/redir.o: cmd/posix/sh/jobs.h
797-cmd/posix/sh/redir.o: cmd/posix/sh/expand.h
798-cmd/posix/sh/redir.o: cmd/posix/sh/redir.h
799-cmd/posix/sh/redir.o: cmd/posix/sh/output.h
800-cmd/posix/sh/redir.o: cmd/posix/sh/memalloc.h
801-cmd/posix/sh/redir.o: cmd/posix/sh/error.h
802-cmd/posix/sh/redir.o: cmd/posix/sh/options.h
803-cmd/posix/sh/show.o: cmd/posix/sh/show.c
804-cmd/posix/sh/show.o: cmd/posix/sh/shell.h
805-cmd/posix/sh/show.o: shared/sig.h
806-cmd/posix/sh/show.o: cmd/posix/sh/parser.h
807-cmd/posix/sh/show.o: cmd/posix/sh/nodes.h
808-cmd/posix/sh/show.o: cmd/posix/sh/mystring.h
809-cmd/posix/sh/show.o: cmd/posix/sh/show.h
810-cmd/posix/sh/test.o: cmd/posix/sh/test.c
811-cmd/posix/sh/trap.o: cmd/posix/sh/trap.c
812-cmd/posix/sh/trap.o: cmd/posix/sh/shell.h
813-cmd/posix/sh/trap.o: shared/sig.h
814-cmd/posix/sh/trap.o: cmd/posix/sh/main.h
815-cmd/posix/sh/trap.o: cmd/posix/sh/nodes.h
816-cmd/posix/sh/trap.o: cmd/posix/sh/eval.h
817-cmd/posix/sh/trap.o: cmd/posix/sh/jobs.h
818-cmd/posix/sh/trap.o: cmd/posix/sh/show.h
819-cmd/posix/sh/trap.o: cmd/posix/sh/options.h
820-cmd/posix/sh/trap.o: cmd/posix/sh/syntax.h
821-cmd/posix/sh/trap.o: cmd/posix/sh/output.h
822-cmd/posix/sh/trap.o: cmd/posix/sh/memalloc.h
823-cmd/posix/sh/trap.o: cmd/posix/sh/error.h
824-cmd/posix/sh/trap.o: cmd/posix/sh/trap.h
825-cmd/posix/sh/trap.o: cmd/posix/sh/mystring.h
826-cmd/posix/sh/trap.o: cmd/posix/sh/builtins.h
827-cmd/posix/sh/var.o: cmd/posix/sh/var.c
828-cmd/posix/sh/var.o: cmd/posix/sh/shell.h
829-cmd/posix/sh/var.o: shared/sig.h
830-cmd/posix/sh/var.o: cmd/posix/sh/output.h
831-cmd/posix/sh/var.o: cmd/posix/sh/expand.h
832-cmd/posix/sh/var.o: cmd/posix/sh/nodes.h
833-cmd/posix/sh/var.o: cmd/posix/sh/eval.h
834-cmd/posix/sh/var.o: cmd/posix/sh/exec.h
835-cmd/posix/sh/var.o: cmd/posix/sh/syntax.h
836-cmd/posix/sh/var.o: cmd/posix/sh/options.h
837-cmd/posix/sh/var.o: cmd/posix/sh/mail.h
838-cmd/posix/sh/var.o: cmd/posix/sh/var.h
839-cmd/posix/sh/var.o: cmd/posix/sh/memalloc.h
840-cmd/posix/sh/var.o: cmd/posix/sh/error.h
841-cmd/posix/sh/var.o: cmd/posix/sh/mystring.h
842-cmd/posix/sh/var.o: cmd/posix/sh/parser.h
843-cmd/posix/sh/var.o: cmd/posix/sh/builtins.h
844-cmd/posix/sh/syntax.o: cmd/posix/sh/syntax.c
845-cmd/posix/sh/syntax.o: cmd/posix/sh/parser.h
846-cmd/posix/sh/syntax.o: cmd/posix/sh/shell.h
847-cmd/posix/sh/syntax.o: shared/sig.h
848-cmd/posix/sh/syntax.o: cmd/posix/sh/syntax.h
849-cmd/posix/sh/nodes.o: cmd/posix/sh/nodes.c
850-cmd/posix/sh/nodes.o: cmd/posix/sh/shell.h
851-cmd/posix/sh/nodes.o: shared/sig.h
852-cmd/posix/sh/nodes.o: cmd/posix/sh/nodes.h
853-cmd/posix/sh/nodes.o: cmd/posix/sh/memalloc.h
854-cmd/posix/sh/nodes.o: cmd/posix/sh/mystring.h
855-cmd/posix/sh/builtins.o: cmd/posix/sh/builtins.c
856-cmd/posix/sh/builtins.o: cmd/posix/sh/shell.h
857-cmd/posix/sh/builtins.o: shared/sig.h
858-cmd/posix/sh/builtins.o: cmd/posix/sh/builtins.h
859-cmd/posix/sleep.o: cmd/posix/sleep.c
860-cmd/posix/sleep.o: shared/util.h
861-cmd/posix/sleep.o: shared/arg.h
862-cmd/posix/sleep.o: shared/compat.h
863-cmd/posix/sort.o: cmd/posix/sort.c
864-cmd/posix/sort.o: shared/queue.h
865-cmd/posix/sort.o: shared/text.h
866-cmd/posix/sort.o: shared/utf.h
867-cmd/posix/sort.o: shared/util.h
868-cmd/posix/sort.o: shared/arg.h
869-cmd/posix/sort.o: shared/compat.h
870-cmd/posix/split.o: cmd/posix/split.c
871-cmd/posix/split.o: shared/util.h
872-cmd/posix/split.o: shared/arg.h
873-cmd/posix/split.o: shared/compat.h
874-cmd/posix/tail.o: cmd/posix/tail.c
875-cmd/posix/tail.o: shared/utf.h
876-cmd/posix/tail.o: shared/util.h
877-cmd/posix/tail.o: shared/arg.h
878-cmd/posix/tail.o: shared/compat.h
879-cmd/posix/tee.o: cmd/posix/tee.c
880-cmd/posix/tee.o: shared/util.h
881-cmd/posix/tee.o: shared/arg.h
882-cmd/posix/tee.o: shared/compat.h
883-cmd/posix/test.o: cmd/posix/test.c
884-cmd/posix/test.o: shared/util.h
885-cmd/posix/test.o: shared/arg.h
886-cmd/posix/test.o: shared/compat.h
887-cmd/posix/touch.o: cmd/posix/touch.c
888-cmd/posix/touch.o: shared/util.h
889-cmd/posix/touch.o: shared/arg.h
890-cmd/posix/touch.o: shared/compat.h
891-cmd/posix/true.o: cmd/posix/true.c
892-cmd/posix/tsort.o: cmd/posix/tsort.c
893-cmd/posix/tsort.o: shared/util.h
894-cmd/posix/tsort.o: shared/arg.h
895-cmd/posix/tsort.o: shared/compat.h
896-cmd/posix/tty.o: cmd/posix/tty.c
897-cmd/posix/tty.o: shared/util.h
898-cmd/posix/tty.o: shared/arg.h
899-cmd/posix/tty.o: shared/compat.h
900-cmd/posix/uname.o: cmd/posix/uname.c
901-cmd/posix/uname.o: shared/util.h
902-cmd/posix/uname.o: shared/arg.h
903-cmd/posix/uname.o: shared/compat.h
904-cmd/posix/unexpand.o: cmd/posix/unexpand.c
905-cmd/posix/unexpand.o: shared/utf.h
906-cmd/posix/unexpand.o: shared/util.h
907-cmd/posix/unexpand.o: shared/arg.h
908-cmd/posix/unexpand.o: shared/compat.h
909-cmd/posix/uniq.o: cmd/posix/uniq.c
910-cmd/posix/uniq.o: shared/text.h
911-cmd/posix/uniq.o: shared/util.h
912-cmd/posix/uniq.o: shared/arg.h
913-cmd/posix/uniq.o: shared/compat.h
914-cmd/posix/unlink.o: cmd/posix/unlink.c
915-cmd/posix/unlink.o: shared/util.h
916-cmd/posix/unlink.o: shared/arg.h
917-cmd/posix/unlink.o: shared/compat.h
918-cmd/posix/uudecode.o: cmd/posix/uudecode.c
919-cmd/posix/uudecode.o: shared/util.h
920-cmd/posix/uudecode.o: shared/arg.h
921-cmd/posix/uudecode.o: shared/compat.h
922-cmd/posix/wc.o: cmd/posix/wc.c
923-cmd/posix/wc.o: shared/utf.h
924-cmd/posix/wc.o: shared/util.h
925-cmd/posix/wc.o: shared/arg.h
926-cmd/posix/wc.o: shared/compat.h
927-cmd/posix/who.o: cmd/posix/who.c
928-cmd/posix/who.o: shared/config.h
929-cmd/posix/who.o: shared/util.h
930-cmd/posix/who.o: shared/arg.h
931-cmd/posix/who.o: shared/compat.h
932-cmd/posix/xargs.o: cmd/posix/xargs.c
933-cmd/posix/xargs.o: shared/util.h
934-cmd/posix/xargs.o: shared/arg.h
935-cmd/posix/xargs.o: shared/compat.h
936-cmd/posix/basename.o: cmd/posix/basename.c
937-cmd/posix/basename.o: shared/util.h
938-cmd/posix/basename.o: shared/arg.h
939-cmd/posix/basename.o: shared/compat.h
940-cmd/posix/cut.o: cmd/posix/cut.c
941-cmd/posix/cut.o: shared/text.h
942-cmd/posix/cut.o: shared/utf.h
943-cmd/posix/cut.o: shared/util.h
944-cmd/posix/cut.o: shared/arg.h
945-cmd/posix/cut.o: shared/compat.h
946-cmd/posix/date.o: cmd/posix/date.c
947-cmd/posix/date.o: shared/util.h
948-cmd/posix/date.o: shared/arg.h
949-cmd/posix/date.o: shared/compat.h
950-cmd/posix/diff.o: cmd/posix/diff.c shared/util.h shared/arg.h shared/compat.h
951-cmd/posix/env.o: cmd/posix/env.c
952-cmd/posix/env.o: shared/util.h
953-cmd/posix/env.o: shared/arg.h
954-cmd/posix/env.o: shared/compat.h
955-cmd/posix/find.o: cmd/posix/find.c
956-cmd/posix/find.o: shared/config.h
957-cmd/posix/find.o: shared/util.h
958-cmd/posix/find.o: shared/arg.h
959-cmd/posix/find.o: shared/compat.h
960-cmd/posix/getconf.o: cmd/posix/getconf.c
961-cmd/posix/getconf.o: shared/util.h
962-cmd/posix/getconf.o: shared/arg.h
963-cmd/posix/getconf.o: shared/compat.h
964-cmd/posix/getconf.o: cmd/posix/getconf.h
965-cmd/posix/grep.o: cmd/posix/grep.c
966-cmd/posix/grep.o: shared/config.h
967-cmd/posix/grep.o: shared/queue.h
968-cmd/posix/grep.o: shared/util.h
969-cmd/posix/grep.o: shared/arg.h
970-cmd/posix/grep.o: shared/compat.h
971-cmd/posix/ln.o: cmd/posix/ln.c
972-cmd/posix/ln.o: shared/util.h
973-cmd/posix/ln.o: shared/arg.h
974-cmd/posix/ln.o: shared/compat.h
975-cmd/posix/ls.o: cmd/posix/ls.c
976-cmd/posix/ls.o: shared/utf.h
977-cmd/posix/ls.o: shared/util.h
978-cmd/posix/ls.o: shared/arg.h
979-cmd/posix/ls.o: shared/compat.h
980-cmd/posix/nice.o: cmd/posix/nice.c
981-cmd/posix/nice.o: shared/util.h
982-cmd/posix/nice.o: shared/arg.h
983-cmd/posix/nice.o: shared/compat.h
984-cmd/posix/nohup.o: cmd/posix/nohup.c
985-cmd/posix/nohup.o: shared/util.h
986-cmd/posix/nohup.o: shared/arg.h
987-cmd/posix/nohup.o: shared/compat.h
988-cmd/posix/printf.o: cmd/posix/printf.c
989-cmd/posix/printf.o: shared/utf.h
990-cmd/posix/printf.o: shared/util.h
991-cmd/posix/printf.o: shared/arg.h
992-cmd/posix/printf.o: shared/compat.h
993-cmd/posix/sed.o: cmd/posix/sed.c
994-cmd/posix/sed.o: shared/config.h
995-cmd/posix/sed.o: shared/utf.h
996-cmd/posix/sed.o: shared/util.h
997-cmd/posix/sed.o: shared/arg.h
998-cmd/posix/sed.o: shared/compat.h
999-cmd/posix/time.o: cmd/posix/time.c
1000-cmd/posix/time.o: shared/util.h
1001-cmd/posix/time.o: shared/arg.h
1002-cmd/posix/time.o: shared/compat.h
1003-cmd/posix/tr.o: cmd/posix/tr.c
1004-cmd/posix/tr.o: shared/utf.h
1005-cmd/posix/tr.o: shared/util.h
1006-cmd/posix/tr.o: shared/arg.h
1007-cmd/posix/tr.o: shared/compat.h
1008-cmd/posix/uuencode.o: cmd/posix/uuencode.c
1009-cmd/posix/uuencode.o: shared/util.h
1010-cmd/posix/uuencode.o: shared/arg.h
1011-cmd/posix/uuencode.o: shared/compat.h
1012-cmd/posix/patch.o: cmd/posix/patch.c shared/util.h shared/arg.h shared/compat.h
1013-cmd/posix/diff3.o: cmd/posix/diff3.c shared/util.h shared/arg.h shared/compat.h
1014-cmd/pseudo/mkpasswd.o: cmd/pseudo/mkpasswd.c shared/util.h shared/arg.h shared/compat.h
1015-cmd/pseudo/base64.o: cmd/pseudo/base64.c
1016-cmd/pseudo/base64.o: shared/util.h
1017-cmd/pseudo/base64.o: shared/arg.h
1018-cmd/pseudo/base64.o: shared/compat.h
1019-cmd/pseudo/base64.o: shared/arg.h
1020+cmd/linux/insmod.o: cmd/linux/insmod.c
1021+cmd/linux/insmod.o: shared/util.h
1022+cmd/linux/insmod.o: shared/arg.h
1023+cmd/linux/insmod.o: shared/compat.h
1024 cmd/pseudo/clear.o: cmd/pseudo/clear.c
1025 cmd/pseudo/clear.o: shared/util.h
1026 cmd/pseudo/clear.o: shared/arg.h
1027 cmd/pseudo/clear.o: shared/compat.h
1028-cmd/pseudo/cols.o: cmd/pseudo/cols.c
1029-cmd/pseudo/cols.o: shared/text.h
1030-cmd/pseudo/cols.o: shared/util.h
1031-cmd/pseudo/cols.o: shared/arg.h
1032-cmd/pseudo/cols.o: shared/compat.h
1033-cmd/pseudo/cron.o: cmd/pseudo/cron.c
1034-cmd/pseudo/cron.o: shared/queue.h
1035-cmd/pseudo/cron.o: shared/util.h
1036-cmd/pseudo/cron.o: shared/arg.h
1037-cmd/pseudo/cron.o: shared/compat.h
1038-cmd/pseudo/dmesg.o: cmd/pseudo/dmesg.c
1039-cmd/pseudo/dmesg.o: shared/util.h
1040-cmd/pseudo/dmesg.o: shared/arg.h
1041-cmd/pseudo/dmesg.o: shared/compat.h
1042-cmd/pseudo/fallocate.o: cmd/pseudo/fallocate.c
1043-cmd/pseudo/fallocate.o: shared/util.h
1044-cmd/pseudo/fallocate.o: shared/arg.h
1045-cmd/pseudo/fallocate.o: shared/compat.h
1046-cmd/pseudo/free.o: cmd/pseudo/free.c
1047-cmd/pseudo/free.o: shared/util.h
1048-cmd/pseudo/free.o: shared/arg.h
1049-cmd/pseudo/free.o: shared/compat.h
1050-cmd/pseudo/halt.o: cmd/pseudo/halt.c
1051-cmd/pseudo/halt.o: shared/reboot.h
1052-cmd/pseudo/halt.o: shared/util.h
1053-cmd/pseudo/halt.o: shared/arg.h
1054-cmd/pseudo/halt.o: shared/compat.h
1055-cmd/pseudo/hostname.o: cmd/pseudo/hostname.c
1056-cmd/pseudo/hostname.o: shared/util.h
1057-cmd/pseudo/hostname.o: shared/arg.h
1058-cmd/pseudo/hostname.o: shared/compat.h
1059-cmd/pseudo/killall5.o: cmd/pseudo/killall5.c
1060-cmd/pseudo/killall5.o: shared/proc.h
1061-cmd/pseudo/killall5.o: shared/queue.h
1062-cmd/pseudo/killall5.o: shared/util.h
1063-cmd/pseudo/killall5.o: shared/arg.h
1064-cmd/pseudo/killall5.o: shared/compat.h
1065+cmd/pseudo/yes.o: cmd/pseudo/yes.c
1066+cmd/pseudo/yes.o: shared/util.h
1067+cmd/pseudo/yes.o: shared/arg.h
1068+cmd/pseudo/yes.o: shared/compat.h
1069+cmd/pseudo/sponge.o: cmd/pseudo/sponge.c
1070+cmd/pseudo/sponge.o: shared/util.h
1071+cmd/pseudo/sponge.o: shared/arg.h
1072+cmd/pseudo/sponge.o: shared/compat.h
1073 cmd/pseudo/last.o: cmd/pseudo/last.c
1074 cmd/pseudo/last.o: shared/config.h
1075+cmd/pseudo/last.o: shared/paths.h
1076 cmd/pseudo/last.o: shared/util.h
1077 cmd/pseudo/last.o: shared/arg.h
1078 cmd/pseudo/last.o: shared/compat.h
1079+cmd/pseudo/truncate.o: cmd/pseudo/truncate.c
1080+cmd/pseudo/truncate.o: shared/util.h
1081+cmd/pseudo/truncate.o: shared/arg.h
1082+cmd/pseudo/truncate.o: shared/compat.h
1083+cmd/pseudo/xinstall.o: cmd/pseudo/xinstall.c
1084+cmd/pseudo/xinstall.o: shared/util.h
1085+cmd/pseudo/xinstall.o: shared/arg.h
1086+cmd/pseudo/xinstall.o: shared/compat.h
1087 cmd/pseudo/lastlog.o: cmd/pseudo/lastlog.c
1088 cmd/pseudo/lastlog.o: shared/text.h
1089 cmd/pseudo/lastlog.o: shared/util.h
1090 cmd/pseudo/lastlog.o: shared/arg.h
1091 cmd/pseudo/lastlog.o: shared/compat.h
1092+cmd/pseudo/base64.o: cmd/pseudo/base64.c
1093+cmd/pseudo/base64.o: shared/util.h
1094+cmd/pseudo/base64.o: shared/arg.h
1095+cmd/pseudo/base64.o: shared/compat.h
1096+cmd/pseudo/base64.o: shared/arg.h
1097+cmd/pseudo/sha384sum.o: cmd/pseudo/sha384sum.c
1098+cmd/pseudo/sha384sum.o: shared/crypt.h
1099+cmd/pseudo/sha384sum.o: shared/sha384.h
1100+cmd/pseudo/sha384sum.o: shared/sha512.h
1101+cmd/pseudo/sha384sum.o: shared/util.h
1102+cmd/pseudo/sha384sum.o: shared/arg.h
1103+cmd/pseudo/sha384sum.o: shared/compat.h
1104+cmd/pseudo/getty.o: cmd/pseudo/getty.c
1105+cmd/pseudo/getty.o: shared/config.h
1106+cmd/pseudo/getty.o: shared/paths.h
1107+cmd/pseudo/getty.o: shared/wexec.h
1108+cmd/pseudo/getty.o: shared/util.h
1109+cmd/pseudo/getty.o: shared/arg.h
1110+cmd/pseudo/getty.o: shared/compat.h
1111+cmd/pseudo/flock.o: cmd/pseudo/flock.c
1112+cmd/pseudo/flock.o: shared/wexec.h
1113+cmd/pseudo/flock.o: shared/util.h
1114+cmd/pseudo/flock.o: shared/arg.h
1115+cmd/pseudo/flock.o: shared/compat.h
1116+cmd/pseudo/pwdx.o: cmd/pseudo/pwdx.c
1117+cmd/pseudo/pwdx.o: shared/util.h
1118+cmd/pseudo/pwdx.o: shared/arg.h
1119+cmd/pseudo/pwdx.o: shared/compat.h
1120+cmd/pseudo/sha512sum.o: cmd/pseudo/sha512sum.c
1121+cmd/pseudo/sha512sum.o: shared/crypt.h
1122+cmd/pseudo/sha512sum.o: shared/sha512.h
1123+cmd/pseudo/sha512sum.o: shared/util.h
1124+cmd/pseudo/sha512sum.o: shared/arg.h
1125+cmd/pseudo/sha512sum.o: shared/compat.h
1126+cmd/pseudo/hostname.o: cmd/pseudo/hostname.c
1127+cmd/pseudo/hostname.o: shared/util.h
1128+cmd/pseudo/hostname.o: shared/arg.h
1129+cmd/pseudo/hostname.o: shared/compat.h
1130 cmd/pseudo/login.o: cmd/pseudo/login.c
1131 cmd/pseudo/login.o: shared/config.h
1132+cmd/pseudo/login.o: shared/paths.h
1133 cmd/pseudo/login.o: shared/passwd.h
1134+cmd/pseudo/login.o: shared/wexec.h
1135 cmd/pseudo/login.o: shared/util.h
1136 cmd/pseudo/login.o: shared/arg.h
1137 cmd/pseudo/login.o: shared/compat.h
1138-cmd/pseudo/md5sum.o: cmd/pseudo/md5sum.c
1139-cmd/pseudo/md5sum.o: shared/crypt.h
1140-cmd/pseudo/md5sum.o: shared/md5.h
1141-cmd/pseudo/md5sum.o: shared/util.h
1142-cmd/pseudo/md5sum.o: shared/arg.h
1143-cmd/pseudo/md5sum.o: shared/compat.h
1144-cmd/pseudo/mktemp.o: cmd/pseudo/mktemp.c
1145-cmd/pseudo/mktemp.o: shared/util.h
1146-cmd/pseudo/mktemp.o: shared/arg.h
1147-cmd/pseudo/mktemp.o: shared/compat.h
1148-cmd/pseudo/nologin.o: cmd/pseudo/nologin.c
1149-cmd/pseudo/pagesize.o: cmd/pseudo/pagesize.c
1150-cmd/pseudo/pagesize.o: shared/util.h
1151-cmd/pseudo/pagesize.o: shared/arg.h
1152-cmd/pseudo/pagesize.o: shared/compat.h
1153-cmd/pseudo/pidof.o: cmd/pseudo/pidof.c
1154-cmd/pseudo/pidof.o: shared/proc.h
1155-cmd/pseudo/pidof.o: shared/queue.h
1156-cmd/pseudo/pidof.o: shared/util.h
1157-cmd/pseudo/pidof.o: shared/arg.h
1158-cmd/pseudo/pidof.o: shared/compat.h
1159+cmd/pseudo/chroot.o: cmd/pseudo/chroot.c
1160+cmd/pseudo/chroot.o: shared/wexec.h
1161+cmd/pseudo/chroot.o: shared/util.h
1162+cmd/pseudo/chroot.o: shared/arg.h
1163+cmd/pseudo/chroot.o: shared/compat.h
1164 cmd/pseudo/printenv.o: cmd/pseudo/printenv.c
1165 cmd/pseudo/printenv.o: shared/util.h
1166 cmd/pseudo/printenv.o: shared/arg.h
1167 cmd/pseudo/printenv.o: shared/compat.h
1168-cmd/pseudo/pwdx.o: cmd/pseudo/pwdx.c
1169-cmd/pseudo/pwdx.o: shared/util.h
1170-cmd/pseudo/pwdx.o: shared/arg.h
1171-cmd/pseudo/pwdx.o: shared/compat.h
1172-cmd/pseudo/rev.o: cmd/pseudo/rev.c
1173-cmd/pseudo/rev.o: shared/text.h
1174-cmd/pseudo/rev.o: shared/util.h
1175-cmd/pseudo/rev.o: shared/arg.h
1176-cmd/pseudo/rev.o: shared/compat.h
1177-cmd/pseudo/seq.o: cmd/pseudo/seq.c
1178-cmd/pseudo/seq.o: shared/util.h
1179-cmd/pseudo/seq.o: shared/arg.h
1180-cmd/pseudo/seq.o: shared/compat.h
1181 cmd/pseudo/sha1sum.o: cmd/pseudo/sha1sum.c
1182 cmd/pseudo/sha1sum.o: shared/crypt.h
1183 cmd/pseudo/sha1sum.o: shared/sha1.h
1184 cmd/pseudo/sha1sum.o: shared/util.h
1185 cmd/pseudo/sha1sum.o: shared/arg.h
1186 cmd/pseudo/sha1sum.o: shared/compat.h
1187+cmd/pseudo/sha256sum.o: cmd/pseudo/sha256sum.c
1188+cmd/pseudo/sha256sum.o: shared/crypt.h
1189+cmd/pseudo/sha256sum.o: shared/sha256.h
1190+cmd/pseudo/sha256sum.o: shared/util.h
1191+cmd/pseudo/sha256sum.o: shared/arg.h
1192+cmd/pseudo/sha256sum.o: shared/compat.h
1193+cmd/pseudo/nologin.o: cmd/pseudo/nologin.c
1194+cmd/pseudo/mktemp.o: cmd/pseudo/mktemp.c
1195+cmd/pseudo/mktemp.o: shared/util.h
1196+cmd/pseudo/mktemp.o: shared/arg.h
1197+cmd/pseudo/mktemp.o: shared/compat.h
1198+cmd/pseudo/uptime.o: cmd/pseudo/uptime.c
1199+cmd/pseudo/uptime.o: shared/config.h
1200+cmd/pseudo/uptime.o: shared/paths.h
1201+cmd/pseudo/uptime.o: shared/util.h
1202+cmd/pseudo/uptime.o: shared/arg.h
1203+cmd/pseudo/uptime.o: shared/compat.h
1204 cmd/pseudo/sha224sum.o: cmd/pseudo/sha224sum.c
1205 cmd/pseudo/sha224sum.o: shared/crypt.h
1206 cmd/pseudo/sha224sum.o: shared/sha224.h
1207@@ -1031,26 +246,39 @@ cmd/pseudo/sha224sum.o: shared/sha256.h
1208 cmd/pseudo/sha224sum.o: shared/util.h
1209 cmd/pseudo/sha224sum.o: shared/arg.h
1210 cmd/pseudo/sha224sum.o: shared/compat.h
1211-cmd/pseudo/sha256sum.o: cmd/pseudo/sha256sum.c
1212-cmd/pseudo/sha256sum.o: shared/crypt.h
1213-cmd/pseudo/sha256sum.o: shared/sha256.h
1214-cmd/pseudo/sha256sum.o: shared/util.h
1215-cmd/pseudo/sha256sum.o: shared/arg.h
1216-cmd/pseudo/sha256sum.o: shared/compat.h
1217-cmd/pseudo/sha384sum.o: cmd/pseudo/sha384sum.c
1218-cmd/pseudo/sha384sum.o: shared/crypt.h
1219-cmd/pseudo/sha384sum.o: shared/sha384.h
1220-cmd/pseudo/sha384sum.o: shared/sha512.h
1221-cmd/pseudo/sha384sum.o: shared/util.h
1222-cmd/pseudo/sha384sum.o: shared/arg.h
1223-cmd/pseudo/sha384sum.o: shared/compat.h
1224-cmd/pseudo/sha512-224sum.o: cmd/pseudo/sha512-224sum.c
1225-cmd/pseudo/sha512-224sum.o: shared/crypt.h
1226-cmd/pseudo/sha512-224sum.o: shared/sha512-224.h
1227-cmd/pseudo/sha512-224sum.o: shared/sha512.h
1228-cmd/pseudo/sha512-224sum.o: shared/util.h
1229-cmd/pseudo/sha512-224sum.o: shared/arg.h
1230-cmd/pseudo/sha512-224sum.o: shared/compat.h
1231+cmd/pseudo/halt.o: cmd/pseudo/halt.c
1232+cmd/pseudo/halt.o: shared/reboot.h
1233+cmd/pseudo/halt.o: shared/util.h
1234+cmd/pseudo/halt.o: shared/arg.h
1235+cmd/pseudo/halt.o: shared/compat.h
1236+cmd/pseudo/mkpasswd.o: cmd/pseudo/mkpasswd.c
1237+cmd/pseudo/mkpasswd.o: shared/passwd.h
1238+cmd/pseudo/mkpasswd.o: shared/paths.h
1239+cmd/pseudo/mkpasswd.o: shared/util.h
1240+cmd/pseudo/mkpasswd.o: shared/arg.h
1241+cmd/pseudo/mkpasswd.o: shared/compat.h
1242+cmd/pseudo/setsid.o: cmd/pseudo/setsid.c
1243+cmd/pseudo/setsid.o: shared/wexec.h
1244+cmd/pseudo/setsid.o: shared/util.h
1245+cmd/pseudo/setsid.o: shared/arg.h
1246+cmd/pseudo/setsid.o: shared/compat.h
1247+cmd/pseudo/fallocate.o: cmd/pseudo/fallocate.c
1248+cmd/pseudo/fallocate.o: shared/util.h
1249+cmd/pseudo/fallocate.o: shared/arg.h
1250+cmd/pseudo/fallocate.o: shared/compat.h
1251+cmd/pseudo/seq.o: cmd/pseudo/seq.c
1252+cmd/pseudo/seq.o: shared/util.h
1253+cmd/pseudo/seq.o: shared/arg.h
1254+cmd/pseudo/seq.o: shared/compat.h
1255+cmd/pseudo/cols.o: cmd/pseudo/cols.c
1256+cmd/pseudo/cols.o: shared/text.h
1257+cmd/pseudo/cols.o: shared/util.h
1258+cmd/pseudo/cols.o: shared/arg.h
1259+cmd/pseudo/cols.o: shared/compat.h
1260+cmd/pseudo/whoami.o: cmd/pseudo/whoami.c
1261+cmd/pseudo/whoami.o: shared/util.h
1262+cmd/pseudo/whoami.o: shared/arg.h
1263+cmd/pseudo/whoami.o: shared/compat.h
1264 cmd/pseudo/sha512-256sum.o: cmd/pseudo/sha512-256sum.c
1265 cmd/pseudo/sha512-256sum.o: shared/crypt.h
1266 cmd/pseudo/sha512-256sum.o: shared/sha512-256.h
1267@@ -1058,360 +286,850 @@ cmd/pseudo/sha512-256sum.o: shared/sha512.h
1268 cmd/pseudo/sha512-256sum.o: shared/util.h
1269 cmd/pseudo/sha512-256sum.o: shared/arg.h
1270 cmd/pseudo/sha512-256sum.o: shared/compat.h
1271-cmd/pseudo/sha512sum.o: cmd/pseudo/sha512sum.c
1272-cmd/pseudo/sha512sum.o: shared/crypt.h
1273-cmd/pseudo/sha512sum.o: shared/sha512.h
1274-cmd/pseudo/sha512sum.o: shared/util.h
1275-cmd/pseudo/sha512sum.o: shared/arg.h
1276-cmd/pseudo/sha512sum.o: shared/compat.h
1277-cmd/pseudo/sponge.o: cmd/pseudo/sponge.c
1278-cmd/pseudo/sponge.o: shared/util.h
1279-cmd/pseudo/sponge.o: shared/arg.h
1280-cmd/pseudo/sponge.o: shared/compat.h
1281+cmd/pseudo/pidof.o: cmd/pseudo/pidof.c
1282+cmd/pseudo/pidof.o: shared/proc.h
1283+cmd/pseudo/pidof.o: shared/queue.h
1284+cmd/pseudo/pidof.o: shared/util.h
1285+cmd/pseudo/pidof.o: shared/arg.h
1286+cmd/pseudo/pidof.o: shared/compat.h
1287+cmd/pseudo/pagesize.o: cmd/pseudo/pagesize.c
1288+cmd/pseudo/pagesize.o: shared/util.h
1289+cmd/pseudo/pagesize.o: shared/arg.h
1290+cmd/pseudo/pagesize.o: shared/compat.h
1291+cmd/pseudo/killall5.o: cmd/pseudo/killall5.c
1292+cmd/pseudo/killall5.o: shared/proc.h
1293+cmd/pseudo/killall5.o: shared/queue.h
1294+cmd/pseudo/killall5.o: shared/util.h
1295+cmd/pseudo/killall5.o: shared/arg.h
1296+cmd/pseudo/killall5.o: shared/compat.h
1297+cmd/pseudo/sha512-224sum.o: cmd/pseudo/sha512-224sum.c
1298+cmd/pseudo/sha512-224sum.o: shared/crypt.h
1299+cmd/pseudo/sha512-224sum.o: shared/sha512-224.h
1300+cmd/pseudo/sha512-224sum.o: shared/sha512.h
1301+cmd/pseudo/sha512-224sum.o: shared/util.h
1302+cmd/pseudo/sha512-224sum.o: shared/arg.h
1303+cmd/pseudo/sha512-224sum.o: shared/compat.h
1304 cmd/pseudo/stat.o: cmd/pseudo/stat.c
1305 cmd/pseudo/stat.o: shared/config.h
1306+cmd/pseudo/stat.o: shared/paths.h
1307 cmd/pseudo/stat.o: shared/util.h
1308 cmd/pseudo/stat.o: shared/arg.h
1309 cmd/pseudo/stat.o: shared/compat.h
1310-cmd/pseudo/truncate.o: cmd/pseudo/truncate.c
1311-cmd/pseudo/truncate.o: shared/util.h
1312-cmd/pseudo/truncate.o: shared/arg.h
1313-cmd/pseudo/truncate.o: shared/compat.h
1314-cmd/pseudo/uptime.o: cmd/pseudo/uptime.c
1315-cmd/pseudo/uptime.o: shared/config.h
1316-cmd/pseudo/uptime.o: shared/util.h
1317-cmd/pseudo/uptime.o: shared/arg.h
1318-cmd/pseudo/uptime.o: shared/compat.h
1319-cmd/pseudo/watch.o: cmd/pseudo/watch.c
1320-cmd/pseudo/watch.o: shared/util.h
1321-cmd/pseudo/watch.o: shared/arg.h
1322-cmd/pseudo/watch.o: shared/compat.h
1323+cmd/pseudo/md5sum.o: cmd/pseudo/md5sum.c
1324+cmd/pseudo/md5sum.o: shared/crypt.h
1325+cmd/pseudo/md5sum.o: shared/md5.h
1326+cmd/pseudo/md5sum.o: shared/util.h
1327+cmd/pseudo/md5sum.o: shared/arg.h
1328+cmd/pseudo/md5sum.o: shared/compat.h
1329+cmd/pseudo/cron.o: cmd/pseudo/cron.c
1330+cmd/pseudo/cron.o: shared/queue.h
1331+cmd/pseudo/cron.o: shared/paths.h
1332+cmd/pseudo/cron.o: shared/wexec.h
1333+cmd/pseudo/cron.o: shared/util.h
1334+cmd/pseudo/cron.o: shared/arg.h
1335+cmd/pseudo/cron.o: shared/compat.h
1336 cmd/pseudo/which.o: cmd/pseudo/which.c
1337 cmd/pseudo/which.o: shared/util.h
1338 cmd/pseudo/which.o: shared/arg.h
1339 cmd/pseudo/which.o: shared/compat.h
1340-cmd/pseudo/whoami.o: cmd/pseudo/whoami.c
1341-cmd/pseudo/whoami.o: shared/util.h
1342-cmd/pseudo/whoami.o: shared/arg.h
1343-cmd/pseudo/whoami.o: shared/compat.h
1344-cmd/pseudo/xinstall.o: cmd/pseudo/xinstall.c
1345-cmd/pseudo/xinstall.o: shared/util.h
1346-cmd/pseudo/xinstall.o: shared/arg.h
1347-cmd/pseudo/xinstall.o: shared/compat.h
1348-cmd/pseudo/yes.o: cmd/pseudo/yes.c
1349-cmd/pseudo/yes.o: shared/util.h
1350-cmd/pseudo/yes.o: shared/arg.h
1351-cmd/pseudo/yes.o: shared/compat.h
1352-cmd/pseudo/chroot.o: cmd/pseudo/chroot.c
1353-cmd/pseudo/chroot.o: shared/util.h
1354-cmd/pseudo/chroot.o: shared/arg.h
1355-cmd/pseudo/chroot.o: shared/compat.h
1356-cmd/pseudo/flock.o: cmd/pseudo/flock.c
1357-cmd/pseudo/flock.o: shared/util.h
1358-cmd/pseudo/flock.o: shared/arg.h
1359-cmd/pseudo/flock.o: shared/compat.h
1360-cmd/pseudo/getty.o: cmd/pseudo/getty.c
1361-cmd/pseudo/getty.o: shared/config.h
1362-cmd/pseudo/getty.o: shared/util.h
1363-cmd/pseudo/getty.o: shared/arg.h
1364-cmd/pseudo/getty.o: shared/compat.h
1365 cmd/pseudo/respawn.o: cmd/pseudo/respawn.c
1366+cmd/pseudo/respawn.o: shared/wexec.h
1367 cmd/pseudo/respawn.o: shared/util.h
1368 cmd/pseudo/respawn.o: shared/arg.h
1369 cmd/pseudo/respawn.o: shared/compat.h
1370-cmd/pseudo/setsid.o: cmd/pseudo/setsid.c
1371-cmd/pseudo/setsid.o: shared/util.h
1372-cmd/pseudo/setsid.o: shared/arg.h
1373-cmd/pseudo/setsid.o: shared/compat.h
1374+cmd/pseudo/free.o: cmd/pseudo/free.c
1375+cmd/pseudo/free.o: shared/util.h
1376+cmd/pseudo/free.o: shared/arg.h
1377+cmd/pseudo/free.o: shared/compat.h
1378+cmd/pseudo/watch.o: cmd/pseudo/watch.c
1379+cmd/pseudo/watch.o: shared/wexec.h
1380+cmd/pseudo/watch.o: shared/util.h
1381+cmd/pseudo/watch.o: shared/arg.h
1382+cmd/pseudo/watch.o: shared/compat.h
1383+cmd/pseudo/dmesg.o: cmd/pseudo/dmesg.c
1384+cmd/pseudo/dmesg.o: shared/util.h
1385+cmd/pseudo/dmesg.o: shared/arg.h
1386+cmd/pseudo/dmesg.o: shared/compat.h
1387+cmd/pseudo/rev.o: cmd/pseudo/rev.c
1388+cmd/pseudo/rev.o: shared/text.h
1389+cmd/pseudo/rev.o: shared/util.h
1390+cmd/pseudo/rev.o: shared/arg.h
1391+cmd/pseudo/rev.o: shared/compat.h
1392 cmd/pseudo/tar.o: cmd/pseudo/tar.c
1393 cmd/pseudo/tar.o: shared/config.h
1394+cmd/pseudo/tar.o: shared/paths.h
1395 cmd/pseudo/tar.o: shared/fs.h
1396 cmd/pseudo/tar.o: shared/utf.h
1397+cmd/pseudo/tar.o: shared/wexec.h
1398 cmd/pseudo/tar.o: shared/util.h
1399 cmd/pseudo/tar.o: shared/arg.h
1400 cmd/pseudo/tar.o: shared/compat.h
1401+cmd/posix/true.o: cmd/posix/true.c
1402+cmd/posix/paste.o: cmd/posix/paste.c
1403+cmd/posix/paste.o: shared/utf.h
1404+cmd/posix/paste.o: shared/util.h
1405+cmd/posix/paste.o: shared/arg.h
1406+cmd/posix/paste.o: shared/compat.h
1407+cmd/posix/logger.o: cmd/posix/logger.c
1408+cmd/posix/logger.o: shared/util.h
1409+cmd/posix/logger.o: shared/arg.h
1410+cmd/posix/logger.o: shared/compat.h
1411+cmd/posix/pathchk.o: cmd/posix/pathchk.c
1412+cmd/posix/pathchk.o: shared/util.h
1413+cmd/posix/pathchk.o: shared/arg.h
1414+cmd/posix/pathchk.o: shared/compat.h
1415+cmd/posix/make/main.o: cmd/posix/make/main.c
1416+cmd/posix/make/main.o: cmd/posix/make/make.h
1417+cmd/posix/make/main.o: shared/util.h
1418+cmd/posix/make/main.o: shared/arg.h
1419+cmd/posix/make/main.o: shared/compat.h
1420+cmd/posix/make/main.o: shared/wexec.h
1421+cmd/posix/make/parser.o: cmd/posix/make/parser.c
1422+cmd/posix/make/parser.o: cmd/posix/make/make.h
1423+cmd/posix/make/parser.o: shared/util.h
1424+cmd/posix/make/parser.o: shared/arg.h
1425+cmd/posix/make/parser.o: shared/compat.h
1426+cmd/posix/make/parser.o: shared/wexec.h
1427+cmd/posix/make/posix.o: cmd/posix/make/posix.c
1428+cmd/posix/make/posix.o: cmd/posix/make/make.h
1429+cmd/posix/make/posix.o: shared/util.h
1430+cmd/posix/make/posix.o: shared/arg.h
1431+cmd/posix/make/posix.o: shared/compat.h
1432+cmd/posix/make/posix.o: shared/wexec.h
1433+cmd/posix/make/defaults.o: cmd/posix/make/defaults.c
1434+cmd/posix/make/rules.o: cmd/posix/make/rules.c
1435+cmd/posix/make/rules.o: cmd/posix/make/make.h
1436+cmd/posix/make/rules.o: shared/util.h
1437+cmd/posix/make/rules.o: shared/arg.h
1438+cmd/posix/make/rules.o: shared/compat.h
1439+cmd/posix/make/rules.o: shared/wexec.h
1440+cmd/posix/tty.o: cmd/posix/tty.c
1441+cmd/posix/tty.o: shared/util.h
1442+cmd/posix/tty.o: shared/arg.h
1443+cmd/posix/tty.o: shared/compat.h
1444+cmd/posix/od.o: cmd/posix/od.c
1445+cmd/posix/od.o: shared/queue.h
1446+cmd/posix/od.o: shared/util.h
1447+cmd/posix/od.o: shared/arg.h
1448+cmd/posix/od.o: shared/compat.h
1449+cmd/posix/df.o: cmd/posix/df.c
1450+cmd/posix/df.o: shared/util.h
1451+cmd/posix/df.o: shared/arg.h
1452+cmd/posix/df.o: shared/compat.h
1453+cmd/posix/uudecode.o: cmd/posix/uudecode.c
1454+cmd/posix/uudecode.o: shared/util.h
1455+cmd/posix/uudecode.o: shared/arg.h
1456+cmd/posix/uudecode.o: shared/compat.h
1457+cmd/posix/uuencode.o: cmd/posix/uuencode.c
1458+cmd/posix/uuencode.o: shared/util.h
1459+cmd/posix/uuencode.o: shared/arg.h
1460+cmd/posix/uuencode.o: shared/compat.h
1461+cmd/posix/mv.o: cmd/posix/mv.c
1462+cmd/posix/mv.o: shared/fs.h
1463+cmd/posix/mv.o: shared/util.h
1464+cmd/posix/mv.o: shared/arg.h
1465+cmd/posix/mv.o: shared/compat.h
1466+cmd/posix/sed.o: cmd/posix/sed.c
1467+cmd/posix/sed.o: shared/config.h
1468+cmd/posix/sed.o: shared/paths.h
1469+cmd/posix/sed.o: shared/utf.h
1470+cmd/posix/sed.o: shared/util.h
1471+cmd/posix/sed.o: shared/arg.h
1472+cmd/posix/sed.o: shared/compat.h
1473+cmd/posix/nl.o: cmd/posix/nl.c
1474+cmd/posix/nl.o: shared/text.h
1475+cmd/posix/nl.o: shared/utf.h
1476+cmd/posix/nl.o: shared/util.h
1477+cmd/posix/nl.o: shared/arg.h
1478+cmd/posix/nl.o: shared/compat.h
1479+cmd/posix/mesg.o: cmd/posix/mesg.c
1480+cmd/posix/mesg.o: shared/util.h
1481+cmd/posix/mesg.o: shared/arg.h
1482+cmd/posix/mesg.o: shared/compat.h
1483+cmd/posix/id.o: cmd/posix/id.c
1484+cmd/posix/id.o: shared/util.h
1485+cmd/posix/id.o: shared/arg.h
1486+cmd/posix/id.o: shared/compat.h
1487+cmd/posix/find.o: cmd/posix/find.c
1488+cmd/posix/find.o: shared/config.h
1489+cmd/posix/find.o: shared/paths.h
1490+cmd/posix/find.o: shared/wexec.h
1491+cmd/posix/find.o: shared/util.h
1492+cmd/posix/find.o: shared/arg.h
1493+cmd/posix/find.o: shared/compat.h
1494+cmd/posix/ed.o: cmd/posix/ed.c
1495+cmd/posix/ed.o: shared/wexec.h
1496+cmd/posix/ed.o: shared/util.h
1497+cmd/posix/ed.o: shared/arg.h
1498+cmd/posix/ed.o: shared/compat.h
1499+cmd/posix/echo.o: cmd/posix/echo.c
1500+cmd/posix/echo.o: shared/util.h
1501+cmd/posix/echo.o: shared/arg.h
1502+cmd/posix/echo.o: shared/compat.h
1503+cmd/posix/touch.o: cmd/posix/touch.c
1504+cmd/posix/touch.o: shared/util.h
1505+cmd/posix/touch.o: shared/arg.h
1506+cmd/posix/touch.o: shared/compat.h
1507+cmd/posix/chmod.o: cmd/posix/chmod.c
1508+cmd/posix/chmod.o: shared/fs.h
1509+cmd/posix/chmod.o: shared/util.h
1510+cmd/posix/chmod.o: shared/arg.h
1511+cmd/posix/chmod.o: shared/compat.h
1512+cmd/posix/basename.o: cmd/posix/basename.c
1513+cmd/posix/basename.o: shared/util.h
1514+cmd/posix/basename.o: shared/arg.h
1515+cmd/posix/basename.o: shared/compat.h
1516+cmd/posix/sort.o: cmd/posix/sort.c
1517+cmd/posix/sort.o: shared/queue.h
1518+cmd/posix/sort.o: shared/text.h
1519+cmd/posix/sort.o: shared/utf.h
1520+cmd/posix/sort.o: shared/util.h
1521+cmd/posix/sort.o: shared/arg.h
1522+cmd/posix/sort.o: shared/compat.h
1523+cmd/posix/mkfifo.o: cmd/posix/mkfifo.c
1524+cmd/posix/mkfifo.o: shared/util.h
1525+cmd/posix/mkfifo.o: shared/arg.h
1526+cmd/posix/mkfifo.o: shared/compat.h
1527+cmd/posix/getconf.o: cmd/posix/getconf.c
1528+cmd/posix/getconf.o: shared/util.h
1529+cmd/posix/getconf.o: shared/arg.h
1530+cmd/posix/getconf.o: shared/compat.h
1531+cmd/posix/getconf.o: cmd/posix/getconf.h
1532+cmd/posix/tsort.o: cmd/posix/tsort.c
1533+cmd/posix/tsort.o: shared/util.h
1534+cmd/posix/tsort.o: shared/arg.h
1535+cmd/posix/tsort.o: shared/compat.h
1536+cmd/posix/pax.o: cmd/posix/pax.c
1537+cmd/posix/pax.o: shared/arg.h
1538+cmd/posix/grep.o: cmd/posix/grep.c
1539+cmd/posix/grep.o: shared/config.h
1540+cmd/posix/grep.o: shared/paths.h
1541+cmd/posix/grep.o: shared/queue.h
1542+cmd/posix/grep.o: shared/util.h
1543+cmd/posix/grep.o: shared/arg.h
1544+cmd/posix/grep.o: shared/compat.h
1545+cmd/posix/tr.o: cmd/posix/tr.c
1546+cmd/posix/tr.o: shared/utf.h
1547+cmd/posix/tr.o: shared/util.h
1548+cmd/posix/tr.o: shared/arg.h
1549+cmd/posix/tr.o: shared/compat.h
1550+cmd/posix/cmp.o: cmd/posix/cmp.c
1551+cmd/posix/cmp.o: shared/util.h
1552+cmd/posix/cmp.o: shared/arg.h
1553+cmd/posix/cmp.o: shared/compat.h
1554+cmd/posix/diff.o: cmd/posix/diff.c
1555+cmd/posix/diff.o: shared/paths.h
1556+cmd/posix/diff.o: shared/util.h
1557+cmd/posix/diff.o: shared/arg.h
1558+cmd/posix/diff.o: shared/compat.h
1559+cmd/posix/diff.o: shared/wexec.h
1560+cmd/posix/uniq.o: cmd/posix/uniq.c
1561+cmd/posix/uniq.o: shared/text.h
1562+cmd/posix/uniq.o: shared/util.h
1563+cmd/posix/uniq.o: shared/arg.h
1564+cmd/posix/uniq.o: shared/compat.h
1565+cmd/posix/time.o: cmd/posix/time.c
1566+cmd/posix/time.o: shared/wexec.h
1567+cmd/posix/time.o: shared/util.h
1568+cmd/posix/time.o: shared/arg.h
1569+cmd/posix/time.o: shared/compat.h
1570+cmd/posix/renice.o: cmd/posix/renice.c
1571+cmd/posix/renice.o: shared/util.h
1572+cmd/posix/renice.o: shared/arg.h
1573+cmd/posix/renice.o: shared/compat.h
1574+cmd/posix/nice.o: cmd/posix/nice.c
1575+cmd/posix/nice.o: shared/wexec.h
1576+cmd/posix/nice.o: shared/util.h
1577+cmd/posix/nice.o: shared/arg.h
1578+cmd/posix/nice.o: shared/compat.h
1579+cmd/posix/cal.o: cmd/posix/cal.c
1580+cmd/posix/cal.o: shared/util.h
1581+cmd/posix/cal.o: shared/arg.h
1582+cmd/posix/cal.o: shared/compat.h
1583+cmd/posix/cut.o: cmd/posix/cut.c
1584+cmd/posix/cut.o: shared/text.h
1585+cmd/posix/cut.o: shared/utf.h
1586+cmd/posix/cut.o: shared/util.h
1587+cmd/posix/cut.o: shared/arg.h
1588+cmd/posix/cut.o: shared/compat.h
1589+cmd/posix/comm.o: cmd/posix/comm.c
1590+cmd/posix/comm.o: shared/text.h
1591+cmd/posix/comm.o: shared/util.h
1592+cmd/posix/comm.o: shared/arg.h
1593+cmd/posix/comm.o: shared/compat.h
1594+cmd/posix/env.o: cmd/posix/env.c
1595+cmd/posix/env.o: shared/wexec.h
1596+cmd/posix/env.o: shared/util.h
1597+cmd/posix/env.o: shared/arg.h
1598+cmd/posix/env.o: shared/compat.h
1599+cmd/posix/sleep.o: cmd/posix/sleep.c
1600+cmd/posix/sleep.o: shared/util.h
1601+cmd/posix/sleep.o: shared/arg.h
1602+cmd/posix/sleep.o: shared/compat.h
1603+cmd/posix/cksum.o: cmd/posix/cksum.c
1604+cmd/posix/cksum.o: shared/util.h
1605+cmd/posix/cksum.o: shared/arg.h
1606+cmd/posix/cksum.o: shared/compat.h
1607+cmd/posix/diff3.o: cmd/posix/diff3.c
1608+cmd/posix/diff3.o: shared/config.h
1609+cmd/posix/diff3.o: shared/paths.h
1610+cmd/posix/diff3.o: shared/diffutil.h
1611+cmd/posix/diff3.o: shared/util.h
1612+cmd/posix/diff3.o: shared/arg.h
1613+cmd/posix/diff3.o: shared/compat.h
1614+cmd/posix/link.o: cmd/posix/link.c
1615+cmd/posix/link.o: shared/util.h
1616+cmd/posix/link.o: shared/arg.h
1617+cmd/posix/link.o: shared/compat.h
1618+cmd/posix/kill.o: cmd/posix/kill.c
1619+cmd/posix/kill.o: shared/sig.h
1620+cmd/posix/kill.o: shared/util.h
1621+cmd/posix/kill.o: shared/arg.h
1622+cmd/posix/kill.o: shared/compat.h
1623+cmd/posix/mkdir.o: cmd/posix/mkdir.c
1624+cmd/posix/mkdir.o: shared/util.h
1625+cmd/posix/mkdir.o: shared/arg.h
1626+cmd/posix/mkdir.o: shared/compat.h
1627+cmd/posix/chgrp.o: cmd/posix/chgrp.c
1628+cmd/posix/chgrp.o: shared/fs.h
1629+cmd/posix/chgrp.o: shared/util.h
1630+cmd/posix/chgrp.o: shared/arg.h
1631+cmd/posix/chgrp.o: shared/compat.h
1632+cmd/posix/dirname.o: cmd/posix/dirname.c
1633+cmd/posix/dirname.o: shared/util.h
1634+cmd/posix/dirname.o: shared/arg.h
1635+cmd/posix/dirname.o: shared/compat.h
1636+cmd/posix/date.o: cmd/posix/date.c
1637+cmd/posix/date.o: shared/util.h
1638+cmd/posix/date.o: shared/arg.h
1639+cmd/posix/date.o: shared/compat.h
1640+cmd/posix/expand.o: cmd/posix/expand.c
1641+cmd/posix/expand.o: shared/utf.h
1642+cmd/posix/expand.o: shared/util.h
1643+cmd/posix/expand.o: shared/arg.h
1644+cmd/posix/expand.o: shared/compat.h
1645+cmd/posix/du.o: cmd/posix/du.c
1646+cmd/posix/du.o: shared/fs.h
1647+cmd/posix/du.o: shared/util.h
1648+cmd/posix/du.o: shared/arg.h
1649+cmd/posix/du.o: shared/compat.h
1650+cmd/posix/nohup.o: cmd/posix/nohup.c
1651+cmd/posix/nohup.o: shared/wexec.h
1652+cmd/posix/nohup.o: shared/util.h
1653+cmd/posix/nohup.o: shared/arg.h
1654+cmd/posix/nohup.o: shared/compat.h
1655+cmd/posix/split.o: cmd/posix/split.c
1656+cmd/posix/split.o: shared/util.h
1657+cmd/posix/split.o: shared/arg.h
1658+cmd/posix/split.o: shared/compat.h
1659+cmd/posix/xargs.o: cmd/posix/xargs.c
1660+cmd/posix/xargs.o: shared/wexec.h
1661+cmd/posix/xargs.o: shared/util.h
1662+cmd/posix/xargs.o: shared/arg.h
1663+cmd/posix/xargs.o: shared/compat.h
1664+cmd/posix/tee.o: cmd/posix/tee.c
1665+cmd/posix/tee.o: shared/util.h
1666+cmd/posix/tee.o: shared/arg.h
1667+cmd/posix/tee.o: shared/compat.h
1668+cmd/posix/false.o: cmd/posix/false.c
1669+cmd/posix/ln.o: cmd/posix/ln.c
1670+cmd/posix/ln.o: shared/util.h
1671+cmd/posix/ln.o: shared/arg.h
1672+cmd/posix/ln.o: shared/compat.h
1673+cmd/posix/wc.o: cmd/posix/wc.c
1674+cmd/posix/wc.o: shared/utf.h
1675+cmd/posix/wc.o: shared/util.h
1676+cmd/posix/wc.o: shared/arg.h
1677+cmd/posix/wc.o: shared/compat.h
1678+cmd/posix/logname.o: cmd/posix/logname.c
1679+cmd/posix/logname.o: shared/util.h
1680+cmd/posix/logname.o: shared/arg.h
1681+cmd/posix/logname.o: shared/compat.h
1682+cmd/posix/fold.o: cmd/posix/fold.c
1683+cmd/posix/fold.o: shared/text.h
1684+cmd/posix/fold.o: shared/util.h
1685+cmd/posix/fold.o: shared/arg.h
1686+cmd/posix/fold.o: shared/compat.h
1687+cmd/posix/fold.o: shared/utf.h
1688+cmd/posix/unlink.o: cmd/posix/unlink.c
1689+cmd/posix/unlink.o: shared/util.h
1690+cmd/posix/unlink.o: shared/arg.h
1691+cmd/posix/unlink.o: shared/compat.h
1692+cmd/posix/printf.o: cmd/posix/printf.c
1693+cmd/posix/printf.o: shared/utf.h
1694+cmd/posix/printf.o: shared/util.h
1695+cmd/posix/printf.o: shared/arg.h
1696+cmd/posix/printf.o: shared/compat.h
1697+cmd/posix/head.o: cmd/posix/head.c
1698+cmd/posix/head.o: shared/util.h
1699+cmd/posix/head.o: shared/arg.h
1700+cmd/posix/head.o: shared/compat.h
1701+cmd/posix/patch.o: cmd/posix/patch.c
1702+cmd/posix/patch.o: shared/wexec.h
1703+cmd/posix/patch.o: shared/paths.h
1704+cmd/posix/patch.o: shared/util.h
1705+cmd/posix/patch.o: shared/arg.h
1706+cmd/posix/patch.o: shared/compat.h
1707+cmd/posix/readlink.o: cmd/posix/readlink.c
1708+cmd/posix/readlink.o: shared/util.h
1709+cmd/posix/readlink.o: shared/arg.h
1710+cmd/posix/readlink.o: shared/compat.h
1711+cmd/posix/rmdir.o: cmd/posix/rmdir.c
1712+cmd/posix/rmdir.o: shared/util.h
1713+cmd/posix/rmdir.o: shared/arg.h
1714+cmd/posix/rmdir.o: shared/compat.h
1715+cmd/posix/tail.o: cmd/posix/tail.c
1716+cmd/posix/tail.o: shared/utf.h
1717+cmd/posix/tail.o: shared/util.h
1718+cmd/posix/tail.o: shared/arg.h
1719+cmd/posix/tail.o: shared/compat.h
1720+cmd/posix/who.o: cmd/posix/who.c
1721+cmd/posix/who.o: shared/config.h
1722+cmd/posix/who.o: shared/paths.h
1723+cmd/posix/who.o: shared/util.h
1724+cmd/posix/who.o: shared/arg.h
1725+cmd/posix/who.o: shared/compat.h
1726+cmd/posix/cat.o: cmd/posix/cat.c
1727+cmd/posix/cat.o: shared/util.h
1728+cmd/posix/cat.o: shared/arg.h
1729+cmd/posix/cat.o: shared/compat.h
1730+cmd/posix/ls.o: cmd/posix/ls.c
1731+cmd/posix/ls.o: shared/utf.h
1732+cmd/posix/ls.o: shared/util.h
1733+cmd/posix/ls.o: shared/arg.h
1734+cmd/posix/ls.o: shared/compat.h
1735+cmd/posix/cp.o: cmd/posix/cp.c
1736+cmd/posix/cp.o: shared/fs.h
1737+cmd/posix/cp.o: shared/util.h
1738+cmd/posix/cp.o: shared/arg.h
1739+cmd/posix/cp.o: shared/compat.h
1740+cmd/posix/chown.o: cmd/posix/chown.c
1741+cmd/posix/chown.o: shared/fs.h
1742+cmd/posix/chown.o: shared/util.h
1743+cmd/posix/chown.o: shared/arg.h
1744+cmd/posix/chown.o: shared/compat.h
1745+cmd/posix/ps.o: cmd/posix/ps.c
1746+cmd/posix/ps.o: shared/proc.h
1747+cmd/posix/ps.o: shared/util.h
1748+cmd/posix/ps.o: shared/arg.h
1749+cmd/posix/ps.o: shared/compat.h
1750+cmd/posix/unexpand.o: cmd/posix/unexpand.c
1751+cmd/posix/unexpand.o: shared/utf.h
1752+cmd/posix/unexpand.o: shared/util.h
1753+cmd/posix/unexpand.o: shared/arg.h
1754+cmd/posix/unexpand.o: shared/compat.h
1755+cmd/posix/test.o: cmd/posix/test.c
1756+cmd/posix/test.o: shared/util.h
1757+cmd/posix/test.o: shared/arg.h
1758+cmd/posix/test.o: shared/compat.h
1759+cmd/posix/rm.o: cmd/posix/rm.c
1760+cmd/posix/rm.o: shared/fs.h
1761+cmd/posix/rm.o: shared/util.h
1762+cmd/posix/rm.o: shared/arg.h
1763+cmd/posix/rm.o: shared/compat.h
1764+cmd/posix/uname.o: cmd/posix/uname.c
1765+cmd/posix/uname.o: shared/util.h
1766+cmd/posix/uname.o: shared/arg.h
1767+cmd/posix/uname.o: shared/compat.h
1768+cmd/posix/join.o: cmd/posix/join.c
1769+cmd/posix/join.o: shared/text.h
1770+cmd/posix/join.o: shared/utf.h
1771+cmd/posix/join.o: shared/util.h
1772+cmd/posix/join.o: shared/arg.h
1773+cmd/posix/join.o: shared/compat.h
1774+cmd/posix/dd.o: cmd/posix/dd.c
1775+cmd/posix/dd.o: shared/util.h
1776+cmd/posix/dd.o: shared/arg.h
1777+cmd/posix/dd.o: shared/compat.h
1778+cmd/posix/expr.o: cmd/posix/expr.c
1779+cmd/posix/expr.o: shared/utf.h
1780+cmd/posix/expr.o: shared/util.h
1781+cmd/posix/expr.o: shared/arg.h
1782+cmd/posix/expr.o: shared/compat.h
1783+cmd/posix/pwd.o: cmd/posix/pwd.c
1784+cmd/posix/pwd.o: shared/util.h
1785+cmd/posix/pwd.o: shared/arg.h
1786+cmd/posix/pwd.o: shared/compat.h
1787+cmd/extra/blkid.o: cmd/extra/blkid.c
1788+cmd/extra/blkid.o: shared/util.h
1789+cmd/extra/blkid.o: shared/arg.h
1790+cmd/extra/blkid.o: shared/compat.h
1791+cmd/extra/blkid.o: shared/diskutil.h
1792+cmd/extra/blkid.o: shared/paths.h
1793+cmd/extra/b3sum.o: cmd/extra/b3sum.c
1794+cmd/extra/b3sum.o: shared/util.h
1795+cmd/extra/b3sum.o: shared/arg.h
1796+cmd/extra/b3sum.o: shared/compat.h
1797+cmd/extra/b3sum.o: shared/arg.h
1798+cmd/extra/sync.o: cmd/extra/sync.c
1799+cmd/extra/sync.o: shared/arg.h
1800+cmd/extra/sync.o: shared/util.h
1801+cmd/extra/sync.o: shared/arg.h
1802+cmd/extra/sync.o: shared/compat.h
1803+cmd/extra/fdisk.o: cmd/extra/fdisk.c
1804+cmd/extra/fdisk.o: shared/util.h
1805+cmd/extra/fdisk.o: shared/arg.h
1806+cmd/extra/fdisk.o: shared/compat.h
1807+cmd/extra/fdisk.o: shared/diskutil.h
1808+cmd/extra/fdisk.o: shared/paths.h
1809+cmd/extra/lsblk.o: cmd/extra/lsblk.c
1810+cmd/extra/lsblk.o: shared/util.h
1811+cmd/extra/lsblk.o: shared/arg.h
1812+cmd/extra/lsblk.o: shared/compat.h
1813+cmd/extra/lsblk.o: shared/diskutil.h
1814+cmd/extra/lsblk.o: shared/paths.h
1815 cmd/xsi/mknod.o: cmd/xsi/mknod.c
1816 cmd/xsi/mknod.o: shared/util.h
1817 cmd/xsi/mknod.o: shared/arg.h
1818 cmd/xsi/mknod.o: shared/compat.h
1819+cmd/xsi/su.o: cmd/xsi/su.c
1820+cmd/xsi/su.o: shared/config.h
1821+cmd/xsi/su.o: shared/paths.h
1822+cmd/xsi/su.o: shared/passwd.h
1823+cmd/xsi/su.o: shared/util.h
1824+cmd/xsi/su.o: shared/arg.h
1825+cmd/xsi/su.o: shared/compat.h
1826 cmd/xsi/passwd.o: cmd/xsi/passwd.c
1827 cmd/xsi/passwd.o: shared/config.h
1828+cmd/xsi/passwd.o: shared/paths.h
1829 cmd/xsi/passwd.o: shared/passwd.h
1830 cmd/xsi/passwd.o: shared/text.h
1831 cmd/xsi/passwd.o: shared/util.h
1832 cmd/xsi/passwd.o: shared/arg.h
1833 cmd/xsi/passwd.o: shared/compat.h
1834-cmd/xsi/su.o: cmd/xsi/su.c
1835-cmd/xsi/su.o: shared/passwd.h
1836-cmd/xsi/su.o: shared/util.h
1837-cmd/xsi/su.o: shared/arg.h
1838-cmd/xsi/su.o: shared/compat.h
1839-shared/libredline/redline.o: shared/libredline/redline.c
1840-shared/libredline/redline.o: shared/redline.h
1841-shared/libutf/fgetrune.o: shared/libutf/fgetrune.c
1842-shared/libutf/fgetrune.o: shared/libutf/../utf.h
1843-shared/libutf/fputrune.o: shared/libutf/fputrune.c
1844-shared/libutf/fputrune.o: shared/libutf/../utf.h
1845-shared/libutf/isalnumrune.o: shared/libutf/isalnumrune.c
1846-shared/libutf/isalnumrune.o: shared/libutf/../utf.h
1847-shared/libutf/isalnumrune.o: shared/libutf/runetype.h
1848-shared/libutf/isalpharune.o: shared/libutf/isalpharune.c
1849-shared/libutf/isalpharune.o: shared/libutf/../utf.h
1850-shared/libutf/isalpharune.o: shared/libutf/runetype.h
1851-shared/libutf/isblankrune.o: shared/libutf/isblankrune.c
1852-shared/libutf/isblankrune.o: shared/libutf/../utf.h
1853-shared/libutf/isblankrune.o: shared/libutf/runetype.h
1854-shared/libutf/iscntrlrune.o: shared/libutf/iscntrlrune.c
1855-shared/libutf/iscntrlrune.o: shared/libutf/../utf.h
1856-shared/libutf/iscntrlrune.o: shared/libutf/runetype.h
1857-shared/libutf/isdigitrune.o: shared/libutf/isdigitrune.c
1858-shared/libutf/isdigitrune.o: shared/libutf/../utf.h
1859-shared/libutf/isdigitrune.o: shared/libutf/runetype.h
1860-shared/libutf/isgraphrune.o: shared/libutf/isgraphrune.c
1861-shared/libutf/isgraphrune.o: shared/libutf/../utf.h
1862-shared/libutf/isgraphrune.o: shared/libutf/runetype.h
1863-shared/libutf/isprintrune.o: shared/libutf/isprintrune.c
1864-shared/libutf/isprintrune.o: shared/libutf/../utf.h
1865-shared/libutf/isprintrune.o: shared/libutf/runetype.h
1866-shared/libutf/ispunctrune.o: shared/libutf/ispunctrune.c
1867-shared/libutf/ispunctrune.o: shared/libutf/../utf.h
1868-shared/libutf/ispunctrune.o: shared/libutf/runetype.h
1869-shared/libutf/isspacerune.o: shared/libutf/isspacerune.c
1870-shared/libutf/isspacerune.o: shared/libutf/../utf.h
1871-shared/libutf/isspacerune.o: shared/libutf/runetype.h
1872-shared/libutf/istitlerune.o: shared/libutf/istitlerune.c
1873-shared/libutf/istitlerune.o: shared/libutf/../utf.h
1874-shared/libutf/istitlerune.o: shared/libutf/runetype.h
1875-shared/libutf/isxdigitrune.o: shared/libutf/isxdigitrune.c
1876-shared/libutf/isxdigitrune.o: shared/libutf/../utf.h
1877-shared/libutf/isxdigitrune.o: shared/libutf/runetype.h
1878-shared/libutf/lowerrune.o: shared/libutf/lowerrune.c
1879-shared/libutf/lowerrune.o: shared/libutf/../utf.h
1880-shared/libutf/lowerrune.o: shared/libutf/runetype.h
1881-shared/libutf/rune.o: shared/libutf/rune.c
1882-shared/libutf/rune.o: shared/libutf/../utf.h
1883-shared/libutf/runetype.o: shared/libutf/runetype.c
1884-shared/libutf/runetype.o: shared/libutf/../utf.h
1885-shared/libutf/upperrune.o: shared/libutf/upperrune.c
1886-shared/libutf/upperrune.o: shared/libutf/../utf.h
1887-shared/libutf/upperrune.o: shared/libutf/runetype.h
1888-shared/libutf/utf.o: shared/libutf/utf.c
1889-shared/libutf/utf.o: shared/libutf/../utf.h
1890-shared/libutf/utftorunestr.o: shared/libutf/utftorunestr.c
1891-shared/libutf/utftorunestr.o: shared/libutf/../utf.h
1892-shared/libutil/agetcwd.o: shared/libutil/agetcwd.c
1893-shared/libutil/agetcwd.o: shared/libutil/../util.h
1894-shared/libutil/agetcwd.o: shared/libutil/../arg.h
1895-shared/libutil/agetcwd.o: shared/libutil/../compat.h
1896-shared/libutil/agetline.o: shared/libutil/agetline.c
1897-shared/libutil/agetline.o: shared/libutil/../text.h
1898-shared/libutil/agetline.o: shared/libutil/../util.h
1899-shared/libutil/agetline.o: shared/libutil/../arg.h
1900-shared/libutil/agetline.o: shared/libutil/../compat.h
1901+cmd/net/tftp.o: cmd/net/tftp.c
1902+cmd/net/tftp.o: shared/util.h
1903+cmd/net/tftp.o: shared/arg.h
1904+cmd/net/tftp.o: shared/compat.h
1905+cmd/net/httpd.o: cmd/net/httpd.c
1906+cmd/net/httpd.o: shared/util.h
1907+cmd/net/httpd.o: shared/arg.h
1908+cmd/net/httpd.o: shared/compat.h
1909+cmd/net/httpd.o: shared/arg.h
1910+cmd/net/host.o: cmd/net/host.c
1911+cmd/net/host.o: shared/util.h
1912+cmd/net/host.o: shared/arg.h
1913+cmd/net/host.o: shared/compat.h
1914+cmd/net/host.o: shared/arg.h
1915+cmd/net/ping.o: cmd/net/ping.c
1916+cmd/net/ping.o: shared/util.h
1917+cmd/net/ping.o: shared/arg.h
1918+cmd/net/ping.o: shared/compat.h
1919+cmd/net/ping.o: shared/arg.h
1920+cmd/net/ip.o: cmd/net/ip.c
1921+cmd/net/ip.o: shared/util.h
1922+cmd/net/ip.o: shared/arg.h
1923+cmd/net/ip.o: shared/compat.h
1924+cmd/net/wget.o: cmd/net/wget.c
1925+cmd/net/wget.o: shared/util.h
1926+cmd/net/wget.o: shared/arg.h
1927+cmd/net/wget.o: shared/compat.h
1928+cmd/net/wget.o: shared/arg.h
1929+cmd/net/wget.o: shared/tls.h
1930+cmd/net/sdhcp.o: cmd/net/sdhcp.c
1931+cmd/net/sdhcp.o: shared/arg.h
1932+cmd/net/sdhcp.o: shared/wexec.h
1933+cmd/net/sdhcp.o: shared/util.h
1934+cmd/net/sdhcp.o: shared/arg.h
1935+cmd/net/sdhcp.o: shared/compat.h
1936+cmd/net/netcat.o: cmd/net/netcat.c
1937+cmd/net/netcat.o: shared/util.h
1938+cmd/net/netcat.o: shared/arg.h
1939+cmd/net/netcat.o: shared/compat.h
1940+cmd/net/ifconfig.o: cmd/net/ifconfig.c
1941+cmd/net/ifconfig.o: shared/util.h
1942+cmd/net/ifconfig.o: shared/arg.h
1943+cmd/net/ifconfig.o: shared/compat.h
1944+shared/libutil/memmem.o: shared/libutil/memmem.c
1945+shared/libutil/memmem.o: shared/libutil/../util.h
1946+shared/libutil/memmem.o: shared/libutil/../arg.h
1947+shared/libutil/memmem.o: shared/libutil/../compat.h
1948+shared/libutil/estrtoul.o: shared/libutil/estrtoul.c
1949+shared/libutil/estrtoul.o: shared/libutil/../util.h
1950+shared/libutil/estrtoul.o: shared/libutil/../arg.h
1951+shared/libutil/estrtoul.o: shared/libutil/../compat.h
1952+shared/libutil/proc.o: shared/libutil/proc.c
1953+shared/libutil/proc.o: shared/libutil/../proc.h
1954+shared/libutil/proc.o: shared/libutil/../paths.h
1955+shared/libutil/proc.o: shared/libutil/../util.h
1956+shared/libutil/proc.o: shared/libutil/../arg.h
1957+shared/libutil/proc.o: shared/libutil/../compat.h
1958+shared/libutil/estrtod.o: shared/libutil/estrtod.c
1959+shared/libutil/estrtod.o: shared/libutil/../util.h
1960+shared/libutil/estrtod.o: shared/libutil/../arg.h
1961+shared/libutil/estrtod.o: shared/libutil/../compat.h
1962+shared/libutil/tty.o: shared/libutil/tty.c
1963+shared/libutil/tty.o: shared/libutil/../paths.h
1964+shared/libutil/tty.o: shared/libutil/../util.h
1965+shared/libutil/tty.o: shared/libutil/../arg.h
1966+shared/libutil/tty.o: shared/libutil/../compat.h
1967+shared/libutil/getlines.o: shared/libutil/getlines.c
1968+shared/libutil/getlines.o: shared/libutil/../text.h
1969+shared/libutil/getlines.o: shared/libutil/../util.h
1970+shared/libutil/getlines.o: shared/libutil/../arg.h
1971+shared/libutil/getlines.o: shared/libutil/../compat.h
1972+shared/libutil/eregcomp.o: shared/libutil/eregcomp.c
1973+shared/libutil/eregcomp.o: shared/libutil/../util.h
1974+shared/libutil/eregcomp.o: shared/libutil/../arg.h
1975+shared/libutil/eregcomp.o: shared/libutil/../compat.h
1976+shared/libutil/strlcat.o: shared/libutil/strlcat.c
1977+shared/libutil/strlcat.o: shared/libutil/../util.h
1978+shared/libutil/strlcat.o: shared/libutil/../arg.h
1979+shared/libutil/strlcat.o: shared/libutil/../compat.h
1980+shared/libutil/unescape.o: shared/libutil/unescape.c
1981+shared/libutil/unescape.o: shared/libutil/../util.h
1982+shared/libutil/unescape.o: shared/libutil/../arg.h
1983+shared/libutil/unescape.o: shared/libutil/../compat.h
1984+shared/libutil/strtonum.o: shared/libutil/strtonum.c
1985+shared/libutil/strtonum.o: shared/libutil/../util.h
1986+shared/libutil/strtonum.o: shared/libutil/../arg.h
1987+shared/libutil/strtonum.o: shared/libutil/../compat.h
1988+shared/libutil/sig.o: shared/libutil/sig.c
1989+shared/libutil/sig.o: shared/libutil/../sig.h
1990 shared/libutil/apathmax.o: shared/libutil/apathmax.c
1991 shared/libutil/apathmax.o: shared/libutil/../util.h
1992 shared/libutil/apathmax.o: shared/libutil/../arg.h
1993 shared/libutil/apathmax.o: shared/libutil/../compat.h
1994-shared/libutil/concat.o: shared/libutil/concat.c
1995-shared/libutil/concat.o: shared/libutil/../util.h
1996-shared/libutil/concat.o: shared/libutil/../arg.h
1997-shared/libutil/concat.o: shared/libutil/../compat.h
1998-shared/libutil/confirm.o: shared/libutil/confirm.c
1999-shared/libutil/confirm.o: shared/libutil/../util.h
2000-shared/libutil/confirm.o: shared/libutil/../arg.h
2001-shared/libutil/confirm.o: shared/libutil/../compat.h
2002-shared/libutil/cp.o: shared/libutil/cp.c
2003-shared/libutil/cp.o: shared/libutil/../fs.h
2004-shared/libutil/cp.o: shared/libutil/../util.h
2005-shared/libutil/cp.o: shared/libutil/../arg.h
2006-shared/libutil/cp.o: shared/libutil/../compat.h
2007-shared/libutil/crypt.o: shared/libutil/crypt.c
2008-shared/libutil/crypt.o: shared/libutil/../crypt.h
2009-shared/libutil/crypt.o: shared/libutil/../text.h
2010-shared/libutil/crypt.o: shared/libutil/../util.h
2011-shared/libutil/crypt.o: shared/libutil/../arg.h
2012-shared/libutil/crypt.o: shared/libutil/../compat.h
2013+shared/libutil/strnsubst.o: shared/libutil/strnsubst.c
2014+shared/libutil/strnsubst.o: shared/libutil/../util.h
2015+shared/libutil/strnsubst.o: shared/libutil/../arg.h
2016+shared/libutil/strnsubst.o: shared/libutil/../compat.h
2017 shared/libutil/diskutil.o: shared/libutil/diskutil.c
2018 shared/libutil/diskutil.o: shared/libutil/../diskutil.h
2019+shared/libutil/diskutil.o: shared/libutil/../paths.h
2020 shared/libutil/diskutil.o: shared/libutil/../util.h
2021 shared/libutil/diskutil.o: shared/libutil/../arg.h
2022 shared/libutil/diskutil.o: shared/libutil/../compat.h
2023-shared/libutil/ealloc.o: shared/libutil/ealloc.c
2024-shared/libutil/ealloc.o: shared/libutil/../util.h
2025-shared/libutil/ealloc.o: shared/libutil/../arg.h
2026-shared/libutil/ealloc.o: shared/libutil/../compat.h
2027-shared/libutil/enmasse.o: shared/libutil/enmasse.c
2028-shared/libutil/enmasse.o: shared/libutil/../util.h
2029-shared/libutil/enmasse.o: shared/libutil/../arg.h
2030-shared/libutil/enmasse.o: shared/libutil/../compat.h
2031-shared/libutil/eprintf.o: shared/libutil/eprintf.c
2032-shared/libutil/eprintf.o: shared/libutil/../util.h
2033-shared/libutil/eprintf.o: shared/libutil/../arg.h
2034-shared/libutil/eprintf.o: shared/libutil/../compat.h
2035-shared/libutil/eregcomp.o: shared/libutil/eregcomp.c
2036-shared/libutil/eregcomp.o: shared/libutil/../util.h
2037-shared/libutil/eregcomp.o: shared/libutil/../arg.h
2038-shared/libutil/eregcomp.o: shared/libutil/../compat.h
2039-shared/libutil/estrtod.o: shared/libutil/estrtod.c
2040-shared/libutil/estrtod.o: shared/libutil/../util.h
2041-shared/libutil/estrtod.o: shared/libutil/../arg.h
2042-shared/libutil/estrtod.o: shared/libutil/../compat.h
2043-shared/libutil/estrtol.o: shared/libutil/estrtol.c
2044-shared/libutil/estrtol.o: shared/libutil/../util.h
2045-shared/libutil/estrtol.o: shared/libutil/../arg.h
2046-shared/libutil/estrtol.o: shared/libutil/../compat.h
2047-shared/libutil/estrtoul.o: shared/libutil/estrtoul.c
2048-shared/libutil/estrtoul.o: shared/libutil/../util.h
2049-shared/libutil/estrtoul.o: shared/libutil/../arg.h
2050-shared/libutil/estrtoul.o: shared/libutil/../compat.h
2051+shared/libutil/confirm.o: shared/libutil/confirm.c
2052+shared/libutil/confirm.o: shared/libutil/../util.h
2053+shared/libutil/confirm.o: shared/libutil/../arg.h
2054+shared/libutil/confirm.o: shared/libutil/../compat.h
2055 shared/libutil/explicit_bzero.o: shared/libutil/explicit_bzero.c
2056 shared/libutil/explicit_bzero.o: shared/libutil/../util.h
2057-shared/libutil/explicit_bzero.o: shared/libutil/../arg.h
2058-shared/libutil/explicit_bzero.o: shared/libutil/../compat.h
2059-shared/libutil/fconcat.o: shared/libutil/fconcat.c
2060-shared/libutil/fconcat.o: shared/libutil/../text.h
2061-shared/libutil/fconcat.o: shared/libutil/../util.h
2062-shared/libutil/fconcat.o: shared/libutil/../arg.h
2063-shared/libutil/fconcat.o: shared/libutil/../compat.h
2064-shared/libutil/fnck.o: shared/libutil/fnck.c
2065-shared/libutil/fnck.o: shared/libutil/../util.h
2066-shared/libutil/fnck.o: shared/libutil/../arg.h
2067-shared/libutil/fnck.o: shared/libutil/../compat.h
2068-shared/libutil/fshut.o: shared/libutil/fshut.c
2069-shared/libutil/fshut.o: shared/libutil/../util.h
2070-shared/libutil/fshut.o: shared/libutil/../arg.h
2071-shared/libutil/fshut.o: shared/libutil/../compat.h
2072-shared/libutil/getlines.o: shared/libutil/getlines.c
2073-shared/libutil/getlines.o: shared/libutil/../text.h
2074-shared/libutil/getlines.o: shared/libutil/../util.h
2075-shared/libutil/getlines.o: shared/libutil/../arg.h
2076-shared/libutil/getlines.o: shared/libutil/../compat.h
2077-shared/libutil/human.o: shared/libutil/human.c
2078-shared/libutil/human.o: shared/libutil/../util.h
2079-shared/libutil/human.o: shared/libutil/../arg.h
2080-shared/libutil/human.o: shared/libutil/../compat.h
2081-shared/libutil/linecmp.o: shared/libutil/linecmp.c
2082-shared/libutil/linecmp.o: shared/libutil/../text.h
2083-shared/libutil/linecmp.o: shared/libutil/../util.h
2084-shared/libutil/linecmp.o: shared/libutil/../arg.h
2085-shared/libutil/linecmp.o: shared/libutil/../compat.h
2086-shared/libutil/md5.o: shared/libutil/md5.c
2087-shared/libutil/md5.o: shared/libutil/../md5.h
2088-shared/libutil/memmem.o: shared/libutil/memmem.c
2089-shared/libutil/memmem.o: shared/libutil/../util.h
2090-shared/libutil/memmem.o: shared/libutil/../arg.h
2091-shared/libutil/memmem.o: shared/libutil/../compat.h
2092-shared/libutil/mkdirp.o: shared/libutil/mkdirp.c
2093-shared/libutil/mkdirp.o: shared/libutil/../util.h
2094-shared/libutil/mkdirp.o: shared/libutil/../arg.h
2095-shared/libutil/mkdirp.o: shared/libutil/../compat.h
2096+shared/libutil/explicit_bzero.o: shared/libutil/../arg.h
2097+shared/libutil/explicit_bzero.o: shared/libutil/../compat.h
2098+shared/libutil/sha224.o: shared/libutil/sha224.c
2099+shared/libutil/sha224.o: shared/libutil/../sha224.h
2100+shared/libutil/sha224.o: shared/libutil/../sha256.h
2101+shared/libutil/estrtol.o: shared/libutil/estrtol.c
2102+shared/libutil/estrtol.o: shared/libutil/../util.h
2103+shared/libutil/estrtol.o: shared/libutil/../arg.h
2104+shared/libutil/estrtol.o: shared/libutil/../compat.h
2105+shared/libutil/strlcpy.o: shared/libutil/strlcpy.c
2106+shared/libutil/strlcpy.o: shared/libutil/../util.h
2107+shared/libutil/strlcpy.o: shared/libutil/../arg.h
2108+shared/libutil/strlcpy.o: shared/libutil/../compat.h
2109 shared/libutil/mode.o: shared/libutil/mode.c
2110 shared/libutil/mode.o: shared/libutil/../util.h
2111 shared/libutil/mode.o: shared/libutil/../arg.h
2112 shared/libutil/mode.o: shared/libutil/../compat.h
2113 shared/libutil/net.o: shared/libutil/net.c
2114+shared/libutil/net.o: shared/libutil/../paths.h
2115 shared/libutil/net.o: shared/libutil/../util.h
2116 shared/libutil/net.o: shared/libutil/../arg.h
2117 shared/libutil/net.o: shared/libutil/../compat.h
2118+shared/libutil/wexec.o: shared/libutil/wexec.c
2119+shared/libutil/wexec.o: shared/libutil/../config.h
2120+shared/libutil/wexec.o: shared/libutil/../paths.h
2121+shared/libutil/wexec.o: shared/libutil/../wexec.h
2122+shared/libutil/wexec.o: shared/libutil/../paths.h
2123+shared/libutil/wexec.o: shared/libutil/../util.h
2124+shared/libutil/wexec.o: shared/libutil/../arg.h
2125+shared/libutil/wexec.o: shared/libutil/../compat.h
2126+shared/libutil/crypt.o: shared/libutil/crypt.c
2127+shared/libutil/crypt.o: shared/libutil/../crypt.h
2128+shared/libutil/crypt.o: shared/libutil/../text.h
2129+shared/libutil/crypt.o: shared/libutil/../util.h
2130+shared/libutil/crypt.o: shared/libutil/../arg.h
2131+shared/libutil/crypt.o: shared/libutil/../compat.h
2132 shared/libutil/parseoffset.o: shared/libutil/parseoffset.c
2133 shared/libutil/parseoffset.o: shared/libutil/../util.h
2134 shared/libutil/parseoffset.o: shared/libutil/../arg.h
2135 shared/libutil/parseoffset.o: shared/libutil/../compat.h
2136-shared/libutil/passwd.o: shared/libutil/passwd.c
2137-shared/libutil/passwd.o: shared/libutil/../passwd.h
2138-shared/libutil/passwd.o: shared/libutil/../text.h
2139-shared/libutil/passwd.o: shared/libutil/../util.h
2140-shared/libutil/passwd.o: shared/libutil/../arg.h
2141-shared/libutil/passwd.o: shared/libutil/../compat.h
2142-shared/libutil/proc.o: shared/libutil/proc.c
2143-shared/libutil/proc.o: shared/libutil/../proc.h
2144-shared/libutil/proc.o: shared/libutil/../util.h
2145-shared/libutil/proc.o: shared/libutil/../arg.h
2146-shared/libutil/proc.o: shared/libutil/../compat.h
2147-shared/libutil/putword.o: shared/libutil/putword.c
2148-shared/libutil/putword.o: shared/libutil/../util.h
2149-shared/libutil/putword.o: shared/libutil/../arg.h
2150-shared/libutil/putword.o: shared/libutil/../compat.h
2151-shared/libutil/reallocarray.o: shared/libutil/reallocarray.c
2152-shared/libutil/reallocarray.o: shared/libutil/../util.h
2153-shared/libutil/reallocarray.o: shared/libutil/../arg.h
2154-shared/libutil/reallocarray.o: shared/libutil/../compat.h
2155+shared/libutil/strsep.o: shared/libutil/strsep.c
2156+shared/libutil/strsep.o: shared/libutil/../util.h
2157+shared/libutil/strsep.o: shared/libutil/../arg.h
2158+shared/libutil/strsep.o: shared/libutil/../compat.h
2159+shared/libutil/concat.o: shared/libutil/concat.c
2160+shared/libutil/concat.o: shared/libutil/../util.h
2161+shared/libutil/concat.o: shared/libutil/../arg.h
2162+shared/libutil/concat.o: shared/libutil/../compat.h
2163+shared/libutil/human.o: shared/libutil/human.c
2164+shared/libutil/human.o: shared/libutil/../util.h
2165+shared/libutil/human.o: shared/libutil/../arg.h
2166+shared/libutil/human.o: shared/libutil/../compat.h
2167+shared/libutil/tls.o: shared/libutil/tls.c
2168+shared/libutil/tls.o: shared/libutil/../tls.h
2169+shared/libutil/tls.o: shared/libutil/../paths.h
2170+shared/libutil/tls.o: shared/libutil/../util.h
2171+shared/libutil/tls.o: shared/libutil/../arg.h
2172+shared/libutil/tls.o: shared/libutil/../compat.h
2173+shared/libutil/sha384.o: shared/libutil/sha384.c
2174+shared/libutil/sha384.o: shared/libutil/../sha384.h
2175+shared/libutil/sha384.o: shared/libutil/../sha512.h
2176+shared/libutil/fnck.o: shared/libutil/fnck.c
2177+shared/libutil/fnck.o: shared/libutil/../util.h
2178+shared/libutil/fnck.o: shared/libutil/../arg.h
2179+shared/libutil/fnck.o: shared/libutil/../compat.h
2180+shared/libutil/agetcwd.o: shared/libutil/agetcwd.c
2181+shared/libutil/agetcwd.o: shared/libutil/../util.h
2182+shared/libutil/agetcwd.o: shared/libutil/../arg.h
2183+shared/libutil/agetcwd.o: shared/libutil/../compat.h
2184+shared/libutil/linecmp.o: shared/libutil/linecmp.c
2185+shared/libutil/linecmp.o: shared/libutil/../text.h
2186+shared/libutil/linecmp.o: shared/libutil/../util.h
2187+shared/libutil/linecmp.o: shared/libutil/../arg.h
2188+shared/libutil/linecmp.o: shared/libutil/../compat.h
2189 shared/libutil/recurse.o: shared/libutil/recurse.c
2190 shared/libutil/recurse.o: shared/libutil/../fs.h
2191 shared/libutil/recurse.o: shared/libutil/../util.h
2192 shared/libutil/recurse.o: shared/libutil/../arg.h
2193 shared/libutil/recurse.o: shared/libutil/../compat.h
2194-shared/libutil/recurse_dir.o: shared/libutil/recurse_dir.c
2195-shared/libutil/recurse_dir.o: shared/libutil/../util.h
2196-shared/libutil/recurse_dir.o: shared/libutil/../arg.h
2197-shared/libutil/recurse_dir.o: shared/libutil/../compat.h
2198-shared/libutil/rm.o: shared/libutil/rm.c
2199-shared/libutil/rm.o: shared/libutil/../fs.h
2200-shared/libutil/rm.o: shared/libutil/../util.h
2201-shared/libutil/rm.o: shared/libutil/../arg.h
2202-shared/libutil/rm.o: shared/libutil/../compat.h
2203+shared/libutil/fshut.o: shared/libutil/fshut.c
2204+shared/libutil/fshut.o: shared/libutil/../util.h
2205+shared/libutil/fshut.o: shared/libutil/../arg.h
2206+shared/libutil/fshut.o: shared/libutil/../compat.h
2207+shared/libutil/agetline.o: shared/libutil/agetline.c
2208+shared/libutil/agetline.o: shared/libutil/../text.h
2209+shared/libutil/agetline.o: shared/libutil/../util.h
2210+shared/libutil/agetline.o: shared/libutil/../arg.h
2211+shared/libutil/agetline.o: shared/libutil/../compat.h
2212+shared/libutil/reallocarray.o: shared/libutil/reallocarray.c
2213+shared/libutil/reallocarray.o: shared/libutil/../util.h
2214+shared/libutil/reallocarray.o: shared/libutil/../arg.h
2215+shared/libutil/reallocarray.o: shared/libutil/../compat.h
2216+shared/libutil/fconcat.o: shared/libutil/fconcat.c
2217+shared/libutil/fconcat.o: shared/libutil/../text.h
2218+shared/libutil/fconcat.o: shared/libutil/../util.h
2219+shared/libutil/fconcat.o: shared/libutil/../arg.h
2220+shared/libutil/fconcat.o: shared/libutil/../compat.h
2221+shared/libutil/cp.o: shared/libutil/cp.c
2222+shared/libutil/cp.o: shared/libutil/../fs.h
2223+shared/libutil/cp.o: shared/libutil/../util.h
2224+shared/libutil/cp.o: shared/libutil/../arg.h
2225+shared/libutil/cp.o: shared/libutil/../compat.h
2226 shared/libutil/sha1.o: shared/libutil/sha1.c
2227 shared/libutil/sha1.o: shared/libutil/../sha1.h
2228-shared/libutil/sha224.o: shared/libutil/sha224.c
2229-shared/libutil/sha224.o: shared/libutil/../sha224.h
2230-shared/libutil/sha224.o: shared/libutil/../sha256.h
2231-shared/libutil/sha256.o: shared/libutil/sha256.c
2232-shared/libutil/sha256.o: shared/libutil/../sha256.h
2233-shared/libutil/sha384.o: shared/libutil/sha384.c
2234-shared/libutil/sha384.o: shared/libutil/../sha384.h
2235-shared/libutil/sha384.o: shared/libutil/../sha512.h
2236-shared/libutil/sha512-224.o: shared/libutil/sha512-224.c
2237-shared/libutil/sha512-224.o: shared/libutil/../sha512-224.h
2238-shared/libutil/sha512-224.o: shared/libutil/../sha512.h
2239+shared/libutil/sysinfo.o: shared/libutil/sysinfo.c
2240+shared/libutil/sysinfo.o: shared/libutil/../util.h
2241+shared/libutil/sysinfo.o: shared/libutil/../arg.h
2242+shared/libutil/sysinfo.o: shared/libutil/../compat.h
2243+shared/libutil/diffutil.o: shared/libutil/diffutil.c
2244+shared/libutil/diffutil.o: shared/libutil/../diffutil.h
2245+shared/libutil/diffutil.o: shared/libutil/../text.h
2246+shared/libutil/diffutil.o: shared/libutil/../util.h
2247+shared/libutil/diffutil.o: shared/libutil/../arg.h
2248+shared/libutil/diffutil.o: shared/libutil/../compat.h
2249+shared/libutil/md5.o: shared/libutil/md5.c
2250+shared/libutil/md5.o: shared/libutil/../md5.h
2251 shared/libutil/sha512-256.o: shared/libutil/sha512-256.c
2252 shared/libutil/sha512-256.o: shared/libutil/../sha512-256.h
2253 shared/libutil/sha512-256.o: shared/libutil/../sha512.h
2254-shared/libutil/sha512.o: shared/libutil/sha512.c
2255-shared/libutil/sha512.o: shared/libutil/../sha512.h
2256-shared/libutil/sig.o: shared/libutil/sig.c
2257-shared/libutil/sig.o: shared/libutil/../sig.h
2258 shared/libutil/strcasestr.o: shared/libutil/strcasestr.c
2259 shared/libutil/strcasestr.o: shared/libutil/../util.h
2260 shared/libutil/strcasestr.o: shared/libutil/../arg.h
2261 shared/libutil/strcasestr.o: shared/libutil/../compat.h
2262-shared/libutil/strlcat.o: shared/libutil/strlcat.c
2263-shared/libutil/strlcat.o: shared/libutil/../util.h
2264-shared/libutil/strlcat.o: shared/libutil/../arg.h
2265-shared/libutil/strlcat.o: shared/libutil/../compat.h
2266-shared/libutil/strlcpy.o: shared/libutil/strlcpy.c
2267-shared/libutil/strlcpy.o: shared/libutil/../util.h
2268-shared/libutil/strlcpy.o: shared/libutil/../arg.h
2269-shared/libutil/strlcpy.o: shared/libutil/../compat.h
2270-shared/libutil/strnsubst.o: shared/libutil/strnsubst.c
2271-shared/libutil/strnsubst.o: shared/libutil/../util.h
2272-shared/libutil/strnsubst.o: shared/libutil/../arg.h
2273-shared/libutil/strnsubst.o: shared/libutil/../compat.h
2274-shared/libutil/strsep.o: shared/libutil/strsep.c
2275-shared/libutil/strsep.o: shared/libutil/../util.h
2276-shared/libutil/strsep.o: shared/libutil/../arg.h
2277-shared/libutil/strsep.o: shared/libutil/../compat.h
2278-shared/libutil/strtonum.o: shared/libutil/strtonum.c
2279-shared/libutil/strtonum.o: shared/libutil/../util.h
2280-shared/libutil/strtonum.o: shared/libutil/../arg.h
2281-shared/libutil/strtonum.o: shared/libutil/../compat.h
2282-shared/libutil/sysinfo.o: shared/libutil/sysinfo.c
2283-shared/libutil/sysinfo.o: shared/libutil/../util.h
2284-shared/libutil/sysinfo.o: shared/libutil/../arg.h
2285-shared/libutil/sysinfo.o: shared/libutil/../compat.h
2286-shared/libutil/tls.o: shared/libutil/tls.c
2287-shared/libutil/tls.o: shared/libutil/../tls.h
2288-shared/libutil/tls.o: shared/libutil/../util.h
2289-shared/libutil/tls.o: shared/libutil/../arg.h
2290-shared/libutil/tls.o: shared/libutil/../compat.h
2291-shared/libutil/tty.o: shared/libutil/tty.c
2292-shared/libutil/tty.o: shared/libutil/../util.h
2293-shared/libutil/tty.o: shared/libutil/../arg.h
2294-shared/libutil/tty.o: shared/libutil/../compat.h
2295-shared/libutil/unescape.o: shared/libutil/unescape.c
2296-shared/libutil/unescape.o: shared/libutil/../util.h
2297-shared/libutil/unescape.o: shared/libutil/../arg.h
2298-shared/libutil/unescape.o: shared/libutil/../compat.h
2299+shared/libutil/putword.o: shared/libutil/putword.c
2300+shared/libutil/putword.o: shared/libutil/../util.h
2301+shared/libutil/putword.o: shared/libutil/../arg.h
2302+shared/libutil/putword.o: shared/libutil/../compat.h
2303 shared/libutil/writeall.o: shared/libutil/writeall.c
2304 shared/libutil/writeall.o: shared/libutil/../util.h
2305 shared/libutil/writeall.o: shared/libutil/../arg.h
2306 shared/libutil/writeall.o: shared/libutil/../compat.h
2307+shared/libutil/sha512-224.o: shared/libutil/sha512-224.c
2308+shared/libutil/sha512-224.o: shared/libutil/../sha512-224.h
2309+shared/libutil/sha512-224.o: shared/libutil/../sha512.h
2310+shared/libutil/sha512.o: shared/libutil/sha512.c
2311+shared/libutil/sha512.o: shared/libutil/../sha512.h
2312+shared/libutil/rm.o: shared/libutil/rm.c
2313+shared/libutil/rm.o: shared/libutil/../fs.h
2314+shared/libutil/rm.o: shared/libutil/../util.h
2315+shared/libutil/rm.o: shared/libutil/../arg.h
2316+shared/libutil/rm.o: shared/libutil/../compat.h
2317+shared/libutil/eprintf.o: shared/libutil/eprintf.c
2318+shared/libutil/eprintf.o: shared/libutil/../util.h
2319+shared/libutil/eprintf.o: shared/libutil/../arg.h
2320+shared/libutil/eprintf.o: shared/libutil/../compat.h
2321+shared/libutil/enmasse.o: shared/libutil/enmasse.c
2322+shared/libutil/enmasse.o: shared/libutil/../util.h
2323+shared/libutil/enmasse.o: shared/libutil/../arg.h
2324+shared/libutil/enmasse.o: shared/libutil/../compat.h
2325+shared/libutil/recurse_dir.o: shared/libutil/recurse_dir.c
2326+shared/libutil/recurse_dir.o: shared/libutil/../util.h
2327+shared/libutil/recurse_dir.o: shared/libutil/../arg.h
2328+shared/libutil/recurse_dir.o: shared/libutil/../compat.h
2329+shared/libutil/passwd.o: shared/libutil/passwd.c
2330+shared/libutil/passwd.o: shared/libutil/../passwd.h
2331+shared/libutil/passwd.o: shared/libutil/../paths.h
2332+shared/libutil/passwd.o: shared/libutil/../text.h
2333+shared/libutil/passwd.o: shared/libutil/../util.h
2334+shared/libutil/passwd.o: shared/libutil/../arg.h
2335+shared/libutil/passwd.o: shared/libutil/../compat.h
2336+shared/libutil/passwd.o: shared/libutil/../config.h
2337+shared/libutil/passwd.o: shared/libutil/../paths.h
2338+shared/libutil/passwd.o: shared/crypt.h
2339+shared/libutil/sha256.o: shared/libutil/sha256.c
2340+shared/libutil/sha256.o: shared/libutil/../sha256.h
2341+shared/libutil/ealloc.o: shared/libutil/ealloc.c
2342+shared/libutil/ealloc.o: shared/libutil/../util.h
2343+shared/libutil/ealloc.o: shared/libutil/../arg.h
2344+shared/libutil/ealloc.o: shared/libutil/../compat.h
2345+shared/libutil/mkdirp.o: shared/libutil/mkdirp.c
2346+shared/libutil/mkdirp.o: shared/libutil/../util.h
2347+shared/libutil/mkdirp.o: shared/libutil/../arg.h
2348+shared/libutil/mkdirp.o: shared/libutil/../compat.h
2349+shared/libredline/redline.o: shared/libredline/redline.c
2350+shared/libredline/redline.o: shared/libredline/../paths.h
2351+shared/libredline/redline.o: shared/redline.h
2352+shared/libutf/isdigitrune.o: shared/libutf/isdigitrune.c
2353+shared/libutf/isdigitrune.o: shared/libutf/../utf.h
2354+shared/libutf/isdigitrune.o: shared/libutf/runetype.h
2355+shared/libutf/lowerrune.o: shared/libutf/lowerrune.c
2356+shared/libutf/lowerrune.o: shared/libutf/../utf.h
2357+shared/libutf/lowerrune.o: shared/libutf/runetype.h
2358+shared/libutf/isblankrune.o: shared/libutf/isblankrune.c
2359+shared/libutf/isblankrune.o: shared/libutf/../utf.h
2360+shared/libutf/isblankrune.o: shared/libutf/runetype.h
2361+shared/libutf/runetype.o: shared/libutf/runetype.c
2362+shared/libutf/runetype.o: shared/libutf/../utf.h
2363+shared/libutf/ispunctrune.o: shared/libutf/ispunctrune.c
2364+shared/libutf/ispunctrune.o: shared/libutf/../utf.h
2365+shared/libutf/ispunctrune.o: shared/libutf/runetype.h
2366+shared/libutf/isalpharune.o: shared/libutf/isalpharune.c
2367+shared/libutf/isalpharune.o: shared/libutf/../utf.h
2368+shared/libutf/isalpharune.o: shared/libutf/runetype.h
2369+shared/libutf/fgetrune.o: shared/libutf/fgetrune.c
2370+shared/libutf/fgetrune.o: shared/libutf/../utf.h
2371+shared/libutf/isprintrune.o: shared/libutf/isprintrune.c
2372+shared/libutf/isprintrune.o: shared/libutf/../utf.h
2373+shared/libutf/isprintrune.o: shared/libutf/runetype.h
2374+shared/libutf/upperrune.o: shared/libutf/upperrune.c
2375+shared/libutf/upperrune.o: shared/libutf/../utf.h
2376+shared/libutf/upperrune.o: shared/libutf/runetype.h
2377+shared/libutf/isalnumrune.o: shared/libutf/isalnumrune.c
2378+shared/libutf/isalnumrune.o: shared/libutf/../utf.h
2379+shared/libutf/isalnumrune.o: shared/libutf/runetype.h
2380+shared/libutf/utftorunestr.o: shared/libutf/utftorunestr.c
2381+shared/libutf/utftorunestr.o: shared/libutf/../utf.h
2382+shared/libutf/isxdigitrune.o: shared/libutf/isxdigitrune.c
2383+shared/libutf/isxdigitrune.o: shared/libutf/../utf.h
2384+shared/libutf/isxdigitrune.o: shared/libutf/runetype.h
2385+shared/libutf/isspacerune.o: shared/libutf/isspacerune.c
2386+shared/libutf/isspacerune.o: shared/libutf/../utf.h
2387+shared/libutf/isspacerune.o: shared/libutf/runetype.h
2388+shared/libutf/rune.o: shared/libutf/rune.c
2389+shared/libutf/rune.o: shared/libutf/../utf.h
2390+shared/libutf/iscntrlrune.o: shared/libutf/iscntrlrune.c
2391+shared/libutf/iscntrlrune.o: shared/libutf/../utf.h
2392+shared/libutf/iscntrlrune.o: shared/libutf/runetype.h
2393+shared/libutf/istitlerune.o: shared/libutf/istitlerune.c
2394+shared/libutf/istitlerune.o: shared/libutf/../utf.h
2395+shared/libutf/istitlerune.o: shared/libutf/runetype.h
2396+shared/libutf/utf.o: shared/libutf/utf.c
2397+shared/libutf/utf.o: shared/libutf/../utf.h
2398+shared/libutf/isgraphrune.o: shared/libutf/isgraphrune.c
2399+shared/libutf/isgraphrune.o: shared/libutf/../utf.h
2400+shared/libutf/isgraphrune.o: shared/libutf/runetype.h
2401+shared/libutf/fputrune.o: shared/libutf/fputrune.c
2402+shared/libutf/fputrune.o: shared/libutf/../utf.h
+345,
-341
1@@ -9,7 +9,7 @@
2 set -e
3
4 : "${CC:=cc}"
5-: "${CPPFLAGS:=-Ishared -D_DEFAULT_SOURCE -D_GNU_SOURCE -D_NETBSD_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_FILE_OFFSET_BITS=64}"
6+: "${CPPFLAGS:=-Ishared -D_DEFAULT_SOURCE -D_GNU_SOURCE -D_NETBSD_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_FILE_OFFSET_BITS=64 -DFEATURE_INPROC_EXEC=1}"
7 : "${CFLAGS:=-std=c99 -Wall -Wextra -pedantic}"
8 : "${LDFLAGS:=}"
9 : "${LDLIBS:=-lcrypt -lresolv}"
10@@ -24,8 +24,8 @@ LIBUTIL="${ROOT}/shared/libutil/libutil.a"
11 LIBUTF="${ROOT}/shared/libutf/libutf.a"
12
13 die() {
14- printf 'mkbox: %s\n' "$*" >&2
15- exit 1
16+ printf 'mkbox: %s\n' "$*" >&2
17+ exit 1
18 }
19
20 # Clean up build directory on exit or signal termination
21@@ -36,9 +36,9 @@ trap 'rm -rf "${BDIR}"' EXIT INT QUIT TERM
22 [ -f "${LIBUTF}" ] || die "libutf.a not found; run 'make' first"
23
24 [ -f "${ROOT}/cmd/posix/getconf.h" ] || {
25- printf 'mkbox: generating getconf.h\n'
26- "${ROOT}/scripts/getconf.sh" > "${ROOT}/cmd/posix/getconf.h" ||
27- die "scripts/getconf.sh failed"
28+ printf 'mkbox: generating getconf.h\n'
29+ "${ROOT}/scripts/getconf.sh" > "${ROOT}/cmd/posix/getconf.h" ||
30+ die "scripts/getconf.sh failed"
31 }
32
33 rm -rf "${BDIR}"
34@@ -48,284 +48,284 @@ OBJS=""
35 DECL_F="${BDIR}/decls.inc"
36 : > "${DECL_F}"
37 for _c in posix linux net pseudo xsi extra; do
38- : > "${BDIR}/entries_${_c}.inc"
39+ : > "${BDIR}/entries_${_c}.inc"
40 done
41 unset _c
42
43 alias_entry() {
44- printf '\t{ "%s", %s_main, "%s" },\n' "$1" "$2" "$3" \
45- >> "${BDIR}/entries_${3}.inc"
46+ printf '\t{ "%s", %s_main, "%s" },\n' "$1" "$2" "$3" \
47+ >> "${BDIR}/entries_${3}.inc"
48 }
49
50 compile_tool() {
51- src="$1"
52- name="$2"
53- fn="$3"
54- catg="$4"
55- extra="${5:-}"
56- out="${BDIR}/${fn}.o"
57- symf="${BDIR}/${fn}.syms"
58-
59- printf 'mkbox: cc %s\n' "${name}"
60- eval "${CC} ${CPPFLAGS} ${extra} ${CFLAGS} -c \"\$src\" -o \"\$out\"" ||
61- die "compile failed: ${src}"
62- printf 'main %s_main\n' "${fn}" > "${symf}"
63- ${OBJCOPY} --redefine-syms="${symf}" "${out}" ||
64- die "objcopy failed: ${name}"
65- ${OBJCOPY} --keep-global-symbol="${fn}_main" "${out}" ||
66- die "objcopy localize failed: ${name}"
67- rm -f "${symf}"
68- OBJS="${OBJS} ${out}"
69- printf 'int %s_main(int, char **);\n' "${fn}" >> "${DECL_F}"
70- printf '\t{ "%s", %s_main, "%s" },\n' "${name}" "${fn}" "${catg}" \
71- >> "${BDIR}/entries_${catg}.inc"
72+ src="$1"
73+ name="$2"
74+ fn="$3"
75+ catg="$4"
76+ extra="${5:-}"
77+ out="${BDIR}/${fn}.o"
78+ symf="${BDIR}/${fn}.syms"
79+
80+ printf 'mkbox: cc %s\n' "${name}"
81+ eval "${CC} ${CPPFLAGS} ${extra} ${CFLAGS} -c \"\$src\" -o \"\$out\"" ||
82+ die "compile failed: ${src}"
83+ printf 'main %s_main\n' "${fn}" > "${symf}"
84+ ${OBJCOPY} --redefine-syms="${symf}" "${out}" ||
85+ die "objcopy failed: ${name}"
86+ ${OBJCOPY} --keep-global-symbol="${fn}_main" "${out}" ||
87+ die "objcopy localize failed: ${name}"
88+ rm -f "${symf}"
89+ OBJS="${OBJS} ${out}"
90+ printf 'int %s_main(int, char **);\n' "${fn}" >> "${DECL_F}"
91+ printf '\t{ "%s", %s_main, "%s" },\n' "${name}" "${fn}" "${catg}" \
92+ >> "${BDIR}/entries_${catg}.inc"
93 }
94
95 compile_make() {
96- mdir="${ROOT}/cmd/posix/make"
97- symf="${BDIR}/make.syms"
98- printf 'mkbox: cc make (multi)\n'
99- make_objs=""
100- for s in defaults parser posix rules; do
101- out="${BDIR}/make_${s}.o"
102- eval "${CC} ${CPPFLAGS} ${CFLAGS} -I\"\$mdir\" -c \"\$mdir/\$s.c\" -o \"\$out\"" ||
103- die "compile failed: make/${s}.c"
104- make_objs="${make_objs} ${out}"
105- done
106- out_main="${BDIR}/make_main.o"
107- eval "${CC} ${CPPFLAGS} ${CFLAGS} -I\"\$mdir\" -c \"\$mdir/main.c\" -o \"\${out_main}\"" ||
108- die "compile failed: make/main.c"
109- make_objs="${make_objs} ${out_main}"
110-
111- # Combined incremental link to resolve internal symbols cleanly
112- combined="${BDIR}/make_combined.o"
113- ${LD:-ld} -r -o "${combined}" ${make_objs} ||
114- die "ld -r failed: make"
115-
116- printf 'main make_main\n' > "${symf}"
117- ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
118- die "objcopy failed: make"
119- ${OBJCOPY} --keep-global-symbol=make_main "${combined}" ||
120- die "objcopy localize failed: make"
121- rm -f "${symf}" ${make_objs}
122-
123- OBJS="${OBJS} ${combined}"
124- printf 'int make_main(int, char **);\n' >> "${DECL_F}"
125- printf '\t{ "make", make_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
126+ mdir="${ROOT}/cmd/posix/make"
127+ symf="${BDIR}/make.syms"
128+ printf 'mkbox: cc make (multi)\n'
129+ make_objs=""
130+ for s in defaults parser posix rules; do
131+ out="${BDIR}/make_${s}.o"
132+ eval "${CC} ${CPPFLAGS} ${CFLAGS} -I\"\$mdir\" -c \"\$mdir/\$s.c\" -o \"\$out\"" ||
133+ die "compile failed: make/${s}.c"
134+ make_objs="${make_objs} ${out}"
135+ done
136+ out_main="${BDIR}/make_main.o"
137+ eval "${CC} ${CPPFLAGS} ${CFLAGS} -I\"\$mdir\" -c \"\$mdir/main.c\" -o \"\${out_main}\"" ||
138+ die "compile failed: make/main.c"
139+ make_objs="${make_objs} ${out_main}"
140+
141+ # Combined incremental link to resolve internal symbols cleanly
142+ combined="${BDIR}/make_combined.o"
143+ ${LD:-ld} -r -o "${combined}" ${make_objs} ||
144+ die "ld -r failed: make"
145+
146+ printf 'main make_main\n' > "${symf}"
147+ ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
148+ die "objcopy failed: make"
149+ ${OBJCOPY} --keep-global-symbol=make_main "${combined}" ||
150+ die "objcopy localize failed: make"
151+ rm -f "${symf}" ${make_objs}
152+
153+ OBJS="${OBJS} ${combined}"
154+ printf 'int make_main(int, char **);\n' >> "${DECL_F}"
155+ printf '\t{ "make", make_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
156 }
157
158 compile_diff() {
159- ddir="${ROOT}/cmd/posix/diff"
160- symf="${BDIR}/diff.syms"
161- diff_objs=""
162-
163- printf 'mkbox: cc diff (multi)\n'
164- for s in diff diffdir diffreg pr xmalloc; do
165- out="${BDIR}/diff_${s}.o"
166- eval "${CC} ${CPPFLAGS} -I\"\$ddir\" ${CFLAGS} -c \"\$ddir/\$s.c\" -o \"\$out\"" ||
167- die "compile failed: diff/${s}.c"
168- diff_objs="${diff_objs} ${out}"
169- done
170-
171- combined="${BDIR}/diff_combined.o"
172- ${LD:-ld} -r -o "${combined}" ${diff_objs} ||
173- die "ld -r failed: diff"
174-
175- printf 'main diff_main\n' > "${symf}"
176- ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
177- die "objcopy failed: diff"
178- ${OBJCOPY} --keep-global-symbol=diff_main "${combined}" ||
179- die "objcopy localize failed: diff"
180- rm -f "${symf}" ${diff_objs}
181-
182- OBJS="${OBJS} ${combined}"
183- LDLIBS="${LDLIBS} -lm"
184- printf 'int diff_main(int, char **);\n' >> "${DECL_F}"
185- printf '\t{ "diff", diff_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
186+ ddir="${ROOT}/cmd/posix/diff"
187+ symf="${BDIR}/diff.syms"
188+ diff_objs=""
189+
190+ printf 'mkbox: cc diff (multi)\n'
191+ for s in diff diffdir diffreg pr xmalloc; do
192+ out="${BDIR}/diff_${s}.o"
193+ eval "${CC} ${CPPFLAGS} -I\"\$ddir\" ${CFLAGS} -c \"\$ddir/\$s.c\" -o \"\$out\"" ||
194+ die "compile failed: diff/${s}.c"
195+ diff_objs="${diff_objs} ${out}"
196+ done
197+
198+ combined="${BDIR}/diff_combined.o"
199+ ${LD:-ld} -r -o "${combined}" ${diff_objs} ||
200+ die "ld -r failed: diff"
201+
202+ printf 'main diff_main\n' > "${symf}"
203+ ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
204+ die "objcopy failed: diff"
205+ ${OBJCOPY} --keep-global-symbol=diff_main "${combined}" ||
206+ die "objcopy localize failed: diff"
207+ rm -f "${symf}" ${diff_objs}
208+
209+ OBJS="${OBJS} ${combined}"
210+ LDLIBS="${LDLIBS} -lm"
211+ printf 'int diff_main(int, char **);\n' >> "${DECL_F}"
212+ printf '\t{ "diff", diff_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
213 }
214
215 compile_patch() {
216- pdir="${ROOT}/cmd/posix/patch"
217- symf="${BDIR}/patch.syms"
218- patch_objs=""
219-
220- printf 'mkbox: cc patch (multi)\n'
221- for s in patch pch inp util backupfile mkpath; do
222- out="${BDIR}/patch_${s}.o"
223- eval "${CC} ${CPPFLAGS} -I\"\$pdir\" ${CFLAGS} -c \"\$pdir/\$s.c\" -o \"\$out\"" ||
224- die "compile failed: patch/${s}.c"
225- patch_objs="${patch_objs} ${out}"
226- done
227-
228- combined="${BDIR}/patch_combined.o"
229- ${LD:-ld} -r -o "${combined}" ${patch_objs} ||
230- die "ld -r failed: patch"
231-
232- printf 'main patch_main\n' > "${symf}"
233- ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
234- die "objcopy failed: patch"
235- ${OBJCOPY} --keep-global-symbol=patch_main "${combined}" ||
236- die "objcopy localize failed: patch"
237- rm -f "${symf}" ${patch_objs}
238-
239- OBJS="${OBJS} ${combined}"
240- printf 'int patch_main(int, char **);\n' >> "${DECL_F}"
241- printf '\t{ "patch", patch_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
242+ pdir="${ROOT}/cmd/posix/patch"
243+ symf="${BDIR}/patch.syms"
244+ patch_objs=""
245+
246+ printf 'mkbox: cc patch (multi)\n'
247+ for s in patch pch inp util backupfile mkpath; do
248+ out="${BDIR}/patch_${s}.o"
249+ eval "${CC} ${CPPFLAGS} -I\"\$pdir\" ${CFLAGS} -c \"\$pdir/\$s.c\" -o \"\$out\"" ||
250+ die "compile failed: patch/${s}.c"
251+ patch_objs="${patch_objs} ${out}"
252+ done
253+
254+ combined="${BDIR}/patch_combined.o"
255+ ${LD:-ld} -r -o "${combined}" ${patch_objs} ||
256+ die "ld -r failed: patch"
257+
258+ printf 'main patch_main\n' > "${symf}"
259+ ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
260+ die "objcopy failed: patch"
261+ ${OBJCOPY} --keep-global-symbol=patch_main "${combined}" ||
262+ die "objcopy localize failed: patch"
263+ rm -f "${symf}" ${patch_objs}
264+
265+ OBJS="${OBJS} ${combined}"
266+ printf 'int patch_main(int, char **);\n' >> "${DECL_F}"
267+ printf '\t{ "patch", patch_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
268 }
269
270 compile_diff3() {
271- ddir="${ROOT}/cmd/extra/diff3"
272- pdir="${ROOT}/cmd/posix/diff"
273- symf="${BDIR}/diff3.syms"
274- diff3_objs=""
275-
276- printf 'mkbox: cc diff3 (multi)\n'
277- for s in diff3; do
278- out="${BDIR}/diff3_${s}.o"
279- eval "${CC} ${CPPFLAGS} -I\"\$pdir\" ${CFLAGS} -c \"\$ddir/\$s.c\" -o \"\$out\"" ||
280- die "compile failed: diff3/${s}.c"
281- diff3_objs="${diff3_objs} ${out}"
282- done
283- out="${BDIR}/diff3_xmalloc.o"
284- eval "${CC} ${CPPFLAGS} -I\"\$pdir\" ${CFLAGS} -c \"\$pdir/xmalloc.c\" -o \"\$out\"" ||
285- die "compile failed: diff/xmalloc.c"
286- diff3_objs="${diff3_objs} ${out}"
287-
288- combined="${BDIR}/diff3_combined.o"
289- ${LD:-ld} -r -o "${combined}" ${diff3_objs} ||
290- die "ld -r failed: diff3"
291-
292- printf 'main diff3_main\n' > "${symf}"
293- ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
294- die "objcopy failed: diff3"
295- ${OBJCOPY} --keep-global-symbol=diff3_main "${combined}" ||
296- die "objcopy localize failed: diff3"
297- rm -f "${symf}" ${diff3_objs}
298-
299- OBJS="${OBJS} ${combined}"
300- printf 'int diff3_main(int, char **);\n' >> "${DECL_F}"
301- printf '\t{ "diff3", diff3_main, "extra" },\n' >> "${BDIR}/entries_extra.inc"
302+ ddir="${ROOT}/cmd/extra/diff3"
303+ pdir="${ROOT}/cmd/posix/diff"
304+ symf="${BDIR}/diff3.syms"
305+ diff3_objs=""
306+
307+ printf 'mkbox: cc diff3 (multi)\n'
308+ for s in diff3; do
309+ out="${BDIR}/diff3_${s}.o"
310+ eval "${CC} ${CPPFLAGS} -I\"\$pdir\" ${CFLAGS} -c \"\$ddir/\$s.c\" -o \"\$out\"" ||
311+ die "compile failed: diff3/${s}.c"
312+ diff3_objs="${diff3_objs} ${out}"
313+ done
314+ out="${BDIR}/diff3_xmalloc.o"
315+ eval "${CC} ${CPPFLAGS} -I\"\$pdir\" ${CFLAGS} -c \"\$pdir/xmalloc.c\" -o \"\$out\"" ||
316+ die "compile failed: diff/xmalloc.c"
317+ diff3_objs="${diff3_objs} ${out}"
318+
319+ combined="${BDIR}/diff3_combined.o"
320+ ${LD:-ld} -r -o "${combined}" ${diff3_objs} ||
321+ die "ld -r failed: diff3"
322+
323+ printf 'main diff3_main\n' > "${symf}"
324+ ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
325+ die "objcopy failed: diff3"
326+ ${OBJCOPY} --keep-global-symbol=diff3_main "${combined}" ||
327+ die "objcopy localize failed: diff3"
328+ rm -f "${symf}" ${diff3_objs}
329+
330+ OBJS="${OBJS} ${combined}"
331+ printf 'int diff3_main(int, char **);\n' >> "${DECL_F}"
332+ printf '\t{ "diff3", diff3_main, "extra" },\n' >> "${BDIR}/entries_extra.inc"
333 }
334
335 compile_awk() {
336- adir="${ROOT}/cmd/posix/awk"
337- symf="${BDIR}/awk.syms"
338- awk_objs=""
339-
340- printf 'mkbox: yacc awk/awkgram.y\n'
341- ${YACC} -d -o "${adir}/awkgram.tab.c" "${adir}/awkgram.y" ||
342- die "yacc failed: awk/awkgram.y"
343-
344- # maketab is a host code-generator, only needs CFLAGS, no CPPFLAGS
345- printf 'mkbox: cc awk/maketab\n'
346- ${CC} ${CFLAGS} -o "${BDIR}/awk_maketab" "${adir}/maketab.c" ||
347- die "compile failed: awk/maketab.c"
348-
349- printf 'mkbox: gen awk/proctab.c\n'
350- "${BDIR}/awk_maketab" "${adir}/awkgram.tab.h" > "${adir}/proctab.c" ||
351- die "maketab failed"
352-
353- for s in b main parse proctab tran lib run lex math; do
354- out="${BDIR}/awk_${s}.o"
355- eval "${CC} ${CPPFLAGS} -I\"\$adir\" ${CFLAGS} -c \"\$adir/${s}.c\" -o \"\$out\"" ||
356- die "compile failed: awk/${s}.c"
357- awk_objs="${awk_objs} ${out}"
358- done
359- out="${BDIR}/awk_awkgram.tab.o"
360- eval "${CC} ${CPPFLAGS} -I\"\$adir\" ${CFLAGS} -c \"\$adir/awkgram.tab.c\" -o \"\$out\"" ||
361- die "compile failed: awk/awkgram.tab.c"
362- awk_objs="${awk_objs} ${out}"
363-
364- combined="${BDIR}/awk_combined.o"
365- ${LD:-ld} -r -o "${combined}" ${awk_objs} ||
366- die "ld -r failed: awk"
367-
368- printf 'main awk_main\n' > "${symf}"
369- ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
370- die "objcopy failed: awk"
371- ${OBJCOPY} --keep-global-symbol=awk_main "${combined}" ||
372- die "objcopy localize failed: awk"
373- rm -f "${symf}" ${awk_objs}
374-
375- OBJS="${OBJS} ${combined}"
376- LDLIBS="${LDLIBS} -lm"
377- printf 'int awk_main(int, char **);\n' >> "${DECL_F}"
378- printf '\t{ "awk", awk_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
379+ adir="${ROOT}/cmd/posix/awk"
380+ symf="${BDIR}/awk.syms"
381+ awk_objs=""
382+
383+ printf 'mkbox: yacc awk/awkgram.y\n'
384+ ${YACC} -d -o "${adir}/awkgram.tab.c" "${adir}/awkgram.y" ||
385+ die "yacc failed: awk/awkgram.y"
386+
387+ # maketab is a host code-generator, only needs CFLAGS, no CPPFLAGS
388+ printf 'mkbox: cc awk/maketab\n'
389+ ${CC} ${CFLAGS} -o "${BDIR}/awk_maketab" "${adir}/maketab.c" ||
390+ die "compile failed: awk/maketab.c"
391+
392+ printf 'mkbox: gen awk/proctab.c\n'
393+ "${BDIR}/awk_maketab" "${adir}/awkgram.tab.h" > "${adir}/proctab.c" ||
394+ die "maketab failed"
395+
396+ for s in b main parse proctab tran lib run lex math; do
397+ out="${BDIR}/awk_${s}.o"
398+ eval "${CC} ${CPPFLAGS} -I\"\$adir\" ${CFLAGS} -c \"\$adir/${s}.c\" -o \"\$out\"" ||
399+ die "compile failed: awk/${s}.c"
400+ awk_objs="${awk_objs} ${out}"
401+ done
402+ out="${BDIR}/awk_awkgram.tab.o"
403+ eval "${CC} ${CPPFLAGS} -I\"\$adir\" ${CFLAGS} -c \"\$adir/awkgram.tab.c\" -o \"\$out\"" ||
404+ die "compile failed: awk/awkgram.tab.c"
405+ awk_objs="${awk_objs} ${out}"
406+
407+ combined="${BDIR}/awk_combined.o"
408+ ${LD:-ld} -r -o "${combined}" ${awk_objs} ||
409+ die "ld -r failed: awk"
410+
411+ printf 'main awk_main\n' > "${symf}"
412+ ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
413+ die "objcopy failed: awk"
414+ ${OBJCOPY} --keep-global-symbol=awk_main "${combined}" ||
415+ die "objcopy localize failed: awk"
416+ rm -f "${symf}" ${awk_objs}
417+
418+ OBJS="${OBJS} ${combined}"
419+ LDLIBS="${LDLIBS} -lm"
420+ printf 'int awk_main(int, char **);\n' >> "${DECL_F}"
421+ printf '\t{ "awk", awk_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
422 }
423
424 compile_sh() {
425- sdir="${ROOT}/cmd/posix/sh"
426- symf="${BDIR}/sh.syms"
427- sh_objs=""
428-
429- # mknodes and mksyntax are host code-generators, not part of the shell
430- printf 'mkbox: cc sh/mknodes\n'
431- ${CC} ${CFLAGS} -o "${BDIR}/sh_mknodes" "${sdir}/mknodes.c" ||
432- die "compile failed: sh/mknodes.c"
433-
434- printf 'mkbox: cc sh/mksyntax\n'
435- ${CC} ${CPPFLAGS} -I"${sdir}" ${CFLAGS} -o "${BDIR}/sh_mksyntax" "${sdir}/mksyntax.c" ||
436- die "compile failed: sh/mksyntax.c"
437-
438- printf 'mkbox: gen sh/nodes.{c,h}\n'
439- (cd "${sdir}" && "${BDIR}/sh_mknodes" nodetypes nodes.c.pat) ||
440- die "mknodes failed"
441-
442- printf 'mkbox: gen sh/syntax.{c,h}\n'
443- (cd "${sdir}" && "${BDIR}/sh_mksyntax") ||
444- die "mksyntax failed"
445-
446- printf 'mkbox: gen sh/builtins.{c,h}\n'
447- (cd "${sdir}" && sh mkbuiltins .) ||
448- die "mkbuiltins failed"
449-
450- printf 'mkbox: gen sh/token.h\n'
451- (cd "${sdir}" && sh mktokens) ||
452- die "mktokens failed"
453-
454- for s in alias arith_yacc arith_yylex cd echo error eval exec \
455- expand lineedit input jobs kill mail main memalloc \
456- miscbltin mystring options output parser printf redir \
457- show test trap var builtins nodes syntax; do
458- out="${BDIR}/sh_${s}.o"
459- eval "${CC} ${CPPFLAGS} -DSHELL -I\"\$sdir\" ${CFLAGS} -c \"\$sdir/${s}.c\" -o \"\$out\"" ||
460- die "compile failed: sh/${s}.c"
461- sh_objs="${sh_objs} ${out}"
462- done
463-
464- combined="${BDIR}/sh_combined.o"
465- ${LD:-ld} -r -o "${combined}" ${sh_objs} ||
466- die "ld -r failed: sh"
467-
468- printf 'main sh_main\n' > "${symf}"
469- ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
470- die "objcopy failed: sh"
471- ${OBJCOPY} --keep-global-symbol=sh_main "${combined}" ||
472- die "objcopy localize failed: sh"
473- rm -f "${symf}" ${sh_objs}
474-
475- OBJS="${OBJS} ${combined}"
476- printf 'int sh_main(int, char **);\n' >> "${DECL_F}"
477- printf '\t{ "sh", sh_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
478+ sdir="${ROOT}/cmd/posix/sh"
479+ symf="${BDIR}/sh.syms"
480+ sh_objs=""
481+
482+ # mknodes and mksyntax are host code-generators, not part of the shell
483+ printf 'mkbox: cc sh/mknodes\n'
484+ ${CC} ${CFLAGS} -o "${BDIR}/sh_mknodes" "${sdir}/mknodes.c" ||
485+ die "compile failed: sh/mknodes.c"
486+
487+ printf 'mkbox: cc sh/mksyntax\n'
488+ ${CC} ${CPPFLAGS} -I"${sdir}" ${CFLAGS} -o "${BDIR}/sh_mksyntax" "${sdir}/mksyntax.c" ||
489+ die "compile failed: sh/mksyntax.c"
490+
491+ printf 'mkbox: gen sh/nodes.{c,h}\n'
492+ (cd "${sdir}" && "${BDIR}/sh_mknodes" nodetypes nodes.c.pat) ||
493+ die "mknodes failed"
494+
495+ printf 'mkbox: gen sh/syntax.{c,h}\n'
496+ (cd "${sdir}" && "${BDIR}/sh_mksyntax") ||
497+ die "mksyntax failed"
498+
499+ printf 'mkbox: gen sh/builtins.{c,h}\n'
500+ (cd "${sdir}" && sh mkbuiltins .) ||
501+ die "mkbuiltins failed"
502+
503+ printf 'mkbox: gen sh/token.h\n'
504+ (cd "${sdir}" && sh mktokens) ||
505+ die "mktokens failed"
506+
507+ for s in alias arith_yacc arith_yylex cd echo error eval exec \
508+ expand lineedit input jobs kill mail main memalloc \
509+ miscbltin mystring options output parser printf redir \
510+ show test trap var builtins nodes syntax; do
511+ out="${BDIR}/sh_${s}.o"
512+ eval "${CC} ${CPPFLAGS} -DSHELL -I\"\$sdir\" ${CFLAGS} -c \"\$sdir/${s}.c\" -o \"\$out\"" ||
513+ die "compile failed: sh/${s}.c"
514+ sh_objs="${sh_objs} ${out}"
515+ done
516+
517+ combined="${BDIR}/sh_combined.o"
518+ ${LD:-ld} -r -o "${combined}" ${sh_objs} ||
519+ die "ld -r failed: sh"
520+
521+ printf 'main sh_main\n' > "${symf}"
522+ ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
523+ die "objcopy failed: sh"
524+ ${OBJCOPY} --keep-global-symbol=sh_main "${combined}" ||
525+ die "objcopy localize failed: sh"
526+ rm -f "${symf}" ${sh_objs}
527+
528+ OBJS="${OBJS} ${combined}"
529+ printf 'int sh_main(int, char **);\n' >> "${DECL_F}"
530+ printf '\t{ "sh", sh_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
531 }
532
533 process_dir() {
534- dir="$1"
535- catg="$2"
536- extra="${3:-}"
537- for src in "${dir}"/*.c; do
538- [ -f "${src}" ] || continue
539- name=${src##*/}
540- name=${name%.c}
541- fn=$(printf '%s' "${name}" | tr '.-' '__')
542- compile_tool "${src}" "${name}" "${fn}" "${catg}" "${extra}"
543- if [ "${name}" = "test" ]; then
544- alias_entry "[" "test" "${catg}"
545- fi
546- if [ "${name}" = "xinstall" ]; then
547- alias_entry "install" "xinstall" "${catg}"
548- fi
549- done
550+ dir="$1"
551+ catg="$2"
552+ extra="${3:-}"
553+ for src in "${dir}"/*.c; do
554+ [ -f "${src}" ] || continue
555+ name=${src##*/}
556+ name=${name%.c}
557+ fn=$(printf '%s' "${name}" | tr '.-' '__')
558+ compile_tool "${src}" "${name}" "${fn}" "${catg}" "${extra}"
559+ if [ "${name}" = "test" ]; then
560+ alias_entry "[" "test" "${catg}"
561+ fi
562+ if [ "${name}" = "xinstall" ]; then
563+ alias_entry "install" "xinstall" "${catg}"
564+ fi
565+ done
566 }
567
568 process_dir "${ROOT}/cmd/posix" "posix"
569@@ -350,6 +350,7 @@ cat > "${DISP}" << 'DISPATCH_HEAD'
570 2026 xplshn [anto@xplshn.com.ar](mailto:anto@xplshn.com.ar) */
571
572 /* routes argv[0] to the appropriate tool main */
573+#include "wexec.h"
574 #include "util.h"
575
576 #include <stdio.h>
577@@ -366,9 +367,9 @@ cat "${DECL_F}" >> "${DISP}"
578 cat >> "${DISP}" << 'DISPATCH_STRUCT'
579
580 struct Cmd {
581- const char *name;
582- int (*fn)(int, char **);
583- const char *cat;
584+ const char *name;
585+ int (*fn)(int, char **);
586+ const char *cat;
587 };
588
589 static struct Cmd cmds[] = {
590@@ -378,115 +379,118 @@ DISPATCH_STRUCT
591 # entries have the form: \t{ "name", fn_main, "cat" },
592 # splitting on " makes field 2 the tool name
593 for _c in posix linux net pseudo xsi extra; do
594- sort -t'"' -k2,2 "${BDIR}/entries_${_c}.inc"
595+ sort -t'"' -k2,2 "${BDIR}/entries_${_c}.inc"
596 done >> "${DISP}"
597 unset _c
598
599 cat >> "${DISP}" << 'DISPATCH_TAIL'
600- { NULL, NULL, NULL }
601+ { NULL, NULL, NULL }
602 };
603
604 static void
605 usage(void)
606 {
607- struct Cmd *c;
608- const char *last;
609- int col;
610-
611- last = NULL;
612- col = 0;
613- fprintf(stderr, "usage: %s [-i path] [command [args...]]\n", argv0);
614- for (c = cmds; c->name; c++) {
615- if (!last || strcmp(c->cat, last) != 0) {
616- if (last)
617- fprintf(stderr, "\n\n");
618- last = c->cat;
619- fprintf(stderr, "%s:\n", last);
620- col = 0;
621- }
622- if (col == 0) {
623- fprintf(stderr, "\t%s", c->name);
624- col = 8 + strlen(c->name);
625- } else if (col + 2 + strlen(c->name) >= 78) {
626- fprintf(stderr, ",\n\t%s", c->name);
627- col = 8 + strlen(c->name);
628- } else {
629- fprintf(stderr, ", %s", c->name);
630- col += 2 + strlen(c->name);
631- }
632- }
633- if (last)
634- fputc('\n', stderr);
635- exit(1);
636+ struct Cmd *c;
637+ const char *last;
638+ int col;
639+
640+ last = NULL;
641+ col = 0;
642+ fprintf(stderr, "usage: %s [-i path] [command [args...]]\n", argv0);
643+ for (c = cmds; c->name; c++) {
644+ if (!last || strcmp(c->cat, last) != 0) {
645+ if (last)
646+ fprintf(stderr, "\n\n");
647+ last = c->cat;
648+ fprintf(stderr, "%s:\n", last);
649+ col = 0;
650+ }
651+ if (col == 0) {
652+ fprintf(stderr, "\t%s", c->name);
653+ col = 8 + strlen(c->name);
654+ } else if (col + 2 + strlen(c->name) >= 78) {
655+ fprintf(stderr, ",\n\t%s", c->name);
656+ col = 8 + strlen(c->name);
657+ } else {
658+ fprintf(stderr, ", %s", c->name);
659+ col += 2 + strlen(c->name);
660+ }
661+ }
662+ if (last)
663+ fputc('\n', stderr);
664+ exit(1);
665 }
666
667 static void
668 x_install(const char *path)
669 {
670- struct Cmd *c;
671- char buf[4096];
672- int r;
673-
674- for (c = cmds; c->name; c++) {
675- r = snprintf(buf, sizeof buf, "%s/%s", path, c->name);
676- if (r < 0 || r >= (int)sizeof buf)
677- eprintf("install: '%s/%s': path too long\n", path, c->name);
678- remove(buf);
679- if (symlink("aruu-box", buf) < 0)
680- eprintf("install: symlink '%s':", buf);
681- }
682+ struct Cmd *c;
683+ char buf[4096];
684+ int r;
685+
686+ for (c = cmds; c->name; c++) {
687+ r = snprintf(buf, sizeof buf, "%s/%s", path, c->name);
688+ if (r < 0 || r >= (int)sizeof buf)
689+ eprintf("install: '%s/%s': path too long\n", path, c->name);
690+ remove(buf);
691+ if (symlink("aruu-box", buf) < 0)
692+ eprintf("install: symlink '%s':", buf);
693+ }
694 }
695
696 int
697 main(int argc, char *argv[])
698 {
699- struct Cmd *c;
700- char *s;
701-
702- argv0 = argv[0];
703-
704- s = strrchr(argv[0], '/');
705- if (s)
706- s++;
707- else
708- s = argv[0];
709-
710- if (strcmp(s, "aruu-box") == 0) {
711- if (argc < 2)
712- usage();
713- argc--;
714- argv++;
715- if (strcmp(argv[0], "-i") == 0) {
716- if (argc < 2)
717- eprintf("usage: aruu-box -i path\n");
718- x_install(argv[1]);
719- return 0;
720- }
721- s = strrchr(argv[0], '/');
722- if (s)
723- s++;
724- else
725- s = argv[0];
726- }
727- for (c = cmds; c->name; c++) {
728- if (strcmp(c->name, s) == 0) {
729- argv0 = (char *)c->name;
730- argv[0] = (char *)c->name;
731- return c->fn(argc, argv);
732- }
733- }
734- enprintf(127, "%s: not found\n", s);
735- return 1;
736+ struct Cmd *c;
737+ char *s;
738+
739+ argv0 = argv[0];
740+
741+ for (c = cmds; c->name; c++)
742+ wexec_register(c->name, c->fn);
743+
744+ s = strrchr(argv[0], '/');
745+ if (s)
746+ s++;
747+ else
748+ s = argv[0];
749+
750+ if (strcmp(s, "aruu-box") == 0) {
751+ if (argc < 2)
752+ usage();
753+ argc--;
754+ argv++;
755+ if (strcmp(argv[0], "-i") == 0) {
756+ if (argc < 2)
757+ eprintf("usage: aruu-box -i path\n");
758+ x_install(argv[1]);
759+ return 0;
760+ }
761+ s = strrchr(argv[0], '/');
762+ if (s)
763+ s++;
764+ else
765+ s = argv[0];
766+ }
767+ for (c = cmds; c->name; c++) {
768+ if (strcmp(c->name, s) == 0) {
769+ argv0 = (char *)c->name;
770+ argv[0] = (char *)c->name;
771+ return c->fn(argc, argv);
772+ }
773+ }
774+ enprintf(127, "%s: not found\n", s);
775+ return 1;
776 }
777 DISPATCH_TAIL
778
779 printf 'mkbox: cc dispatch\n'
780 eval "${CC} ${CPPFLAGS} ${CFLAGS} -c \"\$DISP\" -o \"\${BDIR}/aruu-box.o\"" ||
781- die "compile failed: dispatch"
782+ die "compile failed: dispatch"
783 OBJS="${OBJS} ${BDIR}/aruu-box.o"
784
785 printf 'mkbox: ld aruu-box\n'
786 eval "${CC} ${LDFLAGS} -o \"\$BOX\" \$OBJS \"\$LIBREDLINE\" \"\$LIBUTIL\" \"\$LIBUTF\" \${LDLIBS}" ||
787- die "link failed"
788+ die "link failed"
789
790 printf 'mkbox: done => %s\n' "${BOX}"
1@@ -1,13 +1,14 @@
2 /* See LICENSE file for copyright and license details. */
3+#include "paths.h"
4
5-#define ENV_PATH "/bin"
6-#define PW_CIPHER "$6$" /* sha-512 */
7+#define ENV_PATH ARUU_PATH_BIN
8+#define PW_CIPHER "$6$"
9 #undef UTMP_PATH
10-#define UTMP_PATH "/var/run/utmp"
11+#define UTMP_PATH ARUU_PATH_UTMP
12 #undef BTMP_PATH
13-#define BTMP_PATH "/var/log/btmp"
14+#define BTMP_PATH ARUU_PATH_BTMP
15 #undef WTMP_PATH
16-#define WTMP_PATH "/var/log/wtmp"
17+#define WTMP_PATH ARUU_PATH_WTMP
18
19 #ifndef FEATURE_FIND_DELETE
20 #define FEATURE_FIND_DELETE 1
21@@ -87,3 +88,36 @@
22 #ifndef FEATURE_LS_COLOR
23 #define FEATURE_LS_COLOR 1
24 #endif
25+#ifndef FEATURE_DIFF3_MERGE
26+#define FEATURE_DIFF3_MERGE 1
27+#endif
28+#ifndef FEATURE_DIFF3_EDSCRIPT
29+#define FEATURE_DIFF3_EDSCRIPT 1
30+#endif
31+#ifndef FEATURE_DIFF_CONTEXT
32+#define FEATURE_DIFF_CONTEXT 1
33+#endif
34+#ifndef FEATURE_DIFF_UNIFIED
35+#define FEATURE_DIFF_UNIFIED 1
36+#endif
37+#ifndef FEATURE_DIFF_ED
38+#define FEATURE_DIFF_ED 1
39+#endif
40+#ifndef FEATURE_DIFF_BRIEF
41+#define FEATURE_DIFF_BRIEF 1
42+#endif
43+#ifndef FEATURE_DIFF_SIDEBYSIDE
44+#define FEATURE_DIFF_SIDEBYSIDE 1
45+#endif
46+#ifndef FEATURE_PATCH_BACKUP
47+#define FEATURE_PATCH_BACKUP 1
48+#endif
49+#ifndef FEATURE_PATCH_FUZZ
50+#define FEATURE_PATCH_FUZZ 1
51+#endif
52+#ifndef FEATURE_PATCH_STRIP_CR
53+#define FEATURE_PATCH_STRIP_CR 1
54+#endif
55+#ifndef FEATURE_INPROC_EXEC
56+#define FEATURE_INPROC_EXEC 0
57+#endif
1@@ -0,0 +1,66 @@
2+/* See LICENSE file for copyright and license details. */
3+#ifndef ARUU_DIFFUTIL_H
4+#define ARUU_DIFFUTIL_H
5+
6+#include <stdio.h>
7+#include <sys/types.h>
8+
9+struct diffline {
10+ char *data;
11+ size_t len;
12+};
13+
14+struct difffile {
15+ struct diffline *lines;
16+ size_t nlines;
17+};
18+
19+struct diffrange {
20+ size_t from;
21+ size_t to;
22+};
23+
24+struct diffhunk {
25+ struct diffrange old;
26+ struct diffrange new;
27+};
28+
29+struct diffhunks {
30+ struct diffhunk *v;
31+ size_t n;
32+};
33+
34+enum diffformat {
35+ DIFF_NORMAL,
36+ DIFF_UNIFIED,
37+ DIFF_CONTEXT,
38+ DIFF_ED,
39+ DIFF_RCSED,
40+ DIFF_BRIEF,
41+};
42+
43+struct diffopts {
44+ enum diffformat format;
45+ size_t context;
46+ int ignore_case;
47+ int ignore_blanks;
48+ int strip_cr;
49+ int treat_binary;
50+};
51+
52+#define DIFF_SAME 0
53+#define DIFF_DIFFER 1
54+#define DIFF_ERROR 2
55+
56+int diff_load(struct difffile *df, const char *path);
57+void diff_free(struct difffile *df);
58+int diff_compute(struct diffhunks *hunks, const struct difffile *old,
59+ const struct difffile *new, const struct diffopts *opts);
60+void diff_hunks_free(struct diffhunks *hunks);
61+int diff_format(FILE *out, const struct diffhunks *hunks,
62+ const struct difffile *old, const struct difffile *new,
63+ const char *oldlabel, const char *newlabel,
64+ const struct diffopts *opts);
65+int diff_looks_binary(const struct difffile *df);
66+
67+#endif
1@@ -2,30 +2,21 @@
2 #ifndef ARUU_DISKUTIL_H
3 #define ARUU_DISKUTIL_H
4
5+#include "paths.h"
6+
7 #include <stddef.h>
8 #include <stdint.h>
9
10-#ifndef PATH_DEV
11-#define PATH_DEV "/dev"
12-#endif
13-
14-#ifndef PATH_PROC
15-#define PATH_PROC "/proc"
16-#endif
17-
18-#define PATH_PARTITIONS PATH_PROC "/partitions"
19-#define PATH_MOUNTS PATH_PROC "/mounts"
20-
21 struct BlockDev {
22 int fd;
23- uint64_t size; /* size in bytes */
24- size_t sec_size; /* sector size */
25+ uint64_t size;
26+ size_t sec_size;
27 };
28
29 struct BlockDevInfo {
30 char name[32];
31- char path[128]; /* absolute path to device node */
32- char type[16]; /* disk, part, loop */
33+ char path[128];
34+ char type[16];
35 uint64_t size;
36 int major;
37 int minor;
38@@ -37,14 +28,14 @@ struct BlockDevInfo {
39
40 int blockdev_open(struct BlockDev *dev, const char *path, int writable);
41 int blockdev_read(struct BlockDev *dev, uint64_t sector, void *buf,
42- size_t sector_count);
43+ size_t sector_count);
44 int blockdev_write(struct BlockDev *dev, uint64_t sector, const void *buf,
45- size_t sector_count);
46+ size_t sector_count);
47 void blockdev_close(struct BlockDev *dev);
48
49 int blockdev_detect_fs(struct BlockDev *dev, char *type, size_t type_sz,
50- char *label, size_t label_sz, char *uuid,
51- size_t uuid_sz);
52+ char *label, size_t label_sz, char *uuid,
53+ size_t uuid_sz);
54
55 struct BlockDevInfo *blockdev_get_list(void);
56 void blockdev_free_list(struct BlockDevInfo *list);
1@@ -1,5 +1,6 @@
2 /* see license file for copyright and license details */
3
4+#include "../paths.h"
5 #include "redline.h"
6
7 #include <ctype.h>
8@@ -41,26 +42,26 @@
9 #define ESC 27
10
11 struct redlineState {
12- int in_completion;
13- int ifd;
14- int ofd;
15- char *buf;
16- size_t buflen;
17- const char *prompt;
18- size_t plen;
19- size_t pos;
20- size_t oldpos;
21- size_t len;
22- size_t cols;
23- size_t oldrows;
24- int oldrpos;
25- int history_index;
26+ int in_completion;
27+ int ifd;
28+ int ofd;
29+ char *buf;
30+ size_t buflen;
31+ const char *prompt;
32+ size_t plen;
33+ size_t pos;
34+ size_t oldpos;
35+ size_t len;
36+ size_t cols;
37+ size_t oldrows;
38+ int oldrpos;
39+ int history_index;
40 };
41
42
43 struct abuf {
44- char *b;
45- int len;
46+ char *b;
47+ int len;
48 };
49
50 static struct termios orig_termios;
51@@ -79,1334 +80,1334 @@ static void (*completionCallback)(const char *, struct redlineCompletions *) = N
52 static int
53 utf8ByteLen(char c)
54 {
55- unsigned char uc = (unsigned char)c;
56- if ((uc & 0x80) == 0) return 1;
57- if ((uc & 0xE0) == 0xC0) return 2;
58- if ((uc & 0xF0) == 0xE0) return 3;
59- if ((uc & 0xF8) == 0xF0) return 4;
60- return 1;
61+ unsigned char uc = (unsigned char)c;
62+ if ((uc & 0x80) == 0) return 1;
63+ if ((uc & 0xE0) == 0xC0) return 2;
64+ if ((uc & 0xF0) == 0xE0) return 3;
65+ if ((uc & 0xF8) == 0xF0) return 4;
66+ return 1;
67 }
68
69 /* decode character starting at s */
70 static uint32_t
71 utf8DecodeChar(const char *s, size_t *len)
72 {
73- uint32_t cp = 0;
74- int l = utf8ByteLen(*s);
75- *len = l;
76- if (l == 1) {
77- cp = ((unsigned char)*s);
78- } else if (l == 2) {
79- cp = ((unsigned char)*s & 0x1F) << 6;
80- cp |= ((unsigned char)*(s+1) & 0x3F);
81- } else if (l == 3) {
82- cp = ((unsigned char)*s & 0x0F) << 12;
83- cp |= ((unsigned char)*(s+1) & 0x3F) << 6;
84- cp |= ((unsigned char)*(s+2) & 0x3F);
85- } else if (l == 4) {
86- cp = ((unsigned char)*s & 0x07) << 18;
87- cp |= ((unsigned char)*(s+1) & 0x3F) << 12;
88- cp |= ((unsigned char)*(s+2) & 0x3F) << 6;
89- cp |= ((unsigned char)*(s+3) & 0x3F);
90- }
91- return cp;
92+ uint32_t cp = 0;
93+ int l = utf8ByteLen(*s);
94+ *len = l;
95+ if (l == 1) {
96+ cp = ((unsigned char)*s);
97+ } else if (l == 2) {
98+ cp = ((unsigned char)*s & 0x1F) << 6;
99+ cp |= ((unsigned char)*(s+1) & 0x3F);
100+ } else if (l == 3) {
101+ cp = ((unsigned char)*s & 0x0F) << 12;
102+ cp |= ((unsigned char)*(s+1) & 0x3F) << 6;
103+ cp |= ((unsigned char)*(s+2) & 0x3F);
104+ } else if (l == 4) {
105+ cp = ((unsigned char)*s & 0x07) << 18;
106+ cp |= ((unsigned char)*(s+1) & 0x3F) << 12;
107+ cp |= ((unsigned char)*(s+2) & 0x3F) << 6;
108+ cp |= ((unsigned char)*(s+3) & 0x3F);
109+ }
110+ return cp;
111 }
112
113 static int
114 isZWJ(uint32_t cp)
115 {
116- return cp == 0x200D;
117+ return cp == 0x200D;
118 }
119
120 static int
121 isCombiningMark(uint32_t cp)
122 {
123- return (cp >= 0x0300 && cp <= 0x036F) || (cp >= 0x1DC0 && cp <= 0x1DFF) ||
124- (cp >= 0x20D0 && cp <= 0x20FF) || (cp >= 0xFE20 && cp <= 0xFE2F);
125+ return (cp >= 0x0300 && cp <= 0x036F) || (cp >= 0x1DC0 && cp <= 0x1DFF) ||
126+ (cp >= 0x20D0 && cp <= 0x20FF) || (cp >= 0xFE20 && cp <= 0xFE2F);
127 }
128
129 static int
130 isVariationSelector(uint32_t cp)
131 {
132- return (cp >= 0xFE00 && cp <= 0xFE0F) || (cp >= 0xE0100 && cp <= 0xE01EF);
133+ return (cp >= 0xFE00 && cp <= 0xFE0F) || (cp >= 0xE0100 && cp <= 0xE01EF);
134 }
135
136 static int
137 isSkinToneModifier(uint32_t cp)
138 {
139- return cp >= 0x1F3FB && cp <= 0x1F3FF;
140+ return cp >= 0x1F3FB && cp <= 0x1F3FF;
141 }
142
143
144 static int
145 isGraphemeExtend(uint32_t cp)
146 {
147- return isCombiningMark(cp) || isVariationSelector(cp) || isSkinToneModifier(cp);
148+ return isCombiningMark(cp) || isVariationSelector(cp) || isSkinToneModifier(cp);
149 }
150
151 /* decode character going backward from pos */
152 static uint32_t
153 utf8DecodePrev(const char *buf, size_t pos, size_t *cplen)
154 {
155- size_t i = 1;
156- while (pos >= i && i <= 4) {
157- unsigned char uc = (unsigned char)buf[pos-i];
158- if ((uc & 0x80) == 0) {
159- if (i == 1) {
160- *cplen = 1;
161- return uc;
162- }
163- break;
164- }
165- if ((uc & 0xC0) == 0xC0) {
166- int l = utf8ByteLen(buf[pos-i]);
167- if ((size_t)l == i) {
168- *cplen = i;
169- return utf8DecodeChar(buf + pos - i, cplen);
170- }
171- break;
172- }
173- i++;
174- }
175- *cplen = 1;
176- return (unsigned char)buf[pos-1];
177+ size_t i = 1;
178+ while (pos >= i && i <= 4) {
179+ unsigned char uc = (unsigned char)buf[pos-i];
180+ if ((uc & 0x80) == 0) {
181+ if (i == 1) {
182+ *cplen = 1;
183+ return uc;
184+ }
185+ break;
186+ }
187+ if ((uc & 0xC0) == 0xC0) {
188+ int l = utf8ByteLen(buf[pos-i]);
189+ if ((size_t)l == i) {
190+ *cplen = i;
191+ return utf8DecodeChar(buf + pos - i, cplen);
192+ }
193+ break;
194+ }
195+ i++;
196+ }
197+ *cplen = 1;
198+ return (unsigned char)buf[pos-1];
199 }
200
201 /* calculate width of utf-8 char pos */
202 static size_t
203 utf8PrevCharLen(const char *buf, size_t pos)
204 {
205- size_t len = 0;
206- size_t next_len = 0;
207- uint32_t cp;
208- if (pos == 0) return 0;
209- cp = utf8DecodePrev(buf, pos, &len);
210- pos -= len;
211- while (pos > 0 && isGraphemeExtend(cp)) {
212- cp = utf8DecodePrev(buf, pos, &next_len);
213- len += next_len;
214- pos -= next_len;
215- }
216- if (pos > 0 && isZWJ(cp)) {
217- size_t j = utf8PrevCharLen(buf, pos);
218- if (j > 0) len += j;
219- }
220- return len;
221+ size_t len = 0;
222+ size_t next_len = 0;
223+ uint32_t cp;
224+ if (pos == 0) return 0;
225+ cp = utf8DecodePrev(buf, pos, &len);
226+ pos -= len;
227+ while (pos > 0 && isGraphemeExtend(cp)) {
228+ cp = utf8DecodePrev(buf, pos, &next_len);
229+ len += next_len;
230+ pos -= next_len;
231+ }
232+ if (pos > 0 && isZWJ(cp)) {
233+ size_t j = utf8PrevCharLen(buf, pos);
234+ if (j > 0) len += j;
235+ }
236+ return len;
237 }
238
239 /* calculate width of next utf-8 char */
240 static size_t
241 utf8NextCharLen(const char *buf, size_t pos, size_t len)
242 {
243- size_t clen = 0;
244- size_t offset = 0;
245- uint32_t cp;
246- if (pos >= len) return 0;
247- cp = utf8DecodeChar(buf + pos, &clen);
248- offset = clen;
249- while (pos + offset < len) {
250- size_t next_len = 0;
251- uint32_t next_cp = utf8DecodeChar(buf + pos + offset, &next_len);
252- if (isGraphemeExtend(next_cp)) {
253- offset += next_len;
254- } else if (isZWJ(cp)) {
255- offset += next_len;
256- cp = next_cp;
257- } else {
258- break;
259- }
260- }
261- return offset;
262+ size_t clen = 0;
263+ size_t offset = 0;
264+ uint32_t cp;
265+ if (pos >= len) return 0;
266+ cp = utf8DecodeChar(buf + pos, &clen);
267+ offset = clen;
268+ while (pos + offset < len) {
269+ size_t next_len = 0;
270+ uint32_t next_cp = utf8DecodeChar(buf + pos + offset, &next_len);
271+ if (isGraphemeExtend(next_cp)) {
272+ offset += next_len;
273+ } else if (isZWJ(cp)) {
274+ offset += next_len;
275+ cp = next_cp;
276+ } else {
277+ break;
278+ }
279+ }
280+ return offset;
281 }
282
283 /* get columns needed to display char */
284 static int
285 utf8CharWidth(uint32_t cp)
286 {
287- if (cp == 0) return 0;
288- if (cp < 0x20 || (cp >= 0x7f && cp < 0xa0)) return 0;
289- if ((cp >= 0x1100 && cp <= 0x115f) ||
290- (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) ||
291- (cp >= 0xac00 && cp <= 0xd7a3) ||
292- (cp >= 0xf900 && cp <= 0xfaff) ||
293- (cp >= 0xfe10 && cp <= 0xfe19) ||
294- (cp >= 0xfe30 && cp <= 0xfe6f) ||
295- (cp >= 0xff00 && cp <= 0xff60) ||
296- (cp >= 0xffe0 && cp <= 0xffe6) ||
297- (cp >= 0x20000 && cp <= 0x2fffd) ||
298- (cp >= 0x30000 && cp <= 0x3fffd)) {
299- return 2;
300- }
301- return 1;
302+ if (cp == 0) return 0;
303+ if (cp < 0x20 || (cp >= 0x7f && cp < 0xa0)) return 0;
304+ if ((cp >= 0x1100 && cp <= 0x115f) ||
305+ (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) ||
306+ (cp >= 0xac00 && cp <= 0xd7a3) ||
307+ (cp >= 0xf900 && cp <= 0xfaff) ||
308+ (cp >= 0xfe10 && cp <= 0xfe19) ||
309+ (cp >= 0xfe30 && cp <= 0xfe6f) ||
310+ (cp >= 0xff00 && cp <= 0xff60) ||
311+ (cp >= 0xffe0 && cp <= 0xffe6) ||
312+ (cp >= 0x20000 && cp <= 0x2fffd) ||
313+ (cp >= 0x30000 && cp <= 0x3fffd)) {
314+ return 2;
315+ }
316+ return 1;
317 }
318
319 /* get ansi escape sequence length */
320 static size_t
321 ansiEscapeLen(const char *s, size_t len)
322 {
323- size_t i = 0;
324- if (len < 2 || s[0] != '\x1b' || s[1] != '[') return 0;
325- i = 2;
326- while (i < len) {
327- char c = s[i];
328- if ((c >= '0' && c <= '9') || c == ';' || c == '?' || c == '"') {
329- i++;
330- } else if (c >= 'A' && c <= 'Z') {
331- return i + 1;
332- } else if (c >= 'a' && c <= 'z') {
333- return i + 1;
334- } else {
335- break;
336- }
337- }
338- return 0;
339+ size_t i = 0;
340+ if (len < 2 || s[0] != '\x1b' || s[1] != '[') return 0;
341+ i = 2;
342+ while (i < len) {
343+ char c = s[i];
344+ if ((c >= '0' && c <= '9') || c == ';' || c == '?' || c == '"') {
345+ i++;
346+ } else if (c >= 'A' && c <= 'Z') {
347+ return i + 1;
348+ } else if (c >= 'a' && c <= 'z') {
349+ return i + 1;
350+ } else {
351+ break;
352+ }
353+ }
354+ return 0;
355 }
356
357 /* calculate width of string */
358 static size_t
359 utf8StrWidth(const char *s, size_t len)
360 {
361- size_t width = 0;
362- size_t i = 0;
363- while (i < len) {
364- size_t elen = ansiEscapeLen(s + i, len - i);
365- if (elen > 0) {
366- i += elen;
367- continue;
368- }
369- size_t clen = 0;
370- uint32_t cp = utf8DecodeChar(s + i, &clen);
371- width += utf8CharWidth(cp);
372- i += clen;
373- }
374- return width;
375+ size_t width = 0;
376+ size_t i = 0;
377+ while (i < len) {
378+ size_t elen = ansiEscapeLen(s + i, len - i);
379+ if (elen > 0) {
380+ i += elen;
381+ continue;
382+ }
383+ size_t clen = 0;
384+ uint32_t cp = utf8DecodeChar(s + i, &clen);
385+ width += utf8CharWidth(cp);
386+ i += clen;
387+ }
388+ return width;
389 }
390
391 /* get single character width */
392 static int
393 utf8SingleCharWidth(const char *s, size_t len)
394 {
395- size_t clen = 0;
396- uint32_t cp = utf8DecodeChar(s, &clen);
397- (void)len;
398- return utf8CharWidth(cp);
399+ size_t clen = 0;
400+ uint32_t cp = utf8DecodeChar(s, &clen);
401+ (void)len;
402+ return utf8CharWidth(cp);
403 }
404
405 static int
406 isUnsupportedTerm(void)
407 {
408- char *term = getenv("TERM");
409- int i;
410- static char *unsupported[] = {"dumb", "cons25", "emacs", NULL};
411- if (term == NULL) return 0;
412- for (i = 0; unsupported[i]; i++) {
413- if (strcasecmp(term, unsupported[i]) == 0)
414- return 1;
415- }
416- return 0;
417+ char *term = getenv("TERM");
418+ int i;
419+ static char *unsupported[] = {"dumb", "cons25", "emacs", NULL};
420+ if (term == NULL) return 0;
421+ for (i = 0; unsupported[i]; i++) {
422+ if (strcasecmp(term, unsupported[i]) == 0)
423+ return 1;
424+ }
425+ return 0;
426 }
427
428 static void
429 sigwinchHandler(int sig)
430 {
431- (void)sig;
432- winch_received = 1;
433+ (void)sig;
434+ winch_received = 1;
435 }
436
437 static int
438 enableRawMode(int fd)
439 {
440- struct termios raw;
441- struct sigaction sa;
442-
443- if (!isatty(STDIN_FILENO))
444- return -1;
445- if (tcgetattr(fd, &orig_termios) == -1)
446- return -1;
447-
448- raw = orig_termios;
449- raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
450- raw.c_oflag &= ~(OPOST);
451- raw.c_cflag |= (CS8);
452- raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
453- raw.c_cc[VMIN] = 1;
454- raw.c_cc[VTIME] = 0;
455-
456- if (tcsetattr(fd, TCSAFLUSH, &raw) < 0)
457- return -1;
458-
459- rawmode = 1;
460-
461- /* register sigwinch handler */
462- sa.sa_handler = sigwinchHandler;
463- sigemptyset(&sa.sa_mask);
464- sa.sa_flags = 0;
465- sigaction(SIGWINCH, &sa, &orig_sigwinch);
466-
467- return 0;
468+ struct termios raw;
469+ struct sigaction sa;
470+
471+ if (!isatty(STDIN_FILENO))
472+ return -1;
473+ if (tcgetattr(fd, &orig_termios) == -1)
474+ return -1;
475+
476+ raw = orig_termios;
477+ raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
478+ raw.c_oflag &= ~(OPOST);
479+ raw.c_cflag |= (CS8);
480+ raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
481+ raw.c_cc[VMIN] = 1;
482+ raw.c_cc[VTIME] = 0;
483+
484+ if (tcsetattr(fd, TCSAFLUSH, &raw) < 0)
485+ return -1;
486+
487+ rawmode = 1;
488+
489+ /* register sigwinch handler */
490+ sa.sa_handler = sigwinchHandler;
491+ sigemptyset(&sa.sa_mask);
492+ sa.sa_flags = 0;
493+ sigaction(SIGWINCH, &sa, &orig_sigwinch);
494+
495+ return 0;
496 }
497
498 static void
499 disableRawMode(int fd)
500 {
501- if (rawmode) {
502- tcsetattr(fd, TCSAFLUSH, &orig_termios);
503- sigaction(SIGWINCH, &orig_sigwinch, NULL);
504- rawmode = 0;
505- }
506+ if (rawmode) {
507+ tcsetattr(fd, TCSAFLUSH, &orig_termios);
508+ sigaction(SIGWINCH, &orig_sigwinch, NULL);
509+ rawmode = 0;
510+ }
511 }
512
513 static int
514 getCursorPosition(int ifd, int ofd)
515 {
516- char buf[32];
517- int cols, rows;
518- unsigned int i = 0;
519-
520- if (write(ofd, "\x1b[6n", 4) != 4) return -1;
521-
522- while (i < sizeof(buf)-1) {
523- if (read(ifd,buf+i,1) != 1) break;
524- if (buf[i] == 'R') break;
525- i++;
526- }
527- buf[i] = '\0';
528-
529- if (buf[0] != 27 || buf[1] != '[') return -1;
530- if (sscanf(buf+2,"%d;%d",&rows,&cols) != 2) return -1;
531- return cols;
532+ char buf[32];
533+ int cols, rows;
534+ unsigned int i = 0;
535+
536+ if (write(ofd, "\x1b[6n", 4) != 4) return -1;
537+
538+ while (i < sizeof(buf)-1) {
539+ if (read(ifd,buf+i,1) != 1) break;
540+ if (buf[i] == 'R') break;
541+ i++;
542+ }
543+ buf[i] = '\0';
544+
545+ if (buf[0] != 27 || buf[1] != '[') return -1;
546+ if (sscanf(buf+2,"%d;%d",&rows,&cols) != 2) return -1;
547+ return cols;
548 }
549
550 static int
551 getColumns(int ifd, int ofd)
552 {
553- struct winsize ws;
554- char *cols_env;
555- int tty_fd;
556- int cols = 0;
557-
558- if (ioctl(ofd, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20)
559- return ws.ws_col;
560- if (ioctl(ifd, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20)
561- return ws.ws_col;
562- if (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20)
563- return ws.ws_col;
564- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20)
565- return ws.ws_col;
566- if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20)
567- return ws.ws_col;
568-
569- tty_fd = open("/dev/tty", O_RDWR | O_NOCTTY);
570- if (tty_fd >= 0) {
571- if (ioctl(tty_fd, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20) {
572- cols = ws.ws_col;
573- }
574- close(tty_fd);
575- if (cols >= 20) return cols;
576- }
577-
578- cols_env = getenv("COLUMNS");
579- if (cols_env) {
580- cols = atoi(cols_env);
581- if (cols >= 20) return cols;
582- }
583-
584- /* fallback to cursor position query */
585- int start;
586-
587- if (!isatty(ifd) || !isatty(ofd)) return 80;
588-
589- start = getCursorPosition(ifd,ofd);
590- if (start == -1) return 80;
591-
592- if (write(ofd,"\x1b[999C",6) != 6) return 80;
593- cols = getCursorPosition(ifd,ofd);
594- if (cols == -1) return 80;
595-
596- if (cols > start) {
597- char seq[32];
598- snprintf(seq,sizeof(seq),"\x1b[%dD",cols-start);
599- if (write(ofd,seq,strlen(seq)) == -1) {}
600- }
601- if (cols < 20) return 80;
602- return cols;
603+ struct winsize ws;
604+ char *cols_env;
605+ int tty_fd;
606+ int cols = 0;
607+
608+ if (ioctl(ofd, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20)
609+ return ws.ws_col;
610+ if (ioctl(ifd, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20)
611+ return ws.ws_col;
612+ if (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20)
613+ return ws.ws_col;
614+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20)
615+ return ws.ws_col;
616+ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20)
617+ return ws.ws_col;
618+
619+ tty_fd = open(ARUU_PATH_DEVTTY, O_RDWR | O_NOCTTY);
620+ if (tty_fd >= 0) {
621+ if (ioctl(tty_fd, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 20) {
622+ cols = ws.ws_col;
623+ }
624+ close(tty_fd);
625+ if (cols >= 20) return cols;
626+ }
627+
628+ cols_env = getenv("COLUMNS");
629+ if (cols_env) {
630+ cols = atoi(cols_env);
631+ if (cols >= 20) return cols;
632+ }
633+
634+ /* fallback to cursor position query */
635+ int start;
636+
637+ if (!isatty(ifd) || !isatty(ofd)) return 80;
638+
639+ start = getCursorPosition(ifd,ofd);
640+ if (start == -1) return 80;
641+
642+ if (write(ofd,"\x1b[999C",6) != 6) return 80;
643+ cols = getCursorPosition(ifd,ofd);
644+ if (cols == -1) return 80;
645+
646+ if (cols > start) {
647+ char seq[32];
648+ snprintf(seq,sizeof(seq),"\x1b[%dD",cols-start);
649+ if (write(ofd,seq,strlen(seq)) == -1) {}
650+ }
651+ if (cols < 20) return 80;
652+ return cols;
653 }
654
655 static void
656 redlineBeep(void)
657 {
658- fprintf(stderr, "\x7");
659- fflush(stderr);
660+ fprintf(stderr, "\x7");
661+ fflush(stderr);
662 }
663
664 static void
665 freeCompletions(struct redlineCompletions *lc)
666 {
667- size_t i;
668- if (lc->cvec) {
669- for (i = 0; i < lc->len; i++) {
670- free(lc->cvec[i]);
671- }
672- free(lc->cvec);
673- }
674+ size_t i;
675+ if (lc->cvec) {
676+ for (i = 0; i < lc->len; i++) {
677+ free(lc->cvec[i]);
678+ }
679+ free(lc->cvec);
680+ }
681 }
682
683 static size_t
684 longestCommonPrefix(struct redlineCompletions *lc)
685 {
686- size_t i, j;
687- if (lc->len == 0) return 0;
688- for (i = 0; ; i++) {
689- char c = lc->cvec[0][i];
690- if (c == '\0') return i;
691- for (j = 1; j < lc->len; j++) {
692- if (lc->cvec[j][i] != c) {
693- return i;
694- }
695- }
696- }
697+ size_t i, j;
698+ if (lc->len == 0) return 0;
699+ for (i = 0; ; i++) {
700+ char c = lc->cvec[0][i];
701+ if (c == '\0') return i;
702+ for (j = 1; j < lc->len; j++) {
703+ if (lc->cvec[j][i] != c) {
704+ return i;
705+ }
706+ }
707+ }
708 }
709
710 static void
711 printCompletions(struct redlineState *ls, struct redlineCompletions *lc)
712 {
713- size_t max_len = 0;
714- size_t i, j, k;
715- size_t col_width, num_cols, num_rows;
716- size_t sp, len, idx;
717- const char *comp;
718- const char *name;
719-
720- for (i = 0; i < lc->len; i++) {
721- comp = lc->cvec[i];
722- sp = strlen(comp);
723- if (sp > 0 && comp[sp-1] == ' ') {
724- sp--;
725- }
726- while (sp > 0 && comp[sp-1] != ' ') {
727- sp--;
728- }
729- len = strlen(comp + sp);
730- if (len > 0 && (comp + sp)[len-1] == ' ') {
731- len--;
732- }
733- if (len > max_len) {
734- max_len = len;
735- }
736- }
737-
738- col_width = max_len + 2;
739- num_cols = ls->cols / col_width;
740- if (num_cols == 0) num_cols = 1;
741- num_rows = (lc->len + num_cols - 1) / num_cols;
742-
743- if (write(ls->ofd, "\r\n", 2) == -1) {}
744- for (i = 0; i < num_rows; i++) {
745- for (j = 0; j < num_cols; j++) {
746- idx = j * num_rows + i;
747- if (idx < lc->len) {
748- comp = lc->cvec[idx];
749- sp = strlen(comp);
750- if (sp > 0 && comp[sp-1] == ' ') {
751- sp--;
752- }
753- while (sp > 0 && comp[sp-1] != ' ') {
754- sp--;
755- }
756- name = comp + sp;
757- len = strlen(name);
758- if (len > 0 && name[len-1] == ' ') {
759- len--;
760- }
761- if (write(ls->ofd, name, len) == -1) {}
762- if (j < num_cols - 1) {
763- for (k = len; k < col_width; k++) {
764- if (write(ls->ofd, " ", 1) == -1) {}
765- }
766- }
767- }
768- }
769- if (write(ls->ofd, "\r\n", 2) == -1) {}
770- }
771+ size_t max_len = 0;
772+ size_t i, j, k;
773+ size_t col_width, num_cols, num_rows;
774+ size_t sp, len, idx;
775+ const char *comp;
776+ const char *name;
777+
778+ for (i = 0; i < lc->len; i++) {
779+ comp = lc->cvec[i];
780+ sp = strlen(comp);
781+ if (sp > 0 && comp[sp-1] == ' ') {
782+ sp--;
783+ }
784+ while (sp > 0 && comp[sp-1] != ' ') {
785+ sp--;
786+ }
787+ len = strlen(comp + sp);
788+ if (len > 0 && (comp + sp)[len-1] == ' ') {
789+ len--;
790+ }
791+ if (len > max_len) {
792+ max_len = len;
793+ }
794+ }
795+
796+ col_width = max_len + 2;
797+ num_cols = ls->cols / col_width;
798+ if (num_cols == 0) num_cols = 1;
799+ num_rows = (lc->len + num_cols - 1) / num_cols;
800+
801+ if (write(ls->ofd, "\r\n", 2) == -1) {}
802+ for (i = 0; i < num_rows; i++) {
803+ for (j = 0; j < num_cols; j++) {
804+ idx = j * num_rows + i;
805+ if (idx < lc->len) {
806+ comp = lc->cvec[idx];
807+ sp = strlen(comp);
808+ if (sp > 0 && comp[sp-1] == ' ') {
809+ sp--;
810+ }
811+ while (sp > 0 && comp[sp-1] != ' ') {
812+ sp--;
813+ }
814+ name = comp + sp;
815+ len = strlen(name);
816+ if (len > 0 && name[len-1] == ' ') {
817+ len--;
818+ }
819+ if (write(ls->ofd, name, len) == -1) {}
820+ if (j < num_cols - 1) {
821+ for (k = len; k < col_width; k++) {
822+ if (write(ls->ofd, " ", 1) == -1) {}
823+ }
824+ }
825+ }
826+ }
827+ if (write(ls->ofd, "\r\n", 2) == -1) {}
828+ }
829 }
830
831 static void
832 abInit(struct abuf *ab)
833 {
834- ab->b = NULL;
835- ab->len = 0;
836+ ab->b = NULL;
837+ ab->len = 0;
838 }
839
840 static void
841 abAppend(struct abuf *ab, const char *s, int len)
842 {
843- char *new = realloc(ab->b,ab->len+len);
844- if (new == NULL) return;
845- memcpy(new+ab->len,s,len);
846- ab->b = new;
847- ab->len += len;
848+ char *new = realloc(ab->b,ab->len+len);
849+ if (new == NULL) return;
850+ memcpy(new+ab->len,s,len);
851+ ab->b = new;
852+ ab->len += len;
853 }
854
855 static void
856 abFree(struct abuf *ab)
857 {
858- free(ab->b);
859+ free(ab->b);
860 }
861
862 static void
863 refreshSingleLine(struct redlineState *l, int flags)
864 {
865- char seq[64];
866- size_t pwidth = utf8StrWidth(l->prompt, l->plen);
867- int fd = l->ofd;
868- char *buf = l->buf;
869- size_t len = l->len;
870- size_t pos = l->pos;
871- size_t poscol;
872- size_t lencol;
873- struct abuf ab;
874-
875- poscol = utf8StrWidth(buf, pos);
876- lencol = utf8StrWidth(buf, len);
877-
878- while (pwidth + poscol >= l->cols) {
879- size_t clen = utf8NextCharLen(buf, 0, len);
880- int cwidth = utf8SingleCharWidth(buf, clen);
881- buf += clen;
882- len -= clen;
883- pos -= clen;
884- poscol -= cwidth;
885- lencol -= cwidth;
886- }
887-
888- while (pwidth + lencol > l->cols) {
889- size_t clen = utf8PrevCharLen(buf, len);
890- int cwidth = utf8SingleCharWidth(buf + len - clen, clen);
891- len -= clen;
892- lencol -= cwidth;
893- }
894-
895- abInit(&ab);
896- snprintf(seq,sizeof(seq),"\r");
897- abAppend(&ab,seq,strlen(seq));
898-
899- if (flags & 1) {
900- abAppend(&ab,l->prompt,l->plen);
901- abAppend(&ab,buf,len);
902- }
903-
904- snprintf(seq,sizeof(seq),"\x1b[0K");
905- abAppend(&ab,seq,strlen(seq));
906-
907- if (flags & 1) {
908- snprintf(seq,sizeof(seq),"\r\x1b[%dC", (int)(poscol+pwidth));
909- abAppend(&ab,seq,strlen(seq));
910- }
911-
912- if (write(fd,ab.b,ab.len) == -1) {}
913- abFree(&ab);
914+ char seq[64];
915+ size_t pwidth = utf8StrWidth(l->prompt, l->plen);
916+ int fd = l->ofd;
917+ char *buf = l->buf;
918+ size_t len = l->len;
919+ size_t pos = l->pos;
920+ size_t poscol;
921+ size_t lencol;
922+ struct abuf ab;
923+
924+ poscol = utf8StrWidth(buf, pos);
925+ lencol = utf8StrWidth(buf, len);
926+
927+ while (pwidth + poscol >= l->cols) {
928+ size_t clen = utf8NextCharLen(buf, 0, len);
929+ int cwidth = utf8SingleCharWidth(buf, clen);
930+ buf += clen;
931+ len -= clen;
932+ pos -= clen;
933+ poscol -= cwidth;
934+ lencol -= cwidth;
935+ }
936+
937+ while (pwidth + lencol > l->cols) {
938+ size_t clen = utf8PrevCharLen(buf, len);
939+ int cwidth = utf8SingleCharWidth(buf + len - clen, clen);
940+ len -= clen;
941+ lencol -= cwidth;
942+ }
943+
944+ abInit(&ab);
945+ snprintf(seq,sizeof(seq),"\r");
946+ abAppend(&ab,seq,strlen(seq));
947+
948+ if (flags & 1) {
949+ abAppend(&ab,l->prompt,l->plen);
950+ abAppend(&ab,buf,len);
951+ }
952+
953+ snprintf(seq,sizeof(seq),"\x1b[0K");
954+ abAppend(&ab,seq,strlen(seq));
955+
956+ if (flags & 1) {
957+ snprintf(seq,sizeof(seq),"\r\x1b[%dC", (int)(poscol+pwidth));
958+ abAppend(&ab,seq,strlen(seq));
959+ }
960+
961+ if (write(fd,ab.b,ab.len) == -1) {}
962+ abFree(&ab);
963 }
964
965 static void
966 refreshMultiLine(struct redlineState *l, int flags)
967 {
968- char seq[64];
969- size_t pwidth = utf8StrWidth(l->prompt, l->plen);
970- size_t bufwidth;
971- size_t poswidth;
972- int rows;
973- int rpos2;
974- int col;
975- int old_rows = l->oldrows;
976- int rpos = l->oldrpos;
977- int fd = l->ofd, j;
978- struct abuf ab;
979-
980- (void)flags;
981-
982- bufwidth = utf8StrWidth(l->buf, l->len);
983- poswidth = utf8StrWidth(l->buf, l->pos);
984- rows = (pwidth+bufwidth+l->cols-1)/l->cols;
985- l->oldrows = rows;
986-
987- abInit(&ab);
988-
989- /* move cursor up to the first row, column 0 of the input area */
990- if (rpos > 1) {
991- snprintf(seq, 64, "\r\x1b[%dA", rpos - 1);
992- abAppend(&ab, seq, strlen(seq));
993- } else {
994- abAppend(&ab, "\r", 1);
995- }
996-
997- /* clear all old rows */
998- for (j = 0; j < old_rows; j++) {
999- abAppend(&ab, "\x1b[0K", 4);
1000- if (j < old_rows - 1) {
1001- abAppend(&ab, "\n\r", 2);
1002- }
1003- }
1004-
1005- /* move cursor back to the first row, column 0 */
1006- if (old_rows > 1) {
1007- snprintf(seq, 64, "\r\x1b[%dA", old_rows - 1);
1008- abAppend(&ab, seq, strlen(seq));
1009- } else {
1010- abAppend(&ab, "\r", 1);
1011- }
1012-
1013- /* print prompt and new buffer */
1014- abAppend(&ab, l->prompt, l->plen);
1015- abAppend(&ab, l->buf, l->len);
1016-
1017- /* if cursor is at the end of the line and wraps, print a newline */
1018- if (l->pos && l->pos == l->len && (poswidth+pwidth) % l->cols == 0) {
1019- abAppend(&ab, "\n\r", 2);
1020- rows++;
1021- if (rows > (int)l->oldrows) l->oldrows = rows;
1022- }
1023-
1024- /* calculate cursor row and column */
1025- rpos2 = (pwidth+poswidth+l->cols)/l->cols;
1026- col = (pwidth+poswidth) % l->cols;
1027-
1028- /* move cursor to the correct row and column */
1029- if (rows - rpos2 > 0) {
1030- snprintf(seq, 64, "\x1b[%dA", rows - rpos2);
1031- abAppend(&ab, seq, strlen(seq));
1032- }
1033- if (col) {
1034- snprintf(seq, 64, "\r\x1b[%dC", col);
1035- abAppend(&ab, seq, strlen(seq));
1036- } else {
1037- abAppend(&ab, "\r", 1);
1038- }
1039-
1040- l->oldpos = l->pos;
1041- l->oldrpos = rpos2;
1042-
1043- if (write(fd, ab.b, ab.len) == -1) {}
1044- abFree(&ab);
1045+ char seq[64];
1046+ size_t pwidth = utf8StrWidth(l->prompt, l->plen);
1047+ size_t bufwidth;
1048+ size_t poswidth;
1049+ int rows;
1050+ int rpos2;
1051+ int col;
1052+ int old_rows = l->oldrows;
1053+ int rpos = l->oldrpos;
1054+ int fd = l->ofd, j;
1055+ struct abuf ab;
1056+
1057+ (void)flags;
1058+
1059+ bufwidth = utf8StrWidth(l->buf, l->len);
1060+ poswidth = utf8StrWidth(l->buf, l->pos);
1061+ rows = (pwidth+bufwidth+l->cols-1)/l->cols;
1062+ l->oldrows = rows;
1063+
1064+ abInit(&ab);
1065+
1066+ /* move cursor up to the first row, column 0 of the input area */
1067+ if (rpos > 1) {
1068+ snprintf(seq, 64, "\r\x1b[%dA", rpos - 1);
1069+ abAppend(&ab, seq, strlen(seq));
1070+ } else {
1071+ abAppend(&ab, "\r", 1);
1072+ }
1073+
1074+ /* clear all old rows */
1075+ for (j = 0; j < old_rows; j++) {
1076+ abAppend(&ab, "\x1b[0K", 4);
1077+ if (j < old_rows - 1) {
1078+ abAppend(&ab, "\n\r", 2);
1079+ }
1080+ }
1081+
1082+ /* move cursor back to the first row, column 0 */
1083+ if (old_rows > 1) {
1084+ snprintf(seq, 64, "\r\x1b[%dA", old_rows - 1);
1085+ abAppend(&ab, seq, strlen(seq));
1086+ } else {
1087+ abAppend(&ab, "\r", 1);
1088+ }
1089+
1090+ /* print prompt and new buffer */
1091+ abAppend(&ab, l->prompt, l->plen);
1092+ abAppend(&ab, l->buf, l->len);
1093+
1094+ /* if cursor is at the end of the line and wraps, print a newline */
1095+ if (l->pos && l->pos == l->len && (poswidth+pwidth) % l->cols == 0) {
1096+ abAppend(&ab, "\n\r", 2);
1097+ rows++;
1098+ if (rows > (int)l->oldrows) l->oldrows = rows;
1099+ }
1100+
1101+ /* calculate cursor row and column */
1102+ rpos2 = (pwidth+poswidth+l->cols)/l->cols;
1103+ col = (pwidth+poswidth) % l->cols;
1104+
1105+ /* move cursor to the correct row and column */
1106+ if (rows - rpos2 > 0) {
1107+ snprintf(seq, 64, "\x1b[%dA", rows - rpos2);
1108+ abAppend(&ab, seq, strlen(seq));
1109+ }
1110+ if (col) {
1111+ snprintf(seq, 64, "\r\x1b[%dC", col);
1112+ abAppend(&ab, seq, strlen(seq));
1113+ } else {
1114+ abAppend(&ab, "\r", 1);
1115+ }
1116+
1117+ l->oldpos = l->pos;
1118+ l->oldrpos = rpos2;
1119+
1120+ if (write(fd, ab.b, ab.len) == -1) {}
1121+ abFree(&ab);
1122 }
1123
1124 static void
1125 refreshLineWithFlags(struct redlineState *l, int flags)
1126 {
1127- if (mlmode)
1128- refreshMultiLine(l,flags);
1129- else
1130- refreshSingleLine(l,flags);
1131+ if (mlmode)
1132+ refreshMultiLine(l,flags);
1133+ else
1134+ refreshSingleLine(l,flags);
1135 }
1136
1137 static void
1138 refreshLine(struct redlineState *l)
1139 {
1140- refreshLineWithFlags(l, 1);
1141+ refreshLineWithFlags(l, 1);
1142 }
1143
1144 static int
1145 completeLine(struct redlineState *ls, int keypressed)
1146 {
1147- struct redlineCompletions lc = { 0, NULL };
1148- size_t lcp_len;
1149- int c = keypressed;
1150- int proceed = 1;
1151- char query[128];
1152- char answer = 0;
1153-
1154- if (c != 9) {
1155- ls->in_completion = 0;
1156- return c;
1157- }
1158-
1159- completionCallback(ls->buf, &lc);
1160- if (lc.len == 0) {
1161- redlineBeep();
1162- ls->in_completion = 0;
1163- c = 0;
1164- } else if (lc.len == 1) {
1165- size_t nwritten = snprintf(ls->buf, ls->buflen, "%s", lc.cvec[0]);
1166- ls->len = ls->pos = nwritten;
1167- refreshLine(ls);
1168- ls->in_completion = 0;
1169- c = 0;
1170- } else {
1171- lcp_len = longestCommonPrefix(&lc);
1172- if (lcp_len > ls->len) {
1173- size_t nwritten = snprintf(ls->buf, ls->buflen, "%.*s", (int)lcp_len, lc.cvec[0]);
1174- ls->len = ls->pos = nwritten;
1175- refreshLine(ls);
1176- ls->in_completion = 1;
1177- c = 0;
1178- } else {
1179- /* prefix cannot be expanded further */
1180- if (ls->in_completion == 0) {
1181- /* first tab: beep and wait for the second tab */
1182- redlineBeep();
1183- ls->in_completion = 1;
1184- c = 0;
1185- } else {
1186- /* second tab: display possibilities */
1187- if (lc.len > 100) {
1188- snprintf(query, sizeof(query), "\r\nDisplay all %d possibilities? (y or n) ", (int)lc.len);
1189- if (write(ls->ofd, query, strlen(query)) == -1) {}
1190- while (1) {
1191- if (read(ls->ifd, &answer, 1) != 1) {
1192- proceed = 0;
1193- break;
1194- }
1195- if (answer == 'y' || answer == 'Y' || answer == ' ' || answer == '\t') {
1196- proceed = 1;
1197- break;
1198- }
1199- if (answer == 'n' || answer == 'N' || answer == 27 || answer == 3 || answer == 4) {
1200- proceed = 0;
1201- break;
1202- }
1203- redlineBeep();
1204- }
1205- }
1206- if (proceed) {
1207- printCompletions(ls, &lc);
1208- } else {
1209- if (write(ls->ofd, "\r\n", 2) == -1) {}
1210- }
1211- ls->oldrows = 0;
1212- refreshLine(ls);
1213- ls->in_completion = 0;
1214- c = 0;
1215- }
1216- }
1217- }
1218-
1219- freeCompletions(&lc);
1220- return c;
1221+ struct redlineCompletions lc = { 0, NULL };
1222+ size_t lcp_len;
1223+ int c = keypressed;
1224+ int proceed = 1;
1225+ char query[128];
1226+ char answer = 0;
1227+
1228+ if (c != 9) {
1229+ ls->in_completion = 0;
1230+ return c;
1231+ }
1232+
1233+ completionCallback(ls->buf, &lc);
1234+ if (lc.len == 0) {
1235+ redlineBeep();
1236+ ls->in_completion = 0;
1237+ c = 0;
1238+ } else if (lc.len == 1) {
1239+ size_t nwritten = snprintf(ls->buf, ls->buflen, "%s", lc.cvec[0]);
1240+ ls->len = ls->pos = nwritten;
1241+ refreshLine(ls);
1242+ ls->in_completion = 0;
1243+ c = 0;
1244+ } else {
1245+ lcp_len = longestCommonPrefix(&lc);
1246+ if (lcp_len > ls->len) {
1247+ size_t nwritten = snprintf(ls->buf, ls->buflen, "%.*s", (int)lcp_len, lc.cvec[0]);
1248+ ls->len = ls->pos = nwritten;
1249+ refreshLine(ls);
1250+ ls->in_completion = 1;
1251+ c = 0;
1252+ } else {
1253+ /* prefix cannot be expanded further */
1254+ if (ls->in_completion == 0) {
1255+ /* first tab: beep and wait for the second tab */
1256+ redlineBeep();
1257+ ls->in_completion = 1;
1258+ c = 0;
1259+ } else {
1260+ /* second tab: display possibilities */
1261+ if (lc.len > 100) {
1262+ snprintf(query, sizeof(query), "\r\nDisplay all %d possibilities? (y or n) ", (int)lc.len);
1263+ if (write(ls->ofd, query, strlen(query)) == -1) {}
1264+ while (1) {
1265+ if (read(ls->ifd, &answer, 1) != 1) {
1266+ proceed = 0;
1267+ break;
1268+ }
1269+ if (answer == 'y' || answer == 'Y' || answer == ' ' || answer == '\t') {
1270+ proceed = 1;
1271+ break;
1272+ }
1273+ if (answer == 'n' || answer == 'N' || answer == 27 || answer == 3 || answer == 4) {
1274+ proceed = 0;
1275+ break;
1276+ }
1277+ redlineBeep();
1278+ }
1279+ }
1280+ if (proceed) {
1281+ printCompletions(ls, &lc);
1282+ } else {
1283+ if (write(ls->ofd, "\r\n", 2) == -1) {}
1284+ }
1285+ ls->oldrows = 0;
1286+ refreshLine(ls);
1287+ ls->in_completion = 0;
1288+ c = 0;
1289+ }
1290+ }
1291+ }
1292+
1293+ freeCompletions(&lc);
1294+ return c;
1295 }
1296
1297 static int
1298 redlineEditInsert(struct redlineState *l, const char *c, int clen)
1299 {
1300- if (l->len + clen >= l->buflen) {
1301- return 0;
1302- }
1303- if (l->len == l->pos) {
1304- memcpy(l->buf + l->pos, c, clen);
1305- l->pos += clen;
1306- l->len += clen;
1307- l->buf[l->len] = '\0';
1308- refreshLine(l);
1309- } else {
1310- memmove(l->buf + l->pos + clen, l->buf + l->pos, l->len - l->pos);
1311- memcpy(l->buf + l->pos, c, clen);
1312- l->pos += clen;
1313- l->len += clen;
1314- l->buf[l->len] = '\0';
1315- refreshLine(l);
1316- }
1317- return 1;
1318+ if (l->len + clen >= l->buflen) {
1319+ return 0;
1320+ }
1321+ if (l->len == l->pos) {
1322+ memcpy(l->buf + l->pos, c, clen);
1323+ l->pos += clen;
1324+ l->len += clen;
1325+ l->buf[l->len] = '\0';
1326+ refreshLine(l);
1327+ } else {
1328+ memmove(l->buf + l->pos + clen, l->buf + l->pos, l->len - l->pos);
1329+ memcpy(l->buf + l->pos, c, clen);
1330+ l->pos += clen;
1331+ l->len += clen;
1332+ l->buf[l->len] = '\0';
1333+ refreshLine(l);
1334+ }
1335+ return 1;
1336 }
1337
1338 static void
1339 redlineEditBackspace(struct redlineState *l)
1340 {
1341- if (l->pos > 0 && l->len > 0) {
1342- size_t clen = utf8PrevCharLen(l->buf, l->pos);
1343- memmove(l->buf+l->pos-clen, l->buf+l->pos, l->len-l->pos);
1344- l->pos -= clen;
1345- l->len -= clen;
1346- l->buf[l->len] = '\0';
1347- refreshLine(l);
1348- }
1349+ if (l->pos > 0 && l->len > 0) {
1350+ size_t clen = utf8PrevCharLen(l->buf, l->pos);
1351+ memmove(l->buf+l->pos-clen, l->buf+l->pos, l->len-l->pos);
1352+ l->pos -= clen;
1353+ l->len -= clen;
1354+ l->buf[l->len] = '\0';
1355+ refreshLine(l);
1356+ }
1357 }
1358
1359 static void
1360 redlineEditDelete(struct redlineState *l)
1361 {
1362- if (l->len > 0 && l->pos < l->len) {
1363- size_t clen = utf8NextCharLen(l->buf, l->pos, l->len);
1364- memmove(l->buf+l->pos, l->buf+l->pos+clen, l->len-l->pos-clen);
1365- l->len -= clen;
1366- l->buf[l->len] = '\0';
1367- refreshLine(l);
1368- }
1369+ if (l->len > 0 && l->pos < l->len) {
1370+ size_t clen = utf8NextCharLen(l->buf, l->pos, l->len);
1371+ memmove(l->buf+l->pos, l->buf+l->pos+clen, l->len-l->pos-clen);
1372+ l->len -= clen;
1373+ l->buf[l->len] = '\0';
1374+ refreshLine(l);
1375+ }
1376 }
1377
1378 static void
1379 redlineEditMoveLeft(struct redlineState *l)
1380 {
1381- if (l->pos > 0) {
1382- l->pos -= utf8PrevCharLen(l->buf, l->pos);
1383- refreshLine(l);
1384- }
1385+ if (l->pos > 0) {
1386+ l->pos -= utf8PrevCharLen(l->buf, l->pos);
1387+ refreshLine(l);
1388+ }
1389 }
1390
1391 static void
1392 redlineEditMoveRight(struct redlineState *l)
1393 {
1394- if (l->pos != l->len) {
1395- l->pos += utf8NextCharLen(l->buf, l->pos, l->len);
1396- refreshLine(l);
1397- }
1398+ if (l->pos != l->len) {
1399+ l->pos += utf8NextCharLen(l->buf, l->pos, l->len);
1400+ refreshLine(l);
1401+ }
1402 }
1403
1404 static void
1405 redlineEditMoveHome(struct redlineState *l)
1406 {
1407- if (l->pos != 0) {
1408- l->pos = 0;
1409- refreshLine(l);
1410- }
1411+ if (l->pos != 0) {
1412+ l->pos = 0;
1413+ refreshLine(l);
1414+ }
1415 }
1416
1417 static void
1418 redlineEditMoveEnd(struct redlineState *l)
1419 {
1420- if (l->pos != l->len) {
1421- l->pos = l->len;
1422- refreshLine(l);
1423- }
1424+ if (l->pos != l->len) {
1425+ l->pos = l->len;
1426+ refreshLine(l);
1427+ }
1428 }
1429
1430 static void
1431 redlineEditMoveWordLeft(struct redlineState *l)
1432 {
1433- if (l->pos > 0) {
1434- while (l->pos > 0 && l->buf[l->pos-1] == ' ')
1435- l->pos -= utf8PrevCharLen(l->buf, l->pos);
1436- while (l->pos > 0 && l->buf[l->pos-1] != ' ')
1437- l->pos -= utf8PrevCharLen(l->buf, l->pos);
1438- refreshLine(l);
1439- }
1440+ if (l->pos > 0) {
1441+ while (l->pos > 0 && l->buf[l->pos-1] == ' ')
1442+ l->pos -= utf8PrevCharLen(l->buf, l->pos);
1443+ while (l->pos > 0 && l->buf[l->pos-1] != ' ')
1444+ l->pos -= utf8PrevCharLen(l->buf, l->pos);
1445+ refreshLine(l);
1446+ }
1447 }
1448
1449 static void
1450 redlineEditMoveWordRight(struct redlineState *l)
1451 {
1452- if (l->pos < l->len) {
1453- while (l->pos < l->len && l->buf[l->pos] == ' ')
1454- l->pos += utf8NextCharLen(l->buf, l->pos, l->len);
1455- while (l->pos < l->len && l->buf[l->pos] != ' ')
1456- l->pos += utf8NextCharLen(l->buf, l->pos, l->len);
1457- refreshLine(l);
1458- }
1459+ if (l->pos < l->len) {
1460+ while (l->pos < l->len && l->buf[l->pos] == ' ')
1461+ l->pos += utf8NextCharLen(l->buf, l->pos, l->len);
1462+ while (l->pos < l->len && l->buf[l->pos] != ' ')
1463+ l->pos += utf8NextCharLen(l->buf, l->pos, l->len);
1464+ refreshLine(l);
1465+ }
1466 }
1467
1468 static void
1469 killBufferSave(const char *text, size_t len)
1470 {
1471- free(kill_buffer);
1472- kill_buffer = malloc(len + 1);
1473- if (kill_buffer) {
1474- memcpy(kill_buffer, text, len);
1475- kill_buffer[len] = '\0';
1476- }
1477+ free(kill_buffer);
1478+ kill_buffer = malloc(len + 1);
1479+ if (kill_buffer) {
1480+ memcpy(kill_buffer, text, len);
1481+ kill_buffer[len] = '\0';
1482+ }
1483 }
1484
1485 static void
1486 redlineEditDeleteWordRight(struct redlineState *l)
1487 {
1488- size_t old_pos = l->pos;
1489- size_t diff;
1490- if (l->pos < l->len) {
1491- while (l->pos < l->len && l->buf[l->pos] == ' ')
1492- l->pos += utf8NextCharLen(l->buf, l->pos, l->len);
1493- while (l->pos < l->len && l->buf[l->pos] != ' ')
1494- l->pos += utf8NextCharLen(l->buf, l->pos, l->len);
1495- diff = l->pos - old_pos;
1496- l->pos = old_pos;
1497- killBufferSave(l->buf + l->pos, diff);
1498- memmove(l->buf + l->pos, l->buf + l->pos + diff, l->len - l->pos - diff + 1);
1499- l->len -= diff;
1500- refreshLine(l);
1501- }
1502+ size_t old_pos = l->pos;
1503+ size_t diff;
1504+ if (l->pos < l->len) {
1505+ while (l->pos < l->len && l->buf[l->pos] == ' ')
1506+ l->pos += utf8NextCharLen(l->buf, l->pos, l->len);
1507+ while (l->pos < l->len && l->buf[l->pos] != ' ')
1508+ l->pos += utf8NextCharLen(l->buf, l->pos, l->len);
1509+ diff = l->pos - old_pos;
1510+ l->pos = old_pos;
1511+ killBufferSave(l->buf + l->pos, diff);
1512+ memmove(l->buf + l->pos, l->buf + l->pos + diff, l->len - l->pos - diff + 1);
1513+ l->len -= diff;
1514+ refreshLine(l);
1515+ }
1516 }
1517
1518 static void
1519 redlineEditDeletePrevWord(struct redlineState *l)
1520 {
1521- size_t old_pos = l->pos;
1522- size_t diff;
1523- if (l->pos > 0) {
1524- while (l->pos > 0 && l->buf[l->pos-1] == ' ')
1525- l->pos -= utf8PrevCharLen(l->buf, l->pos);
1526- while (l->pos > 0 && l->buf[l->pos-1] != ' ')
1527- l->pos -= utf8PrevCharLen(l->buf, l->pos);
1528- diff = old_pos - l->pos;
1529- killBufferSave(l->buf + l->pos, diff);
1530- memmove(l->buf + l->pos, l->buf + old_pos, l->len - old_pos + 1);
1531- l->len -= diff;
1532- refreshLine(l);
1533- }
1534+ size_t old_pos = l->pos;
1535+ size_t diff;
1536+ if (l->pos > 0) {
1537+ while (l->pos > 0 && l->buf[l->pos-1] == ' ')
1538+ l->pos -= utf8PrevCharLen(l->buf, l->pos);
1539+ while (l->pos > 0 && l->buf[l->pos-1] != ' ')
1540+ l->pos -= utf8PrevCharLen(l->buf, l->pos);
1541+ diff = old_pos - l->pos;
1542+ killBufferSave(l->buf + l->pos, diff);
1543+ memmove(l->buf + l->pos, l->buf + old_pos, l->len - old_pos + 1);
1544+ l->len -= diff;
1545+ refreshLine(l);
1546+ }
1547 }
1548
1549 void
1550 redlineHistoryAdd(const char *line)
1551 {
1552- char *linecopy;
1553- if (history_max_len == 0) return;
1554- if (history == NULL) {
1555- history = malloc(sizeof(char*) * history_max_len);
1556- if (history == NULL) return;
1557- memset(history,0,sizeof(char*)*history_max_len);
1558- }
1559- if (history_len && strcmp(history[history_len-1], line) == 0) return;
1560- linecopy = strdup(line);
1561- if (!linecopy) return;
1562- if (history_len == history_max_len) {
1563- free(history[0]);
1564- memmove(history,history+1,sizeof(char*)*(history_max_len-1));
1565- history_len--;
1566- }
1567- history[history_len] = linecopy;
1568- history_len++;
1569+ char *linecopy;
1570+ if (history_max_len == 0) return;
1571+ if (history == NULL) {
1572+ history = malloc(sizeof(char*) * history_max_len);
1573+ if (history == NULL) return;
1574+ memset(history,0,sizeof(char*)*history_max_len);
1575+ }
1576+ if (history_len && strcmp(history[history_len-1], line) == 0) return;
1577+ linecopy = strdup(line);
1578+ if (!linecopy) return;
1579+ if (history_len == history_max_len) {
1580+ free(history[0]);
1581+ memmove(history,history+1,sizeof(char*)*(history_max_len-1));
1582+ history_len--;
1583+ }
1584+ history[history_len] = linecopy;
1585+ history_len++;
1586 }
1587
1588 void
1589 redlineHistorySetMaxLen(int len)
1590 {
1591- char **new;
1592- if (len < 1) return;
1593- if (history) {
1594- int tocopy = history_len;
1595- new = malloc(sizeof(char*)*len);
1596- if (new == NULL) return;
1597- if (len < tocopy) {
1598- int j;
1599- for (j = 0; j < tocopy-len; j++) free(history[j]);
1600- tocopy = len;
1601- }
1602- memset(new,0,sizeof(char*)*len);
1603- memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy);
1604- free(history);
1605- history = new;
1606- }
1607- history_max_len = len;
1608- if (history_len > history_max_len)
1609- history_len = history_max_len;
1610+ char **new;
1611+ if (len < 1) return;
1612+ if (history) {
1613+ int tocopy = history_len;
1614+ new = malloc(sizeof(char*)*len);
1615+ if (new == NULL) return;
1616+ if (len < tocopy) {
1617+ int j;
1618+ for (j = 0; j < tocopy-len; j++) free(history[j]);
1619+ tocopy = len;
1620+ }
1621+ memset(new,0,sizeof(char*)*len);
1622+ memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy);
1623+ free(history);
1624+ history = new;
1625+ }
1626+ history_max_len = len;
1627+ if (history_len > history_max_len)
1628+ history_len = history_max_len;
1629 }
1630
1631 int
1632 redlineHistorySave(const char *filename)
1633 {
1634- mode_t old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
1635- FILE *fp;
1636- int j;
1637-
1638- fp = fopen(filename,"w");
1639- umask(old_umask);
1640- if (fp == NULL) return -1;
1641- chmod(filename,S_IRUSR|S_IWUSR);
1642- for (j = 0; j < history_len; j++) {
1643- fprintf(fp,"%s\n",history[j]);
1644- }
1645- fclose(fp);
1646- return 0;
1647+ mode_t old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
1648+ FILE *fp;
1649+ int j;
1650+
1651+ fp = fopen(filename,"w");
1652+ umask(old_umask);
1653+ if (fp == NULL) return -1;
1654+ chmod(filename,S_IRUSR|S_IWUSR);
1655+ for (j = 0; j < history_len; j++) {
1656+ fprintf(fp,"%s\n",history[j]);
1657+ }
1658+ fclose(fp);
1659+ return 0;
1660 }
1661
1662 int
1663 redlineHistoryLoad(const char *filename)
1664 {
1665- FILE *fp = fopen(filename,"r");
1666- char buf[REDLINE_INITIAL_BUFLEN];
1667- if (fp == NULL) return -1;
1668- while (fgets(buf,sizeof(buf),fp) != NULL) {
1669- char *p = strchr(buf,'\r');
1670- if (!p) p = strchr(buf,'\n');
1671- if (p) *p = '\0';
1672- redlineHistoryAdd(buf);
1673- }
1674- fclose(fp);
1675- return 0;
1676+ FILE *fp = fopen(filename,"r");
1677+ char buf[REDLINE_INITIAL_BUFLEN];
1678+ if (fp == NULL) return -1;
1679+ while (fgets(buf,sizeof(buf),fp) != NULL) {
1680+ char *p = strchr(buf,'\r');
1681+ if (!p) p = strchr(buf,'\n');
1682+ if (p) *p = '\0';
1683+ redlineHistoryAdd(buf);
1684+ }
1685+ fclose(fp);
1686+ return 0;
1687 }
1688
1689 char *
1690 redlineHistoryGet(int idx)
1691 {
1692- if (idx >= 0 && idx < history_len)
1693- return history[idx];
1694- return NULL;
1695+ if (idx >= 0 && idx < history_len)
1696+ return history[idx];
1697+ return NULL;
1698 }
1699
1700 int
1701 redlineHistoryLen(void)
1702 {
1703- return history_len;
1704+ return history_len;
1705 }
1706
1707 static void
1708 redlineEditHistoryNext(struct redlineState *l, int dir)
1709 {
1710- if (history_len > 1) {
1711- const char *src;
1712- size_t len;
1713- free(history[history_len - 1 - l->history_index]);
1714- history[history_len - 1 - l->history_index] = strdup(l->buf);
1715- l->history_index += (dir == 1) ? 1 : -1;
1716- if (l->history_index < 0) {
1717- l->history_index = 0;
1718- return;
1719- } else if (l->history_index >= history_len) {
1720- l->history_index = history_len - 1;
1721- return;
1722- }
1723- src = history[history_len - 1 - l->history_index];
1724- len = strlen(src);
1725- if (len >= l->buflen) len = l->buflen - 1;
1726- memcpy(l->buf, src, len);
1727- l->buf[len] = '\0';
1728- l->len = l->pos = len;
1729- refreshLine(l);
1730- }
1731+ if (history_len > 1) {
1732+ const char *src;
1733+ size_t len;
1734+ free(history[history_len - 1 - l->history_index]);
1735+ history[history_len - 1 - l->history_index] = strdup(l->buf);
1736+ l->history_index += (dir == 1) ? 1 : -1;
1737+ if (l->history_index < 0) {
1738+ l->history_index = 0;
1739+ return;
1740+ } else if (l->history_index >= history_len) {
1741+ l->history_index = history_len - 1;
1742+ return;
1743+ }
1744+ src = history[history_len - 1 - l->history_index];
1745+ len = strlen(src);
1746+ if (len >= l->buflen) len = l->buflen - 1;
1747+ memcpy(l->buf, src, len);
1748+ l->buf[len] = '\0';
1749+ l->len = l->pos = len;
1750+ refreshLine(l);
1751+ }
1752 }
1753
1754 static char *
1755 redlineReadLine(FILE *fp)
1756 {
1757- char *line = NULL;
1758- size_t len = 0, cap = 0;
1759- while (1) {
1760- if (len+1 >= cap) {
1761- size_t newcap = cap ? cap*2 : 16;
1762- char *new = realloc(line, newcap);
1763- if (!new) {
1764- free(line);
1765- return NULL;
1766- }
1767- line = new;
1768- cap = newcap;
1769- }
1770- int c = fgetc(fp);
1771- if (c == EOF || c == '\n') {
1772- if (c == EOF && len == 0) {
1773- free(line);
1774- return NULL;
1775- }
1776- line[len] = '\0';
1777- return line;
1778- }
1779- line[len++] = c;
1780- }
1781+ char *line = NULL;
1782+ size_t len = 0, cap = 0;
1783+ while (1) {
1784+ if (len+1 >= cap) {
1785+ size_t newcap = cap ? cap*2 : 16;
1786+ char *new = realloc(line, newcap);
1787+ if (!new) {
1788+ free(line);
1789+ return NULL;
1790+ }
1791+ line = new;
1792+ cap = newcap;
1793+ }
1794+ int c = fgetc(fp);
1795+ if (c == EOF || c == '\n') {
1796+ if (c == EOF && len == 0) {
1797+ free(line);
1798+ return NULL;
1799+ }
1800+ line[len] = '\0';
1801+ return line;
1802+ }
1803+ line[len++] = c;
1804+ }
1805 }
1806
1807 static char *
1808 redlineNoTTY(void)
1809 {
1810- return redlineReadLine(stdin);
1811+ return redlineReadLine(stdin);
1812 }
1813
1814 void
1815 redlineClearScreen(void)
1816 {
1817- if (write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7) == -1) {}
1818+ if (write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7) == -1) {}
1819 }
1820
1821 static char *
1822 redlineEditFeed(struct redlineState *l)
1823 {
1824- char c;
1825- int nread;
1826- char seq[3];
1827- char param[8];
1828- size_t plen;
1829- char final;
1830- char p;
1831- int is_word_jump;
1832- char tmp[32];
1833- size_t prevlen;
1834- size_t currlen;
1835- size_t prevstart;
1836- char utf8[4];
1837- int utf8len;
1838- int i;
1839-
1840- if (!isatty(l->ifd) && !getenv("REDLINE_ASSUME_TTY")) return redlineNoTTY();
1841-
1842- while (1) {
1843- nread = read(l->ifd, &c, 1);
1844- if (nread < 0) {
1845- if (errno == EINTR) {
1846- if (winch_received) {
1847- winch_received = 0;
1848- l->cols = getColumns(l->ifd, l->ofd);
1849- refreshLine(l);
1850- }
1851- continue;
1852- }
1853- return (errno == EAGAIN || errno == EWOULDBLOCK) ? "more" : NULL;
1854- } else if (nread == 0) {
1855- return NULL;
1856- }
1857- break;
1858- }
1859-
1860- if ((l->in_completion || c == 9) && completionCallback != NULL) {
1861- int retval = completeLine(l, c);
1862- if (retval == 0) return "more";
1863- c = retval;
1864- }
1865-
1866- switch (c) {
1867- case ENTER:
1868- if (mlmode) redlineEditMoveEnd(l);
1869- return strdup(l->buf);
1870- case CTRL_C:
1871- errno = EAGAIN;
1872- return NULL;
1873- case BACKSPACE:
1874- case 8:
1875- redlineEditBackspace(l);
1876- break;
1877- case CTRL_D:
1878- if (l->len > 0) {
1879- redlineEditDelete(l);
1880- } else {
1881- errno = ENOENT;
1882- return NULL;
1883- }
1884- break;
1885- case CTRL_T:
1886- if (l->pos > 0 && l->pos < l->len) {
1887- prevlen = utf8PrevCharLen(l->buf, l->pos);
1888- currlen = utf8NextCharLen(l->buf, l->pos, l->len);
1889- prevstart = l->pos - prevlen;
1890- if (prevlen > sizeof(tmp) || currlen > sizeof(tmp)) break;
1891- memcpy(tmp, l->buf + l->pos, currlen);
1892- memmove(l->buf + prevstart + currlen, l->buf + prevstart, prevlen);
1893- memcpy(l->buf + prevstart, tmp, currlen);
1894- if (l->pos + currlen <= l->len) l->pos += currlen;
1895- refreshLine(l);
1896- }
1897- break;
1898- case CTRL_B:
1899- redlineEditMoveLeft(l);
1900- break;
1901- case CTRL_F:
1902- redlineEditMoveRight(l);
1903- break;
1904- case CTRL_P:
1905- redlineEditHistoryNext(l, 1);
1906- break;
1907- case CTRL_N:
1908- redlineEditHistoryNext(l, 0);
1909- break;
1910- case ESC:
1911- if (read(l->ifd, seq, 1) == -1) break;
1912- if (seq[0] == '[' || seq[0] == 'O') {
1913- if (read(l->ifd, seq+1, 1) == -1) break;
1914- if (seq[0] == '[') {
1915- if (seq[1] >= '0' && seq[1] <= '9') {
1916- plen = 1;
1917- final = 0;
1918- param[0] = seq[1];
1919- while (plen < sizeof(param)) {
1920- if (read(l->ifd, &p, 1) != 1) break;
1921- if ((p >= '0' && p <= '9') || p == ';') {
1922- param[plen++] = p;
1923- } else {
1924- final = p;
1925- break;
1926- }
1927- }
1928- if (final == '~') {
1929- if (plen == 1 && param[0] == '3') {
1930- redlineEditDelete(l);
1931- }
1932- } else if (final == 'D' || final == 'C') {
1933- is_word_jump = 0;
1934- if (plen == 3 && param[0] == '1' && param[1] == ';' && (param[2] == '5' || param[2] == '3')) {
1935- is_word_jump = 1;
1936- } else if (plen == 1 && (param[0] == '5' || param[0] == '3')) {
1937- is_word_jump = 1;
1938- }
1939- if (is_word_jump) {
1940- if (final == 'D') {
1941- redlineEditMoveWordLeft(l);
1942- } else {
1943- redlineEditMoveWordRight(l);
1944- }
1945- }
1946- }
1947- } else {
1948- switch (seq[1]) {
1949- case 'A':
1950- redlineEditHistoryNext(l, 1);
1951- break;
1952- case 'B':
1953- redlineEditHistoryNext(l, 0);
1954- break;
1955- case 'C':
1956- redlineEditMoveRight(l);
1957- break;
1958- case 'D':
1959- redlineEditMoveLeft(l);
1960- break;
1961- case 'H':
1962- redlineEditMoveHome(l);
1963- break;
1964- case 'F':
1965- redlineEditMoveEnd(l);
1966- break;
1967- }
1968- }
1969- } else if (seq[0] == 'O') {
1970- switch (seq[1]) {
1971- case 'H':
1972- redlineEditMoveHome(l);
1973- break;
1974- case 'F':
1975- redlineEditMoveEnd(l);
1976- break;
1977- }
1978- }
1979- } else {
1980- if (seq[0] == 'b' || seq[0] == 'B') {
1981- redlineEditMoveWordLeft(l);
1982- } else if (seq[0] == 'f' || seq[0] == 'F') {
1983- redlineEditMoveWordRight(l);
1984- } else if (seq[0] == 'd' || seq[0] == 'D') {
1985- redlineEditDeleteWordRight(l);
1986- } else if (seq[0] == 127 || seq[0] == 8) {
1987- redlineEditDeletePrevWord(l);
1988- }
1989- }
1990- break;
1991- default:
1992- utf8len = utf8ByteLen(c);
1993- utf8[0] = c;
1994- if (utf8len > 1) {
1995- for (i = 1; i < utf8len; i++) {
1996- if (read(l->ifd, utf8+i, 1) != 1) break;
1997- }
1998- }
1999- if (redlineEditInsert(l, utf8, utf8len) == 0) return NULL;
2000- break;
2001- case CTRL_U:
2002- killBufferSave(l->buf, l->pos);
2003- memmove(l->buf, l->buf + l->pos, l->len - l->pos + 1);
2004- l->len -= l->pos;
2005- l->pos = 0;
2006- refreshLine(l);
2007- break;
2008- case CTRL_K:
2009- killBufferSave(l->buf + l->pos, l->len - l->pos);
2010- l->buf[l->pos] = '\0';
2011- l->len = l->pos;
2012- refreshLine(l);
2013- break;
2014- case CTRL_A:
2015- redlineEditMoveHome(l);
2016- break;
2017- case CTRL_E:
2018- redlineEditMoveEnd(l);
2019- break;
2020- case CTRL_L:
2021- redlineClearScreen();
2022- refreshLine(l);
2023- break;
2024- case CTRL_W:
2025- redlineEditDeletePrevWord(l);
2026- break;
2027- case CTRL_Y:
2028- if (kill_buffer) {
2029- redlineEditInsert(l, kill_buffer, strlen(kill_buffer));
2030- }
2031- break;
2032- }
2033- return "more";
2034+ char c;
2035+ int nread;
2036+ char seq[3];
2037+ char param[8];
2038+ size_t plen;
2039+ char final;
2040+ char p;
2041+ int is_word_jump;
2042+ char tmp[32];
2043+ size_t prevlen;
2044+ size_t currlen;
2045+ size_t prevstart;
2046+ char utf8[4];
2047+ int utf8len;
2048+ int i;
2049+
2050+ if (!isatty(l->ifd) && !getenv("REDLINE_ASSUME_TTY")) return redlineNoTTY();
2051+
2052+ while (1) {
2053+ nread = read(l->ifd, &c, 1);
2054+ if (nread < 0) {
2055+ if (errno == EINTR) {
2056+ if (winch_received) {
2057+ winch_received = 0;
2058+ l->cols = getColumns(l->ifd, l->ofd);
2059+ refreshLine(l);
2060+ }
2061+ continue;
2062+ }
2063+ return (errno == EAGAIN || errno == EWOULDBLOCK) ? "more" : NULL;
2064+ } else if (nread == 0) {
2065+ return NULL;
2066+ }
2067+ break;
2068+ }
2069+
2070+ if ((l->in_completion || c == 9) && completionCallback != NULL) {
2071+ int retval = completeLine(l, c);
2072+ if (retval == 0) return "more";
2073+ c = retval;
2074+ }
2075+
2076+ switch (c) {
2077+ case ENTER:
2078+ if (mlmode) redlineEditMoveEnd(l);
2079+ return strdup(l->buf);
2080+ case CTRL_C:
2081+ errno = EAGAIN;
2082+ return NULL;
2083+ case BACKSPACE:
2084+ case 8:
2085+ redlineEditBackspace(l);
2086+ break;
2087+ case CTRL_D:
2088+ if (l->len > 0) {
2089+ redlineEditDelete(l);
2090+ } else {
2091+ errno = ENOENT;
2092+ return NULL;
2093+ }
2094+ break;
2095+ case CTRL_T:
2096+ if (l->pos > 0 && l->pos < l->len) {
2097+ prevlen = utf8PrevCharLen(l->buf, l->pos);
2098+ currlen = utf8NextCharLen(l->buf, l->pos, l->len);
2099+ prevstart = l->pos - prevlen;
2100+ if (prevlen > sizeof(tmp) || currlen > sizeof(tmp)) break;
2101+ memcpy(tmp, l->buf + l->pos, currlen);
2102+ memmove(l->buf + prevstart + currlen, l->buf + prevstart, prevlen);
2103+ memcpy(l->buf + prevstart, tmp, currlen);
2104+ if (l->pos + currlen <= l->len) l->pos += currlen;
2105+ refreshLine(l);
2106+ }
2107+ break;
2108+ case CTRL_B:
2109+ redlineEditMoveLeft(l);
2110+ break;
2111+ case CTRL_F:
2112+ redlineEditMoveRight(l);
2113+ break;
2114+ case CTRL_P:
2115+ redlineEditHistoryNext(l, 1);
2116+ break;
2117+ case CTRL_N:
2118+ redlineEditHistoryNext(l, 0);
2119+ break;
2120+ case ESC:
2121+ if (read(l->ifd, seq, 1) == -1) break;
2122+ if (seq[0] == '[' || seq[0] == 'O') {
2123+ if (read(l->ifd, seq+1, 1) == -1) break;
2124+ if (seq[0] == '[') {
2125+ if (seq[1] >= '0' && seq[1] <= '9') {
2126+ plen = 1;
2127+ final = 0;
2128+ param[0] = seq[1];
2129+ while (plen < sizeof(param)) {
2130+ if (read(l->ifd, &p, 1) != 1) break;
2131+ if ((p >= '0' && p <= '9') || p == ';') {
2132+ param[plen++] = p;
2133+ } else {
2134+ final = p;
2135+ break;
2136+ }
2137+ }
2138+ if (final == '~') {
2139+ if (plen == 1 && param[0] == '3') {
2140+ redlineEditDelete(l);
2141+ }
2142+ } else if (final == 'D' || final == 'C') {
2143+ is_word_jump = 0;
2144+ if (plen == 3 && param[0] == '1' && param[1] == ';' && (param[2] == '5' || param[2] == '3')) {
2145+ is_word_jump = 1;
2146+ } else if (plen == 1 && (param[0] == '5' || param[0] == '3')) {
2147+ is_word_jump = 1;
2148+ }
2149+ if (is_word_jump) {
2150+ if (final == 'D') {
2151+ redlineEditMoveWordLeft(l);
2152+ } else {
2153+ redlineEditMoveWordRight(l);
2154+ }
2155+ }
2156+ }
2157+ } else {
2158+ switch (seq[1]) {
2159+ case 'A':
2160+ redlineEditHistoryNext(l, 1);
2161+ break;
2162+ case 'B':
2163+ redlineEditHistoryNext(l, 0);
2164+ break;
2165+ case 'C':
2166+ redlineEditMoveRight(l);
2167+ break;
2168+ case 'D':
2169+ redlineEditMoveLeft(l);
2170+ break;
2171+ case 'H':
2172+ redlineEditMoveHome(l);
2173+ break;
2174+ case 'F':
2175+ redlineEditMoveEnd(l);
2176+ break;
2177+ }
2178+ }
2179+ } else if (seq[0] == 'O') {
2180+ switch (seq[1]) {
2181+ case 'H':
2182+ redlineEditMoveHome(l);
2183+ break;
2184+ case 'F':
2185+ redlineEditMoveEnd(l);
2186+ break;
2187+ }
2188+ }
2189+ } else {
2190+ if (seq[0] == 'b' || seq[0] == 'B') {
2191+ redlineEditMoveWordLeft(l);
2192+ } else if (seq[0] == 'f' || seq[0] == 'F') {
2193+ redlineEditMoveWordRight(l);
2194+ } else if (seq[0] == 'd' || seq[0] == 'D') {
2195+ redlineEditDeleteWordRight(l);
2196+ } else if (seq[0] == 127 || seq[0] == 8) {
2197+ redlineEditDeletePrevWord(l);
2198+ }
2199+ }
2200+ break;
2201+ default:
2202+ utf8len = utf8ByteLen(c);
2203+ utf8[0] = c;
2204+ if (utf8len > 1) {
2205+ for (i = 1; i < utf8len; i++) {
2206+ if (read(l->ifd, utf8+i, 1) != 1) break;
2207+ }
2208+ }
2209+ if (redlineEditInsert(l, utf8, utf8len) == 0) return NULL;
2210+ break;
2211+ case CTRL_U:
2212+ killBufferSave(l->buf, l->pos);
2213+ memmove(l->buf, l->buf + l->pos, l->len - l->pos + 1);
2214+ l->len -= l->pos;
2215+ l->pos = 0;
2216+ refreshLine(l);
2217+ break;
2218+ case CTRL_K:
2219+ killBufferSave(l->buf + l->pos, l->len - l->pos);
2220+ l->buf[l->pos] = '\0';
2221+ l->len = l->pos;
2222+ refreshLine(l);
2223+ break;
2224+ case CTRL_A:
2225+ redlineEditMoveHome(l);
2226+ break;
2227+ case CTRL_E:
2228+ redlineEditMoveEnd(l);
2229+ break;
2230+ case CTRL_L:
2231+ redlineClearScreen();
2232+ refreshLine(l);
2233+ break;
2234+ case CTRL_W:
2235+ redlineEditDeletePrevWord(l);
2236+ break;
2237+ case CTRL_Y:
2238+ if (kill_buffer) {
2239+ redlineEditInsert(l, kill_buffer, strlen(kill_buffer));
2240+ }
2241+ break;
2242+ }
2243+ return "more";
2244 }
2245
2246 static int
2247 redlineEditStart(struct redlineState *l, int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt)
2248 {
2249- l->in_completion = 0;
2250- l->ifd = stdin_fd;
2251- l->ofd = stdout_fd;
2252- l->buf = buf;
2253- l->buflen = buflen;
2254- l->prompt = prompt;
2255- l->plen = strlen(prompt);
2256- l->pos = 0;
2257- l->oldpos = 0;
2258- l->len = 0;
2259- l->cols = getColumns(stdin_fd, stdout_fd);
2260- l->oldrows = 0;
2261- l->oldrpos = 0;
2262- l->history_index = 0;
2263- l->buf[0] = '\0';
2264-
2265- if (enableRawMode(l->ifd) == -1) return -1;
2266- refreshLine(l);
2267- return 0;
2268+ l->in_completion = 0;
2269+ l->ifd = stdin_fd;
2270+ l->ofd = stdout_fd;
2271+ l->buf = buf;
2272+ l->buflen = buflen;
2273+ l->prompt = prompt;
2274+ l->plen = strlen(prompt);
2275+ l->pos = 0;
2276+ l->oldpos = 0;
2277+ l->len = 0;
2278+ l->cols = getColumns(stdin_fd, stdout_fd);
2279+ l->oldrows = 0;
2280+ l->oldrpos = 0;
2281+ l->history_index = 0;
2282+ l->buf[0] = '\0';
2283+
2284+ if (enableRawMode(l->ifd) == -1) return -1;
2285+ refreshLine(l);
2286+ return 0;
2287 }
2288
2289 static void
2290 redlineEditStop(struct redlineState *l)
2291 {
2292- if (!isatty(l->ifd) && !getenv("REDLINE_ASSUME_TTY")) return;
2293- disableRawMode(l->ifd);
2294- printf("\n");
2295+ if (!isatty(l->ifd) && !getenv("REDLINE_ASSUME_TTY")) return;
2296+ disableRawMode(l->ifd);
2297+ printf("\n");
2298 }
2299
2300 char *
2301 redline(const char *prompt)
2302 {
2303- struct redlineState l;
2304- char *buf;
2305- char *res;
2306-
2307- if (!isatty(STDIN_FILENO) || isUnsupportedTerm()) {
2308- if (write(STDOUT_FILENO, prompt, strlen(prompt)) == -1) {}
2309- return redlineNoTTY();
2310- }
2311-
2312- buf = malloc(REDLINE_INITIAL_BUFLEN);
2313- if (buf == NULL) return NULL;
2314- if (redlineEditStart(&l, STDIN_FILENO, STDOUT_FILENO, buf, REDLINE_INITIAL_BUFLEN, prompt) == -1) {
2315- free(buf);
2316- return NULL;
2317- }
2318- redlineHistoryAdd("");
2319- while (1) {
2320- res = redlineEditFeed(&l);
2321- if (res == NULL || strcmp(res, "more") != 0) {
2322- break;
2323- }
2324- }
2325- redlineEditStop(&l);
2326- if (history_len > 0) {
2327- history_len--;
2328- free(history[history_len]);
2329- }
2330- free(l.buf);
2331- return res;
2332+ struct redlineState l;
2333+ char *buf;
2334+ char *res;
2335+
2336+ if (!isatty(STDIN_FILENO) || isUnsupportedTerm()) {
2337+ if (write(STDOUT_FILENO, prompt, strlen(prompt)) == -1) {}
2338+ return redlineNoTTY();
2339+ }
2340+
2341+ buf = malloc(REDLINE_INITIAL_BUFLEN);
2342+ if (buf == NULL) return NULL;
2343+ if (redlineEditStart(&l, STDIN_FILENO, STDOUT_FILENO, buf, REDLINE_INITIAL_BUFLEN, prompt) == -1) {
2344+ free(buf);
2345+ return NULL;
2346+ }
2347+ redlineHistoryAdd("");
2348+ while (1) {
2349+ res = redlineEditFeed(&l);
2350+ if (res == NULL || strcmp(res, "more") != 0) {
2351+ break;
2352+ }
2353+ }
2354+ redlineEditStop(&l);
2355+ if (history_len > 0) {
2356+ history_len--;
2357+ free(history[history_len]);
2358+ }
2359+ free(l.buf);
2360+ return res;
2361 }
2362
2363 void
2364 redlineSetCompletionCallback(void (*cb)(const char *, struct redlineCompletions *))
2365 {
2366- completionCallback = cb;
2367+ completionCallback = cb;
2368 }
2369
2370 void
2371 redlineAddCompletion(struct redlineCompletions *lc, const char *str)
2372 {
2373- size_t len = strlen(str);
2374- char *copy, **cvec;
2375-
2376- copy = malloc(len+1);
2377- if (copy == NULL) return;
2378- memcpy(copy,str,len+1);
2379- cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1));
2380- if (cvec == NULL) {
2381- free(copy);
2382- return;
2383- }
2384- lc->cvec = cvec;
2385- lc->cvec[lc->len++] = copy;
2386+ size_t len = strlen(str);
2387+ char *copy, **cvec;
2388+
2389+ copy = malloc(len+1);
2390+ if (copy == NULL) return;
2391+ memcpy(copy,str,len+1);
2392+ cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1));
2393+ if (cvec == NULL) {
2394+ free(copy);
2395+ return;
2396+ }
2397+ lc->cvec = cvec;
2398+ lc->cvec[lc->len++] = copy;
2399 }
2400
2401 void
2402 redlineSetMultiLine(int ml)
2403 {
2404- mlmode = ml;
2405+ mlmode = ml;
2406 }
1@@ -0,0 +1,586 @@
2+/* See LICENSE file for copyright and license details. */
3+#include "../diffutil.h"
4+#include "../text.h"
5+#include "../util.h"
6+
7+#include <ctype.h>
8+#include <stdio.h>
9+#include <stdlib.h>
10+#include <string.h>
11+
12+static int
13+read_all(FILE *fp, char **out, size_t *outlen, const char *path)
14+{
15+ char buf[8192];
16+ char *data;
17+ size_t cap, len;
18+ ssize_t n;
19+
20+ data = NULL;
21+ cap = len = 0;
22+ while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
23+ if (len + (size_t)n > cap) {
24+ cap = (len + (size_t)n) * 2 + 64;
25+ data = erealloc(data, cap);
26+ }
27+ memcpy(data + len, buf, (size_t)n);
28+ len += (size_t)n;
29+ }
30+ if (ferror(fp)) {
31+ weprintf("read %s:", path);
32+ free(data);
33+ return -1;
34+ }
35+ if (!data) {
36+ data = emalloc(1);
37+ data[0] = '\0';
38+ } else if (len == cap) {
39+ data = erealloc(data, cap + 1);
40+ data[len] = '\0';
41+ }
42+ *out = data;
43+ *outlen = len;
44+ return 0;
45+}
46+
47+static void
48+split_lines(struct diffline **out, size_t *outn, char *data, size_t len)
49+{
50+ struct diffline *lines;
51+ size_t i, n, start;
52+
53+ n = 0;
54+ for (i = 0; i < len; i++)
55+ if (data[i] == '\n')
56+ n++;
57+ if (len > 0 && (len == 0 || data[len - 1] != '\n'))
58+ n++;
59+ if (n == 0) {
60+ *out = NULL;
61+ *outn = 0;
62+ return;
63+ }
64+ lines = ecalloc(n, sizeof(*lines));
65+ i = 0;
66+ start = 0;
67+ for (n = 0; n < (size_t)len; n++) {
68+ if (data[n] == '\n') {
69+ lines[i].data = data + start;
70+ lines[i].len = n - start;
71+ i++;
72+ start = n + 1;
73+ }
74+ }
75+ if (start < len) {
76+ lines[i].data = data + start;
77+ lines[i].len = len - start;
78+ i++;
79+ }
80+ *out = lines;
81+ *outn = i;
82+}
83+
84+int
85+diff_load(struct difffile *df, const char *path)
86+{
87+ FILE *fp;
88+ char *data;
89+ size_t len;
90+
91+ if (!strcmp(path, "-")) {
92+ fp = stdin;
93+ } else if (!(fp = fopen(path, "r"))) {
94+ weprintf("open %s:", path);
95+ return -1;
96+ }
97+ if (read_all(fp, &data, &len, path) < 0) {
98+ if (fp != stdin)
99+ fclose(fp);
100+ return -1;
101+ }
102+ if (fp != stdin)
103+ fclose(fp);
104+ df->lines = NULL;
105+ df->nlines = 0;
106+ if (len == 0) {
107+ df->lines = ecalloc(1, sizeof(*df->lines));
108+ df->lines[0].data = data;
109+ df->lines[0].len = 0;
110+ df->nlines = 0;
111+ return 0;
112+ }
113+ split_lines(&df->lines, &df->nlines, data, len);
114+ {
115+ struct diffline *grown;
116+ grown = erealloc(df->lines, (df->nlines + 1) * sizeof(*grown));
117+ grown[df->nlines].data = data;
118+ grown[df->nlines].len = 0;
119+ df->lines = grown;
120+ }
121+ return 0;
122+}
123+
124+void
125+diff_free(struct difffile *df)
126+{
127+ char *base;
128+
129+ if (!df->lines)
130+ return;
131+ if (df->nlines == 0) {
132+ free(df->lines[0].data);
133+ free(df->lines);
134+ df->lines = NULL;
135+ df->nlines = 0;
136+ return;
137+ }
138+ base = df->lines[df->nlines].data;
139+ free(base);
140+ free(df->lines);
141+ df->lines = NULL;
142+ df->nlines = 0;
143+}
144+
145+static int
146+lines_equal(const struct diffline *a, const struct diffline *b,
147+ const struct diffopts *opts)
148+{
149+ size_t i, j;
150+
151+ if (opts && opts->ignore_blanks) {
152+ i = j = 0;
153+ while (i < a->len && j < b->len) {
154+ while (i < a->len && isspace((unsigned char)a->data[i]))
155+ i++;
156+ while (j < b->len && isspace((unsigned char)b->data[j]))
157+ j++;
158+ if (i >= a->len || j >= b->len)
159+ break;
160+ if (opts->ignore_case) {
161+ if (tolower((unsigned char)a->data[i]) !=
162+ tolower((unsigned char)b->data[j]))
163+ return 0;
164+ } else if (a->data[i] != b->data[j]) {
165+ return 0;
166+ }
167+ i++;
168+ j++;
169+ }
170+ while (i < a->len && isspace((unsigned char)a->data[i]))
171+ i++;
172+ while (j < b->len && isspace((unsigned char)b->data[j]))
173+ j++;
174+ return i == a->len && j == b->len;
175+ }
176+
177+ if (opts && opts->ignore_case) {
178+ if (a->len != b->len)
179+ return 0;
180+ for (i = 0; i < a->len; i++) {
181+ if (tolower((unsigned char)a->data[i]) !=
182+ tolower((unsigned char)b->data[i]))
183+ return 0;
184+ }
185+ return 1;
186+ }
187+
188+ if (a->len != b->len)
189+ return 0;
190+ return memcmp(a->data, b->data, a->len) == 0;
191+}
192+
193+struct lcs_cell {
194+ int diag;
195+ int up;
196+ int left;
197+};
198+
199+int
200+diff_compute(struct diffhunks *hunks, const struct difffile *old,
201+ const struct difffile *new, const struct diffopts *opts)
202+{
203+ struct lcs_cell *c;
204+ size_t n, m, i, j, k, cap;
205+ struct diffhunk *h;
206+ int *xs, *ys;
207+ size_t hfrom, hto, vfrom, vto;
208+ struct diffopts default_opts;
209+
210+ if (!opts) {
211+ memset(&default_opts, 0, sizeof(default_opts));
212+ default_opts.context = 3;
213+ opts = &default_opts;
214+ }
215+
216+ n = old->nlines;
217+ m = new->nlines;
218+
219+ if (n == 0 && m == 0) {
220+ hunks->v = NULL;
221+ hunks->n = 0;
222+ return 0;
223+ }
224+
225+ c = ecalloc((n + 1) * (m + 1), sizeof(*c));
226+ for (i = 0; i <= n; i++) {
227+ for (j = 0; j <= m; j++) {
228+ if (i == 0 && j == 0) {
229+ c[i * (m + 1) + j].diag = 0;
230+ continue;
231+ }
232+ if (i > 0 && j > 0 &&
233+ lines_equal(&old->lines[i - 1], &new->lines[j - 1], opts)) {
234+ c[i * (m + 1) + j].diag = c[(i - 1) * (m + 1) + (j - 1)].diag + 1;
235+ c[i * (m + 1) + j].up = 0;
236+ c[i * (m + 1) + j].left = 0;
237+ continue;
238+ }
239+ if (i > 0 && (j == 0 || c[(i - 1) * (m + 1) + j].diag >=
240+ c[i * (m + 1) + (j - 1)].diag)) {
241+ c[i * (m + 1) + j].diag = c[(i - 1) * (m + 1) + j].diag;
242+ c[i * (m + 1) + j].up = 1;
243+ c[i * (m + 1) + j].left = 0;
244+ } else {
245+ c[i * (m + 1) + j].diag = c[i * (m + 1) + (j - 1)].diag;
246+ c[i * (m + 1) + j].up = 0;
247+ c[i * (m + 1) + j].left = 1;
248+ }
249+ }
250+ }
251+
252+ cap = n + m + 16;
253+ xs = ecalloc(cap, sizeof(*xs));
254+ ys = ecalloc(cap, sizeof(*ys));
255+ k = 0;
256+ i = n;
257+ j = m;
258+ while (i > 0 || j > 0) {
259+ if (i > 0 && j > 0 &&
260+ lines_equal(&old->lines[i - 1], &new->lines[j - 1], opts)) {
261+ xs[k] = 0;
262+ ys[k] = 0;
263+ i--;
264+ j--;
265+ } else if (i > 0 && c[i * (m + 1) + j].up) {
266+ xs[k] = 1;
267+ ys[k] = 0;
268+ i--;
269+ } else {
270+ xs[k] = 0;
271+ ys[k] = 2;
272+ j--;
273+ }
274+ k++;
275+ }
276+ hunks->v = NULL;
277+ hunks->n = 0;
278+ h = NULL;
279+ i = 0;
280+ j = 0;
281+ {
282+ size_t step, idx;
283+ int op;
284+ step = k;
285+ while (step > 0) {
286+ idx = step - 1;
287+ op = xs[idx] | ys[idx];
288+ if (op == 0) {
289+ step--;
290+ i++;
291+ j++;
292+ continue;
293+ }
294+ hfrom = i;
295+ vfrom = j;
296+ hto = i;
297+ vto = j;
298+ while (step > 0) {
299+ idx = step - 1;
300+ op = xs[idx] | ys[idx];
301+ if (op == 0)
302+ break;
303+ if (xs[idx] == 1)
304+ hto++;
305+ if (ys[idx] == 2)
306+ vto++;
307+ step--;
308+ }
309+ i = hto;
310+ j = vto;
311+ hunks->v = erealloc(hunks->v, (hunks->n + 1) * sizeof(*h));
312+ h = &hunks->v[hunks->n];
313+ h->old.from = hfrom;
314+ h->old.to = hto;
315+ h->new.from = vfrom;
316+ h->new.to = vto;
317+ hunks->n++;
318+ }
319+ }
320+ free(c);
321+ free(xs);
322+ free(ys);
323+ return 0;
324+}
325+
326+void
327+diff_hunks_free(struct diffhunks *hunks)
328+{
329+ if (!hunks)
330+ return;
331+ free(hunks->v);
332+ hunks->v = NULL;
333+ hunks->n = 0;
334+}
335+
336+int
337+diff_looks_binary(const struct difffile *df)
338+{
339+ size_t i, scan;
340+
341+ scan = 4096;
342+ for (i = 0; i < df->nlines && scan > 0; i++) {
343+ size_t take = df->lines[i].len < scan ? df->lines[i].len : scan;
344+ if (memchr(df->lines[i].data, '\0', take))
345+ return 1;
346+ scan -= take;
347+ }
348+ return 0;
349+}
350+
351+static void
352+print_range(FILE *out, size_t from, size_t to)
353+{
354+ if (to - from <= 1)
355+ fprintf(out, "%zu", from + 1);
356+ else
357+ fprintf(out, "%zu,%zu", from + 1, to);
358+}
359+
360+static void
361+print_lines(FILE *out, const struct diffline *lines, size_t from, size_t to,
362+ char prefix)
363+{
364+ size_t i;
365+ for (i = from; i < to; i++) {
366+ fputc(prefix, out);
367+ fwrite(lines[i].data, 1, lines[i].len, out);
368+ fputc('\n', out);
369+ }
370+}
371+
372+static int
373+format_normal(FILE *out, const struct diffhunks *hunks,
374+ const struct difffile *old, const struct difffile *new)
375+{
376+ size_t i;
377+ for (i = 0; i < hunks->n; i++) {
378+ struct diffhunk *h = &hunks->v[i];
379+ size_t oldn = h->old.to - h->old.from;
380+ size_t newn = h->new.to - h->new.from;
381+ char oc;
382+
383+ oc = oldn == 0 ? 'a' : (newn == 0 ? 'd' : 'c');
384+ print_range(out, h->old.from, h->old.to);
385+ fputc(oc, out);
386+ print_range(out, h->new.from, h->new.to);
387+ fputc('\n', out);
388+ if (oldn && newn) {
389+ print_lines(out, old->lines, h->old.from, h->old.to, '<');
390+ fprintf(out, "---\n");
391+ print_lines(out, new->lines, h->new.from, h->new.to, '>');
392+ } else if (oldn) {
393+ print_lines(out, old->lines, h->old.from, h->old.to, '<');
394+ } else {
395+ print_lines(out, new->lines, h->new.from, h->new.to, '>');
396+ }
397+ }
398+ return 0;
399+}
400+
401+static void
402+emit_unified_hunk(FILE *out, const struct diffhunk *h,
403+ const struct difffile *old, const struct difffile *new,
404+ size_t ctx)
405+{
406+ size_t oldfrom, oldto, newfrom, newto;
407+ size_t i;
408+
409+ oldfrom = h->old.from < ctx ? 0 : h->old.from - ctx;
410+ oldto = h->old.to + ctx;
411+ if (oldto > old->nlines)
412+ oldto = old->nlines;
413+ newfrom = h->new.from < ctx ? 0 : h->new.from - ctx;
414+ newto = h->new.to + ctx;
415+ if (newto > new->nlines)
416+ newto = new->nlines;
417+
418+ if (oldto - oldfrom <= 1)
419+ fprintf(out, "@@ -%zu +%zu,%zu @@\n", oldfrom + 1, newfrom + 1,
420+ newto - newfrom);
421+ else if (newto - newfrom <= 1)
422+ fprintf(out, "@@ -%zu,%zu +%zu @@\n", oldfrom + 1, oldto - oldfrom,
423+ newfrom + 1);
424+ else
425+ fprintf(out, "@@ -%zu,%zu +%zu,%zu @@\n", oldfrom + 1,
426+ oldto - oldfrom, newfrom + 1, newto - newfrom);
427+
428+ for (i = oldfrom; i < h->old.from; i++) {
429+ fputc(' ', out);
430+ fwrite(old->lines[i].data, 1, old->lines[i].len, out);
431+ fputc('\n', out);
432+ }
433+ print_lines(out, old->lines, h->old.from, h->old.to, '-');
434+ print_lines(out, new->lines, h->new.from, h->new.to, '+');
435+ for (i = h->old.to; i < oldto; i++) {
436+ fputc(' ', out);
437+ fwrite(old->lines[i].data, 1, old->lines[i].len, out);
438+ fputc('\n', out);
439+ }
440+}
441+
442+static int
443+format_unified(FILE *out, const struct diffhunks *hunks,
444+ const struct difffile *old, const struct difffile *new,
445+ const char *oldlabel, const char *newlabel, size_t ctx)
446+{
447+ size_t i;
448+ if (oldlabel)
449+ fprintf(out, "--- %s\n", oldlabel);
450+ if (newlabel)
451+ fprintf(out, "+++ %s\n", newlabel);
452+ for (i = 0; i < hunks->n; i++)
453+ emit_unified_hunk(out, &hunks->v[i], old, new, ctx);
454+ return 0;
455+}
456+
457+static void
458+emit_context_hunk(FILE *out, const struct diffhunk *h,
459+ const struct difffile *old, const struct difffile *new,
460+ size_t ctx)
461+{
462+ size_t oldfrom, oldto, newfrom, newto;
463+ size_t i;
464+
465+ oldfrom = h->old.from < ctx ? 0 : h->old.from - ctx;
466+ oldto = h->old.to + ctx;
467+ if (oldto > old->nlines)
468+ oldto = old->nlines;
469+ newfrom = h->new.from < ctx ? 0 : h->new.from - ctx;
470+ newto = h->new.to + ctx;
471+ if (newto > new->nlines)
472+ newto = new->nlines;
473+
474+ fprintf(out, "***************\n");
475+ if (oldto - oldfrom <= 1)
476+ fprintf(out, "*** %zu ****\n", oldfrom + 1);
477+ else
478+ fprintf(out, "*** %zu,%zu ****\n", oldfrom + 1, oldto - oldfrom);
479+ for (i = oldfrom; i < h->old.from; i++) {
480+ fputc(' ', out);
481+ fwrite(old->lines[i].data, 1, old->lines[i].len, out);
482+ fputc('\n', out);
483+ }
484+ print_lines(out, old->lines, h->old.from, h->old.to, '-');
485+ for (i = h->old.to; i < oldto; i++) {
486+ fputc(' ', out);
487+ fwrite(old->lines[i].data, 1, old->lines[i].len, out);
488+ fputc('\n', out);
489+ }
490+ if (newto - newfrom <= 1)
491+ fprintf(out, "--- %zu ----\n", newfrom + 1);
492+ else
493+ fprintf(out, "--- %zu,%zu ----\n", newfrom + 1, newto - newfrom);
494+ for (i = newfrom; i < h->new.from; i++) {
495+ fputc(' ', out);
496+ fwrite(new->lines[i].data, 1, new->lines[i].len, out);
497+ fputc('\n', out);
498+ }
499+ print_lines(out, new->lines, h->new.from, h->new.to, '+');
500+ for (i = h->new.to; i < newto; i++) {
501+ fputc(' ', out);
502+ fwrite(new->lines[i].data, 1, new->lines[i].len, out);
503+ fputc('\n', out);
504+ }
505+}
506+
507+static int
508+format_context(FILE *out, const struct diffhunks *hunks,
509+ const struct difffile *old, const struct difffile *new,
510+ const char *oldlabel, const char *newlabel, size_t ctx)
511+{
512+ size_t i;
513+ if (oldlabel)
514+ fprintf(out, "*** %s\n", oldlabel);
515+ if (newlabel)
516+ fprintf(out, "--- %s\n", newlabel);
517+ for (i = 0; i < hunks->n; i++)
518+ emit_context_hunk(out, &hunks->v[i], old, new, ctx);
519+ return 0;
520+}
521+
522+static int
523+format_ed(FILE *out, const struct diffhunks *hunks,
524+ const struct difffile *old, const struct difffile *new)
525+{
526+ size_t i;
527+ (void)old;
528+ for (i = 0; i < hunks->n; i++) {
529+ struct diffhunk *h = &hunks->v[i];
530+ size_t oldn = h->old.to - h->old.from;
531+ size_t newn = h->new.to - h->new.from;
532+ char op;
533+
534+ op = oldn == 0 ? 'a' : (newn == 0 ? 'd' : 'c');
535+ print_range(out, h->old.from, h->old.to);
536+ fputc(op, out);
537+ fputc('\n', out);
538+ if (op == 'a' || op == 'c') {
539+ size_t j;
540+ for (j = h->new.from; j < h->new.to; j++) {
541+ if (new->lines[j].len == 1 && new->lines[j].data[0] == '.')
542+ fprintf(out, "..\n");
543+ else if (new->lines[j].len == 0)
544+ fprintf(out, ".\n");
545+ else {
546+ fwrite(new->lines[j].data, 1, new->lines[j].len, out);
547+ fputc('\n', out);
548+ }
549+ }
550+ fprintf(out, ".\n");
551+ }
552+ }
553+ return 0;
554+}
555+
556+int
557+diff_format(FILE *out, const struct diffhunks *hunks,
558+ const struct difffile *old, const struct difffile *new,
559+ const char *oldlabel, const char *newlabel,
560+ const struct diffopts *opts)
561+{
562+ struct diffopts default_opts;
563+ size_t ctx;
564+
565+ if (!opts) {
566+ memset(&default_opts, 0, sizeof(default_opts));
567+ default_opts.context = 3;
568+ opts = &default_opts;
569+ }
570+ ctx = opts->context ? opts->context : 3;
571+ switch (opts->format) {
572+ case DIFF_NORMAL:
573+ return format_normal(out, hunks, old, new);
574+ case DIFF_UNIFIED:
575+ return format_unified(out, hunks, old, new, oldlabel, newlabel, ctx);
576+ case DIFF_CONTEXT:
577+ return format_context(out, hunks, old, new, oldlabel, newlabel, ctx);
578+ case DIFF_ED:
579+ case DIFF_RCSED:
580+ return format_ed(out, hunks, old, new);
581+ case DIFF_BRIEF:
582+ if (hunks->n > 0)
583+ return 1;
584+ return 0;
585+ }
586+ return 0;
587+}
1@@ -31,711 +31,714 @@
2 int
3 blockdev_open(struct BlockDev *dev, const char *path, int writable)
4 {
5- struct stat st;
6- int fd, flags;
7+ struct stat st;
8+ int fd, flags;
9
10- flags = writable ? O_RDWR : O_RDONLY;
11- fd = open(path, flags);
12- if (fd < 0)
13- return -1;
14+ flags = writable ? O_RDWR : O_RDONLY;
15+ fd = open(path, flags);
16+ if (fd < 0)
17+ return -1;
18
19- if (fstat(fd, &st) < 0) {
20- close(fd);
21- return -1;
22- }
23+ if (fstat(fd, &st) < 0) {
24+ close(fd);
25+ return -1;
26+ }
27
28- dev->fd = fd;
29- dev->size = st.st_size;
30- dev->sec_size = 512;
31+ dev->fd = fd;
32+ dev->size = st.st_size;
33+ dev->sec_size = 512;
34
35- if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
36+ if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
37 #if defined(__linux__)
38- uint64_t size_bytes = 0;
39- int sec_size = 0;
40- if (ioctl(fd, BLKGETSIZE64, &size_bytes) >= 0)
41- dev->size = size_bytes;
42- if (ioctl(fd, BLKSSZGET, &sec_size) >= 0)
43- dev->sec_size = sec_size;
44+ uint64_t size_bytes = 0;
45+ int sec_size = 0;
46+#pragma GCC diagnostic push
47+#pragma GCC diagnostic ignored "-Woverflow"
48+ if (ioctl(fd, BLKGETSIZE64, &size_bytes) >= 0)
49+ dev->size = size_bytes;
50+ if (ioctl(fd, BLKSSZGET, &sec_size) >= 0)
51+ dev->sec_size = sec_size;
52+#pragma GCC diagnostic pop
53 #elif defined(__FreeBSD__)
54- off_t size_bytes = 0;
55- unsigned int sec_size = 0;
56- if (ioctl(fd, DIOCGMEDIASIZE, &size_bytes) >= 0)
57- dev->size = size_bytes;
58- if (ioctl(fd, DIOCGSECTORSIZE, &sec_size) >= 0)
59- dev->sec_size = sec_size;
60+ off_t size_bytes = 0;
61+ unsigned int sec_size = 0;
62+ if (ioctl(fd, DIOCGMEDIASIZE, &size_bytes) >= 0)
63+ dev->size = size_bytes;
64+ if (ioctl(fd, DIOCGSECTORSIZE, &sec_size) >= 0)
65+ dev->sec_size = sec_size;
66 #elif defined(__OpenBSD__) || defined(__NetBSD__)
67- struct disklabel dl;
68- if (ioctl(fd, DIOCGDINFO, &dl) >= 0) {
69- dev->size = (uint64_t)dl.d_secsize * DL_GETDSIZE(&dl);
70- dev->sec_size = dl.d_secsize;
71- }
72+ struct disklabel dl;
73+ if (ioctl(fd, DIOCGDINFO, &dl) >= 0) {
74+ dev->size = (uint64_t)dl.d_secsize * DL_GETDSIZE(&dl);
75+ dev->sec_size = dl.d_secsize;
76+ }
77 #endif
78- }
79+ }
80
81- return 0;
82+ return 0;
83 }
84
85 int
86 blockdev_read(struct BlockDev *dev, uint64_t sector, void *buf, size_t sector_count)
87 {
88- off_t offset = (off_t)sector * dev->sec_size;
89- size_t size = sector_count * dev->sec_size;
90- ssize_t n;
91+ off_t offset = (off_t)sector * dev->sec_size;
92+ size_t size = sector_count * dev->sec_size;
93+ ssize_t n;
94
95- if (lseek(dev->fd, offset, SEEK_SET) == (off_t)-1)
96- return -1;
97+ if (lseek(dev->fd, offset, SEEK_SET) == (off_t)-1)
98+ return -1;
99
100- n = read(dev->fd, buf, size);
101- if (n < 0 || (size_t)n != size)
102- return -1;
103+ n = read(dev->fd, buf, size);
104+ if (n < 0 || (size_t)n != size)
105+ return -1;
106
107- return 0;
108+ return 0;
109 }
110
111 int
112 blockdev_write(struct BlockDev *dev, uint64_t sector, const void *buf, size_t sector_count)
113 {
114- off_t offset = (off_t)sector * dev->sec_size;
115- size_t size = sector_count * dev->sec_size;
116- ssize_t n;
117+ off_t offset = (off_t)sector * dev->sec_size;
118+ size_t size = sector_count * dev->sec_size;
119+ ssize_t n;
120
121- if (lseek(dev->fd, offset, SEEK_SET) == (off_t)-1)
122- return -1;
123+ if (lseek(dev->fd, offset, SEEK_SET) == (off_t)-1)
124+ return -1;
125
126- n = write(dev->fd, buf, size);
127- if (n < 0 || (size_t)n != size)
128- return -1;
129+ n = write(dev->fd, buf, size);
130+ if (n < 0 || (size_t)n != size)
131+ return -1;
132
133- return 0;
134+ return 0;
135 }
136
137 void
138 blockdev_close(struct BlockDev *dev)
139 {
140- if (dev->fd >= 0) {
141- close(dev->fd);
142- dev->fd = -1;
143- }
144+ if (dev->fd >= 0) {
145+ close(dev->fd);
146+ dev->fd = -1;
147+ }
148 }
149
150 struct BlockDevInfo *
151 blockdev_get_list(void)
152 {
153 #if defined(__linux__)
154- FILE *fp;
155- FILE *mfile;
156- char line[256];
157- char mline[512];
158- char devpath[128];
159- char mnt[256];
160- char fs[64];
161- struct BlockDevInfo *head = NULL;
162- struct BlockDevInfo *tail = NULL;
163- struct BlockDevInfo *info;
164- struct BlockDevInfo *curr;
165- unsigned int major, minor;
166- unsigned long long blocks;
167- char name[64];
168- int is_part;
169-
170- fp = fopen(PATH_PARTITIONS, "r");
171- if (!fp)
172- return NULL;
173-
174- while (fgets(line, sizeof(line), fp)) {
175- if (sscanf(line, " %u %u %llu %63s", &major, &minor, &blocks, name) != 4)
176- continue;
177-
178- info = ecalloc(1, sizeof(*info));
179-
180- strlcpy(info->name, name, sizeof(info->name));
181- snprintf(info->path, sizeof(info->path), "%s/%s", PATH_DEV, name);
182- info->size = blocks * 1024;
183- info->major = major;
184- info->minor = minor;
185-
186- /* search tree topology to link partition node under proper target parent disk */
187- is_part = 0;
188- for (curr = head; curr; curr = curr->next) {
189- size_t len = strlen(curr->name);
190- if (strncmp(name, curr->name, len) == 0) {
191- char c = name[len];
192- if (curr->name[len - 1] >= '0' && curr->name[len - 1] <= '9') {
193- if (c == 'p' && name[len + 1] >= '0' && name[len + 1] <= '9')
194- is_part = 1;
195- } else {
196- if (c >= '0' && c <= '9')
197- is_part = 1;
198- }
199- if (is_part) {
200- strlcpy(info->type, "part", sizeof(info->type));
201- struct BlockDevInfo *p = curr->parts;
202- if (!p) {
203- curr->parts = info;
204- } else {
205- while (p->next)
206- p = p->next;
207- p->next = info;
208- }
209- break;
210- }
211- }
212- }
213-
214- if (!is_part) {
215- strlcpy(info->type, "disk", sizeof(info->type));
216- if (!head) {
217- head = info;
218- } else {
219- tail->next = info;
220- }
221- tail = info;
222- }
223- }
224- fclose(fp);
225-
226- mfile = fopen(PATH_MOUNTS, "r");
227- if (mfile) {
228- while (fgets(mline, sizeof(mline), mfile)) {
229- if (sscanf(mline, "%127s %255s %63s", devpath, mnt, fs) == 3) {
230- char *devname = devpath;
231- size_t dev_len = strlen(PATH_DEV);
232- if (strncmp(devpath, PATH_DEV, dev_len) == 0 && devpath[dev_len] == '/')
233- devname = devpath + dev_len + 1;
234- struct BlockDevInfo *curr;
235- for (curr = head; curr; curr = curr->next) {
236- if (strcmp(curr->name, devname) == 0) {
237- strlcpy(curr->mountpoint, mnt, sizeof(curr->mountpoint));
238- strlcpy(curr->fstype, fs, sizeof(curr->fstype));
239- }
240- struct BlockDevInfo *part;
241- for (part = curr->parts; part; part = part->next) {
242- if (strcmp(part->name, devname) == 0) {
243- strlcpy(part->mountpoint, mnt, sizeof(part->mountpoint));
244- strlcpy(part->fstype, fs, sizeof(part->fstype));
245- }
246- }
247- }
248- }
249- }
250- fclose(mfile);
251- }
252-
253- return head;
254+ FILE *fp;
255+ FILE *mfile;
256+ char line[256];
257+ char mline[512];
258+ char devpath[128];
259+ char mnt[256];
260+ char fs[64];
261+ struct BlockDevInfo *head = NULL;
262+ struct BlockDevInfo *tail = NULL;
263+ struct BlockDevInfo *info;
264+ struct BlockDevInfo *curr;
265+ unsigned int major, minor;
266+ unsigned long long blocks;
267+ char name[64];
268+ int is_part;
269+
270+ fp = fopen(ARUU_LINUX_PATH_PROC_PARTITIONS, "r");
271+ if (!fp)
272+ return NULL;
273+
274+ while (fgets(line, sizeof(line), fp)) {
275+ if (sscanf(line, " %u %u %llu %63s", &major, &minor, &blocks, name) != 4)
276+ continue;
277+
278+ info = ecalloc(1, sizeof(*info));
279+
280+ strlcpy(info->name, name, sizeof(info->name));
281+ snprintf(info->path, sizeof(info->path), "%s/%s", ARUU_PATH_DEV, name);
282+ info->size = blocks * 1024;
283+ info->major = major;
284+ info->minor = minor;
285+
286+ /* search tree topology to link partition node under proper target parent disk */
287+ is_part = 0;
288+ for (curr = head; curr; curr = curr->next) {
289+ size_t len = strlen(curr->name);
290+ if (strncmp(name, curr->name, len) == 0) {
291+ char c = name[len];
292+ if (curr->name[len - 1] >= '0' && curr->name[len - 1] <= '9') {
293+ if (c == 'p' && name[len + 1] >= '0' && name[len + 1] <= '9')
294+ is_part = 1;
295+ } else {
296+ if (c >= '0' && c <= '9')
297+ is_part = 1;
298+ }
299+ if (is_part) {
300+ strlcpy(info->type, "part", sizeof(info->type));
301+ struct BlockDevInfo *p = curr->parts;
302+ if (!p) {
303+ curr->parts = info;
304+ } else {
305+ while (p->next)
306+ p = p->next;
307+ p->next = info;
308+ }
309+ break;
310+ }
311+ }
312+ }
313+
314+ if (!is_part) {
315+ strlcpy(info->type, "disk", sizeof(info->type));
316+ if (!head) {
317+ head = info;
318+ } else {
319+ tail->next = info;
320+ }
321+ tail = info;
322+ }
323+ }
324+ fclose(fp);
325+
326+ mfile = fopen(ARUU_LINUX_PATH_PROC_MOUNTS, "r");
327+ if (mfile) {
328+ while (fgets(mline, sizeof(mline), mfile)) {
329+ if (sscanf(mline, "%127s %255s %63s", devpath, mnt, fs) == 3) {
330+ char *devname = devpath;
331+ size_t dev_len = strlen(ARUU_PATH_DEV);
332+ if (strncmp(devpath, ARUU_PATH_DEV, dev_len) == 0 && devpath[dev_len] == '/')
333+ devname = devpath + dev_len + 1;
334+ struct BlockDevInfo *curr;
335+ for (curr = head; curr; curr = curr->next) {
336+ if (strcmp(curr->name, devname) == 0) {
337+ strlcpy(curr->mountpoint, mnt, sizeof(curr->mountpoint));
338+ strlcpy(curr->fstype, fs, sizeof(curr->fstype));
339+ }
340+ struct BlockDevInfo *part;
341+ for (part = curr->parts; part; part = part->next) {
342+ if (strcmp(part->name, devname) == 0) {
343+ strlcpy(part->mountpoint, mnt, sizeof(part->mountpoint));
344+ strlcpy(part->fstype, fs, sizeof(part->fstype));
345+ }
346+ }
347+ }
348+ }
349+ }
350+ fclose(mfile);
351+ }
352+
353+ return head;
354
355 #elif defined(__FreeBSD__)
356- char disks[1024];
357- char devpath[128];
358- char *tok;
359- char *ptr;
360- struct BlockDevInfo *head = NULL;
361- struct BlockDevInfo *tail = NULL;
362- struct BlockDevInfo *info;
363- struct BlockDevInfo *part;
364- struct BlockDevInfo *p;
365- struct BlockDev dev;
366- DIR *dir;
367- struct dirent *de;
368- size_t disk_len;
369- size_t len;
370- struct statfs *mntbuf;
371- int mntsize;
372- int i;
373-
374- len = sizeof(disks);
375- if (sysctlbyname("kern.disks", disks, &len, NULL, 0) < 0)
376- return NULL;
377-
378- ptr = disks;
379- while ((tok = strsep(&ptr, " \t")) != NULL) {
380- if (!*tok)
381- continue;
382-
383- info = ecalloc(1, sizeof(*info));
384-
385- strlcpy(info->name, tok, sizeof(info->name));
386- snprintf(info->path, sizeof(info->path), "%s/%s", PATH_DEV, tok);
387- strlcpy(info->type, "disk", sizeof(info->type));
388-
389- snprintf(devpath, sizeof(devpath), "%s/%s", PATH_DEV, tok);
390- if (blockdev_open(&dev, devpath, 0) == 0) {
391- info->size = dev.size;
392- blockdev_close(&dev);
393- }
394-
395- dir = opendir(PATH_DEV);
396- if (dir) {
397- disk_len = strlen(tok);
398- while ((de = readdir(dir)) != NULL) {
399- if (strncmp(de->d_name, tok, disk_len) == 0) {
400- char c = de->d_name[disk_len];
401- if (c == 's' || c == 'p') {
402- part = ecalloc(1, sizeof(*part));
403- strlcpy(part->name, de->d_name, sizeof(part->name));
404- snprintf(part->path, sizeof(part->path), "%s/%s", PATH_DEV, de->d_name);
405- strlcpy(part->type, "part", sizeof(part->type));
406- snprintf(devpath, sizeof(devpath), "%s/%s", PATH_DEV, de->d_name);
407- if (blockdev_open(&dev, devpath, 0) == 0) {
408- part->size = dev.size;
409- blockdev_close(&dev);
410- }
411- p = info->parts;
412- if (!p) {
413- info->parts = part;
414- } else {
415- while (p->next)
416- p = p->next;
417- p->next = part;
418- }
419- }
420- }
421- }
422- closedir(dir);
423- }
424-
425- if (!head) {
426- head = info;
427- } else {
428- tail->next = info;
429- }
430- tail = info;
431- }
432-
433- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
434- for (i = 0; i < mntsize; i++) {
435- char *frompath = mntbuf[i].f_mntfromname;
436- char *devname = frompath;
437- size_t dev_len = strlen(PATH_DEV);
438- if (strncmp(frompath, PATH_DEV, dev_len) == 0 && frompath[dev_len] == '/')
439- devname = frompath + dev_len + 1;
440- struct BlockDevInfo *curr;
441- for (curr = head; curr; curr = curr->next) {
442- if (strcmp(curr->name, devname) == 0) {
443- strlcpy(curr->mountpoint, mntbuf[i].f_mntonname, sizeof(curr->mountpoint));
444- strlcpy(curr->fstype, mntbuf[i].f_fstypename, sizeof(curr->fstype));
445- }
446- struct BlockDevInfo *part;
447- for (part = curr->parts; part; part = part->next) {
448- if (strcmp(part->name, devname) == 0) {
449- strlcpy(part->mountpoint, mntbuf[i].f_mntonname, sizeof(part->mountpoint));
450- strlcpy(part->fstype, mntbuf[i].f_fstypename, sizeof(part->fstype));
451- }
452- }
453- }
454- }
455-
456- return head;
457+ char disks[1024];
458+ char devpath[128];
459+ char *tok;
460+ char *ptr;
461+ struct BlockDevInfo *head = NULL;
462+ struct BlockDevInfo *tail = NULL;
463+ struct BlockDevInfo *info;
464+ struct BlockDevInfo *part;
465+ struct BlockDevInfo *p;
466+ struct BlockDev dev;
467+ DIR *dir;
468+ struct dirent *de;
469+ size_t disk_len;
470+ size_t len;
471+ struct statfs *mntbuf;
472+ int mntsize;
473+ int i;
474+
475+ len = sizeof(disks);
476+ if (sysctlbyname("kern.disks", disks, &len, NULL, 0) < 0)
477+ return NULL;
478+
479+ ptr = disks;
480+ while ((tok = strsep(&ptr, " \t")) != NULL) {
481+ if (!*tok)
482+ continue;
483+
484+ info = ecalloc(1, sizeof(*info));
485+
486+ strlcpy(info->name, tok, sizeof(info->name));
487+ snprintf(info->path, sizeof(info->path), "%s/%s", ARUU_PATH_DEV, tok);
488+ strlcpy(info->type, "disk", sizeof(info->type));
489+
490+ snprintf(devpath, sizeof(devpath), "%s/%s", ARUU_PATH_DEV, tok);
491+ if (blockdev_open(&dev, devpath, 0) == 0) {
492+ info->size = dev.size;
493+ blockdev_close(&dev);
494+ }
495+
496+ dir = opendir(ARUU_PATH_DEV);
497+ if (dir) {
498+ disk_len = strlen(tok);
499+ while ((de = readdir(dir)) != NULL) {
500+ if (strncmp(de->d_name, tok, disk_len) == 0) {
501+ char c = de->d_name[disk_len];
502+ if (c == 's' || c == 'p') {
503+ part = ecalloc(1, sizeof(*part));
504+ strlcpy(part->name, de->d_name, sizeof(part->name));
505+ snprintf(part->path, sizeof(part->path), "%s/%s", ARUU_PATH_DEV, de->d_name);
506+ strlcpy(part->type, "part", sizeof(part->type));
507+ snprintf(devpath, sizeof(devpath), "%s/%s", ARUU_PATH_DEV, de->d_name);
508+ if (blockdev_open(&dev, devpath, 0) == 0) {
509+ part->size = dev.size;
510+ blockdev_close(&dev);
511+ }
512+ p = info->parts;
513+ if (!p) {
514+ info->parts = part;
515+ } else {
516+ while (p->next)
517+ p = p->next;
518+ p->next = part;
519+ }
520+ }
521+ }
522+ }
523+ closedir(dir);
524+ }
525+
526+ if (!head) {
527+ head = info;
528+ } else {
529+ tail->next = info;
530+ }
531+ tail = info;
532+ }
533+
534+ mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
535+ for (i = 0; i < mntsize; i++) {
536+ char *frompath = mntbuf[i].f_mntfromname;
537+ char *devname = frompath;
538+ size_t dev_len = strlen(ARUU_PATH_DEV);
539+ if (strncmp(frompath, ARUU_PATH_DEV, dev_len) == 0 && frompath[dev_len] == '/')
540+ devname = frompath + dev_len + 1;
541+ struct BlockDevInfo *curr;
542+ for (curr = head; curr; curr = curr->next) {
543+ if (strcmp(curr->name, devname) == 0) {
544+ strlcpy(curr->mountpoint, mntbuf[i].f_mntonname, sizeof(curr->mountpoint));
545+ strlcpy(curr->fstype, mntbuf[i].f_fstypename, sizeof(curr->fstype));
546+ }
547+ struct BlockDevInfo *part;
548+ for (part = curr->parts; part; part = part->next) {
549+ if (strcmp(part->name, devname) == 0) {
550+ strlcpy(part->mountpoint, mntbuf[i].f_mntonname, sizeof(part->mountpoint));
551+ strlcpy(part->fstype, mntbuf[i].f_fstypename, sizeof(part->fstype));
552+ }
553+ }
554+ }
555+ }
556+
557+ return head;
558
559 #elif defined(__OpenBSD__)
560- char disknames[1024];
561- char devpath[128];
562- char *tok;
563- char *ptr;
564- char *colon;
565- struct BlockDevInfo *head = NULL;
566- struct BlockDevInfo *tail = NULL;
567- struct BlockDevInfo *info;
568- struct BlockDevInfo *part;
569- struct BlockDevInfo *p;
570- struct BlockDev dev;
571- size_t len;
572- int mib[2];
573- char c;
574- struct statfs *mntbuf;
575- int mntsize;
576- int i;
577-
578- mib[0] = CTL_HW;
579- mib[1] = HW_DISKNAMES;
580- len = sizeof(disknames);
581- if (sysctl(mib, 2, disknames, &len, NULL, 0) < 0)
582- return NULL;
583-
584- ptr = disknames;
585- while ((tok = strsep(&ptr, ",")) != NULL) {
586- colon = strchr(tok, ':');
587- if (colon)
588- *colon = '\0';
589- if (!*tok)
590- continue;
591-
592- info = ecalloc(1, sizeof(*info));
593-
594- strlcpy(info->name, tok, sizeof(info->name));
595- snprintf(info->path, sizeof(info->path), "%s/r%sc", PATH_DEV, tok);
596- strlcpy(info->type, "disk", sizeof(info->type));
597-
598- snprintf(devpath, sizeof(devpath), "%s/r%sc", PATH_DEV, tok);
599- if (blockdev_open(&dev, devpath, 0) == 0) {
600- info->size = dev.size;
601- blockdev_close(&dev);
602- }
603-
604- for (c = 'a'; c <= 'p'; c++) {
605- if (c == 'c')
606- continue;
607- snprintf(devpath, sizeof(devpath), "%s/r%s%c", PATH_DEV, tok, c);
608- if (blockdev_open(&dev, devpath, 0) == 0) {
609- part = ecalloc(1, sizeof(*part));
610- snprintf(part->name, sizeof(part->name), "%s%c", tok, c);
611- snprintf(part->path, sizeof(part->path), "%s/r%s%c", PATH_DEV, tok, c);
612- strlcpy(part->type, "part", sizeof(part->type));
613- part->size = dev.size;
614- p = info->parts;
615- if (!p) {
616- info->parts = part;
617- } else {
618- while (p->next)
619- p = p->next;
620- p->next = part;
621- }
622- blockdev_close(&dev);
623- }
624- }
625-
626- if (!head) {
627- head = info;
628- } else {
629- tail->next = info;
630- }
631- tail = info;
632- }
633-
634- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
635- for (i = 0; i < mntsize; i++) {
636- char *frompath = mntbuf[i].f_mntfromname;
637- char *devname = frompath;
638- size_t dev_len = strlen(PATH_DEV);
639- if (strncmp(frompath, PATH_DEV, dev_len) == 0 && frompath[dev_len] == '/')
640- devname = frompath + dev_len + 1;
641- struct BlockDevInfo *curr;
642- for (curr = head; curr; curr = curr->next) {
643- if (strcmp(curr->name, devname) == 0) {
644- strlcpy(curr->mountpoint, mntbuf[i].f_mntonname, sizeof(curr->mountpoint));
645- strlcpy(curr->fstype, mntbuf[i].f_fstypename, sizeof(curr->fstype));
646- }
647- struct BlockDevInfo *part;
648- for (part = curr->parts; part; part = part->next) {
649- if (strcmp(part->name, devname) == 0) {
650- strlcpy(part->mountpoint, mntbuf[i].f_mntonname, sizeof(part->mountpoint));
651- strlcpy(part->fstype, mntbuf[i].f_fstypename, sizeof(part->fstype));
652- }
653- }
654- }
655- }
656-
657- return head;
658+ char disknames[1024];
659+ char devpath[128];
660+ char *tok;
661+ char *ptr;
662+ char *colon;
663+ struct BlockDevInfo *head = NULL;
664+ struct BlockDevInfo *tail = NULL;
665+ struct BlockDevInfo *info;
666+ struct BlockDevInfo *part;
667+ struct BlockDevInfo *p;
668+ struct BlockDev dev;
669+ size_t len;
670+ int mib[2];
671+ char c;
672+ struct statfs *mntbuf;
673+ int mntsize;
674+ int i;
675+
676+ mib[0] = CTL_HW;
677+ mib[1] = HW_DISKNAMES;
678+ len = sizeof(disknames);
679+ if (sysctl(mib, 2, disknames, &len, NULL, 0) < 0)
680+ return NULL;
681+
682+ ptr = disknames;
683+ while ((tok = strsep(&ptr, ",")) != NULL) {
684+ colon = strchr(tok, ':');
685+ if (colon)
686+ *colon = '\0';
687+ if (!*tok)
688+ continue;
689+
690+ info = ecalloc(1, sizeof(*info));
691+
692+ strlcpy(info->name, tok, sizeof(info->name));
693+ snprintf(info->path, sizeof(info->path), "%s/r%sc", ARUU_PATH_DEV, tok);
694+ strlcpy(info->type, "disk", sizeof(info->type));
695+
696+ snprintf(devpath, sizeof(devpath), "%s/r%sc", ARUU_PATH_DEV, tok);
697+ if (blockdev_open(&dev, devpath, 0) == 0) {
698+ info->size = dev.size;
699+ blockdev_close(&dev);
700+ }
701+
702+ for (c = 'a'; c <= 'p'; c++) {
703+ if (c == 'c')
704+ continue;
705+ snprintf(devpath, sizeof(devpath), "%s/r%s%c", ARUU_PATH_DEV, tok, c);
706+ if (blockdev_open(&dev, devpath, 0) == 0) {
707+ part = ecalloc(1, sizeof(*part));
708+ snprintf(part->name, sizeof(part->name), "%s%c", tok, c);
709+ snprintf(part->path, sizeof(part->path), "%s/r%s%c", ARUU_PATH_DEV, tok, c);
710+ strlcpy(part->type, "part", sizeof(part->type));
711+ part->size = dev.size;
712+ p = info->parts;
713+ if (!p) {
714+ info->parts = part;
715+ } else {
716+ while (p->next)
717+ p = p->next;
718+ p->next = part;
719+ }
720+ blockdev_close(&dev);
721+ }
722+ }
723+
724+ if (!head) {
725+ head = info;
726+ } else {
727+ tail->next = info;
728+ }
729+ tail = info;
730+ }
731+
732+ mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
733+ for (i = 0; i < mntsize; i++) {
734+ char *frompath = mntbuf[i].f_mntfromname;
735+ char *devname = frompath;
736+ size_t dev_len = strlen(ARUU_PATH_DEV);
737+ if (strncmp(frompath, ARUU_PATH_DEV, dev_len) == 0 && frompath[dev_len] == '/')
738+ devname = frompath + dev_len + 1;
739+ struct BlockDevInfo *curr;
740+ for (curr = head; curr; curr = curr->next) {
741+ if (strcmp(curr->name, devname) == 0) {
742+ strlcpy(curr->mountpoint, mntbuf[i].f_mntonname, sizeof(curr->mountpoint));
743+ strlcpy(curr->fstype, mntbuf[i].f_fstypename, sizeof(curr->fstype));
744+ }
745+ struct BlockDevInfo *part;
746+ for (part = curr->parts; part; part = part->next) {
747+ if (strcmp(part->name, devname) == 0) {
748+ strlcpy(part->mountpoint, mntbuf[i].f_mntonname, sizeof(part->mountpoint));
749+ strlcpy(part->fstype, mntbuf[i].f_fstypename, sizeof(part->fstype));
750+ }
751+ }
752+ }
753+ }
754+
755+ return head;
756
757 #else
758- struct BlockDevInfo *head = NULL;
759- struct BlockDevInfo *tail = NULL;
760- struct BlockDevInfo *info;
761- struct BlockDev dev;
762- char devname[16];
763- char devpath[128];
764- char c;
765-
766- for (c = 'a'; c <= 'z'; c++) {
767- snprintf(devname, sizeof(devname), "sd%c", c);
768- snprintf(devpath, sizeof(devpath), "%s/%s", PATH_DEV, devname);
769- if (blockdev_open(&dev, devpath, 0) == 0) {
770- info = ecalloc(1, sizeof(*info));
771- strlcpy(info->name, devname, sizeof(info->name));
772- snprintf(info->path, sizeof(info->path), "%s/%s", PATH_DEV, devname);
773- strlcpy(info->type, "disk", sizeof(info->type));
774- info->size = dev.size;
775- if (!head) {
776- head = info;
777- } else {
778- tail->next = info;
779- }
780- tail = info;
781- blockdev_close(&dev);
782- }
783- }
784- return head;
785+ struct BlockDevInfo *head = NULL;
786+ struct BlockDevInfo *tail = NULL;
787+ struct BlockDevInfo *info;
788+ struct BlockDev dev;
789+ char devname[16];
790+ char devpath[128];
791+ char c;
792+
793+ for (c = 'a'; c <= 'z'; c++) {
794+ snprintf(devname, sizeof(devname), "sd%c", c);
795+ snprintf(devpath, sizeof(devpath), "%s/%s", ARUU_PATH_DEV, devname);
796+ if (blockdev_open(&dev, devpath, 0) == 0) {
797+ info = ecalloc(1, sizeof(*info));
798+ strlcpy(info->name, devname, sizeof(info->name));
799+ snprintf(info->path, sizeof(info->path), "%s/%s", ARUU_PATH_DEV, devname);
800+ strlcpy(info->type, "disk", sizeof(info->type));
801+ info->size = dev.size;
802+ if (!head) {
803+ head = info;
804+ } else {
805+ tail->next = info;
806+ }
807+ tail = info;
808+ blockdev_close(&dev);
809+ }
810+ }
811+ return head;
812 #endif
813 }
814
815 void
816 blockdev_free_list(struct BlockDevInfo *list)
817 {
818- struct BlockDevInfo *curr = list;
819- while (curr) {
820- struct BlockDevInfo *next = curr->next;
821- struct BlockDevInfo *part = curr->parts;
822- while (part) {
823- struct BlockDevInfo *next_part = part->next;
824- free(part);
825- part = next_part;
826- }
827- free(curr);
828- curr = next;
829- }
830+ struct BlockDevInfo *curr = list;
831+ while (curr) {
832+ struct BlockDevInfo *next = curr->next;
833+ struct BlockDevInfo *part = curr->parts;
834+ while (part) {
835+ struct BlockDevInfo *next_part = part->next;
836+ free(part);
837+ part = next_part;
838+ }
839+ free(curr);
840+ curr = next;
841+ }
842 }
843
844 struct FsType {
845- const char *name;
846- size_t magic_offset;
847- size_t magic_len;
848- uint64_t magic1;
849- uint64_t magic2;
850- size_t uuid_offset;
851- size_t uuid_len;
852- size_t label_offset;
853- size_t label_len;
854+ const char *name;
855+ size_t magic_offset;
856+ size_t magic_len;
857+ uint64_t magic1;
858+ uint64_t magic2;
859+ size_t uuid_offset;
860+ size_t uuid_len;
861+ size_t label_offset;
862+ size_t label_len;
863 };
864
865 static const struct FsType fstypes[] = {
866- /* ext2/3/4 */
867- { "ext", 1080, 2, 0xEF53, 0x53EF, 1128, 16, 1144, 16 },
868- /* vfat / fat32 */
869- { "vfat", 82, 5, 0x3233544146ULL, 0, 67, 4, 71, 11 },
870- /* vfat / fat12/16 */
871- { "vfat", 54, 4, 0x31544146, 0, 39, 4, 43, 11 },
872- /* ntfs */
873- { "ntfs", 3, 4, 0x5346544e, 0, 72, 8, 0, 0 },
874- /* xfs */
875- { "xfs", 0, 4, 0x42534658, 0x58465342, 32, 16, 108, 12 },
876- /* btrfs */
877- { "btrfs", 65600, 8, 0x4D5F53665248425FULL, 0, 65803, 16, 65819, 256 },
878- /* f2fs */
879- { "f2fs", 1024, 4, 0xF2F52010, 0x1020F5F2, 1132, 16, 1148, 512 },
880- /* ufs1 */
881- { "ufs1", 9564, 4, 0x011954, 0x54190100, 8428, 8, 0, 0 },
882- /* ufs2 */
883- { "ufs2", 66908, 4, 0x19540119, 0x19015419, 65772, 8, 66216, 32 },
884- /* fossil */
885- { "fossil", 131200, 4, 0x2340A3B1, 0xB1A34023, 0, 0, 131072, 127 },
886+ /* ext2/3/4 */
887+ { "ext", 1080, 2, 0xEF53, 0x53EF, 1128, 16, 1144, 16 },
888+ /* vfat / fat32 */
889+ { "vfat", 82, 5, 0x3233544146ULL, 0, 67, 4, 71, 11 },
890+ /* vfat / fat12/16 */
891+ { "vfat", 54, 4, 0x31544146, 0, 39, 4, 43, 11 },
892+ /* ntfs */
893+ { "ntfs", 3, 4, 0x5346544e, 0, 72, 8, 0, 0 },
894+ /* xfs */
895+ { "xfs", 0, 4, 0x42534658, 0x58465342, 32, 16, 108, 12 },
896+ /* btrfs */
897+ { "btrfs", 65600, 8, 0x4D5F53665248425FULL, 0, 65803, 16, 65819, 256 },
898+ /* f2fs */
899+ { "f2fs", 1024, 4, 0xF2F52010, 0x1020F5F2, 1132, 16, 1148, 512 },
900+ /* ufs1 */
901+ { "ufs1", 9564, 4, 0x011954, 0x54190100, 8428, 8, 0, 0 },
902+ /* ufs2 */
903+ { "ufs2", 66908, 4, 0x19540119, 0x19015419, 65772, 8, 66216, 32 },
904+ /* fossil */
905+ { "fossil", 131200, 4, 0x2340A3B1, 0xB1A34023, 0, 0, 131072, 127 },
906 };
907
908 static void
909 format_uuid(const unsigned char *buf, size_t len, const char *type, char *out, size_t out_len)
910 {
911- size_t i;
912- char *p;
913-
914- p = out;
915- if (strcmp(type, "vfat") == 0) {
916- snprintf(out, out_len, "%02X%02X-%02X%02X", buf[3], buf[2], buf[1], buf[0]);
917- return;
918- }
919-
920- if (strcmp(type, "ntfs") == 0) {
921- for (i = 8; i > 0; i--) {
922- snprintf(p, out_len - (p - out), "%02X", buf[i - 1]);
923- p += 2;
924- }
925- return;
926- }
927-
928- for (i = 0; i < len; i++) {
929- if (i == 4 || i == 6 || i == 8 || i == 10) {
930- *p++ = '-';
931- }
932- snprintf(p, out_len - (p - out), "%02x", buf[i]);
933- p += 2;
934- }
935- *p = '\0';
936+ size_t i;
937+ char *p;
938+
939+ p = out;
940+ if (strcmp(type, "vfat") == 0) {
941+ snprintf(out, out_len, "%02X%02X-%02X%02X", buf[3], buf[2], buf[1], buf[0]);
942+ return;
943+ }
944+
945+ if (strcmp(type, "ntfs") == 0) {
946+ for (i = 8; i > 0; i--) {
947+ snprintf(p, out_len - (p - out), "%02X", buf[i - 1]);
948+ p += 2;
949+ }
950+ return;
951+ }
952+
953+ for (i = 0; i < len; i++) {
954+ if (i == 4 || i == 6 || i == 8 || i == 10) {
955+ *p++ = '-';
956+ }
957+ snprintf(p, out_len - (p - out), "%02x", buf[i]);
958+ p += 2;
959+ }
960+ *p = '\0';
961 }
962
963 static int
964 zfs_detect(const unsigned char *buf, size_t len)
965 {
966- size_t offset;
967- uint64_t magic;
968-
969- for (offset = 131072; offset + 8 <= len; offset += 1024) {
970- magic = ((uint64_t)buf[offset + 7] << 56) |
971- ((uint64_t)buf[offset + 6] << 48) |
972- ((uint64_t)buf[offset + 5] << 40) |
973- ((uint64_t)buf[offset + 4] << 32) |
974- ((uint64_t)buf[offset + 3] << 24) |
975- ((uint64_t)buf[offset + 2] << 16) |
976- ((uint64_t)buf[offset + 1] << 8) |
977- (uint64_t)buf[offset];
978-
979- if (magic == 0x00bab10c00000000ULL || magic == 0x0cb1ba0000000000ULL ||
980- magic == 0x00bab10cULL || magic == 0x0cb1ba00ULL)
981- return 1;
982- }
983- return 0;
984+ size_t offset;
985+ uint64_t magic;
986+
987+ for (offset = 131072; offset + 8 <= len; offset += 1024) {
988+ magic = ((uint64_t)buf[offset + 7] << 56) |
989+ ((uint64_t)buf[offset + 6] << 48) |
990+ ((uint64_t)buf[offset + 5] << 40) |
991+ ((uint64_t)buf[offset + 4] << 32) |
992+ ((uint64_t)buf[offset + 3] << 24) |
993+ ((uint64_t)buf[offset + 2] << 16) |
994+ ((uint64_t)buf[offset + 1] << 8) |
995+ (uint64_t)buf[offset];
996+
997+ if (magic == 0x00bab10c00000000ULL || magic == 0x0cb1ba0000000000ULL ||
998+ magic == 0x00bab10cULL || magic == 0x0cb1ba00ULL)
999+ return 1;
1000+ }
1001+ return 0;
1002 }
1003
1004 struct Plan9FsDef {
1005- const char *name;
1006- int blocksize;
1007- int namelen;
1008- int dirblks;
1009- int indirblks;
1010- int daddrbits;
1011+ const char *name;
1012+ int blocksize;
1013+ int namelen;
1014+ int dirblks;
1015+ int indirblks;
1016+ int daddrbits;
1017 };
1018
1019 static const struct Plan9FsDef p9_fs_defs[] = {
1020- { "cwfs64x", 16384, 144, 6, 4, 64 },
1021- { "cwfs64", 16384, 56, 6, 4, 64 },
1022- { "cwfs", 16384, 28, 6, 2, 32 },
1023- { "fs64", 8192, 56, 6, 4, 64 },
1024- { "fs", 4096, 28, 6, 2, 32 },
1025+ { "cwfs64x", 16384, 144, 6, 4, 64 },
1026+ { "cwfs64", 16384, 56, 6, 4, 64 },
1027+ { "cwfs", 16384, 28, 6, 2, 32 },
1028+ { "fs64", 8192, 56, 6, 4, 64 },
1029+ { "fs", 4096, 28, 6, 2, 32 },
1030 };
1031
1032 static int
1033 plan9_magic_check(const unsigned char *p, const char **name)
1034 {
1035- if (memcmp(p, "\x01\x1c\xe5\x0d", 4) == 0 || memcmp(p, "\x0d\xe5\x1c\x01", 4) == 0) {
1036- *name = "hjfs";
1037- return 1;
1038- }
1039- if (memcmp(p, "gefs", 4) == 0 || memcmp(p, "sfeg", 4) == 0) {
1040- *name = "gefs";
1041- return 1;
1042- }
1043- return 0;
1044+ if (memcmp(p, "\x01\x1c\xe5\x0d", 4) == 0 || memcmp(p, "\x0d\xe5\x1c\x01", 4) == 0) {
1045+ *name = "hjfs";
1046+ return 1;
1047+ }
1048+ if (memcmp(p, "gefs", 4) == 0 || memcmp(p, "sfeg", 4) == 0) {
1049+ *name = "gefs";
1050+ return 1;
1051+ }
1052+ return 0;
1053 }
1054
1055 static int
1056 plan9_detect_other(const unsigned char *buf, size_t len, const char **name)
1057 {
1058- if (len >= 4 && plan9_magic_check(buf, name))
1059- return 1;
1060- if (len >= 516 && plan9_magic_check(buf + 512, name))
1061- return 1;
1062- return 0;
1063+ if (len >= 4 && plan9_magic_check(buf, name))
1064+ return 1;
1065+ if (len >= 516 && plan9_magic_check(buf + 512, name))
1066+ return 1;
1067+ return 0;
1068 }
1069
1070 static int
1071 plan9_detect_text(const unsigned char *buf, size_t len, const char **name)
1072 {
1073- int blocksize = 0, namelen = 0, dirblks = 0, indirblks = 0, daddrbits = 0;
1074- char line[128];
1075- char key[64];
1076- int val;
1077- size_t i = 0, j;
1078-
1079- if (len >= 256 + 15) {
1080- if (memcmp(buf + 256, "kfs wren device", 15) == 0) {
1081- *name = "kfs";
1082- return 1;
1083- }
1084- }
1085-
1086- if (len < 512)
1087- return 0;
1088- i = 512;
1089- if (len > 1536)
1090- len = 1536;
1091-
1092- while (i < len) {
1093- size_t k = 0;
1094- while (i < len && buf[i] != '\n' && k < sizeof(line) - 1) {
1095- line[k++] = buf[i++];
1096- }
1097- if (i < len && buf[i] == '\n')
1098- i++;
1099- line[k] = '\0';
1100-
1101- if (sscanf(line, "%63s %d", key, &val) == 2) {
1102- if (strcmp(key, "blocksize") == 0) blocksize = val;
1103- else if (strcmp(key, "namelen") == 0) namelen = val;
1104- else if (strcmp(key, "dirblks") == 0) dirblks = val;
1105- else if (strcmp(key, "indirblks") == 0) indirblks = val;
1106- else if (strcmp(key, "daddrbits") == 0) daddrbits = val;
1107- }
1108- }
1109-
1110- for (j = 0; j < LEN(p9_fs_defs); j++) {
1111- if (blocksize == p9_fs_defs[j].blocksize &&
1112- namelen == p9_fs_defs[j].namelen &&
1113- dirblks == p9_fs_defs[j].dirblks &&
1114- indirblks == p9_fs_defs[j].indirblks &&
1115- daddrbits == p9_fs_defs[j].daddrbits) {
1116- *name = p9_fs_defs[j].name;
1117- return 1;
1118- }
1119- }
1120-
1121- return 0;
1122+ int blocksize = 0, namelen = 0, dirblks = 0, indirblks = 0, daddrbits = 0;
1123+ char line[128];
1124+ char key[64];
1125+ int val;
1126+ size_t i = 0, j;
1127+
1128+ if (len >= 256 + 15) {
1129+ if (memcmp(buf + 256, "kfs wren device", 15) == 0) {
1130+ *name = "kfs";
1131+ return 1;
1132+ }
1133+ }
1134+
1135+ if (len < 512)
1136+ return 0;
1137+ i = 512;
1138+ if (len > 1536)
1139+ len = 1536;
1140+
1141+ while (i < len) {
1142+ size_t k = 0;
1143+ while (i < len && buf[i] != '\n' && k < sizeof(line) - 1) {
1144+ line[k++] = buf[i++];
1145+ }
1146+ if (i < len && buf[i] == '\n')
1147+ i++;
1148+ line[k] = '\0';
1149+
1150+ if (sscanf(line, "%63s %d", key, &val) == 2) {
1151+ if (strcmp(key, "blocksize") == 0) blocksize = val;
1152+ else if (strcmp(key, "namelen") == 0) namelen = val;
1153+ else if (strcmp(key, "dirblks") == 0) dirblks = val;
1154+ else if (strcmp(key, "indirblks") == 0) indirblks = val;
1155+ else if (strcmp(key, "daddrbits") == 0) daddrbits = val;
1156+ }
1157+ }
1158+
1159+ for (j = 0; j < LEN(p9_fs_defs); j++) {
1160+ if (blocksize == p9_fs_defs[j].blocksize &&
1161+ namelen == p9_fs_defs[j].namelen &&
1162+ dirblks == p9_fs_defs[j].dirblks &&
1163+ indirblks == p9_fs_defs[j].indirblks &&
1164+ daddrbits == p9_fs_defs[j].daddrbits) {
1165+ *name = p9_fs_defs[j].name;
1166+ return 1;
1167+ }
1168+ }
1169+
1170+ return 0;
1171 }
1172
1173 int
1174 blockdev_detect_fs(struct BlockDev *dev, char *type, size_t type_sz,
1175 char *label, size_t label_sz, char *uuid, size_t uuid_sz)
1176 {
1177- unsigned char *buf;
1178- size_t read_size = 262144; /* 256kb */
1179- size_t sectors_to_read;
1180- size_t i, j;
1181- int found = 0;
1182-
1183- if (dev->size < read_size)
1184- read_size = dev->size;
1185-
1186- buf = emalloc(read_size);
1187- sectors_to_read = (read_size + dev->sec_size - 1) / dev->sec_size;
1188- if (blockdev_read(dev, 0, buf, sectors_to_read) < 0) {
1189- free(buf);
1190- return -2;
1191- }
1192-
1193- for (i = 0; i < LEN(fstypes); i++) {
1194- const struct FsType *fs = &fstypes[i];
1195- if (fs->magic_offset + fs->magic_len > read_size)
1196- continue;
1197-
1198- uint64_t val = 0;
1199- for (j = 0; j < fs->magic_len; j++) {
1200- val |= ((uint64_t)buf[fs->magic_offset + j]) << (8 * j);
1201- }
1202-
1203- if (val == fs->magic1 || (fs->magic2 && val == fs->magic2)) {
1204- const char *type_name = fs->name;
1205- if (strcmp(fs->name, "ext") == 0) {
1206- if (buf[1116] & 4)
1207- type_name = "ext3";
1208- else if (buf[1120] & 64)
1209- type_name = "ext4";
1210- else
1211- type_name = "ext2";
1212- }
1213-
1214- if (type && type_sz)
1215- strlcpy(type, type_name, type_sz);
1216-
1217- if (label && label_sz && fs->label_len && fs->label_offset + fs->label_len <= read_size) {
1218- snprintf(label, label_sz, "%.*s", (int)fs->label_len, buf + fs->label_offset);
1219- /* strip trailing spaces */
1220- char *end = label + strlen(label) - 1;
1221- while (end >= label && *end == ' ') {
1222- *end = '\0';
1223- end--;
1224- }
1225- }
1226-
1227- if (uuid && uuid_sz && fs->uuid_len && fs->uuid_offset + fs->uuid_len <= read_size) {
1228- format_uuid(buf + fs->uuid_offset, fs->uuid_len, fs->name, uuid, uuid_sz);
1229- }
1230-
1231- found = 1;
1232- break;
1233- }
1234- }
1235-
1236- if (!found && zfs_detect(buf, read_size)) {
1237- if (type && type_sz)
1238- strlcpy(type, "zfs_member", type_sz);
1239- found = 1;
1240- }
1241-
1242- if (!found) {
1243- const char *p9_name = NULL;
1244- if (plan9_detect_other(buf, read_size, &p9_name) ||
1245- plan9_detect_text(buf, read_size, &p9_name)) {
1246- if (type && type_sz)
1247- strlcpy(type, p9_name, type_sz);
1248- found = 1;
1249- }
1250- }
1251-
1252- free(buf);
1253- return found ? 0 : -1;
1254+ unsigned char *buf;
1255+ size_t read_size = 262144; /* 256kb */
1256+ size_t sectors_to_read;
1257+ size_t i, j;
1258+ int found = 0;
1259+
1260+ if (dev->size < read_size)
1261+ read_size = dev->size;
1262+
1263+ buf = emalloc(read_size);
1264+ sectors_to_read = (read_size + dev->sec_size - 1) / dev->sec_size;
1265+ if (blockdev_read(dev, 0, buf, sectors_to_read) < 0) {
1266+ free(buf);
1267+ return -2;
1268+ }
1269+
1270+ for (i = 0; i < LEN(fstypes); i++) {
1271+ const struct FsType *fs = &fstypes[i];
1272+ if (fs->magic_offset + fs->magic_len > read_size)
1273+ continue;
1274+
1275+ uint64_t val = 0;
1276+ for (j = 0; j < fs->magic_len; j++) {
1277+ val |= ((uint64_t)buf[fs->magic_offset + j]) << (8 * j);
1278+ }
1279+
1280+ if (val == fs->magic1 || (fs->magic2 && val == fs->magic2)) {
1281+ const char *type_name = fs->name;
1282+ if (strcmp(fs->name, "ext") == 0) {
1283+ if (buf[1116] & 4)
1284+ type_name = "ext3";
1285+ else if (buf[1120] & 64)
1286+ type_name = "ext4";
1287+ else
1288+ type_name = "ext2";
1289+ }
1290+
1291+ if (type && type_sz)
1292+ strlcpy(type, type_name, type_sz);
1293+
1294+ if (label && label_sz && fs->label_len && fs->label_offset + fs->label_len <= read_size) {
1295+ snprintf(label, label_sz, "%.*s", (int)fs->label_len, buf + fs->label_offset);
1296+ /* strip trailing spaces */
1297+ char *end = label + strlen(label) - 1;
1298+ while (end >= label && *end == ' ') {
1299+ *end = '\0';
1300+ end--;
1301+ }
1302+ }
1303+
1304+ if (uuid && uuid_sz && fs->uuid_len && fs->uuid_offset + fs->uuid_len <= read_size) {
1305+ format_uuid(buf + fs->uuid_offset, fs->uuid_len, fs->name, uuid, uuid_sz);
1306+ }
1307+
1308+ found = 1;
1309+ break;
1310+ }
1311+ }
1312+
1313+ if (!found && zfs_detect(buf, read_size)) {
1314+ if (type && type_sz)
1315+ strlcpy(type, "zfs_member", type_sz);
1316+ found = 1;
1317+ }
1318+
1319+ if (!found) {
1320+ const char *p9_name = NULL;
1321+ if (plan9_detect_other(buf, read_size, &p9_name) ||
1322+ plan9_detect_text(buf, read_size, &p9_name)) {
1323+ if (type && type_sz)
1324+ strlcpy(type, p9_name, type_sz);
1325+ found = 1;
1326+ }
1327+ }
1328+
1329+ free(buf);
1330+ return found ? 0 : -1;
1331 }
1@@ -1,3 +1,4 @@
2+#include "../paths.h"
3 #include "../util.h"
4
5 #include <arpa/inet.h>
6@@ -23,162 +24,162 @@
7 static void
8 get_mtu_metric(const char *name, int *mtu, int *metric)
9 {
10- struct ifreq ifr;
11- int sock;
12-
13- *mtu = 0;
14- *metric = 0;
15- sock = socket(AF_INET, SOCK_DGRAM, 0);
16- if (sock < 0)
17- return;
18- memset(&ifr, 0, sizeof(ifr));
19- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
20- if (ioctl(sock, SIOCGIFMTU, &ifr) >= 0)
21- *mtu = ifr.ifr_mtu;
22- if (ioctl(sock, SIOCGIFMETRIC, &ifr) >= 0)
23- *metric = ifr.ifr_metric;
24- close(sock);
25+ struct ifreq ifr;
26+ int sock;
27+
28+ *mtu = 0;
29+ *metric = 0;
30+ sock = socket(AF_INET, SOCK_DGRAM, 0);
31+ if (sock < 0)
32+ return;
33+ memset(&ifr, 0, sizeof(ifr));
34+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
35+ if (ioctl(sock, SIOCGIFMTU, &ifr) >= 0)
36+ *mtu = ifr.ifr_mtu;
37+ if (ioctl(sock, SIOCGIFMETRIC, &ifr) >= 0)
38+ *metric = ifr.ifr_metric;
39+ close(sock);
40 }
41
42 int
43 net_get_interfaces(struct NetInterface **ifaces, int *count)
44 {
45- struct ifaddrs *ifaddr, *ifa;
46- struct NetInterface *list = NULL;
47- struct NetInterface *iface;
48- int found_count = 0;
49- int i;
50-
51- if (getifaddrs(&ifaddr) < 0)
52- return -1;
53-
54- for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
55- iface = NULL;
56- for (i = 0; i < found_count; i++) {
57- if (strcmp(list[i].name, ifa->ifa_name) == 0) {
58- iface = &list[i];
59- break;
60- }
61- }
62- if (!iface) {
63- list = reallocarray(list, found_count + 1, sizeof(*list));
64- if (!list) {
65- freeifaddrs(ifaddr);
66- return -1;
67- }
68- iface = &list[found_count];
69- memset(iface, 0, sizeof(*iface));
70- strlcpy(iface->name, ifa->ifa_name, sizeof(iface->name));
71- iface->flags = ifa->ifa_flags;
72- get_mtu_metric(iface->name, &iface->mtu, &iface->metric);
73- found_count++;
74- }
75-
76- if (!ifa->ifa_addr)
77- continue;
78-
79- if (ifa->ifa_addr->sa_family == AF_INET) {
80- memcpy(&iface->ipv4_addr, ifa->ifa_addr, sizeof(struct sockaddr_in));
81- iface->has_ipv4 = 1;
82- if (ifa->ifa_netmask)
83- memcpy(&iface->ipv4_mask, ifa->ifa_netmask, sizeof(struct sockaddr_in));
84- if (ifa->ifa_dstaddr)
85- memcpy(&iface->ipv4_brd, ifa->ifa_dstaddr, sizeof(struct sockaddr_in));
86- } else if (ifa->ifa_addr->sa_family == AF_INET6) {
87- memcpy(&iface->ipv6_addr, ifa->ifa_addr, sizeof(struct sockaddr_in6));
88- iface->has_ipv6 = 1;
89- /* scope id could be set here from sin6_scope_id */
90- }
91+ struct ifaddrs *ifaddr, *ifa;
92+ struct NetInterface *list = NULL;
93+ struct NetInterface *iface;
94+ int found_count = 0;
95+ int i;
96+
97+ if (getifaddrs(&ifaddr) < 0)
98+ return -1;
99+
100+ for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
101+ iface = NULL;
102+ for (i = 0; i < found_count; i++) {
103+ if (strcmp(list[i].name, ifa->ifa_name) == 0) {
104+ iface = &list[i];
105+ break;
106+ }
107+ }
108+ if (!iface) {
109+ list = reallocarray(list, found_count + 1, sizeof(*list));
110+ if (!list) {
111+ freeifaddrs(ifaddr);
112+ return -1;
113+ }
114+ iface = &list[found_count];
115+ memset(iface, 0, sizeof(*iface));
116+ strlcpy(iface->name, ifa->ifa_name, sizeof(iface->name));
117+ iface->flags = ifa->ifa_flags;
118+ get_mtu_metric(iface->name, &iface->mtu, &iface->metric);
119+ found_count++;
120+ }
121+
122+ if (!ifa->ifa_addr)
123+ continue;
124+
125+ if (ifa->ifa_addr->sa_family == AF_INET) {
126+ memcpy(&iface->ipv4_addr, ifa->ifa_addr, sizeof(struct sockaddr_in));
127+ iface->has_ipv4 = 1;
128+ if (ifa->ifa_netmask)
129+ memcpy(&iface->ipv4_mask, ifa->ifa_netmask, sizeof(struct sockaddr_in));
130+ if (ifa->ifa_dstaddr)
131+ memcpy(&iface->ipv4_brd, ifa->ifa_dstaddr, sizeof(struct sockaddr_in));
132+ } else if (ifa->ifa_addr->sa_family == AF_INET6) {
133+ memcpy(&iface->ipv6_addr, ifa->ifa_addr, sizeof(struct sockaddr_in6));
134+ iface->has_ipv6 = 1;
135+ /* scope id could be set here from sin6_scope_id */
136+ }
137 #ifdef __linux__
138- else if (ifa->ifa_addr->sa_family == AF_PACKET) {
139- struct sockaddr_ll *sll = (struct sockaddr_ll *)ifa->ifa_addr;
140- if (sll->sll_halen == 6) {
141- memcpy(iface->mac, sll->sll_addr, 6);
142- iface->has_mac = 1;
143- }
144- }
145+ else if (ifa->ifa_addr->sa_family == AF_PACKET) {
146+ struct sockaddr_ll *sll = (struct sockaddr_ll *)ifa->ifa_addr;
147+ if (sll->sll_halen == 6) {
148+ memcpy(iface->mac, sll->sll_addr, 6);
149+ iface->has_mac = 1;
150+ }
151+ }
152 #else
153- else if (ifa->ifa_addr->sa_family == AF_LINK) {
154- struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr;
155- if (sdl->sdl_alen == 6) {
156- memcpy(iface->mac, LLADDR(sdl), 6);
157- iface->has_mac = 1;
158- }
159- }
160+ else if (ifa->ifa_addr->sa_family == AF_LINK) {
161+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr;
162+ if (sdl->sdl_alen == 6) {
163+ memcpy(iface->mac, LLADDR(sdl), 6);
164+ iface->has_mac = 1;
165+ }
166+ }
167 #endif
168- }
169+ }
170
171- freeifaddrs(ifaddr);
172- *ifaces = list;
173- *count = found_count;
174- return 0;
175+ freeifaddrs(ifaddr);
176+ *ifaces = list;
177+ *count = found_count;
178+ return 0;
179 }
180
181 #ifdef __linux__
182 int
183 net_get_stats(const char *ifname, struct NetStats *stats)
184 {
185- FILE *fp;
186- char line[256];
187- char *p, *name;
188- int found = 0;
189-
190- memset(stats, 0, sizeof(*stats));
191- fp = fopen("/proc/net/dev", "r");
192- if (!fp)
193- return -1;
194-
195- while (fgets(line, sizeof(line), fp)) {
196- p = strchr(line, ':');
197- if (p) {
198- *p = '\0';
199- name = line;
200- while (isspace(*name))
201- name++;
202- if (strcmp(name, ifname) == 0) {
203- if (sscanf(p + 1, "%llu %llu %llu %llu %*u %*u %*u %*u %llu %llu %llu %llu",
204- &stats->rx_bytes, &stats->rx_packets, &stats->rx_errs, &stats->rx_drop,
205- &stats->tx_bytes, &stats->tx_packets, &stats->tx_errs, &stats->tx_drop) == 8) {
206- found = 1;
207- }
208- break;
209- }
210- }
211- }
212- fclose(fp);
213- return found ? 0 : -1;
214+ FILE *fp;
215+ char line[256];
216+ char *p, *name;
217+ int found = 0;
218+
219+ memset(stats, 0, sizeof(*stats));
220+ fp = fopen(ARUU_LINUX_PATH_PROC "/net/dev", "r");
221+ if (!fp)
222+ return -1;
223+
224+ while (fgets(line, sizeof(line), fp)) {
225+ p = strchr(line, ':');
226+ if (p) {
227+ *p = '\0';
228+ name = line;
229+ while (isspace(*name))
230+ name++;
231+ if (strcmp(name, ifname) == 0) {
232+ if (sscanf(p + 1, "%llu %llu %llu %llu %*u %*u %*u %*u %llu %llu %llu %llu",
233+ &stats->rx_bytes, &stats->rx_packets, &stats->rx_errs, &stats->rx_drop,
234+ &stats->tx_bytes, &stats->tx_packets, &stats->tx_errs, &stats->tx_drop) == 8) {
235+ found = 1;
236+ }
237+ break;
238+ }
239+ }
240+ }
241+ fclose(fp);
242+ return found ? 0 : -1;
243 }
244 #else
245 int
246 net_get_stats(const char *ifname, struct NetStats *stats)
247 {
248- struct ifaddrs *ifaddr, *ifa;
249- int found = 0;
250-
251- memset(stats, 0, sizeof(*stats));
252- if (getifaddrs(&ifaddr) < 0)
253- return -1;
254-
255- for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
256- if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK &&
257- strcmp(ifa->ifa_name, ifname) == 0) {
258- struct if_data *ifd = (struct if_data *)ifa->ifa_data;
259- if (ifd) {
260- stats->rx_bytes = ifd->ifi_ibytes;
261- stats->rx_packets = ifd->ifi_ipackets;
262- stats->rx_errs = ifd->ifi_ierrors;
263- stats->rx_drop = ifd->ifi_iqdrops;
264- stats->tx_bytes = ifd->ifi_obytes;
265- stats->tx_packets = ifd->ifi_opackets;
266- stats->tx_errs = ifd->ifi_oerrors;
267- stats->tx_drop = 0;
268- found = 1;
269- break;
270- }
271- }
272- }
273- freeifaddrs(ifaddr);
274- return found ? 0 : -1;
275+ struct ifaddrs *ifaddr, *ifa;
276+ int found = 0;
277+
278+ memset(stats, 0, sizeof(*stats));
279+ if (getifaddrs(&ifaddr) < 0)
280+ return -1;
281+
282+ for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
283+ if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK &&
284+ strcmp(ifa->ifa_name, ifname) == 0) {
285+ struct if_data *ifd = (struct if_data *)ifa->ifa_data;
286+ if (ifd) {
287+ stats->rx_bytes = ifd->ifi_ibytes;
288+ stats->rx_packets = ifd->ifi_ipackets;
289+ stats->rx_errs = ifd->ifi_ierrors;
290+ stats->rx_drop = ifd->ifi_iqdrops;
291+ stats->tx_bytes = ifd->ifi_obytes;
292+ stats->tx_packets = ifd->ifi_opackets;
293+ stats->tx_errs = ifd->ifi_oerrors;
294+ stats->tx_drop = 0;
295+ found = 1;
296+ break;
297+ }
298+ }
299+ }
300+ freeifaddrs(ifaddr);
301+ return found ? 0 : -1;
302 }
303 #endif
304
305@@ -186,385 +187,385 @@ net_get_stats(const char *ifname, struct NetStats *stats)
306 int
307 net_set_txqueuelen(const char *name, int qlen)
308 {
309- struct ifreq ifr;
310- int sock;
311-
312- sock = socket(AF_INET, SOCK_DGRAM, 0);
313- if (sock < 0)
314- return -1;
315- memset(&ifr, 0, sizeof(ifr));
316- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
317- ifr.ifr_qlen = qlen;
318- if (ioctl(sock, SIOCSIFTXQLEN, &ifr) < 0) {
319- close(sock);
320- return -1;
321- }
322- close(sock);
323- return 0;
324+ struct ifreq ifr;
325+ int sock;
326+
327+ sock = socket(AF_INET, SOCK_DGRAM, 0);
328+ if (sock < 0)
329+ return -1;
330+ memset(&ifr, 0, sizeof(ifr));
331+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
332+ ifr.ifr_qlen = qlen;
333+ if (ioctl(sock, SIOCSIFTXQLEN, &ifr) < 0) {
334+ close(sock);
335+ return -1;
336+ }
337+ close(sock);
338+ return 0;
339 }
340 #else
341 int
342 net_set_txqueuelen(const char *name, int qlen)
343 {
344- (void)name;
345- (void)qlen;
346- return -1;
347+ (void)name;
348+ (void)qlen;
349+ return -1;
350 }
351 #endif
352
353 int
354 net_set_flags(const char *name, unsigned int flags, int set)
355 {
356- struct ifreq ifr;
357- int sock;
358-
359- sock = socket(AF_INET, SOCK_DGRAM, 0);
360- if (sock < 0)
361- return -1;
362- memset(&ifr, 0, sizeof(ifr));
363- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
364- if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
365- close(sock);
366- return -1;
367- }
368- if (set)
369- ifr.ifr_flags |= flags;
370- else
371- ifr.ifr_flags &= ~flags;
372- if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
373- close(sock);
374- return -1;
375- }
376- close(sock);
377- return 0;
378+ struct ifreq ifr;
379+ int sock;
380+
381+ sock = socket(AF_INET, SOCK_DGRAM, 0);
382+ if (sock < 0)
383+ return -1;
384+ memset(&ifr, 0, sizeof(ifr));
385+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
386+ if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
387+ close(sock);
388+ return -1;
389+ }
390+ if (set)
391+ ifr.ifr_flags |= flags;
392+ else
393+ ifr.ifr_flags &= ~flags;
394+ if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
395+ close(sock);
396+ return -1;
397+ }
398+ close(sock);
399+ return 0;
400 }
401
402 int
403 net_set_mtu(const char *name, int mtu)
404 {
405- struct ifreq ifr;
406- int sock;
407-
408- sock = socket(AF_INET, SOCK_DGRAM, 0);
409- if (sock < 0)
410- return -1;
411- memset(&ifr, 0, sizeof(ifr));
412- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
413- ifr.ifr_mtu = mtu;
414- if (ioctl(sock, SIOCSIFMTU, &ifr) < 0) {
415- close(sock);
416- return -1;
417- }
418- close(sock);
419- return 0;
420+ struct ifreq ifr;
421+ int sock;
422+
423+ sock = socket(AF_INET, SOCK_DGRAM, 0);
424+ if (sock < 0)
425+ return -1;
426+ memset(&ifr, 0, sizeof(ifr));
427+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
428+ ifr.ifr_mtu = mtu;
429+ if (ioctl(sock, SIOCSIFMTU, &ifr) < 0) {
430+ close(sock);
431+ return -1;
432+ }
433+ close(sock);
434+ return 0;
435 }
436
437 int
438-net_set_mac(const char *name, const unsigned char mac[6])
439+net_set_mac(const char *name, const unsigned char *mac)
440 {
441 #ifdef __linux__
442- struct ifreq ifr;
443- int sock;
444-
445- sock = socket(AF_INET, SOCK_DGRAM, 0);
446- if (sock < 0)
447- return -1;
448- memset(&ifr, 0, sizeof(ifr));
449- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
450- ifr.ifr_hwaddr.sa_family = 1;
451- memcpy(ifr.ifr_hwaddr.sa_data, mac, 6);
452- if (ioctl(sock, SIOCSIFHWADDR, &ifr) < 0) {
453- close(sock);
454- return -1;
455- }
456- close(sock);
457- return 0;
458+ struct ifreq ifr;
459+ int sock;
460+
461+ sock = socket(AF_INET, SOCK_DGRAM, 0);
462+ if (sock < 0)
463+ return -1;
464+ memset(&ifr, 0, sizeof(ifr));
465+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
466+ ifr.ifr_hwaddr.sa_family = 1;
467+ memcpy(ifr.ifr_hwaddr.sa_data, mac, 6);
468+ if (ioctl(sock, SIOCSIFHWADDR, &ifr) < 0) {
469+ close(sock);
470+ return -1;
471+ }
472+ close(sock);
473+ return 0;
474 #else
475- (void)name;
476- (void)mac;
477- return -1;
478+ (void)name;
479+ (void)mac;
480+ return -1;
481 #endif
482 }
483
484 int
485 net_add_addr(const char *name, const char *addr, int prefix)
486 {
487- struct ifreq ifr;
488- struct sockaddr_in *sin;
489- int sock;
490- unsigned int mask;
491-
492- sock = socket(AF_INET, SOCK_DGRAM, 0);
493- if (sock < 0)
494- return -1;
495-
496- memset(&ifr, 0, sizeof(ifr));
497- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
498-
499- sin = (struct sockaddr_in *)&ifr.ifr_addr;
500- sin->sin_family = AF_INET;
501- if (inet_pton(AF_INET, addr, &sin->sin_addr) <= 0) {
502- close(sock);
503- return -1;
504- }
505-
506- if (ioctl(sock, SIOCSIFADDR, &ifr) < 0) {
507- close(sock);
508- return -1;
509- }
510-
511- if (prefix >= 0) {
512- mask = 0;
513- if (prefix > 0)
514- mask = htonl(~0U << (32 - prefix));
515- sin = (struct sockaddr_in *)&ifr.ifr_netmask;
516- sin->sin_family = AF_INET;
517- sin->sin_addr.s_addr = mask;
518- if (ioctl(sock, SIOCSIFNETMASK, &ifr) < 0) {
519- close(sock);
520- return -1;
521- }
522- }
523-
524- memset(&ifr, 0, sizeof(ifr));
525- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
526- if (ioctl(sock, SIOCGIFFLAGS, &ifr) >= 0) {
527- ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
528- ioctl(sock, SIOCSIFFLAGS, &ifr);
529- }
530-
531- close(sock);
532- return 0;
533+ struct ifreq ifr;
534+ struct sockaddr_in *sin;
535+ int sock;
536+ unsigned int mask;
537+
538+ sock = socket(AF_INET, SOCK_DGRAM, 0);
539+ if (sock < 0)
540+ return -1;
541+
542+ memset(&ifr, 0, sizeof(ifr));
543+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
544+
545+ sin = (struct sockaddr_in *)&ifr.ifr_addr;
546+ sin->sin_family = AF_INET;
547+ if (inet_pton(AF_INET, addr, &sin->sin_addr) <= 0) {
548+ close(sock);
549+ return -1;
550+ }
551+
552+ if (ioctl(sock, SIOCSIFADDR, &ifr) < 0) {
553+ close(sock);
554+ return -1;
555+ }
556+
557+ if (prefix >= 0) {
558+ mask = 0;
559+ if (prefix > 0)
560+ mask = htonl(~0U << (32 - prefix));
561+ sin = (struct sockaddr_in *)&ifr.ifr_netmask;
562+ sin->sin_family = AF_INET;
563+ sin->sin_addr.s_addr = mask;
564+ if (ioctl(sock, SIOCSIFNETMASK, &ifr) < 0) {
565+ close(sock);
566+ return -1;
567+ }
568+ }
569+
570+ memset(&ifr, 0, sizeof(ifr));
571+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
572+ if (ioctl(sock, SIOCGIFFLAGS, &ifr) >= 0) {
573+ ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
574+ ioctl(sock, SIOCSIFFLAGS, &ifr);
575+ }
576+
577+ close(sock);
578+ return 0;
579 }
580
581 int
582 net_del_addr(const char *name, const char *addr, int prefix)
583 {
584- struct ifreq ifr;
585- struct sockaddr_in *sin;
586- int sock;
587-
588- (void)prefix;
589- sock = socket(AF_INET, SOCK_DGRAM, 0);
590- if (sock < 0)
591- return -1;
592-
593- memset(&ifr, 0, sizeof(ifr));
594- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
595-
596- sin = (struct sockaddr_in *)&ifr.ifr_addr;
597- sin->sin_family = AF_INET;
598- if (inet_pton(AF_INET, addr, &sin->sin_addr) <= 0) {
599- close(sock);
600- return -1;
601- }
602-
603- if (ioctl(sock, SIOCDIFADDR, &ifr) < 0) {
604- close(sock);
605- return -1;
606- }
607- close(sock);
608- return 0;
609+ struct ifreq ifr;
610+ struct sockaddr_in *sin;
611+ int sock;
612+
613+ (void)prefix;
614+ sock = socket(AF_INET, SOCK_DGRAM, 0);
615+ if (sock < 0)
616+ return -1;
617+
618+ memset(&ifr, 0, sizeof(ifr));
619+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
620+
621+ sin = (struct sockaddr_in *)&ifr.ifr_addr;
622+ sin->sin_family = AF_INET;
623+ if (inet_pton(AF_INET, addr, &sin->sin_addr) <= 0) {
624+ close(sock);
625+ return -1;
626+ }
627+
628+ if (ioctl(sock, SIOCDIFADDR, &ifr) < 0) {
629+ close(sock);
630+ return -1;
631+ }
632+ close(sock);
633+ return 0;
634 }
635
636 int
637 net_show_routes(void)
638 {
639 #ifdef __linux__
640- FILE *fp;
641- char line[256];
642- char iface[16], dest[16], gateway[16], mask[16];
643- unsigned int d, g, m, flags, metric;
644-
645- fp = fopen("/proc/net/route", "r");
646- if (!fp)
647- return -1;
648-
649- printf("%-10s %-15s %-15s %-15s %-6s %-6s\n", "Iface", "Destination", "Gateway", "Genmask", "Flags", "Metric");
650- if (fgets(line, sizeof(line), fp)) {
651- while (fgets(line, sizeof(line), fp)) {
652- if (sscanf(line, "%15s %x %x %x %*u %*u %u %x", iface, &d, &g, &m, &metric, &flags) == 6) {
653- struct in_addr dest_addr, gw_addr, mask_addr;
654- dest_addr.s_addr = d;
655- gw_addr.s_addr = g;
656- mask_addr.s_addr = m;
657- strlcpy(dest, inet_ntoa(dest_addr), sizeof(dest));
658- strlcpy(gateway, inet_ntoa(gw_addr), sizeof(gateway));
659- strlcpy(mask, inet_ntoa(mask_addr), sizeof(mask));
660- printf("%-10s %-15s %-15s %-15s 0x%04X %-6u\n", iface, dest, gateway, mask, flags, metric);
661- }
662- }
663- }
664- fclose(fp);
665- return 0;
666+ FILE *fp;
667+ char line[256];
668+ char iface[16], dest[16], gateway[16], mask[16];
669+ unsigned int d, g, m, flags, metric;
670+
671+ fp = fopen(ARUU_LINUX_PATH_PROC "/net/route", "r");
672+ if (!fp)
673+ return -1;
674+
675+ printf("%-10s %-15s %-15s %-15s %-6s %-6s\n", "Iface", "Destination", "Gateway", "Genmask", "Flags", "Metric");
676+ if (fgets(line, sizeof(line), fp)) {
677+ while (fgets(line, sizeof(line), fp)) {
678+ if (sscanf(line, "%15s %x %x %x %*u %*u %u %x", iface, &d, &g, &m, &metric, &flags) == 6) {
679+ struct in_addr dest_addr, gw_addr, mask_addr;
680+ dest_addr.s_addr = d;
681+ gw_addr.s_addr = g;
682+ mask_addr.s_addr = m;
683+ strlcpy(dest, inet_ntoa(dest_addr), sizeof(dest));
684+ strlcpy(gateway, inet_ntoa(gw_addr), sizeof(gateway));
685+ strlcpy(mask, inet_ntoa(mask_addr), sizeof(mask));
686+ printf("%-10s %-15s %-15s %-15s 0x%04X %-6u\n", iface, dest, gateway, mask, flags, metric);
687+ }
688+ }
689+ }
690+ fclose(fp);
691+ return 0;
692 #else
693- printf("route listing not implemented on this OS\n");
694- return 0;
695+ printf("route listing not implemented on this OS\n");
696+ return 0;
697 #endif
698 }
699
700 int
701 net_add_route(const char *dst, const char *gateway, const char *mask, const char *dev, int metric)
702 {
703- struct rtentry rt;
704- struct sockaddr_in *sin;
705- int sock;
706-
707- sock = socket(AF_INET, SOCK_DGRAM, 0);
708- if (sock < 0)
709- return -1;
710-
711- memset(&rt, 0, sizeof(rt));
712-
713- sin = (struct sockaddr_in *)&rt.rt_dst;
714- sin->sin_family = AF_INET;
715- if (strcmp(dst, "default") == 0) {
716- sin->sin_addr.s_addr = INADDR_ANY;
717- } else {
718- if (inet_pton(AF_INET, dst, &sin->sin_addr) <= 0) {
719- close(sock);
720- return -1;
721- }
722- }
723-
724- if (gateway) {
725- sin = (struct sockaddr_in *)&rt.rt_gateway;
726- sin->sin_family = AF_INET;
727- if (inet_pton(AF_INET, gateway, &sin->sin_addr) <= 0) {
728- close(sock);
729- return -1;
730- }
731- rt.rt_flags |= RTF_GATEWAY;
732- }
733-
734- if (mask) {
735- sin = (struct sockaddr_in *)&rt.rt_genmask;
736- sin->sin_family = AF_INET;
737- if (inet_pton(AF_INET, mask, &sin->sin_addr) <= 0) {
738- close(sock);
739- return -1;
740- }
741- }
742-
743- rt.rt_flags |= RTF_UP;
744- if (dev)
745- rt.rt_dev = (char *)dev;
746- if (metric >= 0)
747- rt.rt_metric = metric + 1;
748-
749- if (ioctl(sock, SIOCADDRT, &rt) < 0) {
750- close(sock);
751- return -1;
752- }
753-
754- close(sock);
755- return 0;
756+ struct rtentry rt;
757+ struct sockaddr_in *sin;
758+ int sock;
759+
760+ sock = socket(AF_INET, SOCK_DGRAM, 0);
761+ if (sock < 0)
762+ return -1;
763+
764+ memset(&rt, 0, sizeof(rt));
765+
766+ sin = (struct sockaddr_in *)&rt.rt_dst;
767+ sin->sin_family = AF_INET;
768+ if (strcmp(dst, "default") == 0) {
769+ sin->sin_addr.s_addr = INADDR_ANY;
770+ } else {
771+ if (inet_pton(AF_INET, dst, &sin->sin_addr) <= 0) {
772+ close(sock);
773+ return -1;
774+ }
775+ }
776+
777+ if (gateway) {
778+ sin = (struct sockaddr_in *)&rt.rt_gateway;
779+ sin->sin_family = AF_INET;
780+ if (inet_pton(AF_INET, gateway, &sin->sin_addr) <= 0) {
781+ close(sock);
782+ return -1;
783+ }
784+ rt.rt_flags |= RTF_GATEWAY;
785+ }
786+
787+ if (mask) {
788+ sin = (struct sockaddr_in *)&rt.rt_genmask;
789+ sin->sin_family = AF_INET;
790+ if (inet_pton(AF_INET, mask, &sin->sin_addr) <= 0) {
791+ close(sock);
792+ return -1;
793+ }
794+ }
795+
796+ rt.rt_flags |= RTF_UP;
797+ if (dev)
798+ rt.rt_dev = (char *)dev;
799+ if (metric >= 0)
800+ rt.rt_metric = metric + 1;
801+
802+ if (ioctl(sock, SIOCADDRT, &rt) < 0) {
803+ close(sock);
804+ return -1;
805+ }
806+
807+ close(sock);
808+ return 0;
809 }
810
811 int
812 net_del_route(const char *dst, const char *gateway, const char *mask, const char *dev, int metric)
813 {
814- struct rtentry rt;
815- struct sockaddr_in *sin;
816- int sock;
817-
818- sock = socket(AF_INET, SOCK_DGRAM, 0);
819- if (sock < 0)
820- return -1;
821-
822- memset(&rt, 0, sizeof(rt));
823-
824- sin = (struct sockaddr_in *)&rt.rt_dst;
825- sin->sin_family = AF_INET;
826- if (strcmp(dst, "default") == 0) {
827- sin->sin_addr.s_addr = INADDR_ANY;
828- } else {
829- if (inet_pton(AF_INET, dst, &sin->sin_addr) <= 0) {
830- close(sock);
831- return -1;
832- }
833- }
834-
835- if (gateway) {
836- sin = (struct sockaddr_in *)&rt.rt_gateway;
837- sin->sin_family = AF_INET;
838- if (inet_pton(AF_INET, gateway, &sin->sin_addr) <= 0) {
839- close(sock);
840- return -1;
841- }
842- rt.rt_flags |= RTF_GATEWAY;
843- }
844-
845- if (mask) {
846- sin = (struct sockaddr_in *)&rt.rt_genmask;
847- sin->sin_family = AF_INET;
848- if (inet_pton(AF_INET, mask, &sin->sin_addr) <= 0) {
849- close(sock);
850- return -1;
851- }
852- }
853-
854- rt.rt_flags |= RTF_UP;
855- if (dev)
856- rt.rt_dev = (char *)dev;
857- if (metric >= 0)
858- rt.rt_metric = metric + 1;
859-
860- if (ioctl(sock, SIOCDELRT, &rt) < 0) {
861- close(sock);
862- return -1;
863- }
864-
865- close(sock);
866- return 0;
867+ struct rtentry rt;
868+ struct sockaddr_in *sin;
869+ int sock;
870+
871+ sock = socket(AF_INET, SOCK_DGRAM, 0);
872+ if (sock < 0)
873+ return -1;
874+
875+ memset(&rt, 0, sizeof(rt));
876+
877+ sin = (struct sockaddr_in *)&rt.rt_dst;
878+ sin->sin_family = AF_INET;
879+ if (strcmp(dst, "default") == 0) {
880+ sin->sin_addr.s_addr = INADDR_ANY;
881+ } else {
882+ if (inet_pton(AF_INET, dst, &sin->sin_addr) <= 0) {
883+ close(sock);
884+ return -1;
885+ }
886+ }
887+
888+ if (gateway) {
889+ sin = (struct sockaddr_in *)&rt.rt_gateway;
890+ sin->sin_family = AF_INET;
891+ if (inet_pton(AF_INET, gateway, &sin->sin_addr) <= 0) {
892+ close(sock);
893+ return -1;
894+ }
895+ rt.rt_flags |= RTF_GATEWAY;
896+ }
897+
898+ if (mask) {
899+ sin = (struct sockaddr_in *)&rt.rt_genmask;
900+ sin->sin_family = AF_INET;
901+ if (inet_pton(AF_INET, mask, &sin->sin_addr) <= 0) {
902+ close(sock);
903+ return -1;
904+ }
905+ }
906+
907+ rt.rt_flags |= RTF_UP;
908+ if (dev)
909+ rt.rt_dev = (char *)dev;
910+ if (metric >= 0)
911+ rt.rt_metric = metric + 1;
912+
913+ if (ioctl(sock, SIOCDELRT, &rt) < 0) {
914+ close(sock);
915+ return -1;
916+ }
917+
918+ close(sock);
919+ return 0;
920 }
921
922 int
923 net_flush_addrs(const char *dev)
924 {
925- struct NetInterface *ifaces = NULL;
926- int count = 0, i, r = 0;
927-
928- if (net_get_interfaces(&ifaces, &count) < 0)
929- return -1;
930-
931- for (i = 0; i < count; i++) {
932- if (strcmp(ifaces[i].name, dev) == 0) {
933- if (ifaces[i].has_ipv4) {
934- char addr_str[16];
935- struct sockaddr_in *sin = &ifaces[i].ipv4_addr;
936- inet_ntop(AF_INET, &sin->sin_addr, addr_str, sizeof(addr_str));
937- if (net_del_addr(dev, addr_str, -1) < 0)
938- r = -1;
939- }
940- }
941- }
942- free(ifaces);
943- return r;
944+ struct NetInterface *ifaces = NULL;
945+ int count = 0, i, r = 0;
946+
947+ if (net_get_interfaces(&ifaces, &count) < 0)
948+ return -1;
949+
950+ for (i = 0; i < count; i++) {
951+ if (strcmp(ifaces[i].name, dev) == 0) {
952+ if (ifaces[i].has_ipv4) {
953+ char addr_str[16];
954+ struct sockaddr_in *sin = &ifaces[i].ipv4_addr;
955+ inet_ntop(AF_INET, &sin->sin_addr, addr_str, sizeof(addr_str));
956+ if (net_del_addr(dev, addr_str, -1) < 0)
957+ r = -1;
958+ }
959+ }
960+ }
961+ free(ifaces);
962+ return r;
963 }
964
965 int
966 net_set_name(const char *name, const char *newname)
967 {
968 #ifdef __linux__
969- struct ifreq ifr;
970- int sock;
971-
972- sock = socket(AF_INET, SOCK_DGRAM, 0);
973- if (sock < 0)
974- return -1;
975- memset(&ifr, 0, sizeof(ifr));
976- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
977- strlcpy(ifr.ifr_newname, newname, sizeof(ifr.ifr_newname));
978- if (ioctl(sock, SIOCSIFNAME, &ifr) < 0) {
979- close(sock);
980- return -1;
981- }
982- close(sock);
983- return 0;
984+ struct ifreq ifr;
985+ int sock;
986+
987+ sock = socket(AF_INET, SOCK_DGRAM, 0);
988+ if (sock < 0)
989+ return -1;
990+ memset(&ifr, 0, sizeof(ifr));
991+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
992+ strlcpy(ifr.ifr_newname, newname, sizeof(ifr.ifr_newname));
993+ if (ioctl(sock, SIOCSIFNAME, &ifr) < 0) {
994+ close(sock);
995+ return -1;
996+ }
997+ close(sock);
998+ return 0;
999 #else
1000- (void)name;
1001- (void)newname;
1002- return -1;
1003+ (void)name;
1004+ (void)newname;
1005+ return -1;
1006 #endif
1007 }
1@@ -1,77 +1,384 @@
2 /* See LICENSE file for copyright and license details. */
3-#include <sys/resource.h>
4-#include <sys/time.h>
5+#include "../passwd.h"
6+#include "../paths.h"
7+#include "../text.h"
8+#include "../util.h"
9
10 #include <errno.h>
11+#include <fcntl.h>
12 #include <pwd.h>
13-#include <shadow.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17+#include <sys/resource.h>
18+#include <sys/stat.h>
19+#include <sys/wait.h>
20 #include <unistd.h>
21
22-#include "../passwd.h"
23-#include "../text.h"
24-#include "../util.h"
25+#include "../config.h"
26+
27+#if defined(__linux__) || defined(__GLIBC__)
28+#include <crypt.h>
29+#endif
30+
31+#if defined(__linux__) && !defined(__ANDROID__)
32+#define HAVE_SHADOW 1
33+#include <shadow.h>
34+#endif
35+
36+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
37+#define HAVE_MASTER_PASSWD 1
38+#endif
39+
40+int
41+pw_init(void)
42+{
43+ struct rlimit rlim;
44+
45+ rlim.rlim_cur = 0;
46+ rlim.rlim_max = 0;
47+ if (setrlimit(RLIMIT_CORE, &rlim) < 0)
48+ eprintf("setrlimit:");
49+ return 0;
50+}
51
52-/* Returns -1 on error, 0 for incorrect password
53- * and 1 if all went OK */
54 int
55 pw_check(const struct passwd *pw, const char *pass)
56 {
57- char *cryptpass, *p;
58- struct spwd *spw;
59-
60- p = pw->pw_passwd;
61- if (p[0] == '!' || p[0] == '*') {
62- weprintf("denied\n");
63- return -1;
64- }
65-
66- if (pw->pw_passwd[0] == '\0') {
67- if (pass[0] == '\0')
68- return 1;
69- weprintf("incorrect password\n");
70- return 0;
71- }
72-
73- if (pw->pw_passwd[0] == 'x' && pw->pw_passwd[1] == '\0') {
74- errno = 0;
75- spw = getspnam(pw->pw_name);
76- if (!spw) {
77- if (errno)
78- weprintf("getspnam: %s:", pw->pw_name);
79- else
80- weprintf("who are you?\n");
81- return -1;
82- }
83- p = spw->sp_pwdp;
84- if (p[0] == '!' || p[0] == '*') {
85- weprintf("denied\n");
86- return -1;
87- }
88- }
89-
90- cryptpass = crypt(pass, p);
91- if (!cryptpass) {
92- weprintf("crypt:");
93- return -1;
94- }
95- if (strcmp(cryptpass, p) != 0) {
96- weprintf("incorrect password\n");
97- return 0;
98- }
99- return 1;
100+ char *cryptpass, *p;
101+ const char *stored;
102+
103+ stored = pw->pw_passwd;
104+ if (stored[0] == '!' || stored[0] == '*') {
105+ weprintf("denied\n");
106+ return -1;
107+ }
108+
109+ if (stored[0] == '\0') {
110+ if (pass[0] == '\0')
111+ return 1;
112+ weprintf("incorrect password\n");
113+ return 0;
114+ }
115+
116+#if defined(HAVE_SHADOW)
117+ if (stored[0] == 'x' && stored[1] == '\0') {
118+ struct spwd *spw;
119+ errno = 0;
120+ spw = getspnam(pw->pw_name);
121+ if (!spw) {
122+ if (errno)
123+ weprintf("getspnam: %s:", pw->pw_name);
124+ else
125+ weprintf("who are you?\n");
126+ return -1;
127+ }
128+ stored = spw->sp_pwdp;
129+ if (stored[0] == '!' || stored[0] == '*') {
130+ weprintf("denied\n");
131+ return -1;
132+ }
133+ }
134+#endif
135+
136+ cryptpass = crypt(pass, stored);
137+ if (!cryptpass) {
138+ weprintf("crypt:");
139+ return -1;
140+ }
141+ p = estrdup(cryptpass);
142+ if (strcmp(p, stored) != 0) {
143+ free(p);
144+ weprintf("incorrect password\n");
145+ return 0;
146+ }
147+ free(p);
148+ return 1;
149 }
150
151 int
152-pw_init(void)
153+pwdb_lookup(struct pwdb_entry *ent, const char *name)
154 {
155- struct rlimit rlim;
156+ struct passwd *pw;
157+ const char *hash;
158
159- rlim.rlim_cur = 0;
160- rlim.rlim_max = 0;
161- if (setrlimit(RLIMIT_CORE, &rlim) < 0)
162- eprintf("setrlimit:");
163- return 0;
164+ errno = 0;
165+ pw = getpwnam(name);
166+ if (!pw) {
167+ if (errno)
168+ weprintf("getpwnam: %s:", name);
169+ else
170+ weprintf("who are you?\n");
171+ return -1;
172+ }
173+
174+ ent->name = estrdup(pw->pw_name);
175+ ent->uid = pw->pw_uid;
176+ ent->gid = pw->pw_gid;
177+ hash = pw->pw_passwd;
178+
179+#if defined(HAVE_SHADOW)
180+ if (hash[0] == 'x' && hash[1] == '\0') {
181+ struct spwd *spw;
182+ errno = 0;
183+ spw = getspnam(name);
184+ if (spw)
185+ hash = spw->sp_pwdp;
186+ }
187+#endif
188+
189+ ent->hash = estrdup(hash);
190+ return 0;
191+}
192+
193+static int
194+fill_random(void *buf, size_t n)
195+{
196+#if defined(__linux__)
197+ if (getentropy(buf, n) == 0)
198+ return 0;
199+#endif
200+ {
201+ int fd;
202+ size_t off;
203+ fd = open(ARUU_PATH_DEVURANDOM, O_RDONLY);
204+ if (fd < 0) {
205+ weprintf("open /dev/urandom:");
206+ return -1;
207+ }
208+ off = 0;
209+ while (off < n) {
210+ ssize_t r = read(fd, (char *)buf + off, n - off);
211+ if (r <= 0) {
212+ close(fd);
213+ weprintf("read /dev/urandom:");
214+ return -1;
215+ }
216+ off += (size_t)r;
217+ }
218+ close(fd);
219+ }
220+ return 0;
221+}
222+
223+int
224+pw_gensalt_cipher(char *salt, size_t salt_sz, const char *prefix,
225+ size_t rand_len)
226+{
227+ static const char b64[] =
228+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
229+ unsigned char raw[32];
230+ char body[48];
231+ size_t i, n, body_len;
232+ unsigned v;
233+ int prefix_len;
234+
235+ if (rand_len > sizeof(raw))
236+ rand_len = sizeof(raw);
237+ if (rand_len == 0) {
238+ salt[0] = '\0';
239+ return 0;
240+ }
241+
242+ prefix_len = 0;
243+ if (prefix) {
244+ prefix_len = snprintf(salt, salt_sz, "%s", prefix);
245+ if (prefix_len < 0 || (size_t)prefix_len >= salt_sz) {
246+ weprintf("snprintf:");
247+ return -1;
248+ }
249+ }
250+
251+ if (fill_random(raw, rand_len) < 0)
252+ return -1;
253+
254+ body_len = (rand_len * 4 + 2) / 3;
255+ if (body_len >= sizeof(body))
256+ body_len = sizeof(body) - 1;
257+ n = 0;
258+ for (i = 0; i + 3 <= rand_len; i += 3) {
259+ v = (raw[i] << 16) | (raw[i+1] << 8) | raw[i+2];
260+ body[n++] = b64[v & 0x3f]; v >>= 6;
261+ body[n++] = b64[v & 0x3f]; v >>= 6;
262+ body[n++] = b64[v & 0x3f]; v >>= 6;
263+ body[n++] = b64[v & 0x3f];
264+ }
265+ if (i < rand_len) {
266+ v = raw[i] << 16;
267+ if (i + 1 < rand_len)
268+ v |= raw[i+1] << 8;
269+ body[n++] = b64[v & 0x3f]; v >>= 6;
270+ body[n++] = b64[v & 0x3f]; v >>= 6;
271+ if (i + 1 < rand_len)
272+ body[n++] = b64[v & 0x3f];
273+ }
274+ body[n] = '\0';
275+
276+ if ((size_t)prefix_len + n + 1 >= salt_sz) {
277+ weprintf("salt buffer too small\n");
278+ return -1;
279+ }
280+ memcpy(salt + prefix_len, body, n + 1);
281+ return 0;
282+}
283+
284+int
285+pw_gensalt(char *salt, size_t salt_sz)
286+{
287+ return pw_gensalt_cipher(salt, salt_sz, PW_CIPHER, 16);
288+}
289+
290+#if defined(HAVE_SHADOW)
291+static int
292+update_shadow(const char *name, const char *newhash)
293+{
294+ struct spwd *spw, cur;
295+ FILE *fp, *tfp;
296+ int wrote = 0;
297+ char path[256];
298+
299+ snprintf(path, sizeof(path), ARUU_PATH_ETC "/tcb/%s/shadow", name);
300+ fp = fopen(path, "r+");
301+ if (!fp) {
302+ memcpy(path, ARUU_PATH_SHADOW, sizeof(ARUU_PATH_SHADOW));
303+ fp = fopen(path, "r+");
304+ }
305+ if (!fp) {
306+ weprintf("fopen %s:", path);
307+ return -1;
308+ }
309+
310+ tfp = tmpfile();
311+ if (!tfp) {
312+ weprintf("tmpfile:");
313+ fclose(fp);
314+ return -1;
315+ }
316+
317+ while ((spw = getspent())) {
318+ cur = *spw;
319+ if (strcmp(cur.sp_namp, name) == 0) {
320+ cur.sp_pwdp = (char *)newhash;
321+ wrote = 1;
322+ }
323+ errno = 0;
324+ if (putspent(&cur, tfp) == -1) {
325+ weprintf("putspent:");
326+ fclose(tfp);
327+ fclose(fp);
328+ return -1;
329+ }
330+ }
331+ if (!wrote) {
332+ weprintf("shadow: no matching entry\n");
333+ fclose(tfp);
334+ fclose(fp);
335+ return -1;
336+ }
337+ fflush(tfp);
338+ rewind(tfp);
339+ rewind(fp);
340+ fconcat(tfp, "tmpfile", fp, "shadow");
341+ ftruncate(fileno(fp), ftell(tfp));
342+ fclose(tfp);
343+ {
344+ int fd = fileno(fp);
345+ if (fd >= 0)
346+ fsync(fd);
347+ }
348+ fclose(fp);
349+ return 0;
350+}
351+#endif
352+
353+static int
354+update_passwd_file(const char *path, const char *name, const char *newhash)
355+{
356+ struct passwd *pw, cur;
357+ FILE *fp, *tfp;
358+ int wrote = 0;
359+
360+ fp = fopen(path, "r+");
361+ if (!fp) {
362+ weprintf("fopen %s:", path);
363+ return -1;
364+ }
365+ tfp = tmpfile();
366+ if (!tfp) {
367+ weprintf("tmpfile:");
368+ fclose(fp);
369+ return -1;
370+ }
371+ while ((pw = fgetpwent(fp))) {
372+ cur = *pw;
373+ if (strcmp(cur.pw_name, name) == 0) {
374+ cur.pw_passwd = (char *)newhash;
375+ wrote = 1;
376+ }
377+ errno = 0;
378+ if (putpwent(&cur, tfp) == -1) {
379+ weprintf("putpwent:");
380+ fclose(tfp);
381+ fclose(fp);
382+ return -1;
383+ }
384+ }
385+ if (!wrote) {
386+ weprintf("passwd: no matching entry\n");
387+ fclose(tfp);
388+ fclose(fp);
389+ return -1;
390+ }
391+ fflush(tfp);
392+ rewind(tfp);
393+ rewind(fp);
394+ fconcat(tfp, "tmpfile", fp, path);
395+ ftruncate(fileno(fp), ftell(tfp));
396+ {
397+ int fd = fileno(fp);
398+ if (fd >= 0)
399+ fsync(fd);
400+ }
401+ fclose(tfp);
402+ fclose(fp);
403+ return 0;
404+}
405+
406+#if defined(HAVE_MASTER_PASSWD)
407+static int
408+update_master_passwd(const char *name, const char *newhash)
409+{
410+ int r;
411+ pid_t pid;
412+ int st;
413+
414+ r = update_passwd_file(ARUU_BSD_PATH_MASTER_PASSWD, name, newhash);
415+ if (r != 0)
416+ return r;
417+ pid = fork();
418+ if (pid == 0) {
419+ execl(ARUU_BSD_PATH_PWD_MKDB, "pwd_mkdb", "-p", NULL);
420+ _exit(127);
421+ }
422+ if (pid > 0)
423+ waitpid(pid, &st, 0);
424+ return 0;
425+}
426+#endif
427+
428+int
429+pwdb_update(const char *name, const char *newhash)
430+{
431+#if defined(HAVE_SHADOW)
432+ {
433+ struct spwd *spw;
434+ errno = 0;
435+ spw = getspnam(name);
436+ if (spw)
437+ return update_shadow(name, newhash);
438+ }
439+#elif defined(HAVE_MASTER_PASSWD)
440+ return update_master_passwd(name, newhash);
441+#endif
442+ return update_passwd_file(ARUU_PATH_PASSWD, name, newhash);
443 }
1@@ -10,6 +10,7 @@
2 #include <unistd.h>
3
4 #include "../proc.h"
5+#include "../paths.h"
6 #include "../util.h"
7
8 int
9@@ -19,7 +20,7 @@ parsecmdline(pid_t pid, char *buf, size_t siz)
10 char path[PATH_MAX];
11 ssize_t n, i;
12
13- snprintf(path, sizeof(path), "/proc/%ld/cmdline", (long)pid);
14+ snprintf(path, sizeof(path), ARUU_LINUX_PATH_PROC "/%ld/cmdline", (long)pid);
15 fd = open(path, O_RDONLY);
16 if (fd < 0)
17 return -1;
18@@ -48,7 +49,7 @@ parsestat(pid_t pid, struct procstat *ps)
19 FILE *fp;
20 size_t len;
21
22- snprintf(path, sizeof(path), "/proc/%d/stat", pid);
23+ snprintf(path, sizeof(path), ARUU_LINUX_PATH_PROC "/%d/stat", pid);
24 if (!(fp = fopen(path, "r")))
25 return -1;
26 fscanf(fp, "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu",
27@@ -78,7 +79,7 @@ parsestatus(pid_t pid, struct procstatus *pstatus)
28 int fd;
29 ssize_t n;
30
31- snprintf(path, sizeof(path), "/proc/%d/status", pid);
32+ snprintf(path, sizeof(path), ARUU_LINUX_PATH_PROC "/%d/status", pid);
33 fd = open(path, O_RDONLY);
34 if (fd < 0)
35 return -1;
1@@ -1,5 +1,6 @@
2 /* see license file for copyright and license details */
3 #include "../tls.h"
4+#include "../paths.h"
5 #include "../util.h"
6
7 #include <errno.h>
8@@ -13,201 +14,201 @@
9 #include <tls.h>
10
11 struct TlsSocket {
12- int fd;
13- int is_tls;
14- struct tls *ctx;
15+ int fd;
16+ int is_tls;
17+ struct tls *ctx;
18 };
19
20 #elif FEATURE_USE_BEARSSL
21 #include <bearssl.h>
22
23 struct my_x509_context {
24- const br_x509_class *vtable;
25- br_x509_minimal_context minimal;
26+ const br_x509_class *vtable;
27+ br_x509_minimal_context minimal;
28 };
29
30 struct TlsSocket {
31- int fd;
32- int is_tls;
33- br_ssl_client_context sc;
34- struct my_x509_context my_x509;
35- unsigned char iobuf[BR_SSL_BUFSIZE_BIDI];
36- br_sslio_context ioc;
37+ int fd;
38+ int is_tls;
39+ br_ssl_client_context sc;
40+ struct my_x509_context my_x509;
41+ unsigned char iobuf[BR_SSL_BUFSIZE_BIDI];
42+ br_sslio_context ioc;
43 };
44
45 struct dn_accum {
46- unsigned char *data;
47- size_t len;
48- size_t cap;
49+ unsigned char *data;
50+ size_t len;
51+ size_t cap;
52 };
53
54 static void
55 append_dn_callback(void *dn_ctx, const void *src, size_t len)
56 {
57- struct dn_accum *accum = dn_ctx;
58- if (accum->len + len > accum->cap) {
59- accum->cap = accum->len + len + 256;
60- accum->data = erealloc(accum->data, accum->cap);
61- }
62- memcpy(accum->data + accum->len, src, len);
63- accum->len += len;
64+ struct dn_accum *accum = dn_ctx;
65+ if (accum->len + len > accum->cap) {
66+ accum->cap = accum->len + len + 256;
67+ accum->data = erealloc(accum->data, accum->cap);
68+ }
69+ memcpy(accum->data + accum->len, src, len);
70+ accum->len += len;
71 }
72
73 static void
74 my_start_chain(const br_x509_class **ctx, const char *server_name)
75 {
76- struct my_x509_context *t = (struct my_x509_context *)ctx;
77- br_x509_minimal_vtable.start_chain((const br_x509_class **)&t->minimal, server_name);
78+ struct my_x509_context *t = (struct my_x509_context *)ctx;
79+ br_x509_minimal_vtable.start_chain((const br_x509_class **)&t->minimal, server_name);
80 }
81
82 static void
83 my_start_cert(const br_x509_class **ctx, uint32_t length)
84 {
85- struct my_x509_context *t = (struct my_x509_context *)ctx;
86- br_x509_minimal_vtable.start_cert((const br_x509_class **)&t->minimal, length);
87+ struct my_x509_context *t = (struct my_x509_context *)ctx;
88+ br_x509_minimal_vtable.start_cert((const br_x509_class **)&t->minimal, length);
89 }
90
91 static void
92 my_append(const br_x509_class **ctx, const unsigned char *buf, size_t len)
93 {
94- struct my_x509_context *t = (struct my_x509_context *)ctx;
95- br_x509_minimal_vtable.append((const br_x509_class **)&t->minimal, buf, len);
96+ struct my_x509_context *t = (struct my_x509_context *)ctx;
97+ br_x509_minimal_vtable.append((const br_x509_class **)&t->minimal, buf, len);
98 }
99
100 static void
101 my_end_cert(const br_x509_class **ctx)
102 {
103- struct my_x509_context *t = (struct my_x509_context *)ctx;
104- br_x509_minimal_vtable.end_cert((const br_x509_class **)&t->minimal);
105+ struct my_x509_context *t = (struct my_x509_context *)ctx;
106+ br_x509_minimal_vtable.end_cert((const br_x509_class **)&t->minimal);
107 }
108
109 static unsigned
110 my_end_chain(const br_x509_class **ctx)
111 {
112- struct my_x509_context *t = (struct my_x509_context *)ctx;
113- (void)br_x509_minimal_vtable.end_chain((const br_x509_class **)&t->minimal);
114- /* always succeed and accept certificate when check_cert is 0 */
115- return 0;
116+ struct my_x509_context *t = (struct my_x509_context *)ctx;
117+ (void)br_x509_minimal_vtable.end_chain((const br_x509_class **)&t->minimal);
118+ /* always succeed and accept certificate when check_cert is 0 */
119+ return 0;
120 }
121
122 static const br_x509_pkey *
123 my_get_pkey(const br_x509_class *const *ctx, unsigned *usages)
124 {
125- const struct my_x509_context *t = (const struct my_x509_context *)ctx;
126- return br_x509_minimal_vtable.get_pkey((const br_x509_class *const *)&t->minimal, usages);
127+ const struct my_x509_context *t = (const struct my_x509_context *)ctx;
128+ return br_x509_minimal_vtable.get_pkey((const br_x509_class *const *)&t->minimal, usages);
129 }
130
131 static const br_x509_class my_x509_vtable = {
132- sizeof(struct my_x509_context),
133- my_start_chain,
134- my_start_cert,
135- my_append,
136- my_end_cert,
137- my_end_chain,
138- my_get_pkey
139+ sizeof(struct my_x509_context),
140+ my_start_chain,
141+ my_start_cert,
142+ my_append,
143+ my_end_cert,
144+ my_end_chain,
145+ my_get_pkey
146 };
147
148 static int
149 sock_read(void *ctx, unsigned char *buf, size_t len)
150 {
151- int fd = *(int *)ctx;
152- for (;;) {
153- ssize_t rlen = read(fd, buf, len);
154- if (rlen <= 0) {
155- if (rlen < 0 && errno == EINTR)
156- continue;
157- return -1;
158- }
159- return (int)rlen;
160- }
161+ int fd = *(int *)ctx;
162+ for (;;) {
163+ ssize_t rlen = read(fd, buf, len);
164+ if (rlen <= 0) {
165+ if (rlen < 0 && errno == EINTR)
166+ continue;
167+ return -1;
168+ }
169+ return (int)rlen;
170+ }
171 }
172
173 static int
174 sock_write(void *ctx, const unsigned char *buf, size_t len)
175 {
176- int fd = *(int *)ctx;
177- for (;;) {
178- ssize_t wlen = write(fd, buf, len);
179- if (wlen <= 0) {
180- if (wlen < 0 && errno == EINTR)
181- continue;
182- return -1;
183- }
184- return (int)wlen;
185- }
186+ int fd = *(int *)ctx;
187+ for (;;) {
188+ ssize_t wlen = write(fd, buf, len);
189+ if (wlen <= 0) {
190+ if (wlen < 0 && errno == EINTR)
191+ continue;
192+ return -1;
193+ }
194+ return (int)wlen;
195+ }
196 }
197
198 static int
199 b64_decode_char(char c)
200 {
201- if (c >= 'A' && c <= 'Z') return c - 'A';
202- if (c >= 'a' && c <= 'z') return c - 'a' + 26;
203- if (c >= '0' && c <= '9') return c - '0' + 52;
204- if (c == '+') return 62;
205- if (c == '/') return 63;
206- return -1;
207+ if (c >= 'A' && c <= 'Z') return c - 'A';
208+ if (c >= 'a' && c <= 'z') return c - 'a' + 26;
209+ if (c >= '0' && c <= '9') return c - '0' + 52;
210+ if (c == '+') return 62;
211+ if (c == '/') return 63;
212+ return -1;
213 }
214
215 static size_t
216 b64_decode(const char *src, size_t src_len, unsigned char *dst)
217 {
218- size_t i, j = 0;
219- int val = 0, valb = -8;
220- for (i = 0; i < src_len; i++) {
221- int c = b64_decode_char(src[i]);
222- if (c >= 0) {
223- val = (val << 6) | c;
224- valb += 6;
225- if (valb >= 0) {
226- dst[j++] = (val >> valb) & 0xFF;
227- valb -= 8;
228- }
229- }
230- }
231- return j;
232+ size_t i, j = 0;
233+ int val = 0, valb = -8;
234+ for (i = 0; i < src_len; i++) {
235+ int c = b64_decode_char(src[i]);
236+ if (c >= 0) {
237+ val = (val << 6) | c;
238+ valb += 6;
239+ if (valb >= 0) {
240+ dst[j++] = (val >> valb) & 0xFF;
241+ valb -= 8;
242+ }
243+ }
244+ }
245+ return j;
246 }
247
248 static int
249 decode_cert_der(const unsigned char *der, size_t der_len, br_x509_trust_anchor *ta)
250 {
251- br_x509_decoder_context dc;
252- struct dn_accum accum = { NULL, 0, 0 };
253- const br_x509_pkey *pk;
254-
255- br_x509_decoder_init(&dc, append_dn_callback, &accum);
256- br_x509_decoder_push(&dc, der, der_len);
257- if (br_x509_decoder_last_error(&dc) != 0) {
258- free(accum.data);
259- return 0;
260- }
261- pk = br_x509_decoder_get_pkey(&dc);
262- if (!pk) {
263- free(accum.data);
264- return 0;
265- }
266-
267- ta->dn.data = accum.data;
268- ta->dn.len = accum.len;
269- ta->flags = br_x509_decoder_isCA(&dc) ? BR_X509_TA_CA : 0;
270- ta->pkey.key_type = pk->key_type;
271-
272- if (pk->key_type == BR_KEYTYPE_RSA) {
273- ta->pkey.key.rsa.nlen = pk->key.rsa.nlen;
274- ta->pkey.key.rsa.n = emalloc(pk->key.rsa.nlen);
275- memcpy(ta->pkey.key.rsa.n, pk->key.rsa.n, pk->key.rsa.nlen);
276- ta->pkey.key.rsa.elen = pk->key.rsa.elen;
277- ta->pkey.key.rsa.e = emalloc(pk->key.rsa.elen);
278- memcpy(ta->pkey.key.rsa.e, pk->key.rsa.e, pk->key.rsa.elen);
279- } else if (pk->key_type == BR_KEYTYPE_EC) {
280- ta->pkey.key.ec.curve = pk->key.ec.curve;
281- ta->pkey.key.ec.qlen = pk->key.ec.qlen;
282- ta->pkey.key.ec.q = emalloc(pk->key.ec.qlen);
283- memcpy(ta->pkey.key.ec.q, pk->key.ec.q, pk->key.ec.qlen);
284- } else {
285- free(accum.data);
286- return 0;
287- }
288- return 1;
289+ br_x509_decoder_context dc;
290+ struct dn_accum accum = { NULL, 0, 0 };
291+ const br_x509_pkey *pk;
292+
293+ br_x509_decoder_init(&dc, append_dn_callback, &accum);
294+ br_x509_decoder_push(&dc, der, der_len);
295+ if (br_x509_decoder_last_error(&dc) != 0) {
296+ free(accum.data);
297+ return 0;
298+ }
299+ pk = br_x509_decoder_get_pkey(&dc);
300+ if (!pk) {
301+ free(accum.data);
302+ return 0;
303+ }
304+
305+ ta->dn.data = accum.data;
306+ ta->dn.len = accum.len;
307+ ta->flags = br_x509_decoder_isCA(&dc) ? BR_X509_TA_CA : 0;
308+ ta->pkey.key_type = pk->key_type;
309+
310+ if (pk->key_type == BR_KEYTYPE_RSA) {
311+ ta->pkey.key.rsa.nlen = pk->key.rsa.nlen;
312+ ta->pkey.key.rsa.n = emalloc(pk->key.rsa.nlen);
313+ memcpy(ta->pkey.key.rsa.n, pk->key.rsa.n, pk->key.rsa.nlen);
314+ ta->pkey.key.rsa.elen = pk->key.rsa.elen;
315+ ta->pkey.key.rsa.e = emalloc(pk->key.rsa.elen);
316+ memcpy(ta->pkey.key.rsa.e, pk->key.rsa.e, pk->key.rsa.elen);
317+ } else if (pk->key_type == BR_KEYTYPE_EC) {
318+ ta->pkey.key.ec.curve = pk->key.ec.curve;
319+ ta->pkey.key.ec.qlen = pk->key.ec.qlen;
320+ ta->pkey.key.ec.q = emalloc(pk->key.ec.qlen);
321+ memcpy(ta->pkey.key.ec.q, pk->key.ec.q, pk->key.ec.qlen);
322+ } else {
323+ free(accum.data);
324+ return 0;
325+ }
326+ return 1;
327 }
328
329 static br_x509_trust_anchor *tas = NULL;
330@@ -216,222 +217,226 @@ static size_t tas_num = 0;
331 static void
332 load_ca_certs(void)
333 {
334- static const char *ca_paths[] = {
335- "/etc/ssl/certs/ca-certificates.crt",
336- "/etc/ssl/cert.pem",
337- "/etc/pki/tls/certs/ca-bundle.crt",
338- };
339- FILE *fp = NULL;
340- size_t i;
341- char line[512];
342- struct {
343- char *data;
344- size_t len;
345- size_t cap;
346- } pem = { NULL, 0, 0 };
347- int in_cert = 0;
348-
349- for (i = 0; i < LEN(ca_paths); i++) {
350- if ((fp = fopen(ca_paths[i], "r")))
351- break;
352- }
353- if (!fp) {
354- weprintf("no CA certificates found, TLS verification will fail\n");
355- return;
356- }
357-
358- while (fgets(line, sizeof(line), fp)) {
359- if (strncmp(line, "-----BEGIN CERTIFICATE-----", 27) == 0) {
360- in_cert = 1;
361- pem.len = 0;
362- } else if (strncmp(line, "-----END CERTIFICATE-----", 25) == 0) {
363- if (in_cert) {
364- unsigned char *der = emalloc(pem.len);
365- size_t der_len = b64_decode(pem.data, pem.len, der);
366- br_x509_trust_anchor ta;
367- if (decode_cert_der(der, der_len, &ta)) {
368- tas = ereallocarray(tas, tas_num + 1, sizeof(*tas));
369- tas[tas_num++] = ta;
370- }
371- free(der);
372- in_cert = 0;
373- }
374- } else if (in_cert) {
375- size_t llen = strlen(line);
376- while (llen > 0 && (line[llen-1] == '\r' || line[llen-1] == '\n'))
377- llen--;
378- if (pem.len + llen > pem.cap) {
379- pem.cap = pem.len + llen + 1024;
380- pem.data = erealloc(pem.data, pem.cap);
381- }
382- memcpy(pem.data + pem.len, line, llen);
383- pem.len += llen;
384- }
385- }
386- free(pem.data);
387- fclose(fp);
388+ static const char *ca_paths[] = {
389+ ARUU_PATH_ETC "/ssl/certs/ca-certificates.crt",
390+ ARUU_PATH_ETC "/ssl/cert.pem",
391+ ARUU_PATH_ETC "/pki/tls/certs/ca-bundle.crt",
392+ };
393+ FILE *fp = NULL;
394+ size_t i;
395+ char line[512];
396+ struct {
397+ char *data;
398+ size_t len;
399+ size_t cap;
400+ } pem = { NULL, 0, 0 };
401+ int in_cert = 0;
402+
403+ for (i = 0; i < LEN(ca_paths); i++) {
404+ if ((fp = fopen(ca_paths[i], "r")))
405+ break;
406+ }
407+ if (!fp) {
408+ weprintf("no CA certificates found, TLS verification will fail\n");
409+ return;
410+ }
411+
412+ while (fgets(line, sizeof(line), fp)) {
413+ if (strncmp(line, "-----BEGIN CERTIFICATE-----", 27) == 0) {
414+ in_cert = 1;
415+ pem.len = 0;
416+ } else if (strncmp(line, "-----END CERTIFICATE-----", 25) == 0) {
417+ if (in_cert) {
418+ unsigned char *der = emalloc(pem.len);
419+ size_t der_len = b64_decode(pem.data, pem.len, der);
420+ br_x509_trust_anchor ta;
421+ if (decode_cert_der(der, der_len, &ta)) {
422+ tas = ereallocarray(tas, tas_num + 1, sizeof(*tas));
423+ tas[tas_num++] = ta;
424+ }
425+ free(der);
426+ in_cert = 0;
427+ }
428+ } else if (in_cert) {
429+ size_t llen = strlen(line);
430+ while (llen > 0 && (line[llen-1] == '\r' || line[llen-1] == '\n'))
431+ llen--;
432+ if (pem.len + llen > pem.cap) {
433+ pem.cap = pem.len + llen + 1024;
434+ pem.data = erealloc(pem.data, pem.cap);
435+ }
436+ memcpy(pem.data + pem.len, line, llen);
437+ pem.len += llen;
438+ }
439+ }
440+ free(pem.data);
441+ fclose(fp);
442 }
443 #else
444 struct TlsSocket {
445- int fd;
446- int is_tls;
447+ int fd;
448+ int is_tls;
449 };
450 #endif
451
452 struct TlsSocket *
453 tls_connect(int fd, const char *host, int check_cert, int is_tls)
454 {
455- struct TlsSocket *s;
456+ struct TlsSocket *s;
457
458- s = emalloc(sizeof(*s));
459- s->fd = fd;
460- s->is_tls = is_tls;
461+ s = emalloc(sizeof(*s));
462+ s->fd = fd;
463+ s->is_tls = is_tls;
464
465- if (!is_tls)
466- return s;
467+ if (!is_tls)
468+ return s;
469+#if !FEATURE_USE_LIBRESSL && !FEATURE_USE_BEARSSL && !FEATURE_USE_OPENSSL
470+ (void)host;
471+ (void)check_cert;
472+#endif
473
474 #if FEATURE_USE_LIBRESSL
475- {
476- struct tls_config *cfg;
477-
478- s->ctx = tls_client();
479- if (!s->ctx) {
480- weprintf("tls_client failed\n");
481- free(s);
482- return NULL;
483- }
484- cfg = tls_config_new();
485- if (!cfg) {
486- weprintf("tls_config_new failed\n");
487- tls_free(s->ctx);
488- free(s);
489- return NULL;
490- }
491- if (!check_cert) {
492- tls_config_insecure_noverifycert(cfg);
493- tls_config_insecure_noverifyname(cfg);
494- }
495- if (tls_configure(s->ctx, cfg) < 0) {
496- weprintf("tls_configure: %s\n", tls_error(s->ctx));
497- tls_config_free(cfg);
498- tls_free(s->ctx);
499- free(s);
500- return NULL;
501- }
502- tls_config_free(cfg);
503-
504- if (tls_connect_socket(s->ctx, fd, host) < 0) {
505- weprintf("tls_connect_socket: %s\n", tls_error(s->ctx));
506- tls_free(s->ctx);
507- free(s);
508- return NULL;
509- }
510- }
511+ {
512+ struct tls_config *cfg;
513+
514+ s->ctx = tls_client();
515+ if (!s->ctx) {
516+ weprintf("tls_client failed\n");
517+ free(s);
518+ return NULL;
519+ }
520+ cfg = tls_config_new();
521+ if (!cfg) {
522+ weprintf("tls_config_new failed\n");
523+ tls_free(s->ctx);
524+ free(s);
525+ return NULL;
526+ }
527+ if (!check_cert) {
528+ tls_config_insecure_noverifycert(cfg);
529+ tls_config_insecure_noverifyname(cfg);
530+ }
531+ if (tls_configure(s->ctx, cfg) < 0) {
532+ weprintf("tls_configure: %s\n", tls_error(s->ctx));
533+ tls_config_free(cfg);
534+ tls_free(s->ctx);
535+ free(s);
536+ return NULL;
537+ }
538+ tls_config_free(cfg);
539+
540+ if (tls_connect_socket(s->ctx, fd, host) < 0) {
541+ weprintf("tls_connect_socket: %s\n", tls_error(s->ctx));
542+ tls_free(s->ctx);
543+ free(s);
544+ return NULL;
545+ }
546+ }
547 #elif FEATURE_USE_BEARSSL
548- {
549- signal(SIGPIPE, SIG_IGN);
550-
551- if (check_cert) {
552- static int ca_loaded = 0;
553- if (!ca_loaded) {
554- load_ca_certs();
555- ca_loaded = 1;
556- }
557- br_ssl_client_init_full(&s->sc, &s->my_x509.minimal, tas, tas_num);
558- } else {
559- br_ssl_client_init_full(&s->sc, &s->my_x509.minimal, NULL, 0);
560- s->my_x509.vtable = &my_x509_vtable;
561- br_ssl_engine_set_x509(&s->sc.eng, &s->my_x509.vtable);
562- }
563-
564- br_ssl_engine_set_buffer(&s->sc.eng, s->iobuf, sizeof(s->iobuf), 1);
565- br_ssl_client_reset(&s->sc, host, 0);
566- br_sslio_init(&s->ioc, &s->sc.eng, sock_read, &s->fd, sock_write, &s->fd);
567-
568- if (br_sslio_flush(&s->ioc) < 0) {
569- weprintf("TLS handshake failed with %s\n", host);
570- free(s);
571- return NULL;
572- }
573- }
574+ {
575+ signal(SIGPIPE, SIG_IGN);
576+
577+ if (check_cert) {
578+ static int ca_loaded = 0;
579+ if (!ca_loaded) {
580+ load_ca_certs();
581+ ca_loaded = 1;
582+ }
583+ br_ssl_client_init_full(&s->sc, &s->my_x509.minimal, tas, tas_num);
584+ } else {
585+ br_ssl_client_init_full(&s->sc, &s->my_x509.minimal, NULL, 0);
586+ s->my_x509.vtable = &my_x509_vtable;
587+ br_ssl_engine_set_x509(&s->sc.eng, &s->my_x509.vtable);
588+ }
589+
590+ br_ssl_engine_set_buffer(&s->sc.eng, s->iobuf, sizeof(s->iobuf), 1);
591+ br_ssl_client_reset(&s->sc, host, 0);
592+ br_sslio_init(&s->ioc, &s->sc.eng, sock_read, &s->fd, sock_write, &s->fd);
593+
594+ if (br_sslio_flush(&s->ioc) < 0) {
595+ weprintf("TLS handshake failed with %s\n", host);
596+ free(s);
597+ return NULL;
598+ }
599+ }
600 #else
601- weprintf("TLS not supported, compile with FEATURE_USE_LIBRESSL or FEATURE_USE_BEARSSL\n");
602- free(s);
603- return NULL;
604+ weprintf("TLS not supported, compile with FEATURE_USE_LIBRESSL or FEATURE_USE_BEARSSL\n");
605+ free(s);
606+ return NULL;
607 #endif
608
609- return s;
610+ return s;
611 }
612
613 ssize_t
614 tls_read(struct TlsSocket *s, void *buf, size_t len)
615 {
616- if (!s->is_tls) {
617- for (;;) {
618- ssize_t r = read(s->fd, buf, len);
619- if (r < 0 && errno == EINTR)
620- continue;
621- return r;
622- }
623- }
624+ if (!s->is_tls) {
625+ for (;;) {
626+ ssize_t r = read(s->fd, buf, len);
627+ if (r < 0 && errno == EINTR)
628+ continue;
629+ return r;
630+ }
631+ }
632 #if FEATURE_USE_LIBRESSL
633- for (;;) {
634- ssize_t r = tls_read(s->ctx, buf, len);
635- if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT)
636- continue;
637- return r;
638- }
639+ for (;;) {
640+ ssize_t r = tls_read(s->ctx, buf, len);
641+ if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT)
642+ continue;
643+ return r;
644+ }
645 #elif FEATURE_USE_BEARSSL
646- return br_sslio_read(&s->ioc, buf, len);
647+ return br_sslio_read(&s->ioc, buf, len);
648 #else
649- return -1;
650+ return -1;
651 #endif
652 }
653
654 ssize_t
655 tls_write(struct TlsSocket *s, const void *buf, size_t len)
656 {
657- if (!s->is_tls) {
658- for (;;) {
659- ssize_t r = write(s->fd, buf, len);
660- if (r < 0 && errno == EINTR)
661- continue;
662- return r;
663- }
664- }
665+ if (!s->is_tls) {
666+ for (;;) {
667+ ssize_t r = write(s->fd, buf, len);
668+ if (r < 0 && errno == EINTR)
669+ continue;
670+ return r;
671+ }
672+ }
673 #if FEATURE_USE_LIBRESSL
674- for (;;) {
675- ssize_t r = tls_write(s->ctx, buf, len);
676- if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT)
677- continue;
678- return r;
679- }
680+ for (;;) {
681+ ssize_t r = tls_write(s->ctx, buf, len);
682+ if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT)
683+ continue;
684+ return r;
685+ }
686 #elif FEATURE_USE_BEARSSL
687- {
688- int r = br_sslio_write_all(&s->ioc, buf, len);
689- if (r < 0)
690- return -1;
691- if (br_sslio_flush(&s->ioc) < 0)
692- return -1;
693- return len;
694- }
695+ {
696+ int r = br_sslio_write_all(&s->ioc, buf, len);
697+ if (r < 0)
698+ return -1;
699+ if (br_sslio_flush(&s->ioc) < 0)
700+ return -1;
701+ return len;
702+ }
703 #else
704- return -1;
705+ return -1;
706 #endif
707 }
708
709 void
710 tls_close(struct TlsSocket *s, int close_fd)
711 {
712- if (s->is_tls) {
713+ if (s->is_tls) {
714 #if FEATURE_USE_LIBRESSL
715- tls_close(s->ctx);
716- tls_free(s->ctx);
717+ tls_close(s->ctx);
718+ tls_free(s->ctx);
719 #elif FEATURE_USE_BEARSSL
720- br_sslio_close(&s->ioc);
721+ br_sslio_close(&s->ioc);
722 #endif
723- }
724- if (close_fd)
725- close(s->fd);
726- free(s);
727+ }
728+ if (close_fd)
729+ close(s->fd);
730+ free(s);
731 }
1@@ -11,88 +11,89 @@
2 #include <string.h>
3 #include <unistd.h>
4
5+#include "../paths.h"
6 #include "../util.h"
7
8 void
9 devtotty(int dev, int *tty_maj, int *tty_min)
10 {
11- *tty_maj = (dev >> 8) & 0xfff;
12- *tty_min = (dev & 0xff) | ((dev >> 12) & 0xfff00);
13+ *tty_maj = (dev >> 8) & 0xfff;
14+ *tty_min = (dev & 0xff) | ((dev >> 12) & 0xfff00);
15 }
16
17 int
18 ttytostr(int tty_maj, int tty_min, char *str, size_t n)
19 {
20- struct stat sb;
21- struct dirent *dp;
22- DIR *dirp;
23- char path[PATH_MAX];
24- int fd;
25- int r = 0;
26+ struct stat sb;
27+ struct dirent *dp;
28+ DIR *dirp;
29+ char path[PATH_MAX];
30+ int fd;
31+ int r = 0;
32
33- switch (tty_maj) {
34- case 136:
35- snprintf(str, n, "pts/%d", tty_min);
36- return 0;
37- case 4:
38- snprintf(str, n, "tty%d", tty_min);
39- return 0;
40- default:
41- str[0] = '?';
42- str[1] = '\0';
43- break;
44- }
45+ switch (tty_maj) {
46+ case 136:
47+ snprintf(str, n, "pts/%d", tty_min);
48+ return 0;
49+ case 4:
50+ snprintf(str, n, "tty%d", tty_min);
51+ return 0;
52+ default:
53+ str[0] = '?';
54+ str[1] = '\0';
55+ break;
56+ }
57
58- dirp = opendir("/dev");
59- if (!dirp) {
60- weprintf("opendir /dev:");
61- return -1;
62- }
63+ dirp = opendir("/dev");
64+ if (!dirp) {
65+ weprintf("opendir /dev:");
66+ return -1;
67+ }
68
69- while ((dp = readdir(dirp))) {
70- if (!strcmp(dp->d_name, ".") ||
71- !strcmp(dp->d_name, ".."))
72- continue;
73+ while ((dp = readdir(dirp))) {
74+ if (!strcmp(dp->d_name, ".") ||
75+ !strcmp(dp->d_name, ".."))
76+ continue;
77
78- if (strlcpy(path, "/dev/", sizeof(path)) >= sizeof(path)) {
79- weprintf("path too long\n");
80- r = -1;
81- goto err0;
82- }
83- if (strlcat(path, dp->d_name, sizeof(path)) >= sizeof(path)) {
84- weprintf("path too long\n");
85- r = -1;
86- goto err0;
87- }
88+ if (strlcpy(path, ARUU_PATH_DEV "/", sizeof(path)) >= sizeof(path)) {
89+ weprintf("path too long\n");
90+ r = -1;
91+ goto err0;
92+ }
93+ if (strlcat(path, dp->d_name, sizeof(path)) >= sizeof(path)) {
94+ weprintf("path too long\n");
95+ r = -1;
96+ goto err0;
97+ }
98
99- if (stat(path, &sb) < 0) {
100- weprintf("stat %s:", path);
101- r = -1;
102- goto err0;
103- }
104+ if (stat(path, &sb) < 0) {
105+ weprintf("stat %s:", path);
106+ r = -1;
107+ goto err0;
108+ }
109
110- if ((int)major(sb.st_rdev) == tty_maj &&
111- (int)minor(sb.st_rdev) == tty_min) {
112- fd = open(path, O_RDONLY | O_NONBLOCK);
113- if (fd < 0)
114- continue;
115- if (isatty(fd)) {
116- strlcpy(str, dp->d_name, n);
117- close(fd);
118- break;
119- } else {
120- close(fd);
121- r = -1;
122- goto err0;
123- }
124- }
125- }
126+ if ((int)major(sb.st_rdev) == tty_maj &&
127+ (int)minor(sb.st_rdev) == tty_min) {
128+ fd = open(path, O_RDONLY | O_NONBLOCK);
129+ if (fd < 0)
130+ continue;
131+ if (isatty(fd)) {
132+ strlcpy(str, dp->d_name, n);
133+ close(fd);
134+ break;
135+ } else {
136+ close(fd);
137+ r = -1;
138+ goto err0;
139+ }
140+ }
141+ }
142
143 err0:
144- if (closedir(dirp) < 0) {
145- weprintf("closedir /dev:");
146- r = -1;
147- }
148+ if (closedir(dirp) < 0) {
149+ weprintf("closedir /dev:");
150+ r = -1;
151+ }
152
153- return r;
154+ return r;
155 }
1@@ -0,0 +1,343 @@
2+/* See LICENSE file for copyright and license details. */
3+#include "../config.h"
4+#include "../wexec.h"
5+#include "../paths.h"
6+#include "../util.h"
7+
8+#include <errno.h>
9+#include <signal.h>
10+#include <stdlib.h>
11+#include <string.h>
12+#include <sys/wait.h>
13+#include <unistd.h>
14+
15+#define MAX_BUILTINS 128
16+#define MAX_POPEN 32
17+
18+struct builtin {
19+ const char *name;
20+ wexec_fn fn;
21+};
22+
23+static struct builtin builtins[MAX_BUILTINS];
24+static int nbuiltins;
25+
26+struct popen_entry {
27+ FILE *fp;
28+ pid_t pid;
29+};
30+
31+static struct popen_entry popen_tab[MAX_POPEN];
32+static int npopen;
33+
34+int
35+wpopen_track(FILE *fp, pid_t pid)
36+{
37+ if (npopen >= MAX_POPEN)
38+ return -1;
39+ popen_tab[npopen].fp = fp;
40+ popen_tab[npopen].pid = pid;
41+ npopen++;
42+ return 0;
43+}
44+
45+pid_t
46+wpopen_untrack(FILE *fp)
47+{
48+ int i;
49+ pid_t pid = -1;
50+ for (i = 0; i < npopen; i++) {
51+ if (popen_tab[i].fp == fp) {
52+ pid = popen_tab[i].pid;
53+ popen_tab[i] = popen_tab[npopen - 1];
54+ npopen--;
55+ break;
56+ }
57+ }
58+ return pid;
59+}
60+
61+int
62+wexec_register(const char *name, wexec_fn fn)
63+{
64+ int i;
65+ for (i = 0; i < nbuiltins; i++) {
66+ if (strcmp(builtins[i].name, name) == 0)
67+ return -1;
68+ }
69+ if (nbuiltins >= MAX_BUILTINS)
70+ return -1;
71+ builtins[nbuiltins].name = name;
72+ builtins[nbuiltins].fn = fn;
73+ nbuiltins++;
74+ return 0;
75+}
76+
77+int
78+wexec_is_builtin(const char *name)
79+{
80+ int i;
81+ for (i = 0; i < nbuiltins; i++) {
82+ if (strcmp(builtins[i].name, name) == 0)
83+ return 1;
84+ }
85+ return 0;
86+}
87+
88+#if FEATURE_INPROC_EXEC
89+static int
90+call_builtin(const char *name, char *const *argv)
91+{
92+ int i, argc;
93+ char **p;
94+
95+ argc = 0;
96+ for (p = (char **)argv; *p; p++)
97+ argc++;
98+ for (i = 0; i < nbuiltins; i++) {
99+ if (strcmp(builtins[i].name, name) == 0) {
100+ fflush(stdout);
101+ fflush(stderr);
102+ return builtins[i].fn(argc, (char **)argv);
103+ }
104+ }
105+ return -1;
106+}
107+#endif
108+
109+static int
110+fork_exec(const char *path, char *const *argv, int use_path)
111+{
112+ pid_t pid;
113+ int st;
114+
115+ pid = fork();
116+ if (pid < 0) {
117+ weprintf("fork:");
118+ return -1;
119+ }
120+ if (pid == 0) {
121+ if (use_path)
122+ execvp(path, argv);
123+ else
124+ execv(path, argv);
125+ _exit(127);
126+ }
127+ if (waitpid(pid, &st, 0) < 0) {
128+ weprintf("waitpid:");
129+ return -1;
130+ }
131+ if (WIFEXITED(st))
132+ return WEXITSTATUS(st);
133+ if (WIFSIGNALED(st))
134+ return 128 + WTERMSIG(st);
135+ return -1;
136+}
137+
138+int
139+wexecvp(const char *name, char *const *argv)
140+{
141+#if FEATURE_INPROC_EXEC
142+ if (wexec_is_builtin(name)) {
143+ fflush(stdout);
144+ fflush(stderr);
145+ return call_builtin(name, argv);
146+ }
147+#endif
148+ return fork_exec(name, argv, 1);
149+}
150+
151+int
152+wexecv(const char *path, char *const *argv)
153+{
154+#if FEATURE_INPROC_EXEC
155+ {
156+ const char *base = strrchr(path, '/');
157+ base = base ? base + 1 : path;
158+ if (wexec_is_builtin(base)) {
159+ fflush(stdout);
160+ fflush(stderr);
161+ return call_builtin(base, argv);
162+ }
163+ }
164+#endif
165+ return fork_exec(path, argv, 0);
166+}
167+
168+FILE *
169+wpopen(const char *name, char *const *argv, const char *mode)
170+{
171+ int pfd[2];
172+ pid_t pid;
173+ int parent_end, child_end;
174+ char *sh_argv[4];
175+
176+ if (pipe(pfd) < 0) {
177+ weprintf("pipe:");
178+ return NULL;
179+ }
180+
181+ if (*mode == 'r') {
182+ parent_end = pfd[0];
183+ child_end = pfd[1];
184+ } else {
185+ parent_end = pfd[1];
186+ child_end = pfd[0];
187+ }
188+
189+ pid = fork();
190+ if (pid < 0) {
191+ weprintf("fork:");
192+ close(pfd[0]);
193+ close(pfd[1]);
194+ return NULL;
195+ }
196+
197+ if (pid == 0) {
198+ close(parent_end);
199+ if (child_end != (*mode == 'r' ? STDOUT_FILENO : STDIN_FILENO)) {
200+ dup2(child_end, *mode == 'r' ? STDOUT_FILENO : STDIN_FILENO);
201+ close(child_end);
202+ }
203+ if (argv) {
204+#if FEATURE_INPROC_EXEC
205+ if (wexec_is_builtin(name)) {
206+ int argc;
207+ char **p;
208+ argc = 0;
209+ for (p = (char **)argv; *p; p++)
210+ argc++;
211+ call_builtin(name, argv);
212+ fflush(stdout);
213+ fflush(stderr);
214+ _exit(0);
215+ }
216+#endif
217+ execvp(name, argv);
218+ _exit(127);
219+ } else {
220+ sh_argv[0] = "sh";
221+ sh_argv[1] = "-c";
222+ sh_argv[2] = (char *)name;
223+ sh_argv[3] = NULL;
224+#if FEATURE_INPROC_EXEC
225+ if (wexec_is_builtin("sh")) {
226+ call_builtin("sh", sh_argv);
227+ fflush(stdout);
228+ fflush(stderr);
229+ _exit(0);
230+ }
231+#endif
232+ execvp("sh", sh_argv);
233+ _exit(127);
234+ }
235+ }
236+
237+ close(child_end);
238+ {
239+ FILE *fp = fdopen(parent_end, mode);
240+ if (!fp) {
241+ weprintf("fdopen:");
242+ close(parent_end);
243+ kill(pid, SIGTERM);
244+ waitpid(pid, NULL, 0);
245+ return NULL;
246+ }
247+ if (wpopen_track(fp, pid) < 0) {
248+ fclose(fp);
249+ kill(pid, SIGTERM);
250+ waitpid(pid, NULL, 0);
251+ return NULL;
252+ }
253+ return fp;
254+ }
255+}
256+
257+int
258+wpclose(FILE *fp)
259+{
260+ int st;
261+ pid_t pid;
262+
263+ pid = wpopen_untrack(fp);
264+ if (fclose(fp) == EOF)
265+ weprintf("fclose:");
266+ if (pid < 0)
267+ return -1;
268+ if (waitpid(pid, &st, 0) < 0) {
269+ weprintf("waitpid:");
270+ return -1;
271+ }
272+ if (WIFEXITED(st))
273+ return WEXITSTATUS(st);
274+ if (WIFSIGNALED(st))
275+ return 128 + WTERMSIG(st);
276+ return -1;
277+}
278+
279+int
280+wsystem(const char *cmd)
281+{
282+#if FEATURE_INPROC_EXEC
283+ if (wexec_is_builtin("sh")) {
284+ char *sh_argv[4];
285+ sh_argv[0] = "sh";
286+ sh_argv[1] = "-c";
287+ sh_argv[2] = (char *)cmd;
288+ sh_argv[3] = NULL;
289+ return wexecvp("sh", sh_argv);
290+ }
291+#endif
292+ {
293+ char *sh_argv[4];
294+ int ret;
295+ sh_argv[0] = "sh";
296+ sh_argv[1] = "-c";
297+ sh_argv[2] = (char *)cmd;
298+ sh_argv[3] = NULL;
299+ ret = fork_exec("sh", sh_argv, 1);
300+ return ret;
301+ }
302+}
303+
304+void
305+wexecvp_self(const char *name, char *const *argv)
306+{
307+#if FEATURE_INPROC_EXEC
308+ if (wexec_is_builtin(name)) {
309+ int ret;
310+ fflush(stdout);
311+ fflush(stderr);
312+ ret = call_builtin(name, argv);
313+ fflush(stdout);
314+ fflush(stderr);
315+ exit(ret);
316+ }
317+#endif
318+ execvp(name, argv);
319+ weprintf("execvp %s:", name);
320+ exit((errno == ENOENT) ? 127 : 126);
321+}
322+
323+void
324+wexecv_self(const char *path, char *const *argv)
325+{
326+#if FEATURE_INPROC_EXEC
327+ {
328+ const char *base = strrchr(path, '/');
329+ base = base ? base + 1 : path;
330+ if (wexec_is_builtin(base)) {
331+ int ret;
332+ fflush(stdout);
333+ fflush(stderr);
334+ ret = call_builtin(base, argv);
335+ fflush(stdout);
336+ fflush(stderr);
337+ exit(ret);
338+ }
339+ }
340+#endif
341+ execv(path, argv);
342+ weprintf("execv %s:", path);
343+ exit((errno == ENOENT) ? 127 : 126);
344+}
1@@ -1,4 +1,25 @@
2 /* See LICENSE file for copyright and license details. */
3-/* passwd.c */
4-int pw_check(const struct passwd *, const char *);
5+#ifndef ARUU_PASSWD_H
6+#define ARUU_PASSWD_H
7+
8+#include <pwd.h>
9+#include <sys/types.h>
10+
11+struct pwdb_entry {
12+ char *name;
13+ char *hash;
14+ uid_t uid;
15+ gid_t gid;
16+};
17+
18 int pw_init(void);
19+int pw_check(const struct passwd *pw, const char *pass);
20+int pwdb_lookup(struct pwdb_entry *ent, const char *name);
21+
22+#define PW_SALT_MAX 64
23+int pw_gensalt(char *salt, size_t salt_sz);
24+int pw_gensalt_cipher(char *salt, size_t salt_sz, const char *prefix,
25+ size_t rand_len);
26+int pwdb_update(const char *name, const char *newhash);
27+
28+#endif
1@@ -0,0 +1,96 @@
2+/* See LICENSE file for copyright and license details. */
3+#ifndef ARUU_PATHS_H
4+#define ARUU_PATHS_H
5+
6+/*
7+ * portable paths. override at compile time for non-FHS systems:
8+ * -DARUU_PATH_ETC="/config"
9+ *
10+ * OS-specific paths (procfs, sysfs) are prefixed ARUU_LINUX_PATH_*
11+ * and only defined under __linux__. a util that reads /proc/modules
12+ * will fail to compile on BSD because ARUU_LINUX_PATH_PROC is not
13+ * defined there. this is intentional: the BSD code path must use
14+ * a different mechanism (sysctl, getmntinfo, etc)
15+ */
16+
17+#ifndef ARUU_PATH_ETC
18+#define ARUU_PATH_ETC "/etc"
19+#endif
20+
21+#ifndef ARUU_PATH_VAR
22+#define ARUU_PATH_VAR "/var"
23+#endif
24+
25+#ifndef ARUU_PATH_DEV
26+#define ARUU_PATH_DEV "/dev"
27+#endif
28+
29+#ifndef ARUU_PATH_RUN
30+#define ARUU_PATH_RUN "/run"
31+#endif
32+
33+#ifndef ARUU_PATH_TMP
34+#define ARUU_PATH_TMP "/tmp"
35+#endif
36+
37+#ifndef ARUU_PATH_BIN
38+#define ARUU_PATH_BIN "/bin"
39+#endif
40+
41+#ifndef ARUU_PATH_SBIN
42+#define ARUU_PATH_SBIN "/sbin"
43+#endif
44+
45+#ifndef ARUU_PATH_USR_BIN
46+#define ARUU_PATH_USR_BIN "/usr/bin"
47+#endif
48+
49+#ifndef ARUU_PATH_USR_SBIN
50+#define ARUU_PATH_USR_SBIN "/usr/sbin"
51+#endif
52+
53+#define ARUU_PATH_PASSWD ARUU_PATH_ETC "/passwd"
54+#define ARUU_PATH_SHADOW ARUU_PATH_ETC "/shadow"
55+#define ARUU_PATH_GROUP ARUU_PATH_ETC "/group"
56+#define ARUU_PATH_DEVNULL ARUU_PATH_DEV "/null"
57+#define ARUU_PATH_DEVURANDOM ARUU_PATH_DEV "/urandom"
58+#define ARUU_PATH_DEVRANDOM ARUU_PATH_DEV "/random"
59+#define ARUU_PATH_DEVTTY ARUU_PATH_DEV "/tty"
60+#define ARUU_PATH_DEVCONSOLE ARUU_PATH_DEV "/console"
61+#define ARUU_PATH_UTMP ARUU_PATH_RUN "/utmp"
62+#define ARUU_PATH_WTMP ARUU_PATH_VAR "/log/wtmp"
63+#define ARUU_PATH_BTMP ARUU_PATH_VAR "/log/btmp"
64+#define ARUU_PATH_LASTLOG ARUU_PATH_VAR "/log/lastlog"
65+#define ARUU_PATH_BSHELL ARUU_PATH_BIN "/sh"
66+#define ARUU_PATH_STDPATH ARUU_PATH_BIN ":/usr/bin"
67+#define ARUU_PATH_DEFPATH ARUU_PATH_BIN ":/usr/bin"
68+
69+#if defined(__linux__)
70+#define ARUU_LINUX_PATH_PROC "/proc"
71+#define ARUU_LINUX_PATH_SYS "/sys"
72+#define ARUU_LINUX_PATH_PROC_MOUNTS ARUU_LINUX_PATH_PROC "/mounts"
73+#define ARUU_LINUX_PATH_PROC_PARTITIONS ARUU_LINUX_PATH_PROC "/partitions"
74+#define ARUU_LINUX_PATH_PROC_MEMINFO ARUU_LINUX_PATH_PROC "/meminfo"
75+#define ARUU_LINUX_PATH_PROC_LOADAVG ARUU_LINUX_PATH_PROC "/loadavg"
76+#define ARUU_LINUX_PATH_PROC_CMDLINE ARUU_LINUX_PATH_PROC "/cmdline"
77+#define ARUU_LINUX_PATH_PROC_VERSION ARUU_LINUX_PATH_PROC "/version"
78+#define ARUU_LINUX_PATH_PROC_MODULES ARUU_LINUX_PATH_PROC "/modules"
79+#define ARUU_LINUX_PATH_PROC_SYS ARUU_LINUX_PATH_PROC "/sys"
80+#define ARUU_LINUX_PATH_SYS_MODULE ARUU_LINUX_PATH_SYS "/module"
81+#define ARUU_LINUX_PATH_SYS_BLOCK ARUU_LINUX_PATH_SYS "/block"
82+#define ARUU_LINUX_PATH_SYS_CLASS_NET ARUU_LINUX_PATH_SYS "/class/net"
83+#define ARUU_LINUX_PATH_SYS_KERNEL ARUU_LINUX_PATH_SYS "/kernel"
84+#define ARUU_LINUX_PATH_SYS_BUS_USB ARUU_LINUX_PATH_SYS "/bus/usb/devices"
85+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
86+/* BSD systems do not have procfs or sysfs. utils that need this data
87+ * must use sysctl(3), getmntinfo(3), or kvm(3) instead */
88+#else
89+#error "paths.h: unsupported platform. define ARUU_LINUX_PATH_* or ARUU_BSD_PATH_* manually"
90+#endif
91+
92+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
93+#define ARUU_BSD_PATH_MASTER_PASSWD ARUU_PATH_ETC "/master.passwd"
94+#define ARUU_BSD_PATH_PWD_MKDB ARUU_PATH_USR_SBIN "/pwd_mkdb"
95+#endif
96+
97+#endif
1@@ -116,45 +116,45 @@ int ttytostr(int, int, char *, size_t);
2 #endif
3
4 struct NetStats {
5- unsigned long long rx_bytes;
6- unsigned long long rx_packets;
7- unsigned long long rx_errs;
8- unsigned long long rx_drop;
9- unsigned long long tx_bytes;
10- unsigned long long tx_packets;
11- unsigned long long tx_errs;
12- unsigned long long tx_drop;
13+ unsigned long long rx_bytes;
14+ unsigned long long rx_packets;
15+ unsigned long long rx_errs;
16+ unsigned long long rx_drop;
17+ unsigned long long tx_bytes;
18+ unsigned long long tx_packets;
19+ unsigned long long tx_errs;
20+ unsigned long long tx_drop;
21 };
22
23 struct NetInterface {
24- char name[IFNAMSIZ];
25- unsigned int flags;
26- int mtu;
27- int metric;
28- unsigned char mac[6];
29- int has_mac;
30-
31- /* ipv4 addresses */
32- struct sockaddr_in ipv4_addr;
33- int has_ipv4;
34- struct sockaddr_in ipv4_mask;
35- struct sockaddr_in ipv4_brd;
36-
37- /* ipv6 addresses */
38- struct sockaddr_in6 ipv6_addr;
39- int has_ipv6;
40- unsigned int ipv6_scope;
41- unsigned int ipv6_prefix;
42+ char name[IFNAMSIZ];
43+ unsigned int flags;
44+ int mtu;
45+ int metric;
46+ unsigned char mac[6];
47+ int has_mac;
48+
49+ /* ipv4 addresses */
50+ struct sockaddr_in ipv4_addr;
51+ int has_ipv4;
52+ struct sockaddr_in ipv4_mask;
53+ struct sockaddr_in ipv4_brd;
54+
55+ /* ipv6 addresses */
56+ struct sockaddr_in6 ipv6_addr;
57+ int has_ipv6;
58+ unsigned int ipv6_scope;
59+ unsigned int ipv6_prefix;
60 };
61
62 struct MemInfo {
63- unsigned long long total;
64- unsigned long long free;
65- unsigned long long shared;
66- unsigned long long buffers;
67- unsigned long long cached;
68- unsigned long long totalswap;
69- unsigned long long freeswap;
70+ unsigned long long total;
71+ unsigned long long free;
72+ unsigned long long shared;
73+ unsigned long long buffers;
74+ unsigned long long cached;
75+ unsigned long long totalswap;
76+ unsigned long long freeswap;
77 };
78
79 int net_get_interfaces(struct NetInterface **, int *);
1@@ -0,0 +1,27 @@
2+/* See LICENSE file for copyright and license details. */
3+#ifndef ARUU_WEXEC_H
4+#define ARUU_WEXEC_H
5+
6+#include <stdio.h>
7+#include <sys/types.h>
8+
9+typedef int (*wexec_fn)(int argc, char **argv);
10+
11+int wexec_register(const char *name, wexec_fn fn);
12+int wexec_is_builtin(const char *name);
13+
14+int wexecvp(const char *name, char *const *argv);
15+int wexecv(const char *path, char *const *argv);
16+
17+FILE *wpopen(const char *name, char *const *argv, const char *mode);
18+int wpclose(FILE *fp);
19+
20+int wsystem(const char *cmd);
21+
22+void wexecvp_self(const char *name, char *const *argv);
23+void wexecv_self(const char *path, char *const *argv);
24+
25+int wpopen_track(FILE *fp, pid_t pid);
26+pid_t wpopen_untrack(FILE *fp);
27+
28+#endif