Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!purdue!decwrl!ucbvax!tut.cis.ohio-state.edu!rutgers!rochester!uhura.cc.rochester.edu!ur-valhalla!moscom!jgp From: jgp@moscom.UUCP (Jim Prescott) Newsgroups: comp.unix.wizards Subject: Re: friendly messages Summary: Code for a simple way to print error messages Message-ID: <1411@moscom.UUCP> Date: 29 Mar 89 06:23:02 GMT References: <435@laic.UUCP> <955@auspex.UUCP> <9218@bloom-beacon.MIT.EDU> <9780@smoke.BRL.MIL> <3314@ficc.uu.net> Reply-To: jgp@moscom.UUCP (Jim Prescott) Organization: Moscom Corp., E. Rochester, NY Lines: 89 In article <3314@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes: >Perhaps we (the usenet community) should spec a better interface: A nice quick 90% solution is a printf-like function that writes to stderr, prepends the program name to the message, and can append the system error message. Something like: if (open(fname, O_RDRW, 0) == -1) errmsg("Cannot open \"%s\" for read/write -- ", fname); would output: prog: Cannot open "somefile" for read/write -- Read-only file system This makes it fairly painless for the programmer to come up with an informative message without worrying about the little details. Trying to use perror to get a nice message is too much work, which is probably why it isn't used as often as it should be. The problems in implementing this are: - finding the program name; most likely needs to be stashed away while in main(). (It would have been nice if the ANSI-C folks had invented some globals to hold copies of main's arguments. (I know it isn't their job to invent :-).) - deciding where to put the system error. The code below tacks it on the end of the message iff it doesn't end in a newline. Not a great solution but certainly much simpler than doing a new % escape. An enhancement would be introduce error levels (we use FATAL, ERROR, INFO and DEBUG) and provide some way to specify which you want to see (we default to FATAL & ERROR). I've even enclosed a function to implement it below (about 99% of which is from an article on varargs by Chris Torek). I'm not sure how portable vsprintf is, its on our sun but wasn't in V7 so it probably isn't universal. If anyone can tell me where to get a pd vsprintf I'd be grateful. While we're on the subject, Guy mentioned TECO error messages but not how nifty they actually are. You can tell it to print just the 3 letter code (eg. ?FNF), to print the 1 line error (eg. ?FNF File not found.) or to print the 1 line message followed by a couple of likely paragraphs out of the manual (this is called "war and peace" mode). Its flexible even if not overly useful (I can't imagine using anything other than 1 line messages. Maybe the 3 letter only would be good on 110 baud ttys). ========= varargs version #include int errmsg(va_alist) va_dcl /* N.B.: no semicolon */ { int ret; char *fmt; va_list ap; char buf[1024]; /* shouldn't be fixed size */ va_start(ap); fmt = va_arg(ap, char *); ret = vsprintf(buf, fmt, ap); va_end(ap); fprintf(stderr, "%s: %s", Progname, buf); if (*(buf + strlen(buf) - 1) != '\n') perror(""); return ret; } #endif ========= stdarg version #include int errmsg(char *fmt, ...) /* the `...'s are part of the syntax */ { int ret; va_list ap; char buf[1024]; /* shouldn't be fixed size */ va_start(ap, fmt); ret = vsprintf(buf, fmt, ap); va_end(ap); fprintf(stderr, "%s: %s", Progname, buf); if (*(buf + strlen(buf) - 1) != '\n') perror(""); return ret; } -- Jim Prescott moscom!jgp@cs.rochester.edu {rutgers,ames,harvard}!rochester!moscom!jgp