1. 程式人生 > >《UNIX環境高階程式設計》筆記--system函式

《UNIX環境高階程式設計》筆記--system函式

1.system函式的用法

system函式能夠執行函式引數中的命令。函式的定義如下:

#include <stdlib.h>
int system(const char* cmdstring);

當cmdstring為NULL:

如果shell可用則返回非0值,否則返回0.

因為system函式在其實現中呼叫了fork,exec和waitopid,分解開來相當於執行了: 1.fork  生成一個子程序。 2. 在子程序執行 execl("/bin/sh","sh","-c" cmdstring,(char*)0); 3.waitpid 使用system函式而不直接使用fork,exec的原因是,system函式進行了各種出錯處理以及各種訊號的處理。

system函式有三種返回值:

1.如果fork失敗或者waitpid返回出EINTR(EINTR為中斷返回的錯誤型別)之外的錯誤,則system返回-1,而且errno中設

置了錯誤型別值。

2.如果exec失敗(表示不能執行shell),則其返回值如同shell執行了exit(127)一樣。

3.否則所有三個函式都執行成功,並且system的返回值是shell的終止狀態,其格式已在waitpid中說明。

下面的程式呼叫system函式,並對返回值進行分析:

#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>

void pr_exit(int status){
        printf("status = %d\n", status);
        if(WIFEXITED(status)){
                printf("normal terminaton, exit status = %d\n", WEXITSTATUS(status));
        }else if(WIFSIGNALED(status)){
                printf("abnormal termination, signal number = %d%s\n",
                WTERMSIG(status),
#ifdef WCOREDUMP
                WCOREDUMP(status)?"(core file generated)" : "");
#else
                "");
#endif
        }else if(WIFSTOPPED(status)){
                printf("child stopped, signal number = %d\n", WSTOPSIG(status));
        }
}

int main(int argc, char* argv[]){
        if(argc != 2){
                printf("usage:./a.out [cmdstring]\n");
                return -1;
        }
        int status;
        status = system(argv[1]);
        pr_exit(status);
        return 0;
}
執行上面的程式:

[email protected]:~/apue$ ./a.out nosuchcmd
sh: 1: nosuchcmd: not found
status = 32512
normal terminaton, exit status = 127

nosuchcmd不是shell支援的命令,所以,shell命令返回了127(exec失敗),對於system函式,返回值為127*256 = 32512;

因為shell的返回值是 system返回值的8~15位(所以在程式中返回超過255的錯誤程式碼是無意義的)。

[email protected]:~/apue$ ./a.out "ls /a/b/c"
ls: cannot access /a/b/c: No such file or directory
status = 512
normal terminaton, exit status = 2

雖然沒有這個/a/b/c目錄,但是命令是成功執行了,所以沒有返回127,而是返回了ls /a/b/c命令的錯誤程式碼2(2*256 = 512)。

[email protected]:~/apue$ ./a.out "date"
Sat Jul 27 20:48:22 CST 2013
status = 0
normal terminaton, exit status = 0

system成功執行了date,date程式退出碼為0。

2.system函式的一個漏洞

使用system函式執行命令列引數(a.out):

#include <stdio.h>

int main(int argc, char* argv[]){
        if(argc < 2){
                printf("usage:./a.out [cmdstring]\n");
                return -1;
        }
        if(system(argv[1])<0){
                perror("system\n");
                return -1;
        }
        return 0;
}
列印程式的uid和euid(getuid):
#include <stdio.h>

int main(void){
        printf("real uid =%d, effective uid=%d.\n",getuid(),geteuid());
        return 0;
}
執行結果:

[email protected]:~/apue$ ./a.out /home/yan/apue/getuid  
real uid =1000, effective uid=1000.   //使用普通使用者列印的uid和euid是正常的。
[email protected]:~/apue$ su
Password:
[email protected]:/home/yan/apue# chown root a.out  //將程式的所有者改為root
[email protected]:/home/yan/apue# chmod u+s a.out  //設定程式的setuid標誌
[email protected]:/home/yan/apue# ll a.out
-rwsrwxr-x 1 root yan 7443 Jul 27 22:54 a.out* //確認成功設定
[email protected]:/home/yan/apue# exit   //退出root使用者
exit
[email protected]:~/apue$ ./a.out /home/yan/apue/getuid  
real uid =1000, effective uid=0. //euid變成了root

我們給予a.out超級使用者許可權在system中執行了fork和exec後仍然保持了下來。

如果一個程序正以特殊的許可權(setuid或setgid)執行,它又想生成一個程式,則它應該直接使用fork和exec,而且fork以後,exec之前

要改回到普通許可權,setuid或setgid的程式決不應呼叫system函式。

相關推薦

unix環境高階程式設計》--- 資料庫函式

大多數訪問資料庫的函式庫使用兩個檔案儲存資訊:索引檔案和資料檔案。索引檔案包含索引值(鍵)和指向資料檔案中對應資料記錄的指標。為提高按鍵查詢的速度和效率,可用雜湊法和B+樹組織索引檔案,本文采用固定大小的散列表, 並採用連結串列法解決雜湊衝突。 由於只有

UNIX環境高階程式設計筆記--system函式

1.system函式的用法 system函式能夠執行函式引數中的命令。函式的定義如下: #include <stdlib.h> int system(const char* cmdstring); 當cmdstring為NULL: 如果shell可用則返回非0值

UNIX環境高階程式設計筆記--kill函式,raise函式,alarm函式,pause函式

1.kill函式和raise函式 kill函式將訊號傳送給程序或者程序組,raise函式則執行程序向自身傳送訊號。 #include <signal.h> int kill(pid_t pid,int signo); int raise(int signo);

