[alt.folklore.computers] "Invalid null command"

rcd@ico.isc.com (Dick Dunn) (04/02/91)

Bourne shell users, accustomed to creating or emptying a file with a
command like:
	>splot
or rewinding a tape with:
	</dev/mt0
are occasionally annoyed to find that csh rejects this syntax with the
confusing message "Invalid null command".  (It is confusing because there
is no such thing as a *valid* null command; attempts to find one will only
end in frustration.)

This can be solved as follows:
	touch /bin/IEFBR14
	chmod 755 IEFBR14
The name is chosen for historical relevance, since most of us who still
use the Bourne shell are Luddites or recidivists anyway.  Of course,
	IEFBR14 >splot
seems a bit naked without some slashes and an EXEC PGM=, but that's the
way these modern systems are...

Some folks may note a more-than-coincidental resemblance between this
version of IEFBR14 and older versions of /bin/true.  So it is, but our
example lacks the sophistication of the modern System V "true" command,
which is now 9 lines long and includes
	- an entirely superfluous :
	- five lines of copyright notice (so don't y'all go trying to use
	  empty files any more; AT&T owns the copyright)
	- a #ident--which, of course, is meaningless to the shell, but
	  reveals the interesting fact that we're now up to version 2.3
	  of a formerly-empty file

However, the preceding was only for illustration anyway.  Nobody wants a
dirty old shell script for the null command; it should of course be a C
program for efficiency.  So here we have the first cut at IEFBR14.c:
	main()
	{
	}
This also serves only for illustration; it is historically accurate in that
it contains the same bug as IBM's original IEFBR14.  (It may be of some
interest that IEFBR14 proved the old CS aphorism "Every program contains
at least one bug and can be shortened by one instruction" at the inductive
limit:  It was a single instruction which didn't work...but I digress...) 
Here's the first correction:
	main()
	{
		exit(0);
	}
But to make this proper in today's brave new world, we need <stdlib.h>.
Also, for formality's sake and international propriety, we should add the
normally-obligatory setlocale() call (actually not necessary--this may be
the *only* program for which that's true--but it's hard to pass up poking
fun at a requirement to set a default explicitly), and this in turn
requires <locale.h>.  OK, so here's the penultimate version of IEFBR14.c,
our properly ANSI and internationalized (unless I screwed up) program-to-
do-nothing:

	#include <stdlib.h>
	#include <locale.h>

	#ifndef	lint
	static char *sccsid = "%W% - %E%";
	#endif

	/*ARGSUSED*/
	main(argc,argv)
	int	argc;
	char	**argv;
	{
		setlocale(LC_ALL, "");
		exit(0);
	}

To create the final version, all you need is your local draconian
corporate screenful of copyright notice and disclaimer.
-- 
Dick Dunn     rcd@ico.isc.com -or- ico!rcd       Boulder, CO   (303)449-2870
   The Official Colorado State Vegetable is now the "state legislator".

tom@sco.COM (Tom Kelly) (04/03/91)

In article <1991Apr2.005620.11434@ico.isc.com> rcd@ico.isc.com (Dick Dunn)
pedantically derives the C version of good old IEFBR14.  In that spirit,
here are some pedantic comments:

First try:

>	main()
>	{
>	}
 ...

>Here's the first correction:
>	main()
>	{
>		exit(0);
>	}
>But to make this proper in today's brave new world, we need <stdlib.h>.

Actually, no you don't.  The ANSI C Standard, Section 2.1.2.2
"Hosted Environment", subparagraph titled "Program termination" says:

	A return from the initial call to the main function is equivalent
	to calling the exit function with the value returned by the
	main function as its argument ... [Jan 11 '88 draft]

So, we can replace "exit(0)" with "return(0)".

>Also, for formality's sake and international propriety, we should add the
>normally-obligatory setlocale() call (actually not necessary--this may be
>the *only* program for which that's true--but it's hard to pass up poking
>fun at a requirement to set a default explicitly), and this in turn
>requires <locale.h>.  OK, so here's the penultimate version of IEFBR14.c,
>our properly ANSI and internationalized (unless I screwed up) program-to-
>do-nothing:
>
>	#include <stdlib.h>
>	#include <locale.h>
>
>	#ifndef	lint
>	static char *sccsid = "%W% - %E%";
>	#endif
>
>	/*ARGSUSED*/
>	main(argc,argv)
>	int	argc;
>	char	**argv;
>	{
>		setlocale(LC_ALL, "");
>		exit(0);
>	}

Not really.  Section 4.4.1.1 says:

	At program startup, the equivalent of "setlocale(LC_ALL, "C")"
	is executed.

This is the responsibility of the implementation, (e.g., done by crt0)
so there is a well-defined default locale.  Since this program produces no
locale-dependent output, there is no need to change the locale from the
default.

Furthermore, the declaration of main could be "int main(void)":

	#ifndef	lint
	static char *sccsid = "%W% - %E%";
	#endif

	int
	main(void)
	{
		return(0);
	}


That doesn't look quite so bad.  Unfortunately, it is not strictly
conforming, because the termination status is implementation defined.
This is because the committee could not agree that a return (or exit)
value of zero means "success"; there are systems on which this is not
true.  [I won't say more, they know where I live].  So, we have
to change "return(0)" to "return(EXIT_SUCCESS)", which, tragically,
requires "#include <stdlib.h>".  But this is not required if you
only want to run on Unix (and _probably_ POSIX-conforming systems).

>To create the final version, all you need is your local draconian
>corporate screenful of copyright notice and disclaimer.

You forgot the 40 pounds of paperwork to get it included in the
release ...

Tom Kelly  (416) 922-1937
SCO Canada, Inc. (formerly HCR) 130 Bloor St. W., Toronto, Ontario, Canada
{utzoo, utcsri, uunet}!scocan!tom or tom@sco.com

rbj@uunet.UU.NET (Root Boy Jim) (04/04/91)

In article <PPDuZ1w164w@dogface>  writes:
?rcd@ico.isc.com (Dick Dunn) writes:
?> [users] are occasionally annoyed to find that csh rejects this syntax
?> with the confusing message "Invalid null command".
?
?What about
?	cat /dev/null > splot
?to create an empty file?  Not as, umm, Rube Goldberg-ish as your program,
?though.

OVERKILL! There is a builtin command, `:' which works nicely,
and is even easy to type. To empty a file, type :>file
-- 
		[rbj@uunet 1] stty sane
		unknown mode: sane

tom@sco.COM (Tom Kelly) (04/07/91)

In a recent article, I suggested some changes to Dick Dunn's ANSI C version
of IEFBR14.  I originally suggested that exit(0) could be replaced
by return(0), and the setlocale() could be dropped, eliminating the need
for include files.  But then I said that return(0) was non portable;
it had to be EXIT_SUCCESS, which required an include file.

Apparently, Gordon Burditt (gordon@sneaky.lonestar.org) can read
better than I can, since he pointed out in mail that the section on exit()
in the C standard makes a special case for zero as successful
termination.  So:

int
main(void)
{
	return 0;
}

is all you need for IEFBR14.

As penance, I suppose I should read the standard again, but
I've already lost as much hair as I can afford.

Tom Kelly  (416) 922-1937
SCO Canada, Inc. (formerly HCR) 130 Bloor St. W., Toronto, Ontario, Canada
{utzoo, utcsri, uunet}!scocan!tom or tom@sco.com