|
|
1.1 ! root 1: static char _version[]="env version 1.0"; ! 2: /* ! 3: * env - execute a command in an environment ! 4: * ! 5: * usage: env [-] [VARIABLE=value ...] [command args] ! 6: * ! 7: * Executes "command" with "args", modifying the existing environment ! 8: * by doing the requested assignments. The "-" option means that the ! 9: * environment should be _replaced_ with the list assignements, otherwise ! 10: * the assignments are added to the environment. ! 11: * If "command" is ommitted, the resulting environment is printed. ! 12: */ ! 13: ! 14: #include <stdio.h> ! 15: #include <string.h> ! 16: #include <errno.h> ! 17: ! 18: #define BIG_NUMBER 2048 ! 19: #define TRUE (1==1) ! 20: #define FALSE (1==0) ! 21: #define VAR_SEPERATOR '=' /* Seperates an environment variable ! 22: from its value. */ ! 23: ! 24: void parse_args(); ! 25: int arglen(); ! 26: char **argcpy(); ! 27: char **envncat(); ! 28: int is_assignment(); ! 29: ! 30: /* Flags that tell us about our arguments */ ! 31: int replace_env = FALSE; ! 32: int have_command = FALSE; ! 33: ! 34: int assignment_count; /* Number of assignments to add to environment. */ ! 35: char *first_assignment_argument = NULL; ! 36: ! 37: int i; /* Generic index, used repeatedly */ ! 38: ! 39: char **new_argv; /* Build new command line here. */ ! 40: char **new_envp; /* Build the new environment here. */ ! 41: ! 42: ! 43: void ! 44: main(argc, argv, envp) ! 45: int argc; ! 46: char *argv[]; ! 47: char *envp[]; ! 48: { ! 49: /* Parse arguments. */ ! 50: parse_args(argc, argv); ! 51: ! 52: /* Build the new environment. */ ! 53: ! 54: if (! replace_env) { ! 55: /* Make enough space for the disjoint union of the two sets of ! 56: * environment assignments. This is a guarenteed upper bound. ! 57: */ ! 58: new_envp = (char **) malloc( sizeof(char *) ! 59: * (arglen(envp) ! 60: + assignment_count + 1) ! 61: ); ! 62: argcpy(new_envp, envp); ! 63: } else { ! 64: /* Otherwise, we only need enough space for the new ! 65: * environment. ! 66: */ ! 67: new_envp = (char **) malloc( sizeof(char *) ! 68: * (assignment_count + 1) ! 69: ); ! 70: } /* if (! replace_env) */ ! 71: ! 72: ! 73: envncat(new_envp, first_assignment_argument, assignment_count); ! 74: ! 75: ! 76: /* Do something--either a command or print the environment. */ ! 77: if (have_command) { ! 78: execvep(new_argv[0], new_argv, new_envp); ! 79: perror(new_argv[0]); ! 80: exit(1); ! 81: } else { ! 82: char **pntr; ! 83: ! 84: for (pntr = new_envp; *pntr != NULL; ++pntr){ ! 85: printf("%s\n", *pntr); ! 86: } /* for pntr in new_envp */ ! 87: ! 88: } /* if have_command */ ! 89: ! 90: exit(0); ! 91: } ! 92: ! 93: ! 94: void ! 95: parse_args(argc, argv) ! 96: int argc; ! 97: char *argv[]; ! 98: { ! 99: int current_arg; ! 100: ! 101: if (argc > 1) { ! 102: current_arg = 1; /* Start looking at the first argument. */ ! 103: ! 104: /* - option -- Replace the existing environment. */ ! 105: if (strcmp(argv[current_arg], "-") == 0) { ! 106: replace_env = TRUE; ! 107: ++current_arg; ! 108: } /* if first argument is "-" */ ! 109: ! 110: /* Count the number of arguments which are assignments. */ ! 111: for (assignment_count = 0; ! 112: current_arg < argc; ! 113: current_arg++, assignment_count++) { ! 114: ! 115: if (! is_assignment(argv[current_arg])) { ! 116: break; ! 117: } ! 118: ! 119: if (first_assignment_argument == NULL) { ! 120: first_assignment_argument = &argv[current_arg]; ! 121: } ! 122: ! 123: } /* for (Count the assignments on the command line. ) */ ! 124: ! 125: ! 126: if ( current_arg < argc ) { ! 127: /* We broke out of the assignment couting loop ! 128: * early--this must be a command. ! 129: */ ! 130: new_argv = &argv[current_arg]; ! 131: have_command = TRUE; ! 132: } /* if ( current_arg <= argc ) */ ! 133: ! 134: } /* if there are any args */ ! 135: ! 136: } /* void parse_args() */ ! 137: ! 138: ! 139: ! 140: /* Count the number of arguments in an argument vector. ! 141: * arg_vector MUST be NULL terminated! ! 142: */ ! 143: int ! 144: arglen(arg_vector) ! 145: char **arg_vector; ! 146: { ! 147: int count; ! 148: ! 149: for (count = 0; arg_vector[count] != NULL; ++count) { ! 150: } ! 151: ! 152: return(count); ! 153: } /* arglen() */ ! 154: ! 155: ! 156: /* Copy src argument vector to dest argument vector (pointer copy only). ! 157: */ ! 158: char ** ! 159: argcpy(dest, src) ! 160: char **dest, **src; ! 161: { ! 162: while (*src != NULL) { ! 163: *dest++ = *src++; ! 164: } /* while (walk two pointers down envp and new_envp) */ ! 165: *dest = NULL; ! 166: return (dest); ! 167: } /* char **argcpy() */ ! 168: ! 169: ! 170: ! 171: ! 172: /* Merge one environment onto another, overwriting duplicate ! 173: * variable names. Compare at most n patterns. ! 174: */ ! 175: char ** ! 176: envncat(dest, src, n) ! 177: char **dest, **src; ! 178: int n; ! 179: { ! 180: char **dest_walker; ! 181: char *sep_loc; /* Seperator ("=") location in assignment */ ! 182: int i; ! 183: int name_size; /* Number of characters in a given variable name */ ! 184: ! 185: for (i=0; *src != NULL && i < n; ++i, ++src) { ! 186: ! 187: /* Extract the variable name from the assignment *src. */ ! 188: if ((sep_loc = strchr(*src, VAR_SEPERATOR)) == NULL) { ! 189: fprintf(stderr, ! 190: "Programming error: %s is not an assignment\n", ! 191: *src); ! 192: exit(1); ! 193: } ! 194: name_size = sep_loc - *src; ! 195: ! 196: /* Look for variable part of *src in dest. ! 197: * Point at end if not found. ! 198: */ ! 199: for(dest_walker = dest; *dest_walker != NULL; ++dest_walker) { ! 200: ! 201: /* NB: the + 1 is so the "=" is compared too. */ ! 202: if(strncmp(*dest_walker, *src, name_size + 1) == 0) { ! 203: /* We have found an exact match. */ ! 204: break; ! 205: } /* if *dest_walker and *src are same variable */ ! 206: ! 207: } /* for Walk down dest environment */ ! 208: ! 209: /* Checkpoint - *dest_walker either matches *src or is NULL. */ ! 210: ! 211: /* WARNING: possible memory leak-- ! 212: * *dest_walker is always clobbered. ! 213: * Usually *dest_walker was copied from global ! 214: * envp, so it isn't really lost memory. ! 215: */ ! 216: *dest_walker = *src; ! 217: ! 218: } /* for (i=0; *src != NULL && i < n; ++i, ++src) */ ! 219: ! 220: return(dest); ! 221: } /* char ** envncat() */ ! 222: ! 223: int ! 224: is_assignment(s) ! 225: char *s; ! 226: { ! 227: if ( strchr(s, VAR_SEPERATOR) != NULL ) { ! 228: return(TRUE); ! 229: } else { ! 230: return(FALSE); ! 231: } ! 232: ! 233: } /* int is_assignment() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.