[comp.os.msdos.programmer] More on sensing stdout redirection in C

naga@wet.UUCP (Peter Davidson) (05/07/91)

>>In article <collinsa.672410890@p4.cs.man.ac.uk>, collinsa@p4.cs.man.ac.uk
>>(Adrian Collins) writes:
>>>[deletions]
>>> As I've had quite a few requests for responses to my original query, here
>>> is a method of working out whether STDIN and STDOUT are being redirected.
>>> This is a slightly altered version of the code sent to me by
>>> Nick FitzGerald.
>>
>>Adrian should have pointed out that the code I sent him was posted late
>>last year (to this group ?) by Peter Davidson.
>>
>>If Peter's still reading along, thanks and apologies (I'm presumptuous
>>enough to extend apologies on Adrian's behalf as well, 8-) ).
>>
>>Nick.
>
>Oops.  sorry about that.  Thanks Peter Davidson, and sorry about that Nick.
>
>Adrian

Well actually my attention was temporarily distracted by the goings-on
in alt.msdos and comp.lang.c.  I'm glad that the code to detect redir-
ection of stdout has been found useful (it sure gets around).  I should,
however, point out that Adrian's alteration of the bit mask, from 0x2 to
0x82, is unnecessary.  My original code (given below) detects redirection
both to the printer and to a disk file.

unsigned int get_device_data(int handle)
{
union REGS regs;

regs.h.ah = 0x44;           /*  function number  */
regs.h.al = 0;              /*  subfunction number  */
regs.x.bx = handle;         /*  file or device handle  */
int86(0x21,&regs,&regs);
return ( regs.x.dx );
}

int output_redirected(void)
{
return ( ! ( get_device_data(fileno(stdout)) & 0x2 ) );
}

To detect redirection of stdout the only question is whether bit 1 of
the value returned by get_device_data() is 0 or 1.  Changing the bit
mask as suggested has no effect on the behavior of the function,
regardless of whether redirection is to printer or to file.

Thanks, however, to Adrian for suggesting the adaptation for redirection
of stdin.  And following up on Adrian's concern with bit 7, the code can
be modified to return explicitly whether redirection (if in effect) is
to (or from) a device or a disk file, as follows:

/*  this returns
 *  0 if output not redirected from stdout
 *  1 if redirected to printer or some other device
 *  2 if redirected to a disk file
 */
int output_redirected(void)
{
int result = 0;

switch ( get_device_data(fileno(stdout)) & 0x82 )
    {
    case 0x0:
        result++;       /*  no break  */
    case 0x80:
        result++;
    }
return ( result );
}

/*  this returns
 *  0 if input not redirected from stdin
 *  1 if redirected from some other device
 *  2 if redirected from a disk file
 */
int input_redirected(void)
{
int result = 0;

switch ( get_device_data(fileno(stdin)) & 0x81 )
    {
    case 0x0:
        result++;       /*  no break  */
    case 0x80:
        result++;
    }
return ( result );
}

To test these functions one can use:

void main(void)
{
switch ( output_redirected() )
    {
    case 0: printf("\nOutput not redirected.\n");   break;
    case 1: printf("\nOutput redirected to device.\n"); break;
    case 2: printf("\nOutput redirected to disk file.\n");
    }

switch ( input_redirected() )
    {
    case 0: printf("\nInput not redirected.\n");   break;
    case 1: printf("\nInput redirected from device.\n"); break;
    case 2: printf("\nInput redirected from disk file.\n");
    }
}

These functions are part of a library of useful routines I'm about to
release.  Anyone wanting further information about this library (and
others) should send a real-world mailing address to wet!naga@cca.ucsf.edu
(or to naga@wet.UUCP).  I have lots of useful stuff lying around here,
but it's quite an effort to pack it all up nicely and get the word out.
Still, I try.

By the way, I wish to relocate permanently to Europe, Canada or perhaps
Oz/NZ, so if anyone knows of someone who can use a good C programmer ...