作者 主題: 請問用C寫CGI,如何執行外部程式?  (閱讀 16607 次)

0 會員 與 1 訪客 正在閱讀本文。

pontiff

  • 懷疑的國中生
  • **
  • 文章數: 44
    • 檢視個人資料
請問各位大大,

我現在用C寫CGI程式,需要執行外部的程式,
除了exec以外,還有其他的嗎?
我希望這個函數可以有傳回值(成功或失敗)。

謝謝各位

abelyang

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 1097
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #1 於: 2003-07-29 18:11 »
man page
man 3 system
man 3 exec

有幾種做法,看你的需要而定
仔細看~~ man page 寫的

pontiff

  • 懷疑的國中生
  • **
  • 文章數: 44
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #2 於: 2003-07-30 09:12 »
我試過
system ("cp ./hello.c /tmp");
是可以的。

但是若我要啟動一個Daemon,或是將啟動Daemon步驟寫成一script file,
則都無法啟動。
system ("/path/Daemon");  
or
system ("/path/script file");

請問要如何啟動一個Daemon呢?謝謝

dark

  • 俺是博士!
  • *****
  • 文章數: 1581
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #3 於: 2003-07-30 09:33 »
這是因為啟動此 daimon 所需的環境變數不足
到 /etc/rc.d/init.d/ 下找找 , 這 daimon 啟動身分與所需環境變數

最快的方法是
在 /etc/passwd 新增一個權限夠的使用者 , 並將其 shell 指向您的 script file
再把 su 或 ssh 或 telnet 開給 apache 用即可
反正要編譯 , 密碼就給 100 字元應該就降低危險了吧

對了 , 記得 perl 的 cgi 可以轉變身份的樣子...
c 呢 ... 找找函式庫說不定有 ...

abelyang

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 1097
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #4 於: 2003-07-30 10:01 »
c 是 setuid
NAME
       setuid - set user identity

SYNOPSIS
       #include <sys/types.h>
       #include <unistd.h>

       int setuid(uid_t uid);

當然也可以 getuid

至於啟動 daemon 之問題, 一般都是可以的, system 也不過是 call shell
再去執行您的 command,  您的情況或許如 dark 兄說的, 權限及環境變數吧

pontiff

  • 懷疑的國中生
  • **
  • 文章數: 44
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #5 於: 2003-08-04 11:42 »
我看到函數中,有setuid, seteuid, setruid, seteruid幾個~
我不知道差別在哪邊,但是我想基本上要執行外部程式前,使用setuid,之後再把set回原本的uid。

我目前還是無法執行,以下是我的code,請各位幫我看看。
我寫的是CGI,有利用CGIC套件。程式執行後,會出現無法設定uid的
訊息,但是我不知道為何不能轉換uid,謝謝各位。

#include <stdio.h>
 #include "cgic.h"
 #include "cgic.c"
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/types.h>
 
 int cgiMain()
 {
    static uid_t uid=0;  //將轉換成root的UID
    int status;
   
    cgiHeaderContentType ("text/plain");
    fprintf (cgiOut, "<html><head>\n");
    fprintf (cgiOut, "<title>Button Test</title></head>\n");
    fprintf (cgiOut, "<body><h1>Button Test</h1>\n");
   
    //按下按鈕後,啟動slapd Daemon。
    if (cgiFormSubmitClicked("start") == cgiFormSuccess)
    {
       status = setuid (uid);
       if (status < 0)
    fprintf (cgiOut, "Set uid fail\n");
       else
    {
       fprintf (cgiOut, "Success\n");
       system ("slapd");
    }
       
    }
    fprintf (cgiOut, "</body></html>");
    return 0;
 }

pontiff

  • 懷疑的國中生
  • **
  • 文章數: 44
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #6 於: 2003-08-04 16:46 »
再發問一個問題吧~

同樣是在CGI執行環境下,
我要把ls -al的結果,顯示在網頁上,
應該怎麼做呢?謝謝

elleryq

  • 鑽研的研究生
  • *****
  • 文章數: 908
  • 性別: 男
    • 檢視個人資料
    • Thinking more...
請問用C寫CGI,如何執行外部程式?
« 回覆 #7 於: 2003-08-04 17:21 »
使用setuid(), 必須要有足夠權限~
通常由一般使用者沒辦法切回 root, 而由 root 則可以切為任何使用者~
我自己以前用是直接讓 Apache 以 root 權限執行, 但這樣子作會有安全問題.
建議把該 CGI 設為 SUID 或者讓執行 Apache 的這個使用者擁有啟動其他 Daemon 的權限.

