text: /**
   * @file
   * @brief Run program in modified environment or print current one
   *
   * @date 28.02.13
   * @author Ilia Vaprol
   *          - Initial implementation
   * @author Dmitry Danilov
   *          - Program invocation in modified environment
   */
  
  #include <unistd.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <errno.h>
  
  int main(int argc, char *argv[]) {
  	int opt;
  	int clear_env = 0;
  	int print_null = 0;
  	
  	while (-1 != (opt = getopt(argc, argv, "0ihu:"))) {
  		switch (opt) {
  			case '0':
  				print_null = 1;
  				break;
  			case 'i':
  				clear_env = 1;
  				break;
  			case 'u':
  				if (-1 == unsetenv(optarg)) {
  					perror("env: unsetenv");
  					return -errno;
  				}
  				break;
  			case '?':
  				printf("Try '%s -h` for more information.\n", argv[0]);
  				return -EINVAL;
  			case 'h':
  				printf("Usage: %s [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARGS]...]\n", argv[0]);
  				return 0;
  			default:
  				break;
  		}
  	}
  	if (optind < argc && !strcmp(argv[optind], "-")) {
  		clear_env = 1;
  		++optind;
  	}
  	
  	if (clear_env) {
  		if (clearenv()) {
  			perror("env: clearenv");
  			return -errno;
  		}
  	}
  
  	while ((optind < argc) && (NULL != strchr(argv[optind], '='))
  			&& ('=' != argv[optind][0])) {
  		if (putenv(argv[optind]) == -1) {
  			perror("env: putenv");
  			return -errno;
  		}
  		++optind;
  	}
  	
  	/* difference from posix: execv return 0 and does not set errno on errors */
  	if (optind < argc) {
  		execv(argv[optind], argv+optind);
  		return -errno;
  	}
  	
  	if (environ)
  		for (char **env = environ; *env; env++)
  			printf("%s%c", *env, print_null ? '\0' : '\n');
  	return 0;
  }
  