maart@cs.vu.nl (Maarten Litmaath) (02/25/88)
Has anyone noticed the following oddities? 1) % a.out < a.out a.out: Text file busy. % Why shouldn't a process be able to read its text file? 2) % cat ~/.cshrc echo echo hello % cp /bin/echo . % ./echo > echo hello: Command not found. % cat echo echo hello hello % What kinda weird thing is going on here? Shouldn't there be an error message "Text file busy." in this case? -- "Brothers & sisters, praise the Lord, |Maarten Litmaath @ Free U Amsterdam: send your money, Rolls Royce > Ford." |maart@cs.vu.nl, mcvax!botter!ark!maart
sjoerd@cs.vu.nl (Sjoerd Mullender) (02/25/88)
In article <1193@ark.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >Has anyone noticed the following oddities? >1) > % a.out < a.out > a.out: Text file busy. > % > If you are debugging a.out then this could happen. Especially if you have set breakpoints. >Why shouldn't a process be able to read its text file? It can! >2) > % cat ~/.cshrc > echo echo hello > % cp /bin/echo . > % ./echo > echo > hello: Command not found. > % cat echo > echo hello > hello > % When executing the command "./echo > echo" the shell will first create the file echo. It then tries to exec ./echo. The kernel refuses (it's not an object anymore, it an empty file) and the shell will start interpreting the script. The shell will fork off a new shell to do the work. This new shell will first execute ~/.cshrc which contains the command "echo echo hello". So the string "echo hello" is echoed into the output file (echo). Then the shell really starts executing the script. It now contians the string "echo hello", so that command is executed. The result (the string "hello") is appended to the output file (that file was never closed or re-created). After that the next line of the script is "hello" and the shell is not able to find the command. Hence the error message. > >What kinda weird thing is going on here? >Shouldn't there be an error message "Text file busy." >in this case? Nothing that cannot be explained. Why was this cross-posted to comp.unix.wizards? -- Sjoerd Mullender sjoerd@cs.vu.nl When this doesn't work try sending via seismo.css.gov or mcvax.uucp.
ugfailau@sunybcs.uucp (Fai Lau) (02/27/88)
In article <1193@ark.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >Has anyone noticed the following oddities? >1) > % a.out < a.out > a.out: Text file busy. > % > This is not as bad as this, cat file | grep john > file There will be nothing withsoever in file "file". UNIX is kinds strange when you put the same file name at both "ends" of a pipeline or redirect. Aviod doing it or sooner or later you'll find out some files you're working on would be strangely deleted against your wish. Speaking from experience here. >Why shouldn't a process be able to read its text file? >2) > % cat ~/.cshrc > echo echo hello > % cp /bin/echo . > % ./echo > echo > hello: Command not found. > % cat echo > echo hello > hello > % > Find the source code echo.c, compile it, put the executable in you directory, and the problem would go away. The only explanation I can give for the phenomonen is that for some reason csh wants to parse .cshrc, and somehow thinks hello is a command. I'm using tcsh in /usr/local/bin and I got the error message "/bin/tcsh: not found" until I restarted with csh did I got the behavior you described. Fai Lau SUNY at Buffalo (The Arctic Wonderland) UU: ..{rutgers,ames}!sunybcs!ugfailau BI: ugfailau@sunybcs INT: ugfailau@joey.cs.buffalo.EDU
pdb@sei.cmu.edu (Patrick Barron) (02/27/88)
In article <1193@ark.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >Has anyone noticed the following oddities? >1) > % a.out < a.out > a.out: Text file busy. > % >Why shouldn't a process be able to read its text file? I can't reproduce this under Ultrix 1.2. >2) > % cat ~/.cshrc > echo echo hello > % cp /bin/echo . > % ./echo > echo > hello: Command not found. > % cat echo > echo hello > hello > % > >What kinda weird thing is going on here? >Shouldn't there be an error message "Text file busy." >in this case? This is actually pretty simple. When you redirect output to "echo", the file gets overwritten *before* "./echo" is executed. So, it ends up trying to execute an empty file. Since it doesn't have a valid magic number, and the execute bits are set (copying /bin/echo left them set, and overwriting the file didn't change that), it's assumed to be a shell script. Your .cshrc file gets executed, echoing "echo hello" using the C-shell's built-in echo. That goes into the file "./echo", and the shell then starts to execute commands from "./echo". (Why isn't the Bourne shell used to do this? The file does not start with "#!/bin/csh") That file now contains "echo hello", so the shell's "echo" echoes "hello". Remember, standard output is still the "./echo" file, so that gets tacked on to the end. The shell then reads the next command, which is "hello", and it complains "Command not found." --Pat.
ka@june.cs.washington.edu (Kenneth Almquist) (02/29/88)
> % a.out < a.out > a.out: Text file busy. > % The basic problem that the "text file busy" error was designed to solve is this. When several copies of the same program are run concurrently, UNIX will only create a text segment for the first copy. Subsequent invocations of the program will reuse this text segment rather than creating a new one. The problem with this approach is that if a program is modified, the system may continue to reuse the old version of the text segment rather than using the new version. This problem was avoided by making the following actions illegal: 1) Opening a file that is being executed. 2) Executing an open file. 3) Deleting the last link to a file that is being executed. So when you say "a.out < a.out", the shell opens a.out and then tries to execute it. The attempt to execute it fails due to rule 2. You are presumably running some version of 2 BSD; both 4 BSD and System V have relaxed rules 1 and 2 to allow files that are being executed to be opened for reading and vice versa. My view is that these rules should be eliminated all together. They are inconvenient, since they make program installation harder. They are inconsistent with the rest of the design of the UNIX file system calls, which permits any operation to be performed at any time (even operations like deleting other people's current working directories). It is a bit simpler to enforce these rules than to design things so that they are unnecessary, but given the growth of the kernel in recent years it is hard to justify taking some of the complexity of supporting shared text out of the kernel and pushing it onto the users. Kenneth Almquist ka@june.cs.washington.edu
maart@cs.vu.nl (Maarten Litmaath) (03/01/88)
In article <4320@june.cs.washington.edu> ka@june.cs.washington.edu (Kenneth Almquist) writes:
\> % a.out < a.out
\> a.out: Text file busy.
\> %
\
\... You
\are presumably running some version of 2 BSD; both 4 BSD and System V
\have relaxed rules 1 and 2 to allow files that are being executed to
\be opened for reading and vice versa.
Our version is 4.1BSD!
--
Which of Santa Claus and God |Maarten Litmaath @ Free U Amsterdam:
is more likely to exist? |maart@cs.vu.nl, mcvax!botter!ark!maart
rcodi@yabbie.rmit.oz (Ian Donaldson) (03/02/88)
In article <1193@ark.cs.vu.nl>, maart@cs.vu.nl (Maarten Litmaath) writes: > % a.out < a.out > a.out: Text file busy. You didn't say which system. Yep, its a kernel bug in some pre 4.[23]bsd systems. Exec processing only checks for open files rather than files open for writing when determining if the file is busy. Its also a -big- security bug in such systems that leave most system binaries publicly readable. The workaround is to -not- make such binaries publicly readable. Simple. ie: chmod o-r `file /bin/* /usr/bin/* /usr/ucb/* |egrep "demand|pure" |cut -d: -f1` (this won't work right if your binaries are OMAGIC types, in which case you will probably need to do it by hand, since grepping for the word "executable" might discover shellscripts too) > Why shouldn't a process be able to read its text file? > 2) > % cat ~/.cshrc > echo echo hello > % cp /bin/echo . > % ./echo > echo > hello: Command not found. > % cat echo > echo hello > hello > % > > What kinda weird thing is going on here? You are paving the road before you tread on it. I'll elaborate: > % cp /bin/echo . Creates a binary "./echo". Fine. > % ./echo > echo First clobbers "./echo" then csh tries to execute it with stdout sent to it. execv() fails because the kernel sees an empty file, so csh tries to execute it as a script. Since a new csh is started up to execute it, it reads your ".cshrc" and executes that first. The first line says "echo echo hello" and since "echo" is a csh builtin, it echo's the words "echo hello" to stdout, which gets written onto "./echo". Csh then finishes executing your ".cshrc" and then executes "./echo", seeing the words "echo hello". Again it is a builtin, so the word "hello" gets written to stdout ("./echo"). Csh then reads the next line of "./echo" which is "hello". Obviously not a known command so it complains to stdout (the terminal). It then runs out of things to do and stops. A great puzzle! > Shouldn't there be an error message "Text file busy." > in this case? Nope. You clobbered "./echo" before excuting it. There is no text there anymore. Ian D
maart@cs.vu.nl (Maarten Litmaath) (03/05/88)
In article <716@yabbie.rmit.oz> rcodi@yabbie.rmit.oz (Ian Donaldson) writes: \In article <1193@ark.cs.vu.nl>, maart@cs.vu.nl (Maarten Litmaath) writes: \> % a.out < a.out \> a.out: Text file busy. \ \You didn't say which system. 4.1BSD! \Yep, its a kernel bug in some pre 4.[23]bsd systems. Exec processing \only checks for open files rather than files open for writing when \determining if the file is busy. \ \Its also a -big- security bug in such systems that leave most system binaries \publicly readable. The workaround is to -not- make such binaries publicly \readable. Simple. You're completely right. \... \> % ./echo > echo \ \ First clobbers "./echo" then csh tries to execute it with stdout \ sent to it. execv() fails because the kernel sees an empty file, \ so csh tries to execute it as a script. \ \ Since a new csh is started up to execute it, it reads your ".cshrc" \ and executes that first. Normally a Bourne shell is started up (default for shell scripts), but - as Ronald Khoo mentioned in a reply I got - if the file size is zero, csh appears to execute the shell mentioned in the internal variable "shell": % : > gnome % chmod 755 gnome % set shell=hobgoblin % gnome hobgoblin: No such file or directory % echo '' > gnome % ls -l gnome -rwxr-xr-x 1 3754 1 Mar 5 15:23 gnome % gnome % \ A great puzzle! Thanks! :-) -- Which of Santa Claus and God |Maarten Litmaath @ Free U Amsterdam: is more likely to exist? |maart@cs.vu.nl, mcvax!botter!ark!maart