levy@ttrdc.UUCP (Daniel R. Levy) (05/13/88)
[Please skip this if you've already seen it once. My first attempt fell on the floor.] I am trying to write a program UNDER SYSTEM V RELEASE 2 AND 3 which disassociates itself from the controlling terminal (using setpgrp() after redirecting all file descriptors still open onto the terminal, into a file), tries to exec() a machine binary or shell script, and if that doesn't work sends an error message to the terminal and exits. The reason I want this is so I can put a command in background a la nohup, BUT, unlike nohup, even if the command turns interrupt/quit/hangup signal catching back on, or a gremlin tries to kill -9 my entire login process group (like one $#@!! version of telnet I am using does upon logout), it will not be affected by goings-on at the terminal. However, I am having a problem with always getting an error message back to the terminal from which the command was issued. It does no good to try to write to "/dev/tty" once one has divorced from the controlling terminal. In fact, even if a file descriptor is kept open onto "/dev/tty" during the setpgrp(), writing onto it afterward fails with errno==ENXIO (No such device or address). Now, of course, if I knew the explicit name of the ex-controlling terminal, I could open that and send the error message to it. In many cases, I can indeed determine that name as the program begins, and save it. If there is still a file descriptor open onto the terminal (e.g., fd 2, error output) I can use ttyname() to determine what it was attached to. If there is no file descriptor open onto the terminal (the user has redirected them all), I am still in luck if the program is a direct child of the login shell. I can use getppid() to find out what that pid is, and search through /etc/utmp to determine the controlling terminal associated with it. However, if neither of these is the case (user redirected stdout and stderr, and put the program into background [stdin is closed] from a non-login shell), I am stuck. I _could_ run /bin/ps -u <my_username> and parse through the process geneology to find out what terminal I was attached to (or rather, the terminal my parent process is still attached to). But this can be slow, especially if ps decides it must rebuild /etc/ps_data (my user may have logged out by the time that finishes and would miss the error message, which could have warned him of a typo in the command). A shotgun write to all terminals the user is logged onto is not really desireable, as the user might be running a graphics application on one of them. Is there any better way to do this that I am overlooking? Wizards please send suggestions by email, flamers please cat your flame > /dev/null. Thanks in advance. Oh yes, as I indicated above, this is for SYSTEM V RELEASE 2 and 3. I really would like any suggested solution to work on both. I don't really care how it would be done under BSD. -- |------------Dan Levy------------| Path: ihnp4,<most AT&T machines>!ttrdc!levy | AT&T | Weinberg's Principle: An expert is a | Data Systems Group | person who avoids the small errors while |--------Skokie, Illinois--------| sweeping on to the grand fallacy.
les@chinet.UUCP (Leslie Mikesell) (05/13/88)
In article <2661@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes: >I am trying to write a program UNDER SYSTEM V RELEASE 2 AND 3 which >disassociates itself from the controlling terminal (using setpgrp() after >redirecting all file descriptors still open onto the terminal, into a file), >tries to exec() a machine binary or shell script, and if that doesn't work >sends an error message to the terminal and exits. >... >However, I am having a problem with always getting an error message back to >the terminal from which the command was issued. It does no good to try to If ttyname() doesn't work on file descriptor 0,1, or 2, you can: a) forget the error message b) send the error message by mail to the appropriate user found by the environment variable LOGNAME (it's good enough for /bin/mail) or looking for the uid in /etc/passwd. c) check all the reasons that the exec might fail before closing stderr. d) fork before closing stderr and let the parent wait a "reasonable" amount of time for a signal from the child indicating that the exec failed. I'd go for (a) myself. If the error message isn't going to appear on the terminal, you might as well find it where you expected the output from the exec'ed program. A reasonable facsimile of (b) is available from the at command, if you are in the at.allow file. Les Mikesell
terry@wsccs.UUCP (Every system needs one) (05/28/88)
In article <2661@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes: >I am trying to write a program UNDER SYSTEM V RELEASE 2 AND 3 which >disassociates itself from the controlling terminal (using setpgrp() after >redirecting all file descriptors still open onto the terminal, into a file), >tries to exec() a machine binary or shell script, and if that doesn't work >sends an error message to the terminal and exits. >... >However, I am having a problem with always getting an error message back to >the terminal from which the command was issued. Use ttyname() before leaving you program clueless. If you are redirecting at a shell level, don't; use freopen() after using ttyname(). This will leave your poor program clueless just as efficiently. Or use getpgrp() before using setpgrp(). "exec()" a shell script? Try an execl() of 'sh -c script' instead, unless your exec() is weird. | Terry Lambert UUCP: ...{ decvax, ihnp4 } ...utah-cs!century!terry | | @ Century Software OR: ...utah-cs!uplherc!sp7040!obie!wsccs!terry | | SLC, Utah | | These opinions are not my companies, but if you find them | | useful, send a $20.00 donation to Brisbane Australia... | | 'Admit it! You're just harrasing me because of the quote in my signature!' |
ford@elgar.UUCP (Mike "Ford" Ditto) (06/06/88)
In article <550@wsccs.UUCP> terry@wsccs.UUCP (Every system needs one) writes: >In article <2661@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes: >>tries to exec() a machine binary or shell script, and if that doesn't work >>sends an error message to the terminal and exits. > >"exec()" a shell script? Try an execl() of 'sh -c script' instead, unless >your exec() is weird. There is no function called exec(), it's a generic name for the exec{l,v}{p,e} set of entrypoints to the exec system service. The "p" versions (execlp, execvp) automatically run a shell if they are passed the name of a script. Mr. Levy obviously meant exec() in the generic sense, and there's nothing wrong with that. -=] Ford [=- "Once there were parking lots, (In Real Life: Mike Ditto) now it's a peaceful oasis. ford%kenobi@crash.CTS.COM This was a Pizza Hut, ...!sdcsvax!crash!kenobi!ford now it's all covered with daisies." -- Talking Heads