/* $Header$*/
/*
 * Copyright © 2003 Keith Packard and Bart Massey.
 * All Rights Reserved.  See the file COPYING in this directory
 * for licensing information.
 */

extend namespace File {
    public file stdnull () { 
	static bool set = false;
	static file f;
	if (!set)
	    f = open("/dev/null", "r+");
	return f;
    }

    public typedef union {
	file input;
	file output;
	file error;
    } childfd;

    public int mkchild(string path, string[*] argv, childfd fds ...) 
	/*
	 * Call filter transforming 'fds' into an array of three files.
	 * This is what happens when you fork()
	 */
    {
	file[3] filter_fds = { stdnull(), ... };
	for (int i = 0; i < dim(fds); i++) {
	    union switch(fds[i]) {
	    case input f: filter_fds[0] = f; break;
	    case output f: filter_fds[1] = f; break;
	    case error f: filter_fds[2] = f; break;
	    }
	}
	return filter(path, argv, filter_fds);
    }

    public namespace FileGlobals {

	public int getchar ()
	    /* return getc (stdin); */
	{
	    return getc (stdin);
	}

	public void ungetchar (int ch)
	    /* ungetc (ch, stdin); */
	{
	    ungetc (ch, stdin);
	}

	public void putchar (int c)
	    /* putc (c, stdout) */
	{
	    putc (c, stdout);
	}

	public int getbyte ()
	    /* return getb (stdin) */
	{
	    return getb (stdin);
	}

	public void putbyte (int b)
	    /* putb (b, stdout) */
	{
	    putb (b, stdout);
	}

	public string fgets (file f)
	    /*
	     * Return a line from 'f' as a string.
	     * The trailing newline will be stripped off.
	     */
	{
	    string	s;
	    int	c;

	    s = "";
	    while (!end(f))
	    {
		c = getc (f);
		switch (c) {
		case '\n':
		    return s;
		default:
		    s = s + String::new (c);
		}
	    }
	    return s;
	}

	public string gets ()
	    /* return fgets (stdin); */
	{
	    return fgets (stdin);
	}
    }
    
    public import FileGlobals;
}
public import File::FileGlobals;
