ISO C定義了system函數,但是其操作對系統的依賴性很強。POSIX.1包括了system接口,它擴展了ISO C定義,以描述system在POSIX.1環境中的運行行為。
#include <stdlib.h>int system( const char *cmdstring );
如果cmdstring是一個空指針,則僅當命令處理程序可用時,system返回非0值,這一特征可以確定在一個給定的操作系統上是否支持system函數。在UNIX中,system總是可用的。
因為system在其實現中調用了fork、exec和waitpid,因此有三種返回值:
(1)如果fork失敗或者waitpid返回除EINTR之外的出錯,則system返回-1,并且在errno中設置相應的錯誤類型值。
(2)如果exec失?。ū硎静荒軋绦衧hell),則其返回值如同shell執行了exit(127)一樣。
(3)否則所有三個函數(fork、exec和waitpid)都執行成功,并且system的返回值是shell的終止狀態,其格式已在waipid中說明(參見http://www.CUOXin.com/nufangrensheng/p/3510101.html)。
程序清單8-12 system函數(沒有信號處理)
[root@localhost apue]# cat system_nosighandling.c#include <sys/wait.h>#include <errno.h>#include <unistd.h>intsystem(const char *cmdstring) /* version without signal handling */{ pid_t pid; int status; if (cmdstring == NULL) return(1); /* always a command PRocessor with UNIX */ if ((pid = fork()) < 0) { status = -1; /* probably out of processes */ } else if (pid == 0) /* child */ { /* * execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); * _exit(127); /* execl error */ * 此處程序原來是如上面所示,但我無法理解這里的邏輯(感覺是有問題的,但是執行也可獲得正確結果) * 改為了下面的形式 */ if (execl("/bin/sh", "sh", "-c", cmdstring, (char *)0) < 0) { _exit(127); /* execl error */ } } else /* parent */ { while (waitpid(pid, &status, 0) < 0) { if (errno != EINTR) { status = -1; /* error other than EINTR from waitpid() */ break; } } } return(status);}
shell的-c選項告訴shell程序取下一個命令行參數(在這里是cmdstring)作為命令輸入(而不是標準輸入或從一個給定的文件中讀命令)。shell對以null字符終止的命令字符串進行語法分析,將它們分成命令行參數(如果不使用shell執行此命令,而是試圖由我們自己去執行它,那么將相當困難)。傳遞給shell的實際命令字符串可以包含任一有效的shell命令。
注意,我們調用_exit而不是exit。這是為了防止任一標準I/O緩沖區(這些緩沖區會在fork中由父進程復制給子進程,詳情請參考:http://www.CUOXin.com/nufangrensheng/p/3509492.html)在子進程中被沖洗。
程序清單8-13 調用system函數
[root@localhost apue]# cat prog8-13.c#include "apue.h"#include <sys/wait.h>intmain(void){ int status; if ((status = system("date")) < 0) err_sys("system() error"); pr_exit(status); if ((status = system("nosuchcommand")) < 0) err_sys("system() error"); pr_exit(status); if ((status = system("who; exit 44")) < 0) err_sys("system() error"); pr_exit(status); exit(0);}
運行程序清單8-13得到:
[root@localhost apue]# ./prog8-13Wed Jan 8 23:06:53 PST 2014normal termination, exit status = 0 對于datesh: nosuchcommand: command not foundnormal termination, exit status = 127 對于無此種命令root pts/0 2014-01-03 22:57 (:0.0)normal termination, exit status = 44 對于exit
使用system而不是直接使用fork和exec的優點是:system進行了所需的各種出錯處理,以及各種信號處理(在帶信號處理的system版本中)。
設置用戶ID程序
如果在一個設置用戶ID程序中調用system,那么會發生什么呢?這是一個安全性方面的漏洞,決不應當這樣做。
如果一個進程正以特殊的權限(設置用戶ID或設置組ID)運行,它又想生成另一個進程執行另一個程序,則它應當直接使用fork和exec,而且在fork之后、exec之前要改回到普通權限。設置用戶ID或設置組ID程序決不應調用system函數。
本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/。
新聞熱點
疑難解答