File:  [MW Coherent from dump] / coherent / b / bin / env / env.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:36 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

static char _version[]="env version 1.0";
/*
 * env - execute a command in an environment
 *
 * usage: env [-] [VARIABLE=value ...] [command args]
 *
 * Executes "command" with "args", modifying the existing environment
 * by doing the requested assignments.  The "-" option means that the
 * environment should be _replaced_ with the list assignements, otherwise
 * the assignments are added to the environment.
 * If "command" is ommitted, the resulting environment is printed.
 */

#include <stdio.h>
#include <string.h>
#include <errno.h>

#define BIG_NUMBER 2048
#define TRUE (1==1)
#define FALSE (1==0)
#define VAR_SEPERATOR '='	/* Seperates an environment variable
				   from its value.  */

void parse_args();
int arglen();
char **argcpy();
char **envncat();
int is_assignment();

/* Flags that tell us about our arguments */
int replace_env = FALSE;
int have_command = FALSE;

int assignment_count;	/* Number of assignments to add to environment.  */
char *first_assignment_argument = NULL;

int i;	/* Generic index, used repeatedly */

char **new_argv;	/* Build new command line here.  */
char **new_envp;	/* Build the new environment here.  */


void
main(argc, argv, envp)
	int argc;
	char *argv[];
	char *envp[];
{
/* Parse arguments.  */
	parse_args(argc, argv);

/* Build the new environment.  */

	if (! replace_env) {
		/* Make enough space for the disjoint union of the two sets of
		 * environment assignments.  This is a guarenteed upper bound.
		 */
		new_envp = (char **) malloc( sizeof(char *)
					     * (arglen(envp)
						+ assignment_count + 1)
			  		   );
		argcpy(new_envp, envp);
	} else {
		/* Otherwise, we only need enough space for the new
		 * environment.
		 */
		new_envp = (char **) malloc( sizeof(char *)
					     * (assignment_count + 1)
			  		   );
	} /* if (! replace_env) */


	envncat(new_envp, first_assignment_argument, assignment_count);


/* Do something--either a command or print the environment.  */
	if (have_command) {
		execvep(new_argv[0], new_argv, new_envp);
		perror(new_argv[0]);
		exit(1);
	} else {
		char **pntr;

		for (pntr = new_envp; *pntr != NULL; ++pntr){
			printf("%s\n", *pntr);
		} /* for pntr in new_envp */

	} /* if have_command */

	exit(0);
}


void
parse_args(argc, argv)
	int argc;
	char *argv[];
{
	int current_arg;

	if (argc > 1) {
		current_arg = 1; /* Start looking at the first argument.  */

		/* - option -- Replace the existing environment.  */
		if (strcmp(argv[current_arg], "-") == 0) {
			replace_env = TRUE;
			++current_arg;
		} /* if first argument is "-" */

		/* Count the number of arguments which are assignments.  */
		for (assignment_count = 0;
		     current_arg < argc;
		     current_arg++, assignment_count++) {

			if (! is_assignment(argv[current_arg])) {
				break;
			}

			if (first_assignment_argument == NULL) {
				first_assignment_argument = &argv[current_arg];
			}

		} /* for (Count the assignments on the command line.  ) */


		if ( current_arg < argc ) {
			/* We broke out of the assignment couting loop
			 * early--this must be a command.
			 */
			new_argv = &argv[current_arg];
			have_command = TRUE;
		} /* if ( current_arg <= argc ) */

	} /* if there are any args */

} /* void parse_args() */



/* Count the number of arguments in an argument vector.
 * arg_vector MUST be NULL terminated!
 */
int
arglen(arg_vector)
	char **arg_vector;
{
	int count;
	
	for (count = 0; arg_vector[count] != NULL; ++count) {
	}

	return(count);
} /* arglen() */


/* Copy src argument vector to dest argument vector (pointer copy only).
 */
char **
argcpy(dest, src)
	char **dest, **src;
{
	while (*src != NULL) {
		*dest++ = *src++;
	} /* while (walk two pointers down envp and new_envp) */
	*dest = NULL;
	return (dest);
} /* char **argcpy() */




/* Merge one environment onto another, overwriting duplicate
 * variable names.  Compare at most n patterns.
 */
char **
envncat(dest, src, n)
	char **dest, **src;
	int n;
{
	char **dest_walker;
	char *sep_loc;	/* Seperator ("=") location in assignment */
	int i;
	int name_size;	/* Number of characters in a given variable name */

	for (i=0; *src != NULL && i < n; ++i, ++src) {

		/* Extract the variable name from the assignment *src.  */
		if ((sep_loc = strchr(*src, VAR_SEPERATOR)) == NULL) {
			fprintf(stderr,
				"Programming error:  %s is not an assignment\n",
				*src);
			exit(1);
		}
		name_size = sep_loc - *src;
		
		/* Look for variable part of *src in dest.
		 * Point at end if not found.
		 */
		for(dest_walker = dest; *dest_walker != NULL; ++dest_walker) {

			/* NB: the + 1 is so the "=" is compared too.  */
			if(strncmp(*dest_walker, *src, name_size + 1) == 0) {
				/* We have found an exact match.  */
				break;
			} /* if *dest_walker and *src are same variable */

		} /* for Walk down dest environment */

		/* Checkpoint - *dest_walker either matches *src or is NULL.  */

		/* WARNING: possible memory leak--
		 *	    *dest_walker is always clobbered.
		 *	     Usually *dest_walker was copied from global
		 *	     envp, so it isn't really lost memory.
		 */
		*dest_walker = *src;

	} /* for (i=0; *src != NULL && i < n; ++i, ++src) */

	return(dest);
} /* char ** envncat() */

int
is_assignment(s)
	char *s;
{
	if ( strchr(s, VAR_SEPERATOR) != NULL ) {
		return(TRUE);
	} else {
		return(FALSE);
	}

} /* int is_assignment() */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.