UNIX環境高階程式設計(第三版) 第五章筆記

5.2 流和物件 只有兩個函式可以改變流的定向: freopen函式清楚一個流的定向,fwide函式可用於設定一個流的定向。 #include <stdio.h> #include <wchar.h> int fwide(FILE

Unix環境高階程式設計 讀書筆記 第三章 檔案IO

概述 對於open、read、write、lseek、close等函式,被稱為不帶緩衝的I/O。即unbuffered i/O,術語“不帶緩衝”指的是每個read或者write都呼叫核心中的一個系統呼叫。 檔案描述符 檔案描述符是一個非負的整數; 檔案描述符0與程序

unix環境高階程式設計(第三版)-讀書筆記2

限制 unix系統實現定義了很多幻數和常量,其中有很多已被硬編碼到程式中,或用特定的技術確定。 已下兩種型別是必須的。 (1)編譯時限制(例如,短整型的最大值是什麼?) (2)執行時限制(例如,檔名有多少個字串?) 編譯時限制可在標頭檔案中定義。程式在編譯時包含這些標頭檔案。但是執行

UNIX環境高階程式設計學習筆記(九)程序控制

1.程序標識 每個程序都有一個非負整型表示的唯一程序ID。因為程序ID識別符號總是唯一的,常將其用作其他識別符號的一部分以保證其唯一性。程序ID是可複用的,當一個程序終止後,其程序ID就成為複用的候選者。 ID為0的程序通常是排程程序,常常被稱為交換程序(s

一步一步實現自己的shell程式(一)---《Unix環境高階程式設計》讀書筆記

引言 用過Unix/Linux系統的人都知道,Unix系統中很多命令和程式都是在終端中執行,這個終端就是shell。不同的Unix都有不同的預設shell程式,包括sh、csh、bash等等不同的shell程式。那麼什麼是shell,shell究竟做了什麼

unix環境高階程式設計》 讀書筆記 (5)

date and time 涉及到的函式列出如下,然後再舉例執行,輸出結果,比較直觀。 時間這塊資料有限,如果有誤,還望指正。 #include <time.h>

UNIX環境高階程式設計》(APUE) 筆記第十一章 - 執行緒

# 11 - 執行緒 [Github 地址](https://github.com/XutongLi/Learning-Notes/blob/master/APUE/11-%E7%BA%BF%E7%A8%8B.md) *** ## 1. 執行緒概念 典型的 **UNIX程序** 可以看成只有一個 **控制

UNIX環境高階程式設計的學習(二)

UNIX系統程序控制程式說明 該程式從標準輸入讀取命令,然後執行這些命令,程式涉及到的函式主要用法包括: fgets的用法 execlp的用法 waitpid的用法 程式如下: #include "apue.h" #include <sys/wai

UNIX環境高階程式設計的學習(一)

UNIX環境高階程式設計第一個例子的編譯 這本書中有很多的例子,為了加深理解,習慣性自己敲一遍程式碼然後看執行結果,再去理解其中的知識點,但是在虛擬機器下如何編譯這些程式碼呢,需要以下幾步: 下載並解壓縮apue.3e檔案包 在“apue.h”中最後一行加:#inclu

[UNIX環境高階程式設計] 檔案和目錄

1 引言 上文圍繞了普通檔案I/O進行了討論——開啟檔案、讀檔案或寫檔案。本文將描述檔案系統的其他特徵和檔案的性質。將從stat函式開始,stat結構中的大多數成員都是基本系統資料型別,逐個分解stat結構的每一個成員以瞭解檔案的所有屬性。 使用stat函式最多的地方可能就是[ls -l

[Unix環境高階程式設計] 檔案I/O

1.引言 UNIX系統中的大多數檔案I/O只需要用到5個函式:open、read、write、lseek以及close,這裡所涉及到的函式經常被稱為不帶緩衝的I/O1。只要涉及在多個程序之間共享資源,原子操作的概念就變得非常重要,我們將通過I/O和open函式的引數來討論此概念,dup、

UNIX環境高階程式設計(三) 第六章

6 系統資料檔案和資訊 6.2 口令檔案 #include <pwd.h> struct passwd *getpwuid(uid_t uid); /* 檢視使用者登入名 */ struct passwd *getpwnam(const

UNIX環境高階程式設計(3) 第三章

3 檔案I/O 3.1 引言 3.2 檔案描述符 檔案描述符是一個標示,非負整數,類似於windows裡的控制代碼,為了與標準C保持一致(標準C裡的檔案的讀寫都是通過File Pointer)UNIX採用了這樣的三級結構,我混淆於檔案描述標誌和檔案

UNIX環境高階程式設計(3) 第八章

8 程序控制 8.1 引言 8.2 程序標識 #include <unistd.h> pid_t getpid(void); return: 呼叫程序的程序ID pid_t getppid(void

UNIX環境高階程式設計(3) 第二章

2.2UNIX標準化 2.2.1 ISO C 國際標準化組織(International Organization for Standardization,ISO) 國際電子技術委員會(International Electrotechnical Co

UNIX環境高階程式設計(3) 第一章

1.1 引言 所有作業系統都為他們所執行的程式提供服務。典型的服務包括:執行新程式、開啟檔案、讀檔案、分配儲存區以及獲取當前時間等。 1.2 UNIX體系結構 層級從裡向外擴充套件應用。 1. 核心:可將作業系統定義為一種軟體,即稱為核心,它控制

UNIX環境高階程式設計-概述

    檔案I/O 基本的系統呼叫函式 open,create,close,lseek,read,write 以及原子性的pread,pwrite 複製檔案描述符 dup 同步重新整理fsync,fdatasync,sync 更改已經開啟的檔案屬性 fcntl,雜物箱