我有一個C函數來做一個fork和exec,它會被調用兩次。如何在fork和exec之後捕獲環境c?
第一次調用執行shell腳本(稱爲setenv.sh),它可以是任何類型的外殼(bash中/科恩/ C/perl的等),將設置環境變量。此調用的envp數組將爲NULL,但意圖是在setenv.sh運行後,它將從子進程返回一個基於environ的已填充數組。
第二呼叫將是一個C或Java程序,它需要一定的環境中,以便該呼叫運行時,envp陣列將是從第一個呼叫所填充的一個返回。
int execute(char **args, int argc, char **envp)
{
char *function = "execute";
int status, i;
pid_t p, pid;
extern int errno;
sigset_t mask, savemask;
struct sigaction ignore, saveint, savequit;
int fd[2];
pipe(fd);
sigemptyset(&ignore.sa_mask);
ignore.sa_handler = SIG_IGN;
ignore.sa_flags=0;
sigaction(SIGINT, &ignore, &saveint);
sigaction(SIGQUIT, &ignore, &savequit);
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &mask, &savemask);
if ((pid=fork()) < 0) status = -1;
if (pid ==0) {
/* Child */
close(fd[0]);
sigaction(SIGINT, &saveint, (struct sigaction *) 0);
sigaction(SIGQUIT, &savequit, (struct sigaction *) 0);
sigprocmask(SIG_SETMASK, &savemask, (sigset_t *) 0);
printf("Command Line Parameters\n");
printf("-----------------------\n");
for (i = 0; i < argc; i++) {
printf("[%d]: %s\n", (i+1), args[i]);
}
if (execve(*args, args, envp) < 0)
{
sprintf(err_data,"Failed to execute %s", args[0]);
perror(err_data);
return(FAILED);
}
write(fd[1], &environ, sizeof(environ));
close(fd[1]);
}
while (waitpid(pid, &status, 0) < 0) {
if (errno != EINTR) {
status = -1;
break;
}
}
if (status==0) {
read(fd[0], &envp, sizeof(envp));
}
close(fd[0]);
sigaction(SIGINT, &saveint, (struct sigaction *) 0);
sigaction(SIGQUIT, &savequit, (struct sigaction *) 0);
sigprocmask(SIG_SETMASK, &savemask, (sigset_t *) 0);
return(status);
}
此功能,而不管代碼工作正常執行傳入的一個真實的程序,我也可以通過它的一組環境變量在envp數組,並將其在該環境中運行細。
但是,在使用包含管道進行測試時,我發現在setenv.sh的exec後,子進程從不執行將environ寫入管道,然後父進程將阻塞從管道讀取。
我明白爲什麼它不工作 - 因爲shell腳本的EXEC覆蓋在孩子原來的C代碼。問題是,是否有辦法實現使用exec運行shell腳本並將生成的環境捕獲到父級(不同於捕獲stdin/stdout/stderr)的目的。假設您不能更改setenv.sh的內容,因爲它可能由第三方提供。
無需雞蛋裏挑骨頭了錯誤處理等,這是一個進展中的工作,所以只是在如何實現目標的一些輸入後。
一種替代我認爲被解析setenv.sh腳本在父獲取變量引入然後可被傳遞給真正的程序的陣列。問題在於setenv.sh腳本可能包含if語句塊幷包含其他shell腳本,所以我真的想在setenv.sh運行結束時捕獲環境(通過執行它)並將其傳遞迴父母。
任何建議表示讚賞?
你可以做的事情不多 - 你想要獲取運行腳本後得到的環境,這意味着子進程已經終止。內核不存儲殭屍進程的環境,所以你無法獲取它。你可以做的最好的是寫一個包裝腳本,如Art的答案中所述。 –