aboutsummaryrefslogtreecommitdiff
path: root/scripts/Menuconfig (unfollow)
Commit message (Collapse)AuthorFilesLines
3 daysstat: use correct format for time valuesRon Yorston1-3/+3
Upstream commit a61d158d5 (stat: fix negative %X/%Y/%Z timestamps after Y2038 on 32-bit builds) changed how timestamps are printed. Update the code to use the correct format specifiers on Windows. Signed-off-by: Ron Yorston <rmy@pobox.com>
5 daysPost-merge fixesRon Yorston3-1/+9
Signed-off-by: Ron Yorston <rmy@pobox.com>
8 dayssort: compute -k END.ENDCHAR from the end field, not the line startbusyboxAli Ahmet Memis2-6/+23
get_key() locates a key in two passes: j=0 walks to the start of the START field, j=1 walks to the end of the END field. When END carries an ENDCHAR (-kSTART,N.ENDCHAR), that char position is supposed to be counted from the start of field N. Instead the code overwrote 'end' with the raw parsed value, an offset from the very start of the line: if (key->range[3]) { end = key->range[3]; For END field 1 this happens to be the same thing, but for any later field it is not. The result usually lands before 'start', which then gets clamped to 'start', producing an empty key. Sort has an ASCII whole-line fallback when keys tie, so it silently sorts by the whole line instead of the requested key: $ printf '%s\n' 'b:aa' 'a:ba' 'a:aa' | busybox sort -t : -k 2.1,2.1 a:aa a:ba b:aa $ printf '%s\n' 'b:aa' 'a:ba' 'a:aa' | sort -t : -k 2.1,2.1 a:aa b:aa a:ba Make the j=1 pass stop at the start of field N instead of its end when ENDCHAR is given, one field-skip short of the usual pass, and add the ENDCHAR offset from there. This mirrors how STARTCHAR is already applied relative to the start of the START field. Verified against several -k combinations (endchar past the field's own length, multiple fields skipped, startchar and endchar together) matching GNU sort. Add a regression test; the existing ENDCHAR test only exercises field 1, where the old absolute offset and the correct field-relative one happen to coincide. function old new delta get_key 490 516 +26 Signed-off-by: Ali Ahmet Memis <ali@iusegentoo.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
8 daysplatform.h: UNINITIALIZED_VAR() macro for suppressing gcc warningsDenys Vlasenko4-13/+29
With gcc-15.0.1: function old new delta tftpd_main 603 617 +14 expand_one_var 1923 1929 +6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 20/0) Total: 20 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
8 daysvi: explain what vim 9.2 is doing with ":e FILE" escapingDenys Vlasenko1-1/+7
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
9 daysvi: code shrinkDenys Vlasenko1-3/+1
function old new delta expand_args 186 181 -5 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
9 daysinetd: build fix if RPC is selected in .configDenys Vlasenko1-1/+1
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
9 daysdevfsd: heed warningsDenys Vlasenko1-2/+2
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
9 dayshush: heed warnings about strchr() returning const char*Denys Vlasenko1-3/+3
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
9 days*: selinux: replace deprecated security_context_t with char*Denys Vlasenko18-37/+37
Suppresses a lot of selinux warnings. This does not change the code. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
9 dayshdparm: fix ATA identification string outputRomain Guyard2-1/+52
print_ascii() is intended to skip leading spaces before printing ATA IDENTIFY strings, but the condition is inverted and skips non-space characters instead. As a result, left-justified strings such as serial numbers and firmware revisions can be printed as empty, while strings containing embedded spaces, such as model names, are truncated up to the first space. Fix the condition so only leading spaces are skipped, and add a regression test covering left-justified strings, embedded spaces, and leading-space padding. function old new delta ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0) Total: 0 bytes Signed-off-by: Romain Guyard <foss@romainguyard.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
9 daysawk: disallow OFMT/CONVFMT to have more than one %SPEC, implement %sDenys Vlasenko2-6/+75
function old new delta fmt_num 257 380 +123 .rodata 107332 107342 +10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 133/0) Total: 133 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
9 daystar: Sanitize verbose file namesAnton Skorup1-1/+1
function old new delta writeTarHeader 859 869 +10 Signed-off-by: Anton Skorup <anton.skorup@axis.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-08-24awk: fix 1-byte heap-buffer-overflow in next_token() string parseEdiz1-16/+33
When the awk program ends with \<newline> right after the last string token, nextchar() eats the newline and then reads the terminating NUL that xmalloc_read_with_initial_buf() appends, advancing past the end of the buffer. The string-scan loop in next_token() then dereferences one byte past the buffer (heap-buffer-overflow, READ of size 1). Fix: test every nextchar() return for NULs. Reproducer (ASan build): awk 'BEGIN { print "string\ ' function old new delta next_token 934 933 -1 Signed-off-by: Ediz <ediz.research@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-08-24stat: code shrinkDenys Vlasenko1-72/+78
function old new delta printf_llu - 35 +35 printf_lx - 30 +30 printf_lu - 30 +30 printf_s - 28 +28 printfs 28 - -28 print_statfs 338 260 -78 print_stat 858 761 -97 ------------------------------------------------------------------------------ (add/remove: 4/1 grow/shrink: 0/2 up/down: 123/-203) Total: -80 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-08-24stat: fix negative %X/%Y/%Z timestamps after Y2038 on 32-bit buildsBenjamin Robin1-9/+15
Introduce a utility function to always print `time_t` values using either `long long` or `unsigned long long`, depending on whether `time_t` is signed. This fixes the bug reported in [1]. Previously, `time_t` values were cast to `long`, which is a 32-bit value on 32-bit builds. [1]: https://lists.busybox.net/pipermail/busybox/2026-August/092413.html function old new delta print_stat 869 858 -11 Signed-off-by: Benjamin Robin <benjamin.robin@bootlin.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-08-19Remove FAST_FUNC from variadic function (again)Ron Yorston1-1/+1
The merge with upstream in commit 4afa250a0 accidentally reintroduced one of the FAST_FUNC annotations removed in commit 99d22da0e (Remove FAST_FUNC from variadic functions). Remove it again as it caused a 32-bit cross-compilation with gcc to fail on Alma Linux 10. Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-08-16ash: PROMPT_COMMAND shouldn't affect $?Ron Yorston1-0/+2
When PROMPT_COMMAND is run the exit status of the last command should be preserved so $? reports the correct value. Adds 16 bytes. (GitHub issue #615) Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-08-10tar: fix verbose output with extract-to-stdoutThorsten B9-17/+50
Combining the verbose (-v) and extract-to-stdout (-O) options caused verbose output and extracted file data to be interleaved unpredictably on stdout. Verbose listing uses buffered stdio (printf()/puts()), while file contents are written directly to the stdout file descriptor. GNU tar also combines buffered verbose output with unbuffered writes for "-vO", however, GNU tar writes verbose output to stderr, so the two streams remain separate and consistent. Fix this by making "tar xvO" send output to stderr. function old new delta header_verbose_list 244 279 +35 header_list 15 49 +34 get_header_tar 1764 1769 +5 header_verbose_list_ar 77 78 +1 get_header_ar 542 540 -2 get_header_cpio 959 948 -11 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/2 up/down: 75/-13) Total: 62 bytes Signed-off-by: Thorsten B <brehmt@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-08-10rpm2cpio: print name of unknown compression methodRon Yorston1-2/+2
Commit f13f68288 (rpm2cpio: extract cpio even if compression is not known) added an error message if the compression method was unknown. When support for lzma was disabled this resulted in a null pointer being passed to bb_error_msg(). The call to rpm_getstr0() to fetch the name of the compression method shouldn't depend on lzma being supported. This doesn't affect the size of a default build. In a build with lzma disabled: function old new delta rpm2cpio_main 110 121 +11 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 11/0) Total: 11 bytes Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-08-09shell: correctly count backslashes in read built-inRon Yorston5-1/+9
When the read built-in's '-n' option is used to limit the number of characters read, backslashes should only be counted if the '-r' option is also suppiled. This matches how bash behaves. function old new delta shell_builtin_read 1360 1358 -2 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-2) Total: -2 bytes Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-08-09shell: read: if poll() fails, attempt to process any data collected so farDenys Vlasenko1-2/+1
This was already done on read() failure, why not on poll()? Making it consistent. function old new delta shell_builtin_read 1318 1308 -10 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-08-09patch: handle files with no final newlineRon Yorston2-4/+92
GNU and BSD patch both handle patches which include the annotation '\ No newline at end of file'. BusyBox patch doesn't, even though its diff emits it. Implement this feature and add some tests. function old new delta patch_main 1912 2002 +90 do_line 88 116 +28 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 118/0) Total: 118 bytes Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-08-02ash: prevent SEGV when printing promptRon Yorston1-30/+29
If PROMPT_COMMAND is set early in execution, via the -c option or in .profile, the shell segfaults when trying to print the prompt. Moving the handling of PROMPT_COMMAND out of parsecmd() into cmdloop() fixes this. Adds 16-64 bytes. (GitHub issue #615) Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-08-02ash: make shell exit if PROMPT_COMMAND exitsRon Yorston1-0/+8
Commit 4496f1338 (ash: limited support for PROMPT_COMMAND) didn't cause the shell to exit if PROMPT_COMMAND exited. This is not how bash behaves: PROMPT_COMMAND=exit really does cause the shell to exit. Implement this. Adds 0-16 bytes. (GitHub issue #615) Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-07-30ash: limited support for PROMPT_COMMANDRon Yorston1-0/+22
Bash supports the PROMPT_COMMAND variable as a way to run commands just before the PS1 prompt is issued. Add a similar feature to ash. Unlike bash, ash doesn't support array variables so it's only possible to set a single command to be run. Adds 164-268 bytes. (GitHub issue #615) Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-07-30ash: tweak appearance of ctrl-c on command lineRon Yorston1-1/+5
Commit f7bcc977c (ash: make ctrl-c trap handling closer to upstream) resulted in ctrl-c on the command line issuing an extra newline: $ ^C $ In the past this looked more like what bash does: $ ^C $ This is entirely cosmetic and the output from other shells may well be different. Adjust the code so the output looks more like bash in this particular case. Saves 36-72 bytes. (GitHub issue #616) Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-07-24grep: support --quietDenys Vlasenko1-7/+70
function old new delta static.grep_longopts - 17 +17 packed_usage 36237 36243 +6 .rodata 107341 107332 -9 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/1 up/down: 23/-9) Total: 14 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-07-24win32: code shrink reset of stat(2) flagsRon Yorston5-21/+37
Recent changes mean there are now three places where calls to stat(2) require the flags which control expensive operations to be reset to their default values and back to their current setting. It becomes useful to provide a function to handle this operation. Also add tests to ensure this doesn't break the previous fix. Saves 48 bytes. Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-07-24win32: fix another stat callmbartlett211-1/+8
For running files that are a proper Windows executable format, but without an extension, this stat call could fail. $ cp busybox.exe busybox_noext $ ./busybox.exe find -name win32 -exec ./busybox_noext echo {} + find: ./busybox_noext: Permission denied
2026-07-24win32: fix another occurrence of statmbartlett211-1/+6
Applied the same fix as previous, resetting the flags to default, then restoring them afterwards. This previously resulted in the following failing: $ echo -e '#!/bin/sh\necho "$@"' >echo_sh $ find -name win32 -exec ./echo_sh {} + find: ./echo_sh: No such file or directory
2026-07-17ash: code shrink waitpid_child()Ron Yorston1-31/+14
Commit 158b6215a (ash: allow more than 64 background jobs) fixed an issue in 'ash' for shells with more than 64 jobs. There were a couple of problems: - The test to break out of the for loop failed to take account of pending_int and waitcmd_int. - The code could incorrectly identify the process with index 258 (WAIT_TIMEOUT, 0x102) as having terminated. Rearrange the code to fix these issues and to save a few bytes. Saves 80-96 bytes. Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-07-17xargs: limit number of processes to 64Ron Yorston1-18/+4
Commit 194f95902 (xargs: fix handling for more than 64 processes) fixed some errors in the code to handle more than 64 processes. On reflection, why bother with that code in the first place? The '-P 0' option already limits the number of processes to 64. Letting the user choose a larger value seems unnecessary. Apply the limit in all cases and remove the code to handle more than MAXIMUM_WAIT_OBJECTS processes. Saves 64-80 bytes. Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-07-17ash: allow more than 64 background jobsmbartlett211-1/+25
WaitForMultipleObjects only allows waiting on 64 handles or threads at a time (MAXIMUM_WAIT_OBJECTS), meaning that we instead need to do multiple calls to it, each with only that many items. For example: for i in $(seq 1 70); do echo $i; sleep 10 & done Signed-off-by: Morgan Bartlett <mjmouse9999@gmail.com>
2026-07-17xargs: fix handling for more than 64 processesmbartlett211-2/+2
The previous code wouldn't ever work as the condition was around the wrong way. Also fixed an off-by-one error under the loop. Signed-off-by: Morgan Bartlett <mjmouse9999@gmail.com>
2026-07-15win32: code shrink procps_scan()Ron Yorston3-28/+29
The principal change is to replace four separate arrays (one for pids and three for time values) with a single array of structs. There are some other minor adjustments. Saves 96-144 bytes. (GitHub PR #609) Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-07-15fix: procps_scan: do not confirm a process to be parent if either creation ↵Shun Zi1-4/+4
time is unknown.
2026-07-15fix: procps_scan: compare process creation times to ensure ppid is realshunf43-16/+55
Windows aggressively reuses PIDs of exited processes. When a new irrelevant process gets assigned the former PID of the parent of an orphaned process, `pkill -P`, `pgrep -P`, `ps -o ppid` sees the new process as the parent of the orphaned process, and PPID of the orphan is no longer 1. So in theory, all `pkill -P`, `pgrep -P` calls are potentially dangerous and possible to kill an innocent process which outlives its parent. This issue is already discussed in various Internet communities: - https://stackoverflow.com/questions/6593003/how-can-i-reliably-check-whether-one-windows-process-is-the-parent-of-another-in - https://web.archive.org/web/20140701081232/https://www.sapphiresteel.com/Blog/Killing-Trees-the-Windows-way Comparing process creation times seems a feasible mitigation that should almost always work (though not theoretically sound). The executable is added 512 bytes after the patch.
2026-07-14cp: fix --sparse to have mandatory argument, fix --remove-destination bit ↵Denys Vlasenko2-5/+19
position cp --remove-destination was broken by commit 56bbbfae "cp: implement -n" function old new delta cp_main 527 533 +6 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-07-14cp: accept --sparse=ANYTHINGDenys Vlasenko1-0/+15
function old new delta cp_main 514 527 +13 .rodata 107332 107341 +9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 22/0) Total: 22 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-07-14win32: workaround for overflow of 8.3 short name (2)Ron Yorston1-1/+1
Replace a call to 'FindNextFileA()' in 'get_reparse_tag()'. This has no effect on the standard builds. Builds with the UTF-8 manifest included save 4-8 bytes as this removes the only remaining call to 'FindNextFileA()'. (GitHub issue #506) Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-07-13win32: workaround for overflow of 8.3 short nameRon Yorston3-2/+36
In certain circumstances 'FindNextFileA()' can fail because the legacy DOS 8.3 short name doesn't fit in the buffer supplied. This can be avoided by using 'FindFirstFileExA()' instead, but with a setting that isn't available on Windows XP. - The problem doesn't arise in the standard 32 and 64 bit builds, so no change is required. - Builds with full Unicode support target platforms which have the required setting. They can use 'FindFirstFileExA()' unconditionally, at the cost of 36-56 bytes. - Builds which include the UTF-8 manifest but which are allowed to run on systems prior to Windows 10 need to check whether they need to call 'FindFirstFileExA()' at runtime. This adds 100 bytes. (GitHub issue #506) Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-07-13xxd: allow '-p -c 0' to cause a single line to be outputRon Yorston2-2/+26
Since 2022 the 'xxd' which comes with 'vim' has allowed the combination of options '-p -c 0' as a way to request output on a single line. Details: https://github.com/vim/vim/pull/9524 Add this feature to the BusyBox 'xxd' applet. Adds 64 bytes. (GitHub issue #610) Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-07-08join: code shrink by making some variables "global"Denys Vlasenko1-50/+58
function old new delta readfields 442 437 -5 printfields 462 457 -5 join_main 843 760 -83 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-93) Total: -93 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-07-08join: new appletRon Yorston2-0/+595
function old new delta join_main - 843 +843 printfields - 462 +462 readfields - 442 +442 .rodata 107120 107332 +212 packed_usage 36078 36237 +159 applet_names 2870 2875 +5 applet_main 1652 1656 +4 ------------------------------------------------------------------------------ (add/remove: 4/0 grow/shrink: 4/0 up/down: 2127/0) Total: 2127 bytes text data bss dec hex filename 1080964 555 4992 1086511 10942f busybox_old 1083091 555 4992 1088638 109c7e busybox_unstripped v2: Add a missing return statement which broke the '-t' option. Thanks to Roberto A. Foglietta for pointing this out. Signed-off-by: Morgan Bartlett <mjmouse9999@gmail.com> Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-07-06make: fix build with FEATURE_CLEAN_UP enabledRon Yorston1-0/+1
The 'make' applet failed to build with FEATURE_CLEAN_UP enabled. Add an early declaration of freerules() to avoid this. This doesn't affect the default builds. Signed-off-by: Ron Yorston <rmy@pobox.com>
2026-07-06ash: fix out-of-bounds read in ifsbreakup()Sanghyun Park1-9/+15
ifsfree() does not only release allocated ifsregion nodes; it also clears the global IFS region state used by ifsbreakup(). If argstr() raises an error while expanding an argument, ash longjmps out of expandarg() before that cleanup runs, leaving stale IFS split offsets behind. A later expansion can reuse the stack for a shorter string. ifsbreakup() then sees the stale IFS state, trusts the old offsets, and can walk past the current stack block before dereferencing p. Follow dash's root-cause fix: when an expansion-related handler catches EXERROR and continues, restore the handler and call ifsfree(). Apply the cleanup to redirectsafe(), expandstr(), and evaltree(). Upstream commit: Date: Mon Dec 5 23:02:01 2022 +0800 expand: Add ifsfree to expand to fix a logic error that causes a buffer over-read On Mon, Jun 20, 2022 at 02:27:10PM -0400, Alex Gorinson wrote: > Due to a logic error in the ifsbreakup function in expand.c if a > heredoc and normal command is run one after the other by means of a > semi-colon, when the second command drops into ifsbreakup the command > will be evaluated with the ifslastp/ifsfirst struct that was set when > the here doc was evaluated. This results in a buffer over-read that > can leak the program's heap, stack, and arena addresses which can be > used to beat ASLR. > > Steps to Reproduce: > First bug: > cmd args: ~/exampleDir/example> dash > $ M='AAAAAAAAAAAAAAAAA' <note: 17 A's> > $ q00(){ > $ <<000;echo > $ ${D?$M$M$M$M$M$M} <note: 6 $M's> > $ 000 > $ } > $ q00 <note: After the q00 is typed in, the leak > should be echo'd out; this works with ash, busybox ash, and dash and > with all option args.> > > Patch: > Adding the following to expand.c will fix both bugs in one go. > (Thank you to Harald van Dijk and Michael Greenberg for doing the > heavy lifting for this patch!) > ========================== > --- a/src/expand.c > +++ b/src/expand.c > @@ -859,6 +859,7 @@ > if (discard) > return -1; > > +ifsfree(); > sh_error("Bad substitution"); > } > > @@ -1739,6 +1740,7 @@ > } else > msg = umsg; > } > +ifsfree(); > sh_error("%.*s: %s%s", end - var - 1, var, msg, tail); > } > ========================== Thanks for the report! I think it's better to add the ifsfree() call to the exception handling path as other sh_error calls may trigger this too. function old new delta restore_handler_expandarg - 33 +33 evaltree 725 711 -14 static.redirectsafe 141 124 -17 expandstr 262 242 -20 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/3 up/down: 36/-45) Total: -18 bytes Signed-off-by: Sanghyun Park <sanghyun.park.cnu@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-07-06join: re-add accidentally removed returnmbartlett212-0/+7
It broke single-character splitting
2026-07-06awk: fix printf "%o\n", -1Denys Vlasenko2-5/+7
function old new delta awk_printf 1381 1387 +6 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-07-05join: code shrink (5)Ron Yorston1-10/+14
Add a freelines() function to free the line data associated with an FDAT struct. This has no effect in the default build but saves 48-64 bytes if FEATURE_CLEAN_UP is enabled. Change the type of the 'first' flag in readfields() to be consistent with that in printfields(). The 'lines' array should be freed for each FDAT struct during clean up, as it was before I broke it. Signed-off-by: Ron Yorston <rmy@pobox.com>