我正在尝试使用进程fork并在子进程中运行execve
,以便它将打开一个新的终端窗口并在那里执行自定义命令。
我想要执行的程序是gestore
这些是我传递给execve
的论据:
char * argv_exec[5];
argv_exec[0]="/usr/bin/xfce4-terminal";
argv_exec[1]="--geometry";
argv_exec[2]="480x320";
argv_exec[3]="-x";
argv_exec[4]="./gestore"; // the program I want to execute in new window
argv_exec[5]=NULL;
char sess_m[80];
strcat(sess_m,"SESSION_MANAGER=");
strcat(sess_m,getenv("SESSION_MANAGER"));
char * envp[3];
envp[0]="DISPLAY=:0.0";
envp[1]=sess_m;
envp[2]=NULL;
在这里我打电话给execve
:
if(pid_tv==0)
if(execve(argv_exec[0],argv_exec,&envp)==-1) {...}
但我不断获得Session manager variable not defined
。
任何人都有人建议为什么这不起作用或我怎么能做得更好?
答案 0 :(得分:1)
一些重写,既显示了对流程环境的更多习惯用法(请参阅environ(7)
),并演示了一些避免硬连接数组大小的方法:始终是C中fence-post错误的来源。
有关一些解释/理由,请参阅代码注释。
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char **environ; /* see environ(7) */
int
main(void)
{
char *argv_exec[] = {
"/usr/bin/xfce4-terminal",
"--geometry",
"480x320",
"-x",
"./gestore",
NULL };
/*
* Structure to drive search for a few variables present in
* current environment, and construct a new, minimal, environment
* containing just those values. Use the direct value from the
* current process's environ variable to set "value" (the string
* of the form "NAME=VALUE"). Just add more entries to nv to handle
* more variables; the code below will adjust sizes.
*
* Any value missing in the environment will be an error.
*/
struct {
char *name;
char *value;
} nv[] = {
{ "DISPLAY", NULL },
{ "SESSION_MANAGER", NULL }
};
/* size new_envp to have one more entry than nv */
char *new_envp[sizeof(nv) / sizeof(nv[0]) + 1];
char **e;
int i, error_flag;
pid_t pid;
/*
* For each variable needed...
*/
for (i = 0; i < sizeof(nv) / sizeof(nv[0]); i++) {
/* ...search in current environment */
for (e = environ; *e; e++) {
size_t slen = strlen(nv[i].name);
if (strncmp(*e, nv[i].name, slen) == 0 && (*e)[slen] == '=') {
nv[i].value = *e;
break;
}
}
}
/*
* Check that we found all values, setting up new_envp as we go.
*/
error_flag = 0;
for (i = 0; i < sizeof(nv) / sizeof(nv[0]); i++) {
if (nv[i].value == NULL) {
(void) fprintf(stderr, "%s not set in environment\n",
nv[i].name);
error_flag = 1;
} else {
new_envp[i] = nv[i].value;
}
}
if (error_flag) {
return 1;
}
new_envp[i] = NULL;
/* very minimal fork/exec processing */
pid = fork();
if (pid == -1) {
perror("fork");
return 1;
}
if (pid == 0) {
(void) execve(argv_exec[0], argv_exec, new_envp);
/*
* If execve succeeded, the invoked program has
* replaced this process, and will either run or
* (presumably) report its own errors. If we're
* still in control, the execve failed, so print
* an error and exit.
*/
perror(argv_exec[0]);
return 1;
} else {
if (wait(0) != pid) {
perror("wait");
return 1;
}
}
return 0;
}