Missing stdio features.

AAAARRRRGGGGv argv at sri-spam.ARPA
Tue Aug 12 14:18:09 AEST 1986


> Here are the things I have wanted badly enough to add to stdio:
> 

> 
> FILE *fopenfxn(int (*fxn)(), char *mode)
> 	Function-stream I/O.  Returns a FILE*, open for read or write
> 	(not both, "r+" is treated as "r").  When a character is
> 	written to (resp. read from) the stream, the function is
> 	called.  On write, the character written is passed as an
> 	argument; on read, the returned value is returned to the user
> 	(or to scanf etc).

This shouldn't be that hard to do:
first, take the fildes of the open stream, set it to be asynch IO, then loop.
When data is there to be read, you'll get a SIGIO.  For some strange reason,
I seem to remember that this is can only be done on pseudo-tty's or other
types of devices (I use it frequently for windows on the SUN); so I don't know
if this will work well on normal files or sockets.

/* (no error checking here -- don't try this at home without mom's help! */

#include <fcntl.h>
...
int fd = open ("/dev/tty", 0);  /* read a tty for example */
signal (SIGIO, io_handler);  /* this proc will get a sigio if data on a stream
			       is ready to be read */
ioctl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | FASYNC)); /* set async IO */

for (;;)
    looping_proc();
...

io_handler()
{
    char buf[BUFSIZ]l
    puts("Hey, there's data to be read on the fildes!");
    read(fd, buf, BUFSIZ);
    do_something_with_data(buf);
}

> FILE *fopenstr(char *str, int len, char *mode)
> 	An extension to sprintf() and sscanf().  This returns a stream
> 	which performs I/O to a string (this makes sprintf() and
> 	sscanf() unnecessay, though they are still convenient).

I request you more fully describe this functionality. I don't see how adding
the routines of an IO library is going to speed up what sprintf and sscanf
already do.  Perhaps to do something like this would be "interesting", but
that's about it.  Again, please elaborate.

> unfdopen(FILE *f)
> 	Undoes fdopen(), that is, closes the FILE* without close()ing
> 	the underlying file descriptor.
This would be nice.

> Unfdopen is trivial; fopenfxn and fopenstr are implemented by making
> the stream appear unbuffered to putc and getc and then changing _flsbuf
> and _filbuf to add the functionality.

Looking at the source to puts (fputs) and so forth, I've found that it
is much faster to never unbuffer anything and to simply macro that which
you'd like to have "unbuffered":
#define unbuffered_puts(s,f)   fputs(s,f), fflush(f)

The reason for this is that if the data is unbuffered, fputs merely sets
the buffer to a buffer within the routine, sets a few flags, goes thru a
while loop, using the macro in stdio to putc to the stream, then fflushes
again, finally resettting all the flags it started with.  Finallly (not
that this has anything to do with it), it returns the last character put
to the stream (undocumented).

In any event, what's preventing you from free()ing the structure and leaving
the fd open?  The biggest problem with routines that people write that do
popen like
read_write_popen(command, &Stdin, &Stdout, &Stderr);
/* open a process and be able to read and write to/from it */
is that they pipe for each fildes, fdopen, and in case of error,
return without closing all open fildes's, unallocating the FILE*'s
and closing the process if necessary. A more elegant routine to 
unfdopen (as you described) would be a matter of convenience.


dan  <argv at sri-spam.arpa>

"Wouldn't ya like to be a pointer, too...
     (be a pointer, be a double pointer, [repeat and fade])"



More information about the Comp.lang.c mailing list