You've invented buffered I/O.
#include <u.h>
#include <libc.h>
#include <bio.h>
void
usage(void)
{
fprint(2, "usage: runecvt [-l | -t | -u] [file...]\n");
exits("usage");
}
void
convert(Biobuf *bin, Biobuf *bout, Rune (*fn)(Rune))
{
int c;
while((c = Bgetrune(bin)) != -1)
Bputrune(bout, fn(c));
}
void
main(int argc, char **argv)
{
int i;
Biobuf *b, bin, bout;
Rune (*fn)(Rune);
fn = toupperrune;
ARGBEGIN{
case 'l':
fn = tolowerrune;
break;
case 't':
fn = totitlerune;
break;
case 'u':
fn = toupperrune;
break;
default:
usage();
}ARGEND
Binit(&bout, 1, OWRITE);
if(argc == 0){
Binit(&bin, 0, OREAD);
convert(&bin, &bout, fn);
}else{
for(i=0; i<argc; i++){
if((b = Bopen(argv[i], OREAD)) == nil)
sysfatal("open %s: %r", argv[i]);
convert(b, &bout, fn);
}
}
Bterm(&bout);
exits(nil);
}