static char *appid = NULL;
static int app_pid = -1;
static int cmd_pid = -1;
+static int cmd_idx = -1;
static char *pname = NULL;
static char *ename = NULL;
static char *oname = NULL;
static FILE *data_file_out = NULL;
static FILE *stat_file_out = NULL;
+#ifndef ADDITIONAL_ENV_SIZE
+#define ADDITIONAL_ENV_SIZE 128
+#endif
+
+static int env_mode = 0;
+static char *additional_env[ADDITIONAL_ENV_SIZE];
+static int additional_env_index = 0;
+
volatile int global_stop = 0;
int is_running(int pid)
{"control", required_argument, 0, 'c'},
{"data", required_argument, 0, 'd'},
{"stat", required_argument, 0, 's'},
+ {"env", optional_argument, 0, 'E'},
{0, 0, 0, 0}
};
static int process_option(int argc, char **argv)
{
int option_index;
+ int result = -1;
+
+ result = getopt_long(argc, argv, "-a:p:ve:o:it:wc:d:s:E::",
+ long_options, &option_index);
+
+ if (result == 1) {
+ // NOTE: check if -E params handled
+ if (env_mode) {
+ // NOTE: code duplication, should be refactored (see below)
+ if (additional_env_index == ADDITIONAL_ENV_SIZE) {
+ log_error("Too many environment variables");
+ exit(1);
+ }
+ additional_env[additional_env_index++] = optarg;
+ return 0;
+ } else {
+ // NOTE: start of command line, case `profctl ... <cmd> ...`
+ cmd_idx = optind - 1;
+ return -1;
+ }
+ } else {
+ env_mode = 0;
+ }
- switch (getopt_long(argc, argv, "+a:p:ve:o:it:wc:d:s:",
- long_options, &option_index)) {
+ switch (result) {
case 'a': CheckValue(&appid, "appid"); break;
case 'p': CheckValue(&pname, "pipe name"); break;
case 'e': CheckValue(&ename, "exe name"); break;
case 'c': controlPort = atoi(optarg); break;
case 'd': dataPort = atoi(optarg); break;
case 's': statPort = atoi(optarg); break;
+ case 'E':
+ env_mode = 1;
+ // NOTE: -E option can be used as -Eu=a v=b, not only -E u=a v=b
+ if (optarg) {
+ // NOTE: code duplication, should be refactored (see above)
+ if (additional_env_index == ADDITIONAL_ENV_SIZE) {
+ log_error("Too many environment variables");
+ exit(1);
+ }
+ additional_env[additional_env_index++] = optarg;
+ }
+ break;
case '?': exit(1);
- default:
+ case -1:
+ // NOTE: start of command line, case `profctl ... -- <cmd> ...`
+ if (optind != argc) {
+ cmd_idx = optind;
+ }
return -1;
+ default:
+ // NOTE: should not be reachable
+ abort();
}
return 0;
}
fclose(stdout); // NOTE: detaching from stdin/out/err streams
}
- if (optind != argc) {
+ if (cmd_idx != -1) {
// TODO: should be refactored: use separated launcher
if (verbose) {
- log_message("launch command process %s", argv[optind]);
+ log_message("launch command process %s", argv[cmd_idx]);
+ for (int i = 0; i < additional_env_index; i++) {
+ log_message(" additional environment: %s", additional_env[i]);
+ }
}
cmd_pid = fork();
close(STDOUT_FILENO);
close(STDERR_FILENO);
- execv(argv[optind], &argv[optind]);
+ for (int i = 0; i < additional_env_index; i++) {
+ putenv(additional_env[i]);
+ }
+ execv(argv[cmd_idx], &argv[cmd_idx]);
exit(1);
} else if (cmd_pid == -1) {
log_system_error_and_exit("cannot fork command process");