[net.sources] 'env' non-proprietary rewrite

ignatz@ihuxx.UUCP (Dave Ihnat, Chicago, IL) (08/30/84)

Following is the source of a rewrite of the 'env' command,
as mentioned in net.{unix-wizards|micro|unix}, in shar format.
Simply cut on the dotted line and run as a shellscript to extract
the source and man page.
Please feel free do use and distribute; bug reports/fixes and comments?
Mail to me.

	Dave Ihnat
	ihuxx!ignatz
------------------------CUT-------------------------------------------
echo x - env.c
cat >env.c <<'!E!O!F!'
/*
 * env.c - display user environment, or set for command execution
 *
 *	Copyright (c) 1984 by David M. Ihnat
 * 
 * Usage:  env [-] [ name=val]... [ command [arg]...]
 *
 * where:
 *
 *	-		: Only pass on newly-defined names; otherwise,
 *				add and modify as indicated.
 *
 *	name=val 	: name-value pairs to be added to the env, or
 *				changed.
 *
 *	command [arg]	: command to be executed with the changed
 *				environment, if any.
 *
 * This command is a total rewrite of the command of the same name on
 * the AT&T Unix(Tm) System V release.  There is no proprietary code
 * involved; it is available for use and distribution, provided these
 * notices remain intact, and it is not sold for profit.  Every
 * effort was made to recreate the behavior of the 'official' version,
 * so I would suggest maintaining this congruence. The user assumes all
 * liability for any damages, real or incidental, arising from use of
 * this program.  Caveat Utilitor! -Dave Ihnat, ihuxx!ignatz
 */

#include <stdio.h>

#define	NELTS	128
char	*nenv[NELTS];	/* New environment structure */
char	**endaddr = &nenv[NELTS-1];

/* A bit of magic from poking around in execvp's namelist. */
extern char **environ;

char	*empty = NULL;	/* For an empty environment pointer */

extern int errno;
extern char *sys_errlist[];

main(argc,argv,envp)
int argc;
char **argv;
char **envp;
{
	argc--;
	argv++;

	/* First, should the environment be passed through, or not? */
	if(argc && strcmp(*argv, "-") == 0)
	{
		envp = &empty;	/* Throw out the extant  environment */
		argc--;		/* And get past the flag */
		argv++;
	}

	/* Now, pass on existing arguments */
	for(;*envp != NULL; envp++)
		newval(*envp);

	/* And add or replace any command-line environment variables */
	while(*argv != NULL)
	{
		/* Have to check this for end of environment mods/adds */
		if(strrchr(*argv,'=') == NULL)
			break;

		newval(*argv++);
	}

	/* Now, if no command, just print the environment */

	environ = nenv;
	if(*argv == NULL)
	{
		while(*environ != NULL)
			puts(*environ++);
		exit(0);
	}else
	{
		execvp(*argv,argv); /* Gets environment from 'environ' */
		puts(sys_errlist[errno],stderr);
		puts(": ",stderr);
		puts(*argv,stderr);
		putc('\n',stderr);
		exit(1);
	}
}

int
newval(newname)
char *newname;
{
	register char **eptr = nenv;

	for(;*eptr != NULL;eptr++)
	{
		if(eptr>=endaddr)
		{
			puts("too many values in environment\n",stderr);
			eptr = nenv;
			while(*eptr != NULL)
				puts(*eptr++);
			exit(1);
		}

		if(!strncmp(newname,*eptr,(strrchr(*eptr,'=')-2)))
		{ /* Found a match--it's a replacement */
			*eptr = newname;
			return;
		}
	}
	/* New value */
	*eptr = newname;
}
!E!O!F!
echo x - env.mp
cat >env.mp <<'!E!O!F!'
.TH ENV 1 ""
.SH NAME
env \- set environment for command execution
.SH SYNOPSIS
\fBenv\fP [\-] [ name=value]... [ command [ arg]... ]
.SH DESCRIPTION
\fIEnv\fP obtains the current \fIenvironment\fP, modifies it according
to its arguments, then executes the command with the modified
environment.  Arguments of the form \fIname=value\fP are merged into
the inherited environment before the command is executed.  The
\fB\-\fP flag causes the inherited environment to be ignored
completely, so that the command is executed with exactly the
environment specified by the arguments.
.PP
If no command is specified, the resulting environment is printed, one
name\-value pair per line.
.SH SEE ALSO
sh(1),exec(2),profile(4),environ(5).
.SH CAVEATS
This program is a complete rewrite of the Bell Laboratories command of
the same name; no part of the original source or manual is included.
Therefore, you may feel free to use it, and its source, without violation
of \fPany\fP contract agreements.  However, I retain the copyright in order to
specify it remain available for use by all and sundry, without
cost.  Feel free to modify as necessary, although I went to great
pains to recreate the behavior of the original command; I would suggest
this congruence be maintained.
.PP
Along the same lines, although I've made a reasonable effort to test
the behavior of the original \fIenv\fP and reproduce it,
there are no guarantees.  The user assumes all liability for any loss,
either direct or incidental, that may be incurred through use of this
command.  I do ask that any bugs (and, hopefully, fixes) be reported
back to me as encountered. \- David M. Ihnat, ihuxx!ignatz
!E!O!F!