scs@adam.mit.edu (Steve Summit) (11/16/90)
[I've included comp.unix.programmer since this is a bit of a tutorial which gets fairly Unix-specific...] In article <roarment.658423394@faui09> roarment@faui09.informatik.uni-erlangen.de (Roberto Armenti) writes: >i'm working on a programm that takes >its input from stdin. If however someone chooses to redirect the input >to a file, so that data is read from that file, how can I figure that >out ( Prompting and so on should not occur in this case ) ??? In article <1990Nov13.073315.2831@ericsson.se> epames@eos.ericsson.se writes: >isatty(fileno(stdin)) should do what you want. I have seen it implemented >on Unix, MS_DOS and CP/M systems but I can't say how portable it is. Correct (but see below for one addition). (Notwithstanding my crosspost to comp.unix, isatty does indeed exist on non-Unix systems.) >I also find it very handy to determine when to give a usage message >when file names are omitted from the command line, I hate programmes >that do nothing when I make a mistake. Excellent! I hit upon this maneuver myself just last week. The implication may not be obvious, so it deserves some explication. Many, many utilities which follow the "everything's a text stream" model usefully read from their standard input if they are invoked without explicit input filenames on their invocation command line. That is, the code looks something like this: #include <stdio.h> main(argc, argv) int argc; char *argv[]; { if(argc <= 1) process(stdin, "standard input"); else { int argi; for(argi = 1; argi < argc; argi++) { FILE *ifd = fopen(argv[argi], "r"); if(ifd == NULL) perror(argv[argi]); else { process(ifd, argv[argi]); (void)fclose(ifd); } } } exit(0); } The problem is that when you've forgotten what the thing is or how it works or what option flags it takes, you can't just invoke it with no arguments and get a usage message. Therefore, a useful wrinkle is if(argc <= 1) { if(isatty(fileno(stdin))) { fprintf(stderr, "usage: ...\n"); exit(1); } process(stdin); } The one drawback here is that the "expert" user now can't type in raw input directly. (Does the Unix beginner/novice/expert hierarchy include "creates programs with `/lib/ccom | as'"?) If easily-accessible usage messages are more important to you than coddling gurus, just tell the gurus to use cat | yourprogram which will let them type away. (Note that one program which therefore _can't_ receive this treatment is cat itself, which is fine, since you also want to leave cat > file working as expected, although it could again be argued that this is guru-coddling :-) .) In article <14447@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: >What you really want to determine is whether or not input is coming >from an interactive device. >The usual UNIX kludge is to invoke isatty(fileno(stdin)); >it is not a reliable test, since just because something is coming via >a terminal port does not necessarily mean that there is a human typing >the input. Kludge? I doubt this is much of a problem in practice; presumably non-humans (i.e. programs) which have gone to the trouble to talk to another program through a tty or pty are clever enough (and, I should think, rare enough) that they can figure out how to deal with prompts.%% A somewhat bigger problem than noninteractive tty's is the case when stdin is not a tty, but is interactive. Have you (not Doug; I'm just being didactic) ever wondered why /bin/sh has a -i flag? This tells it to be interactive and issue prompts, even when isatty(0) fails. You need this when you're typing at a shell through a pipe or something, which is admittedly rare, but it does happen. (One example, from BSD Unix, is rsh machine sh -i which is a quick-and-dirty rlogin, without .profile/.login overhead, but which uses sockets rather than pty's, so you need -i if you want prompts. A contrived but perhaps more appreciable example would be something like dd conv=lcase | sh -i when your caps lock key is stuck and you don't know about stty lcase, although how you'd type it is another question :-) ...) %% I do not mean to imply that ignoring prompts is easy for a program to do; in fact, it's surprisingly hard. But I'd rather that programs attempt to be useful to large numbers of users, by using isatty if necessary even if it's imperfect, than that they worry about the occasional non-human-but-on-a-tty "user." And, before someone gives me a lecture on the importance, in the toolkit model, of programs' being invokable by other programs, remember that the vast majority of them do so through pipes or files. (In fact, I could give quite a lecture on the importance of programs' being invokable by other programs, and the way it's being forgotten in the rush towards highly interactive, graphical, mouse-based applications, but that's another article.) Steve Summit scs@adam.mit.edu