penneyj@servio.UUCP (D. Jason Penney) (05/11/89)
I have a question that some one with Unix source should be able to easily answer for me. THE ENVIRONMENT: SunOS (or AIX) Unix. THE SCENARIO: my program is fork()'ing another process which eventually execve()'s a shell script. Before the execve(), the program reroutes stdout and stderr to a disk file: fork(); ... setpgrp(0, getpid()); close(1); /* stdout */ close(2); /* stderr */ dup(creat("logfile", 0644); /* points 1 and 2 at logfile */ ... execve("script", argv, envp); THE PROBLEM: If script is as follows, #! /bin/sh frob logfile contains frob: not found (Other more sophisticated tests show that stderr is indeed being rerouted properly.) If script is as follows, #! /bin/csh frob nothing appears! (Other tests indicate that the writes to stderr are trashing my address space!) Workaround: If script is as follows, #! /bin/csh (frob) |& cat logfile contains frob: Command not found. THE QUESTION: csh is obviously doing something "smart" with stderr. Just what is going on? Please reply directly to me -- if results are interesting enough, I may post a followup. Thank you in advance... -- D. Jason Penney Ph: (503) 629-8383 Beaverton, OR 97006 uucp: ...ogccse!servio!penneyj STANDARD DISCLAIMER: Should I or my opinions be caught or killed, the company will disavow any knowledge of my actions...
penneyj@servio.UUCP (D. Jason Penney) (05/16/89)
I've found my problem! The answer is interesting enough that I'm posting this follow-up, as I threatened I would. To recap the problem description: In a fork()'d and execve()'d task, stderr was not getting printed, and in fact programs were trashing their address space in an odd way. This ONLY happened under csh -- Bourne shell worked properly. Here is what I did wrong: before doing the execve() I closed stdin so that the forked process would not share stdin with the parent process: close(0); What csh is evidently doing is closing stderr and then re-opening it, thus leaving descriptor 2 uninitialized. Thus, if you want to bit-bucket stdin in a forked process, the correct approach is, close(0); open("/dev/null", O_RDONLY); so that csh will get file descriptor 2 when it reopens stderr. Many thanks to Maarten Litmaath @ VU Amsterdam, who encouraged me to keep looking until I found the problem. -- D. Jason Penney Ph: (503) 629-8383 Beaverton, OR 97006 uucp: ...ogccse!servio!penneyj STANDARD DISCLAIMER: Should I or my opinions be caught or killed, the company will disavow any knowledge of my actions...