liuqing@cvl.umd.edu (Larry Liuqing Huang) (04/26/88)
Now more people are dialing into a system via telephone lines. It is not unusual that the connection died out in the middle of a big C program which you hate to start running from the beginning again. Is it possible for the C program or Shell to detect the line problem? If so, is it possible to redirect all standard output and error messages to a designated file from the POINT where the problem is detected and continue running? Any hints highly appreciated. liuqing@cvl.umd.edu
root@didsgn.UUCP (didsgn) (04/26/88)
In article <2841@cvl.umd.edu>, liuqing@cvl.umd.edu (Larry Liuqing Huang) writes: > Now more people are dialing into a system via telephone lines. It is > not unusual that the connection died out in the middle of a big C > program which you hate to start running from the beginning again. > > Is it possible for the C program or Shell to detect the line problem? > > If so, is it possible to redirect all standard output and error messages > to a designated file from the POINT where the problem is detected and > continue running? > > Any hints highly appreciated. There is a way....If your system can pass you a SIGHUP signal telling you that the controlling terminal of your process has 'hung up' then you can handle() the signal (see: signal() etc..). At this point and in the 'handling' subroutine you can fopen() one or more files and replace stdout, and stderr. WATCH OUT: as in many unix systems stdXXX are defined as &iob[X], you will need to to copy the FILE structure associated to your newly opened files to &iob[X]. Once this is done, you can keep on with your p rogram execution. Now this can be fairly easy for stderr and stdout but tricky for stdin as you cannot really tell when the event occurs and where is your input stream at...But this is another story. Here is a sort of an illustration of what I tried to explain (I am french so my english constructions are not perfect): void myhandlerofsighup(); { static FILE *emergencyout,*emergencyerr; if ( (emergencyout = fopen(EMERGENCYOUT,"a")) == (FILE *)0 ) { /* THIS IS REALLY BAD */ . . } if ( (emergencyerr = fopen(EMERGENCYERR,"a")) == (FILE *)0 ) { /* THIS IS REALLY REALLY BAD */ . . } (void) memcpy(stdout,emergencyout,sizeof(FILE)); (void) memcpy(stderr,emergencyerr,sizeof(FILE)); Go on .... } I am not finished... What you could do is write a small process that does this work for any process that is passed as and argv[] and fexeced(). Have fun... jlc Jean-Luc Chatelain 404 447 0274 ...!gatech!rebel!didsgn!jlc
bak@csd-v.UUCP (Bruce) (04/27/88)
In article <2841@cvl.umd.edu> liuqing@cvl.UUCP (Larry Liuqing Huang) writes: > >Is it possible for the C program or Shell to detect the line problem? The following program (redir) will accomplish what you want. It is called with the command you wish executed as arguments. Say you want to call: $ cmd arg_1 ... arg_n then you execute the command: $ redir cmd arg_1 ... arg_n Included is a sample command (output) which produces plenty of output. To demo redir build both executables via $ make redir $ make output Then issue the following commands: $ redir output 762 $ kill -1 1037 # Simulates a hangup and causes output redirection # to file "newout". Note that during this command # output is streaming to the screen and you will # not be able to see the command being typed. $ ps # get the proc id of the output process. PID TTY TIME COMMAND 52 cons3 0:33 ksh 762 cons3 3:07 redir [output] 763 cons3 0:26 [output] 773 cons3 0:01 ps $ kill -15 763 # Simulate software termination of the output # process. This will cause redir to exit also. $ head newdir # print the first few lines of newdir (which will # be pretty big by now). Note that output should # begin where the screen output left off. The details of starting this program up on terminal lines and doing similar redirection of standard error should be fairly straight forward. The principles used here are explained very lucidly in Rochkind's admirable book ADVANCED UNIX PROGRAMMING. The following is redir.c: #--- cut here ---#--- cut here ---#--- cut here ---#--- cut here ---* #include <stdio.h> #include <fcntl.h> #include <signal.h> main( argc, argv, envp ) int argc ; char **argv, **envp; { int i, redir(); int fpipe[2]; char c; /* ** Set signal handler to redirect output on receipt of ** SIGHUP. */ signal( SIGHUP, redir ); /* ** Open a pipe for the child to write its standard output to. */ And the parent to read it's standard input from. if( pipe( fpipe ) == -1 ) { perror( "redir: pipe" ); exit( 1 ); } switch( fork() ) { case 0: /* child process */ /* ** Now exec the child with args. */ close( 1 ); dup( fpipe[1] ); /* prepare pipe as child's stdout */ close( fpipe[0] ); close( fpipe[1] ); execve( argv[1], &argv[1], envp ); exit( 1 ); default: /* parent process */ close( 0 ); dup( fpipe[0] ); /* prepare pipe as parent's stdin */ close( fpipe[0] ); close( fpipe[1] ); /* ** Read child's standard output and write it to parent's ** standard output. Note that initially this is the terminal ** but upon receipt of a hangup it will become the file newout ** ( see the signal handler below). */ while( read( 0, &c, 1 ) ) write( 1, &c, 1 ); /* ** Exit when the pipe is closed by the child. */ exit( 0 ); } } int redir() /* Handle receipt of SIGHUP */ { int fout; /* ** Create the output file newout. */ if( ( fout = open( "newout", O_WRONLY | O_CREAT, 0666 ) ) < 0 ) { perror( "redir: open" ); exit( 1 ); } /* ** Close stdout and dup the file just opened. ** Upon return from this signal handler, the new ** file will become the redirected stdoutput file. */ close( 1 ); if( dup( fout ) == -1 ) { perror( "redir: dup" ); exit( 2 ); } } #--- cut here ---#--- cut here ---#--- cut here ---#--- cut here ---* This is output.c: #--- cut here ---#--- cut here ---#--- cut here ---#--- cut here ---* #include <stdio.h> main() /* Sample application to produce lots of output */ { int i=0; while( 1 ) fprintf( stdout, "%d\n", i++ ); } -- Bruce Kern | uunet!swlabs!csd-v!bak Computer Systems Design | 1-203-270-0399 29 High Rock Rd., Sandy Hook, Ct. 06482 | This space for rent.
karish@denali.UUCP (karish) (04/28/88)
In article <2841@cvl.umd.edu> liuqing@cvl.UUCP (Larry Liuqing Huang) writes: >Now more people are dialing into a system via telephone lines. It is >not unusual that the connection died out in the middle of a big C >program which you hate to start running from the beginning again. > >Is it possible for the C program or Shell to detect the line problem? > >If so, is it possible to redirect all standard output and error messages >to a designated file from the POINT where the problem is detected and >continue running? > >Any hints highly appreciated. > >liuqing@cvl.umd.edu If the modem on the computer end hangs up when this happens, there is a way to do what you wish. The tty driver should send a SIGHUP to the login process group when the modem hangs up. The user's program can catch the SIGHUP, using a signal handler assigned by the signal() function. This handler can use fopen() to open outfiles, and freopen() to reassign the output streams. It would probably save a lot of programming effort to teach the users to run their jobs in the background. This prevents the process from being killed when the connection dies. You might also wish to point out the 'nice' and 'tee -f' commands. Chuck
chris@mimsy.UUCP (Chris Torek) (04/28/88)
In article <62@denali.UUCP> karish@denali.UUCP (karish) writes: >... The user's program can catch the SIGHUP, using a signal handler >assigned by the signal() function. This handler can use fopen() to >open outfiles, and freopen() to reassign the output streams. This is quite dangerous. The proposed technique is likely to work until you need it to do so. A SIGHUP can occur while all sorts of internal states are inconsistent; opening a new stream, or reopening an existing one, is liable to result in a core dump or lost or duplicated output. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
csch@tmpmbx.UUCP (Clemens Schrimpe) (04/28/88)
Larry Liuqing Huang (liuqing@cvl.UUCP) writes:
{} Now more people are dialing into a system via telephone lines. It is
{} not unusual that the connection died out in the middle of a big C
{} program which you hate to start running from the beginning again.
{}
{} Is it possible for the C program or Shell to detect the line problem?
Sure! The system will generate a SIGHUP (Hangup) signal to all processes,
which have the "hung-up" tty as their controlling tty.
[this will work ONLY, if you are using a tty, which supports modem-control
signals (mainly DTR & DCD) and this modem-control is also enabled
(~CLOCAL, HUPCL and open with ~O_NDELAY)]
{} If so, is it possible to redirect all standard output and error messages
{} to a designated file from the POINT where the problem is detected and
{} continue running?
Sure (normally :-)
Simply catch the SIGHUP, close 0, reopen it on /dev/null and
close 1 & 2 and reopen both on the file you want, then return from
the signal-routine. I havn't tried this, but it should work.
{} Any hints highly appreciated.
Ya' welcome ... ]:-}
Clemens Schrimpe
UUCP: csch@tmpmbx = {pyramid!tub!unido}!tmpmbx!csch
BITNET: csch@db0tui6 csch@tub.BITNET
PHONE: +49-30-332 40 15
FAX: +49-30-361 40 93
TELEX: 186672 net d
mac@esl.UUCP (Mike McNamara) (04/29/88)
The discussion concerned writing large programs that "noticed" the user logged off, and changed their output device from the terminal to a file, automagicaly. I'd be more interested in a way I could type % make interesting lines from make.... ^Z % bg > make.out Which, if you didn't catch my drift, allows me to stop a job, and restart it with it's stdout redirected to a file. Any one done this? -- Michael Mc Namara ESL Incorporated ARPA: mac%esl@lll-lcc.ARPA
bob@cloud9.UUCP (Bob Toxen) (04/30/88)
In article <11257@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes: > In article <62@denali.UUCP> karish@denali.UUCP writes: > >... The user's program can catch the SIGHUP. This handler can use > >fopen() to open outfiles, and freopen() to reassign the output streams. > This is quite dangerous. > In-Real-Life: Chris Torek uunet!mimsy!chris (Edited to satisfy inews.) The safe way is to do a close and then an open on the desired file descriptors. This will work even while executing stdio code. System calls are internally consistent (except in some non-native UNIXes). If you want to be ultra-safe, have your interrupt ignore signals before doing this and then restore them afterwards. -- Bob Toxen {ucbvax!ihnp4,harvard,cloud9!es}!anvil!cavu!bob Stratus Computer, Marlboro, MA Pilot to Copilot: What's a mountain goat doing way up here in a cloud bank?
amos@taux01.UUCP (Amos Shapir) (05/01/88)
I usually do make >& make.out & tail -f make.out (This is csh; with sh, do make 2>&1 > make.out) Thus, the make is always in the background, but its output can be followed on the screen, stopped, restarted etc. Even if the line goes down, the output will remain. (This can be put in a command file or alias) -- Amos Shapir (My other cpu is a NS32532) National Semiconductor (Israel) 6 Maskit st. P.O.B. 3007, Herzlia 46104, Israel Tel. +972 52 522261 amos%taux01@nsc.com 34 48 E / 32 10 N
allbery@ncoast.UUCP (Brandon Allbery) (05/05/88)
As quoted from <2841@cvl.umd.edu> by liuqing@cvl.umd.edu (Larry Liuqing Huang): +--------------- | Now more people are dialing into a system via telephone lines. It is | not unusual that the connection died out in the middle of a big C | program which you hate to start running from the beginning again. | Is it possible for the C program or Shell to detect the line problem? +--------------- From the time the program starts, the shell has no control over the program's I/O. You would have to patch stdio to detect SIGHUP on an fd attached to the controlling terminal. (Ecch!) I use the following scripts instead. (4.xBSDers will, of course, want to change the names....) ----------------------------------- cut here ----------------------------------- : bg - run program in the background (essentially nohup) case $# in 0) echo "Usage: bg command [args]" >&2 exit 1 esac > ./do.out { [ "$TERM" = vt100 ] && echo '\033[1q\c' trap '' 3 2 1 { eval nice -20 "$@" } > ./do.out 2>&1 [ "$TERM" = vt100 ] && echo '\033[q\c' if [ $? -ne 0 ]; then echo '\007\c' [ "$TERM" = vt100 ] && echo '\033[4q\c' sleep 1 fi echo '\007\c' sleep 1 echo '\007\c' } & ----------------------------------- cut here ----------------------------------- ----------------------------------- cut here ----------------------------------- : fg - run command in background, catching output which is displayed case "$#" in 0) echo "usage: fg command [args]" >&2 exit 1 ;; esac > ./do.out { SHELL=/bin/sh export SHELL case "$TERM" in vt1??) echo '\033[q\033[1q\c' ;; esac trap '' 3 2 1 eval nice -20 "sh -c '$@' > ./do.out 2>&1 < /dev/null" rc=$? case "$TERM" in vt1??) echo '\033[q\c' ;; esac case $rc in 0) ;; *) echo '\007\c' case "$TERM" in vt100) echo '\033[4q\c' ;; vt1??) echo '\033[2q\c' ;; esac # sleep 1 esac echo '\007\c' sleep 1 echo '\007\c' kill -2 $$ 2> /dev/null } & exec tail -f ./do.out ----------------------------------- cut here ----------------------------------- -- Brandon S. Allbery, moderator of comp.sources.misc {well!hoptoad,uunet!marque,cbosgd,sun!mandrill}!ncoast!allbery Delphi: ALLBERY MCI Mail: BALLBERY
james@cantuar.UUCP (J. Collier) (05/09/88)
Mike McNamara (mac@esl.UUCP) writes: > I'd be more interested in a way I could type > % make > interesting lines from make.... > ^Z > % bg > make.out [....] > Any one done this? Robert Biddle (robert@cantuar.uucp) and I discussed a scheme for this with Robert Elz (kre@munnari.oz) last year. We didn't follow it up for several reasons. After toying with various signal+IPC schemes (this is a 4.3BSD site), we decided that it would be preferable to avoid compiling the handling mechanism into every program. We proposed a new system call: dup3(localfd, remotefd, pid) which would replace the file descriptor 'remotefd' in the process 'pid' with the descriptor 'localfd' from the calling process - perhaps sending a warning signal at the same time (c.f. SIGWINCH - urk). Although this looked clean enough at first sight, we acknowledged a few potential problems: 1) Security - it would probably be insufficient just to compare the effective uid's; there may be r/e/uid-swapping programs which rely on the fact that a given file descriptor refers to a known file. 2) Device types - there are plenty of programs which modify their I/O behaviour on the basis of isatty(fileno(stdout)) etc. The most seriously (fatally?) affected interactive applications would probably be unlikely targets for re-direction, but new features which can cause core dumps on hitherto healthy programs are undesirable. Stdio buffering assumptions would also cause unnatural behaviour in many programs. 3) The system would have to assume that (fileno(stdin) == 0) etc. This is not guaranteed. 4) Implementing it would involve something like ptrace()'s hideous machinations to access the target process's u area. 5) Yet another context dependent, multiple-occurrence-significant signal. Robert Elz's advice was "do it right, or not at all". He also pointed out that ptrace()'s methods were neither philosophically sound nor suitable for contemplation as a Sunday afternoon hack. This seemed reason enough to can that system, so I then looked at putting switchable pipelines into a shell using pseudo-terminals. On reflection I concluded that the idea was grotesque. Nevertheless, there would be many uses for such a system. Apart from the two already mentioned, one advantage would be the ability to move a process group to a different terminal or window - although the latter can be built into the window manager. Quite often I wish there was some method of doing this for input as well - e.g. to provide a prologue for an interactive program. ("cat foo - | bar" is not as useful as it looks for reason (2) above; in frustration I have at times used pseudo-terminals or TIOCSTI to achieve the desired effect, but these are ugly solutions). I think some fairly radical alterations would be needed to implement this facility cleanly. On its own it wouldn't justify these alterations, but the main underlying problems are becoming painful in other respects and may be due for attention anyway. Another subject, another posting... >-- > Michael Mc Namara ESL Incorporated ARPA: mac%esl@lll-lcc.ARPA > ------------------------- James Collier Internet(ish): james@cantuar.uucp Computer Science Dept., UUCP: {watmath,munnari,mcvax}!cantuar!james University of Canterbury, Spearnet/Janet: j.collier@nz.ac.canty (unreliable) Christchurch, New Zealand. Office: +64 3 482 009 x8356 Home: +64 3 554 025