rac@sherpa.UUCP (Roger A. Cornelius) (02/27/89)
I've been searching for the past several days for references to this, but haven't been able to find it. I know I've read it somewhere, or maybe saw it here. Anyway, can someone tell me how to determine (in C) if output is being redirected, or more precisely, how to determine the file output is being redirected to. The cat command does this (at least the Xenix version of cat, I don't think the BSD version does), i.e.: cat catfile > catfile produces the error "cat: input catfile is output". Any help appreciated. Roger rac@sherpa uunet!sherpa!rac
klee@daisy.UUCP (Ken Lee) (02/28/89)
In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: > Anyway, can someone tell me how to determine (in C) >if output is being redirected, or more precisely, how to determine the >file output is being redirected to. In BSD UNIX, you can fstat(2) stdout to determine if the output is a file or terminal (or whatever) and, what inode number it has. Since several file names can have the same inode, you can't tell exactly what file name was specified, but the inode number should be enough information for cat and other such applications. Ken Lee -- klee@daisy.uucp Daisy Systems Corp., Interactive Graphics Tools Dept.
curci@stat.uucp (Ray Curci (scri)) (02/28/89)
In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: >... Anyway, can someone tell me how to determine (in C) >if output is being redirected, or more precisely, how to determine the >file output is being redirected to. >Roger rac@sherpa > uunet!sherpa!rac You may want to investigate the isatty() function call. I believe that you can use something like: isatty(stdout) which will tell you if standard out is going to a terminal (the usual case), or if it has been redirected via a pipe or into a file. ray curci florida state university supercomputer institute curci@stat.fsu.edu, curci@nu.cs.fsu.edu
guy@auspex.UUCP (Guy Harris) (02/28/89)
>Anyway, can someone tell me how to determine (in C) if output is being >redirected, or more precisely, how to determine the file output is >being redirected to. The cat command does this (at >least the Xenix version of cat, I don't think the BSD version does), Yes, the BSD version does. So does the System V Release 3 version, and I think every version since the V7 version does. However: 1) It doesn't "determine that output is being redirected"; all it does is determine that one of the input files is the same as the output file. 2) It doesn't do the latter by finding the path name for any of the files; it does an "fstat" on the file (descriptor) in question, and compares the "st_dev" and "st_ino" fields of the results. That's all it needs to do, since the "st_dev" and "st_ino" fields are sufficient to uniquely identify a file; it doesn't have to find the file's name (and that wouldn't help anyway, since the same file can have more than one name). So if you really want the name of the file, you'll have to work *very* hard to get it (you basically have to scan all mounted file systems, or at least the ones whose mount points have an "st_dev" that matches that of the file in question), and you may not get it anyway if the input is a pipe, or a file that has been unlinked.
jbayer@ispi.UUCP (Jonathan Bayer) (02/28/89)
In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: >I've been searching for the past several days for references to this, >but haven't been able to find it. I know I've read it somewhere, or >maybe saw it here. Anyway, can someone tell me how to determine (in C) >if output is being redirected, or more precisely, how to determine the >file output is being redirected to. The cat command does this (at Use the stat() and fstat() functions, then compare the inode numbers in the structure. If they are the same then the two files are identical. JB -- Jonathan Bayer Beware: The light at the end of the Intelligent Software Products, Inc. tunnel may be an oncoming dragon 19 Virginia Ave. ...uunet!ispi!jbayer Rockville Centre, NY 11570 (516) 766-2867 jbayer@ispi.UUCP
frankb@usource.UUCP (Frank Bicknell) (02/28/89)
In article <10@sherpa.UUCP>, rac@sherpa.UUCP (Roger A. Cornelius) writes: > ... can someone tell me how to determine (in C) if output is > being redirected, or more precisely, how to determine the > file output is being redirected to. ... I presume you know how to determine whether the std* is directed to a terminal with isatty(). Your request seemed to hint at being able to determine whether the stdout and a file given in *argv[] were the same file. One way which comes to mind (this might be the hard way) is to use stat() on the file and fstat() on stdout. Then you compare st_ino and st_dev in both returned structures. If both sets match (ie r.st_ino == f.st_ino && r.st_dev == f.st_dev) then they must be the same file. (Network fans: is this true for remotely-mounted filesystems?) As for the general case of finding out the name of the file to which output (input) has been redirected to (from), that's more difficult, I think. The only way which comes to mind is to take that inode number and device id from fstat() and run system ("ncheck -i inode filesystem") on them. This takes a while, but beats rewriting the code to search through the directory structure (and your code would take as long as theirs, I would assume). -- Frank Bicknell; 1405 Main St, Ste 709; Sarasota, FL 34236-5701 killer!usource!frankb
md@sco.COM (Michael Davidson) (03/01/89)
In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: >Anyway, can someone tell me how to determine (in C) >if output is being redirected, or more precisely, how to determine the >file output is being redirected to. You can determine the type of file associated with your standard output (or any other file descriptor) by using fstat(). This will tell you the type of file (regular, block special, character special, fifo) and the device and inode #. There is no easy way of going from a device and inode # to a pathname, short of searching through the entire directory hierarchy on the appropriate filesystem (or invoking ncheck to do it for you) - remember also that the file may have many links to it or, by the time you go looking for the path name, it may have none.... cat simply checks whether it's output has been redirected to a regular file and, if it has, does a stat() of each of it's input files, comparing device and inode # with that of the output file - if it finds a match it reports the error "cat: input foo is output".
daveh@marob.MASA.COM (Dave Hammond) (03/01/89)
In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: >.................. Anyway, can someone tell me how to determine (in C) >if output is being redirected, or more precisely, how to determine the >file output is being redirected to. The cat command does this [...] > > cat catfile > catfile >produces the error "cat: input catfile is output". 1. Determine if your stdout has been redirected (isatty(fileno(stdout)) will fail if stdout is redirected). 2. Do an fstat() on fileno(stdout), and a stat() on the other file in question. 3. Compare the st_ino and st_dev members of the two stat structures. If the inode (st_ino) and device-of-directory-entry (st_dev) for the two match, your standard output and the other file are the same. Hope this helps. -- Dave Hammond daveh@marob.masa.com
arnold@mathcs.emory.edu (Arnold D. Robbins {EUCC}) (03/02/89)
>In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: >> Anyway, can someone tell me how to determine (in C) >>if output is being redirected, or more precisely, how to determine the >>file output is being redirected to. The cat command does this (at In article <475@ispi.UUCP> jbayer@ispi.UUCP (Jonathan Bayer) writes: >Use the stat() and fstat() functions, then compare the inode numbers >in the structure. If they are the same then the two files are identical. Rather, compare the device and inode numbers, and if both are the same the two files are really the same file. Two files on two different filesystems (i.e. devices) can both have the same inode numbers. -- "Unix is a Registered | Arnold Robbins -- Emory University Computing Center Bell of AT&T Trademark | DOMAIN: arnold@unix.cc.emory.edu Laboratories." | UUCP: gatech!emory!arnold PHONE: +1 404 727-7636 -- Donn Seeley | BITNET: arnold@emoryu1 FAX: +1 404 727-2599
guy@auspex.UUCP (Guy Harris) (03/02/89)
>In BSD UNIX, you can fstat(2) stdout to determine if the output is a >file or terminal (or whatever) and, what inode number it has. In *any* UNIX worth of the name, you can do that; I know of none so feeble-minded that they don't allow that. >Since several file names can have the same inode, you can't tell exactly >what file name was specified, but the inode number should be enough >information for cat and other such applications. It's certainly almost enough for "cat", since all it cares about is whether any of the input files are the same as the output file or not. The inode number isn't enough, however; you also need the file system identifier, which is in the "st_dev" field. If two files have the same "st_dev" and "st_ino", they're the same file, otherwise not.
guy@auspex.UUCP (Guy Harris) (03/02/89)
>You may want to investigate the isatty() function call. I believe that >you can use something like: isatty(stdout) which will tell you if >standard out is going to a terminal (the usual case), or if it has been >redirected via a pipe or into a file. We've been here before. No, "isatty(stdout)" won't tell you anything of the sort. "isatty" takes a file descriptor, *not* a standard I/O "FILE *". "isatty(fileno(stdout))", or "isatty(1)", will tell you whether the standard output is a tty or not.
guy@auspex.UUCP (Guy Harris) (03/02/89)
>Use the stat() and fstat() functions, then compare the inode numbers >in the structure. If they are the same then the two files are identical. Wrong. If the inode numbers (st_ino) *AND* the file system IDs (st_dev) are the same, then the two files are identical. If just the inode numbers are the same, you can't conclude anything about whether the files are the same or not. They could have the same inode number but be on two different file systems; inode numbers are *not* unique across file systems.
jbayer@ispi.UUCP (Jonathan Bayer) (03/02/89)
In article <1105@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes: } } }Use the stat() and fstat() functions, then compare the inode numbers } }in the structure. If they are the same then the two files are identical. } }Wrong. If the inode numbers (st_ino) *AND* the file system IDs (st_dev) }are the same, then the two files are identical. If just the inode }numbers are the same, you can't conclude anything about whether the }files are the same or not. They could have the same inode number but be }on two different file systems; inode numbers are *not* unique across }file systems. I stand corrected. Working on one filesystem for a while tends to make one forget that the inodes can come from multiple filesystems. JB -- Jonathan Bayer Beware: The light at the end of the Intelligent Software Products, Inc. tunnel may be an oncoming dragon 19 Virginia Ave. ...uunet!ispi!jbayer Rockville Centre, NY 11570 (516) 766-2867 jbayer@ispi.UUCP
guy@auspex.UUCP (Guy Harris) (03/03/89)
>One way which comes to mind (this might be the hard way) is >to use stat() on the file and fstat() on stdout. The only "easier" way might be to open the file first and do an "fstat" on it as well; it's probably slightly more efficient. >Then you compare st_ino and st_dev in both returned structures. If both >sets match (ie r.st_ino == f.st_ino && r.st_dev == f.st_dev) >then they must be the same file. (Network fans: is this true >for remotely-mounted filesystems?) It's true of the SunOS NFS implementation, and probably on all NFS implementations derived from it. The AT&T S5R3 RFS implementation looks as if it attempts to preserve this property, also. Any file system implementation that *doesn't* preserve that property is broken; POSIX quite explicitly says that "st_dev" and "st_ino" uniquely identify a file.
david@wubios.wustl.edu (David J. Camp) (03/04/89)
In article <7419@pyr.gatech.EDU> curci@stat.fsu.edu (Ray Curci (scri)) writes: :>In article <10@sherpa.UUCP> rac@sherpa.UUCP (Roger A. Cornelius) writes: :>>... Anyway, can someone tell me how to determine (in C) :>>if output is being redirected, or more precisely, how to determine the :>>file output is being redirected to. :>>Roger rac@sherpa :>> uunet!sherpa!rac :> :>You may want to investigate the isatty() function call. I believe that :>you can use something like: isatty(stdout) which will tell you if :>standard out is going to a terminal (the usual case), or if it has been :>redirected via a pipe or into a file. :> :>ray curci I just received umpteen replies about this. The function call is isatty(fileno(stdout)); -David- -- Bitnet: david@wubios.wustl ^ Mr. David J. Camp Internet: david%wubios@wucs1.wustl.edu < * > Box 8067, Biostatistics uucp: uunet!wucs1!wubios!david v 660 South Euclid Washington University Medical School Saint Louis, MO 63110
les@chinet.chi.il.us (Leslie Mikesell) (03/05/89)
In article <1111@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes: >>Then you compare st_ino and st_dev in both returned structures. If both >>sets match (ie r.st_ino == f.st_ino && r.st_dev == f.st_dev) >>then they must be the same file. (Network fans: is this true >>for remotely-mounted filesystems?) >It's true of the SunOS NFS implementation, and probably on all NFS >implementations derived from it. The AT&T S5R3 RFS implementation looks >as if it attempts to preserve this property, also. Does st_dev become unique for each remote filesystem or does it just get a bit set to indicate that it is remote? If the latter case is true then the test above might falsely indicate that files on two different remote systems were the same file. Hmmm, cpio and tar might get confused also and think the files should be linked - something to consider with the versions that only store the first copy in the archive (GNUtar, PAX, perhaps others). Les Mikesell