emf@eleazar.dartmouth.edu (Eric Friets) (06/28/90)
I need to redirect output in the middle of a program from the standard output to a file. The use of fprintf is ruled out because I do not have the source of the functions whose output I want. Options that are not acceptable: 1. redirect output of the entire program, as in prog > file 2. have the rest of the program write to stderr, and then redirect the entire program, as above 3. write the necessary data to a file, and have a smaller program that redirects to a file What is really needed is a way to change the pointer to stdout to a file pointer returned by fopen(). Any suggestions would be appreciated. I will summarize and post responses that are mailed to me. Eric Friets emf@eleazar.dartmouth.edu .
jason@cs.odu.edu (Jason C Austin) (06/29/90)
In article <22931@dartvax.Dartmouth.EDU> emf@eleazar.dartmouth.edu (Eric Friets) writes:
->
-> I need to redirect output in the middle of a program
-> from the standard output to a file. The use of
-> fprintf is ruled out because I do not have the
-> source of the functions whose output I want.
->
-> Options that are not acceptable:
-> 1. redirect output of the entire program, as in
-> prog > file
-> 2. have the rest of the program write to stderr, and
-> then redirect the entire program, as above
-> 3. write the necessary data to a file, and have a
-> smaller program that redirects to a file
->
-> What is really needed is a way to change the pointer
-> to stdout to a file pointer returned by fopen(). Any
-> suggestions would be appreciated. I will summarize and
-> post responses that are mailed to me.
->
-> Eric Friets
-> emf@eleazar.dartmouth.edu
-> .
freopen will do the job for you. In fact the unix manual page
says that this command is mostly used for this purpose.
freopen( "filename", "w", stdout );
Anything sent to stdout after this command is executed will go
to filename. The function returns the previous value of stdout, so
you'll probably want to keep it and restore the value, if you want to
start sending things back to the screen.
--
Jason C. Austin
jason@cs.odu.edu
scjones@thor (Larry Jones) (06/29/90)
In article <JASON.90Jun28152010@oswine.cs.odu.edu>, jason@cs.odu.edu (Jason C Austin) writes: > freopen( "filename", "w", stdout ); > > Anything sent to stdout after this command is executed will go > to filename. The function returns the previous value of stdout, so > you'll probably want to keep it and restore the value, if you want to > start sending things back to the screen. No, freopen does NOT return the previous value of stdout, it returns the current value of stdout (which should, I think, be the same). The old file has been CLOSED, so there is no way to continue sending data to it without reopening it, which you probably can't do since you probably don't know its name. freopen is portable and works fine for a permanent diversion. For a temporary diversion, you have to do something system dependent. On most unix systems you need to use fileno, dup, and fdopen to make it all work. ---- Larry Jones UUCP: uunet!sdrc!scjones SDRC scjones@SDRC.UU.NET 2000 Eastman Dr. BIX: ltl Milford, OH 45150-2789 AT&T: (513) 576-2070 "This probably just goes to show something, but I sure don't know what." -Calvin
henry@zoo.toronto.edu (Henry Spencer) (06/30/90)
In article <JASON.90Jun28152010@oswine.cs.odu.edu> jason@cs.odu.edu (Jason C Austin) writes: > freopen will do the job for you. In fact the unix manual page >says that this command is mostly used for this purpose. > > freopen( "filename", "w", stdout ); You have the right idea, but you left something out. Try this instead: #define FILENAME "filename" if (freopen(FILENAME, "w", stdout) == NULL) { fprintf(stderr, "freopen on `%s' failed", FILENAME) exit(1); } God is not on your side; such a call *will* fail eventually. Life is much more pleasant if your code copes properly. -- "Either NFS must be scrapped or NFS | Henry Spencer at U of Toronto Zoology must be changed." -John K. Ousterhout | henry@zoo.toronto.edu utzoo!henry
peter@ficc.ferranti.com (Peter da Silva) (07/02/90)
In article <1990Jun29.172429.2818@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: > You have the right idea, but you left something out. Try this instead: While picking nits, how about doing it right. There's really no excuse for not calling perror: > #define FILENAME "filename" > if (freopen(FILENAME, "w", stdout) == NULL) { + perror(FILENAME); ! fprintf(stderr, "Can't re-open standard output -- exiting\n"); > exit(1); > } > God is not on your side; such a call *will* fail eventually. Life is > much more pleasant if your code copes properly. And life is even better if it tells you *why* it fails. If your C runtime doesn't implement perror, make it. I don't know of any operating system where you can't at least differentiate between missing files and other errors. Well, outside the top levels of the orange book, anyway. -- Peter da Silva. `-_-' +1 713 274 5180. <peter@ficc.ferranti.com>
peter@ficc.ferranti.com (Peter da Silva) (07/03/90)
In article <17008@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: > Technically, there is. OK, but it's not a *good* excuse. > The polite action is to set errno iff an error > occurs, but most non-syscall functions are not guaranteed to be polite. In > particular, many implementations of fopen() can fail without setting errno (by > running out of buffers); Didn't know about that... > conversely, an internal call to isatty() may have set > errno when no error has really occurred. I knew about this one, but it's not relevant to the problem at hand. It does mean you can't use perror to tell if an error occurred... just what it was. -- Peter da Silva. `-_-' +1 713 274 5180. <peter@ficc.ferranti.com>: Inappropriate ioctl for device --
henry@zoo.toronto.edu (Henry Spencer) (07/04/90)
In article <JID4B=4@ficc.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes: >While picking nits, how about doing it right. There's really no excuse for >not calling perror... Yes there is: it doesn't do what I want, which is a more informative message about the high-level nature of the problem. A major reason why perror() doesn't get used is that it is simply too inflexible: it takes too much extra work to put together a useful message, since that generally requires assembling an argument string out of pieces. One often wants more information than just the filename and the error code. Something like the Kernighan&Pike error() function is vastly more useful, but alas, not everyone has it. If you're willing to rely on ANSI C facilities (or imitations of same, e.g. my old strings package), then strerror() can be used to get much the same effect. -- "Either NFS must be scrapped or NFS | Henry Spencer at U of Toronto Zoology must be changed." -John K. Ousterhout | henry@zoo.toronto.edu utzoo!henry
karl@haddock.ima.isc.com (Karl Heuer) (07/04/90)
In article <JID4B=4@ficc.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes: >While picking nits, how about doing it right. There's really no excuse for >not calling perror: Technically, there is. The polite action is to set errno iff an error occurs, but most non-syscall functions are not guaranteed to be polite. In particular, many implementations of fopen() can fail without setting errno (by running out of buffers); conversely, an internal call to isatty() may have set errno when no error has really occurred. Some people maintain that, for this reason, one should not use perror() under the circumstances we're talking about. I disagree; even though errno is badly botched, it's reasonable to use it until something better comes along. (And I use a version of isatty() that leaves errno alone.) Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
peter@ficc.ferranti.com (Peter da Silva) (07/05/90)
In article <1990Jul3.171151.6137@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: > In article <JID4B=4@ficc.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes: > >While picking nits, how about doing it right. There's really no excuse for > >not calling perror... > Yes there is: it doesn't do what I want, which is a more informative > message about the high-level nature of the problem. "Can't open %s for reading" does? > A major reason why > perror() doesn't get used is that it is simply too inflexible: it takes > too much extra work to put together a useful message, since that generally > requires assembling an argument string out of pieces. Or simply calling perror and following it with a text description, which is what I have done in the past in the fow cases a simple perror hasn't been enough. Let's face it. Perror isn't perfect, but it's a LOT better than what people actually use. Strerror will be better, when it becomes widely available, but a simple call to perror covers most cases. In any case, there isn't any excuse for using something *worse* than perror. And there's no excuse for cat(1) still not using perror in System V.3.2. -- Peter da Silva. `-_-' +1 713 274 5180. <peter@ficc.ferranti.com>
emf@eleazar.dartmouth.edu (Eric Friets) (07/27/90)
A while ago I posted a request concerning redirecting output in midprogram. Thanks for the many responses; the only workable one (received from a few netters) looks something like this: (the key is the dup2...) int fdstdout,fdplot; fflush(stdout); fdplot=fopen("plot.out",O_WRONLY|O_CREAT,0644); fdstdout=dup(1); dup2(fdplot,1); ... ... ... fflush(&_iob[fdplot]); dup2(fdstdout,1); close(fdplot); close(fdstdout); This works, but has a small glitch. When unredirecting the output (ie, sending to stdout instead of the file), a few characters at the end of the file are corrupted. Running the program without this redirection results in the correct output. I tried pausing the program for a few seconds before unredirecting, but this had no effect. The computer is a SUN 3/160, running under the UNIX operating system. Thanks, Eric Friets emf@eleazar.dartmouth.edu .