如果要顯示 ls -al 的結果顯示出來
則直接用 system("ls -al"); 應該就可以了

另外你也可以參考 popen() / pclose() 這兩個 function
Plan your work, then work your plan.
我的首頁:http://blog.elleryq.idv.tw
351899by http://counter.li.org

pontiff

  • 懷疑的國中生
  • **
  • 文章數: 44
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #8 於: 2003-08-04 21:17 »
我覺得,可能在CGI下,無法使用setuid這個功能。
若下system("ls -al")是無法執行的,很多command在CGI環境無法執行。
我發覺:需要show message在螢幕的指令,都無法執行,如 ls -al, pwd等等。
或者Daemon也無法執行。

您講的popen,我同學也跟我提過,不過這個不是開檔案用的嗎?請問要如何使用這個函數呢?

我有找到一個super套件,可以將某些指令在執行前,change成root。
我試過ls -al和啟動Daemon兩種模式。
若用nobody登入,則兩種模式都可以正常運作。
若透過Browser開啟CGI程式,則兩個都不行,因為兩個都需要show message到console。
(以上兩個方式都執行同一個程式)

所以,可以請您說明一下popen要如何使用嗎?謝謝

dark

  • 俺是博士!
  • *****
  • 文章數: 1581
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #9 於: 2003-08-05 06:52 »
是否可給執行檔 suid root 權限呢?

pontiff

  • 懷疑的國中生
  • **
  • 文章數: 44
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #10 於: 2003-08-05 09:49 »
我用的super套件,就是使用suid Root的方式。
但是我還是無法正確執行程式。
但是cp指令,卻是不用super套件,就可以執行的指令。(why?)

Example:

在nobody下,無法使用mv指令(mv /tmp/1.txt /tmp/2.txt)。

所以我在程式中(command.cgi),有兩個敘述
system ("/bin/mv /tmp/1.txt /tmp/2.txt");
system ("/usr/local/bin/super mv /tmp/1.txt /tmp2.txt");
第一個指令是無法執行的,會有錯誤訊息。第二個可以執行(??)。

現在狀況出現在可以執行的環境。
若我用瀏覽器執行command.cgi,沒有錯誤傳回,但是檔案沒有另名。
若我在root下,使用su nobody,然後打./command.cgi,就可以另名了。

我實在不知道這個問題到底怎麼解決,您看得出來關鍵嗎?謝謝!

dark

  • 俺是博士!
  • *****
  • 文章數: 1581
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #11 於: 2003-08-05 10:24 »
nobody 應該可以使用 mv 指令 , 除非 /tmp/1.txt 並非 nobody 所有

在 browser 下大概無法 su ssh telnet 吧... 不知是否嘗試 sudo 呢 ?

還有... 您好像不是 RedHat 的 , 小弟寫的 c++ (一般程式 , 無須網管權限)
在自己 RedHat 下跑好好的 , 上傳到學校工作站就不能跑了... 怪怪..
所以小弟的建議 , 只可參考...
不過呀... win98 下 compiler 完上傳到 RH 執行 , 只出現 "c:\XX error" 其他正常 ... 乖乖..

pontiff

  • 懷疑的國中生
  • **
  • 文章數: 44
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #12 於: 2003-08-05 10:46 »
因為我最終的目的,是要執行程式(Daemon),如我要啟動LDAP功能,需要一個button去start,所以當start按下後,就要執行slapd這隻程式。

通常這些程式都是root安裝的,所以我才想用super套件,將管理者(透過網頁)設成root去啟動之。

以之前的例子,檔案的擁有者是root。
我是在Linux 8.0上面跑的。我現在擔心不是程式語法的問題,而是系統設定的問題 :cry:

abelyang

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 1097
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #13 於: 2003-08-05 10:59 »
可以去找 sudo 的用法看看 ~
一般 web server 的 runtime 時的權限都不足 ( Security issue)
你需要有轉換身份的功能, 轉成 root (su) 後 call daemon,
再回覆成一般 Web 的身份 ...

elleryq

  • 鑽研的研究生
  • *****
  • 文章數: 908
  • 性別: 男
    • 檢視個人資料
    • Thinking more...
請問用C寫CGI,如何執行外部程式?
« 回覆 #14 於: 2003-08-05 18:52 »
引用

我覺得,可能在CGI下,無法使用setuid這個功能。

