跳到內容

C 程式設計/stdlib.h/system

來自華夏公益教科書,開放的書籍,開放的世界

在 C 標準庫中,system 是一個用於執行子程序和命令的函式。它在 stdlib.h 標頭檔案中定義。它與 exec/spawn 函式系列的不同之處在於,它不是將引數傳遞給執行的物件,而是將單個字串傳遞給系統 shell,通常是 POSIX shell,/bin/sh -c

int system (const char *command);

system 函式是阻塞的;也就是說,呼叫將等待直到子程序終止並返回其退出值。在此期間,SIGCHLD 將被阻塞,因為 system 等待子程序死亡;此外,SIGINTSIGQUIT 被忽略,因此為了確保響應性,程式設計師應該檢查返回值以檢視使用者是否試圖終止程序。發生錯誤時,system 在 fork 之前或期間(例如,程序計數限制已達到)失敗時將返回 -1,但在 fork 之後(例如,無法執行 sh)失敗時將返回 127;這與命令以狀態 127 退出無法區分。

在 POSIX 中,system 使用兩個引數: “-c” 和 command 分叉並執行 /bin/sh。雖然 sh 的行為在其他地方有規定,但需要注意的是 command 不必是單個命令;它實際上可以是一個管道,甚至是一系列管道。例如,考慮一個希望顯示螢幕截圖的程式

system ("pngtopnm \"My Screenshot.png\" | pnmtoxwd > out.xwd && xwud out.xwd");

這行展示了一個重要的考慮因素:由於 command 將被解析為 shell 命令列,因此圍繞例如檔名引號必須轉義。然而,這會引發安全問題,因為如果 command 是從使用者提供的 資料構建的,攻擊者可能能夠跳出任何引號並在父級上下文中執行任意命令;事實上,這幾乎是規範的程式碼注入漏洞。因此,建議僅對預先確定的命令字串使用 system,使用其他函式(spawn 等)在 argv 中傳遞使用者提供的資料,或透過管道或臨時檔案傳遞此類資料。

system 生成的子程序繼承其父程序的標準流;因此,子程序可以接收鍵盤輸入並寫入終端。請注意,這意味著父程序不會接收子程序的輸出,除非使用重定向或 tee。

[編輯 | 編輯原始碼]
華夏公益教科書