int system(const char * cmdstring)
{
pid_t pid;
int status;
if(cmdstring == NULL){
return (1);
}
if((pid = fork())<0){
status = -1;
}
else if(pid == 0){
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
-exit(127); //子進程正常執行則不會執行此語句
}
else{
while(waitpid(pid, &status, 0) < 0){
if(errno != EINTER){
status = -1;
break;
}
}
}
return status;
}
http://blog.sina.com.cn/s/blog_62274fd70100iscf.html
相關函數
fork,execve,waitpid,popen
表標頭檔
#include<stdlib.h>
定義函數
int system(const char * string);
函數說明
system()會調用fork()產生子進程,由子進程來調用/bin/sh-c string來執行參數string字串所代表的命令,此命>令執行完後隨即返回原調用的進程。
在調用system()期間SIGCHLD 訊號會被暫時擱置,SIGINT和SIGQUIT 訊號則會被忽略。
傳回值
=-1:出現錯誤
=0:調用成功但是沒有出現子進程
>0:成功退出的子進程的id
如果system()在調用/bin/sh時失敗則返回127,其他失敗原因返回-1。若參數string為空白指標(NULL),則返回非零值>。如果system()調用成功則最後會返回
執行shell命令後的傳回值,但是此傳回值也有可能為 system()調用/bin/sh失敗所返回的127,因此最好能再檢查errno 來確認執行成功。
附加說明
在編寫具有SUID/SGID許可權的程式時請勿使用system(),system()會繼承環境變數,通過環境變數可能會造成系統安全的問題。
Linux system函數傳回值
本篇文章來源於 Linux公社網站(www.linuxidc.com) 原文連結:http://www.linuxidc.com/Linux/2011-09/42425.htm
例:
1.status = system("./test.sh");
1、先統一兩個說法:
(1)system傳回值:指調用system函數後的傳回值,比如上例中status為system傳回值
(2)shell傳回值:指system所調用的shell命令的傳回值,比如上例中,test.sh中返回的值為shell傳回值。
2、如何正確判斷test.sh是否正確執行?
僅判斷status是否==0?或者僅判斷status是否!=-1?
都錯!
3、man中對於system的說明
RETURN VALUE
The value returned is -1 on error (e.g. fork() failed), and the return
status of the command otherwise. This latter return status is in the
format specified in wait(2). Thus, the exit code of the command will
be WEXITSTATUS(status). In case /bin/sh could not be executed, the
exit status will be that of a command that does exit(127).
看得很暈吧?
system函數對傳回值的處理,涉及3個階段:
階段1:建立子進程等準備工作。如果失敗,返回-1。
階段2:調用/bin/sh拉起shell指令碼,如果拉起失敗或者shell未正常執行結束(參見備忘1),原因值被寫入到status的低8~15位元位中。system的man中只說明了會寫了127這個值,但實測發現還會寫126等值。
階段3:如果shell指令碼正常執行結束,將shell傳回值填到status的低8~15位元位中。
備忘1:
只要能夠調用到/bin/sh,並且執行shell過程中沒有被其他訊號異常中斷,都算正常結束。
比如:不管shell指令碼中返回什麼原因值,是0還是非0,都算正常執行結束。即使shell指令碼不存在或沒有執行許可權,也都算正常執行結束。
如果shell指令碼執行過程中被強制kill掉等情況則算異常結束。
如何判斷階段2中,shell指令碼是否正常執行結束呢?系統提供了宏:WIFEXITED(status)。如果WIFEXITED(status)為真,則說明正常結束。
如何取得階段3中的shell傳回值?你可以直接通過右移8bit來實現,但安全的做法是使用系統提供的宏:WEXITSTATUS(status)。
由於我們一般在shell指令碼中會通過傳回值判斷本指令碼是否正常執行,如果成功返回0,失敗返回正數。
所以綜上,判斷一個system函數調用shell指令碼是否正常結束的方法應該是如下3個條件同時成立:
(1)-1 != status
(2)WIFEXITED(status)為真
(3)0 == WEXITSTATUS(status)
注意:
根據以上分析,當shell指令碼不存在、沒有執行許可權等情境下時,以上前2個條件仍會成立,此時WEXITSTATUS(status)為127,126等數值。
所以,我們在shell指令碼中不能將127,126等數值定義為傳回值,否則無法區分中是shell的傳回值,還是調用shell指令碼異常的原因值。shell指令碼中的傳回值最好多1開始遞增。
判斷shell指令碼正常執行結束的健全代碼如下:
1.#include <stdio.h>
2.#include <stdlib.h> 3.#include <sys/wait.h> 4.#include <sys/types.h>
5.
6.int main() 7.{
8. pid_t status;
9.
10.
11. status = system("./test.sh");
12.
13. if (-1 == status)
14. {
15. printf("system error!");
16. }
17. else
18. {
19. printf("exit status value = [0x%x]\n", status);
20.
21. if (WIFEXITED(status))
22. {
23. if (0 == WEXITSTATUS(status))
24. {
25. printf("run shell script successfully.\n");
26. }
27. else
28. {
29. printf("run shell script fail, script exit code: %d\n", WEXITSTATUS(status));
30. }
31. }
32. else
33. {
34. printf("exit status = [%d]\n", WEXITSTATUS(status));
35. }
36. }
37.
38. return 0;
39.}
WIFEXITED(stat_val) Evaluates to a non-zero value if status
was returned for a child process that
terminated normally.
WEXITSTATUS(stat_val) If the value of WIFEXITED(stat_val) is
non-zero, this macro evaluates to the
low-order 8 bits of the status argument
that the child process passed to _exit()
or exit(), or the value the child
process returned from main().
本篇文章來源於 Linux公社網站(www.linuxidc.com) 原文連結:http://www.linuxidc.com/Linux/2011-09/42425.htm