From mboxrd@z Thu Jan 1 00:00:00 1970 Received: by archone.tamu.edu id <45337>; Wed, 1 Apr 1992 19:31:24 -0600 From: Byron Rakitzis To: rc Subject: rc-1.4beta Message-Id: <92Apr1.193124cst.45337@archone.tamu.edu> Date: Wed, 1 Apr 1992 19:31:16 -0600 Work on rc has been proceeding at a steady, but far reduced pace ever since the last major release (1.2, Sept. 1991). I think it's about time to put out another version into the various archives, but quite a lot has happened since February (when 1.3beta was announced to this list) so I would like to try your patience and ask you to review what I am now calling "1.4beta". rc unfortunately still needs some work before I can put my conscience to rest and say that I've done everything that needs doing for now, e.g., fixed every bug I knew about. In particular, there are these issues in my mind: 1) editline. Last time I checked it, it was a little flaky, and if it's going to be distributed with rc I want to make sure it's solid. If you'll allow a little immodesty, having put hundreds of hours of my own time into rc (not to speak of the generous help I have received from many of you), if I am going to pair something else with rc in an archive, I would like to make sure it is at least as stable. This is something I just haven't gotten around to personally overseeing yet. Maybe I shouldn't be so paranoid, but... 2) trip.rc. It needs to be improved, and work on trip.rc is just tedious, boring and time-consuming. Here's a current list of basic-block coverage I've got with a ~500 line rc script now: main.tcov: 100.00 Percent of the file executed list.tcov: 100.00 Percent of the file executed getopt.tcov: 100.00 Percent of the file executed glob.tcov: 98.91 Percent of the file executed hash.tcov: 96.52 Percent of the file executed match.tcov: 95.56 Percent of the file executed heredoc.tcov: 95.56 Percent of the file executed lex.tcov: 94.77 Percent of the file executed var.tcov: 94.67 Percent of the file executed fn.tcov: 94.44 Percent of the file executed which.tcov: 92.31 Percent of the file executed wait.tcov: 92.11 Percent of the file executed tree.tcov: 91.89 Percent of the file executed except.tcov: 90.32 Percent of the file executed builtins.tcov: 89.82 Percent of the file executed nalloc.tcov: 88.24 Percent of the file executed status.tcov: 87.50 Percent of the file executed exec.tcov: 87.50 Percent of the file executed input.tcov: 87.10 Percent of the file executed footobar.tcov: 83.21 Percent of the file executed walk.tcov: 82.64 Percent of the file executed glom.tcov: 80.77 Percent of the file executed utils.tcov: 77.78 Percent of the file executed signal.tcov: 76.00 Percent of the file executed redir.tcov: 71.88 Percent of the file executed print.tcov: 66.67 Percent of the file executed open.tcov: 66.67 Percent of the file executed Some of these percentages will never reach 100, unless I simulate failures to fork(), malloc(), pipe(), etc. Some of the code coverage in trip.rc is completely superficial, and real tests need to be devised. Other parts of the code are just completely untested (by trip.rc). Of course, in principle such a test suite is useless because it will never uncover all the bugs. If anyone has any suggestions about how to make a test suite like this more useful, I'm listening. You could help out the trip.rc effort by running it on your Unix and letting me know if 1) there are any bugs in the script, or 2) if there are any bugs in rc. Of course, if you're foolhardy enough to want to extend trip.rc yourself, you are more than welcome! 3) race condition. There is a race condition in the fork-exec sequence that rc uses to start a process and wait for it to finish. Essentially, it is possible to send a SIGINT to rc and to have it get lost. This is because rc uses the following paradigm for spawning a process: fork/exec ignore SIGINT wait() restore SIGINT If a SIGINT arrives after the wait() but before SIGINT's handler is restored, the signal gets lost. The solution that /bin/sh uses is to simply collect SIGINTs that arrive during a wait(). However, I find this unacceptable for the following reason: a signal destined for a child is usually not destined for the shell as well. For example, in sh: if true; then ed bar fi If I type "^C" inside ed to abort some ed operation, let ed catch the SIGINT, continue to edit and then exit ed normally, the command "bar" will never get executed. Whereas, if (true) { ed bar } does try to find bar. So it's a dilemma: adopt poor semantics for SIGINT, or allow a race condition into the code. I really don't know which one is worse right now, so I'm leaving things as they are (though I must note that 1.4beta signals are more reliable than in previous versions---there were other problems with signals that have been fixed in the current release). 4) FIFO's. As long as I'm picking nits, I should mention that this (mis)feature of rc seems to cause more trouble than it's worth. I've mostly ignored it up to now, and it's easily the flakiest part of the shell. Part of the problem is that FIFO's themselves are so flaky. e.g., on a Sun if you put one on a tmpfs filesystem, the machine can crash(!). I want to do something to clean up this mess, if possible. Anyway, here's a list of changes since 1.3beta, and of course rc is available in the usual way. I'm using a tar file format because of the non-printable characters in trip.rc. Changes since 1.3beta: New Makefile/config.h setup. builtin echo may now be conditionally included out, to use a Goldwynism. builtin exit takes any legal exit status. If the status is not a single digit, (e.g., (0 1 2), sigint, (sigiot+core 0), etc.) rc exits with 1. rc's exit status is zero if and only if the status given to exit is all zeros. (or $status is all zeros, of course) (BTW, having "exit sigiot" produce a core dump would be going a little far, I think.) limit does not append a unit after a zero limit; 0g was too confusing. exec > /nonexistentfile does not cause rc to exit any more. If a noninteractive rc is started with sigint ignored, rc does not install its own signal handler. error messages produced by rc in a subshell were cleaned up. (rc erroneously reset the 'interactive' flag after a fork) print.c was cleaned up a little; no functionality was changed, but should be more portable now. a bug in rc-1.3beta (not previous versions) was fixed: setting the first element of $path to '' caused PATH to be exported as '':etc.. getopt's "illegal option" message was gratuitously changed to something less abrupt. some dead code was removed from input.c %term was changed to %token in parse.y; apparently newer yacc's don't grok %term any more. a race condition in the signal handler was fixed. the variable in for() was getting evaluated each time through the loop (e.g., for (`{echo i;date>[1=2]} in 1 2 3)echo $i would print the date three times). This was cleaned up. a redundant fork() was removed from walk.c; this showed up when running a braced command with a redirection in the background. e.g., {a;b}>c& man pages for history and rc were cleaned up by david (thanks). rc set SIGQUIT and SIGTERM to SIG_DFL on background jobs---even when trying to do old-style backgrounding (i.e., don't use process groups, just ignore SIGINT & SIGQUIT & SIGTERM). $0 is now changed to the name of the signal when entering a signal handler. Thus it's possible to write code like fn sigint sigterm sigquit { switch ($0) { case sigint ... case sigterm ... wait with no arguments now prints the pid of any and all children that died with a signal. e.g., ; wait 25321: terminated 25325: terminated as opposed to ; wait terminated An error saving/restoring state in the input stream code would cause rc to exit with the (erroneous) command: eval '|[a'