這是權限問題,就跟我前面提到的一樣, 一般 user 無法切換為 root, 但 root 可以切換為任何 user.

引用

若下system("ls -al")是無法執行的,很多command在CGI環境無法執行。
我發覺:需要show message在螢幕的指令,都無法執行,如 ls -al, pwd等等。
或者Daemon也無法執行。

可以執行,下面是我剛剛寫的一段 code, httpd 的身分是 apache
代碼: [選擇]

#include <stdio.h>
int main( int argc, char* argv[] )
{
        printf("Content-type: text/plain\n\n");
        fflush( stdout );
        system("ls -l");
        exit(0);
}


引用

您講的popen,我同學也跟我提過,不過這個不是開檔案用的嗎?請問要如何使用這個函數呢?

這不是開檔案用的,我不知道你有沒有 man 一下?
這是用來執行一個執行檔,並讀取其執行結果的 function.
你可以試試這段 code
代碼: [選擇]

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
        FILE *fp;
        char s_line[1024];

        printf("=====\n");
        fp=popen("tar cvzf gdbm.tar.gz gdbm  2>&1","r");
        if(fp==NULL)
                exit(-1);
        while(!feof(fp)) {
                fgets( s_line, 1024, fp );
                printf(">%s",s_line);
        }
        pclose(fp);
}


引用

我有找到一個super套件,可以將某些指令在執行前,change成root。

如果你放在 system() 裡面,那還是一樣啊,因為執行 system() 的這個 CGI, 仍然是以 httpd 的身分(apache或www)在執行,所以仍然是沒辦法切換成 root.
我的意思是在你寫好此 CGI 之後,將權限改為 SUID, owner 改為 root, 應該就可以了.
這樣子執行此 CGI 時,會以 root 身分執行起來.
Plan your work, then work your plan.
我的首頁:http://blog.elleryq.idv.tw
351899by http://counter.li.org

pontiff

  • 懷疑的國中生
  • **
  • 文章數: 44
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #15 於: 2003-08-05 21:44 »
感謝您還show出一段code給我。很抱歉我沒有更正我之前的留言。
我是用telnet, ls -al等指令,來 try popen的功能,是可以執行的。
#include <stdio.h>
int main( int argc, char* argv[] )
{
        printf("Content-type: text/plain\n\n");
        fflush( stdout );
        system("ls -l");
        exit(0);
}
請問您這段程式,我只是沒有寫fflush(stdout),為何會造成無法ls -al呢?


最後一項,請問若我將passwd中的apache改成跟root一樣的uid (0),有沒有任何意義?
我將apache改成root的uid後,發覺su成apache,啟動cgi程式可以正確呼叫daemon。但是若我用瀏覽器執行cgi程式,卻不行。您知道原因嗎?
謝謝!

elleryq

  • 鑽研的研究生
  • *****
  • 文章數: 908
  • 性別: 男
    • 檢視個人資料
    • Thinking more...
請問用C寫CGI,如何執行外部程式?
« 回覆 #16 於: 2003-08-05 22:48 »
是因為 buffer 的原因
printf() 會先把東西丟到 stdout ,而不會立即送出~
所以得用fflush(stdout) 強制輸出 buffer 內的資料
這是我前年遇到的狀況~~

最後一項,你的這個做法我也沒試過
可是你可以在 cgi 程式中利用 getuid() 去看一下自己的身分為何
這樣就知道 apache 是怎麼處理 cgi 的了~
Plan your work, then work your plan.
我的首頁:http://blog.elleryq.idv.tw
351899by http://counter.li.org

pontiff

  • 懷疑的國中生
  • **
  • 文章數: 44
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #17 於: 2003-08-06 10:53 »
嗯~我目前用sudo的方式,是可以執行程式的:)

再來又碰到一個問題了,很對不起各位:p

我在網頁執行那個cgi程式,程式中啟動一個Daemon,
然後瀏覽器底下狀態bar就慢慢跑(就像用Modem上網,然後瀏覽大量動畫網頁的樣子)。
似乎一直卡在執行Daemon的那行指令。
我有導向到null,但是似乎無效。

system ("..../start.sh > /dev/null &");

請問要如何寫,才能在執行cgi後,馬上跟server斷離?

dark

  • 俺是博士!
  • *****
  • 文章數: 1581
    • 檢視個人資料
請問用C寫CGI,如何執行外部程式?
« 回覆 #18 於: 2003-08-06 11:47 »
網頁瀏覽不能背景執行 ... 不過您關掉網頁 , 它仍然在背景執行...