Try   HackMD

popen, select, PHP client, 執行遠端程式

tags: C LANGUAGE PHP popen 執行遠端程式 select remote execution http simple web server web based linux

Author: WhoAmI
email: kccddb@gmail.com
Date: 20220729
Copyright: CC BY-NC-SA

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

特別注意 PHP 網路 IO 與 c 語言方法, 再使用 popen (與 system() 有何不同?)之間的差異!

Linux mkfifo Command Tutorial for Beginners (with Examples)

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

PHP 基本語言使用可參閱 PHP Tutorial( w3schools)
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

a. PHP 另外重要的是 PHP Sessions 與 PHP Cookies (請用 Wireshark 觀察 HTTP frames)
b. PHP 與 Database(MySQL, SQLite, )除了考慮安全性以外, 也應考慮 網路連線的特性(避免每一次重新連線至Database, Why?)
c. HTTP 基本上是 stateless protocol 應用, 當 Cookies 不允許使用時您會如何處理?
d.一般 網路上提供的 virtual server 的作法是什麼? Why?

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Source code: selectexe.c, run.php

a. 為什麼 需要用 int writet(int fd,char *buf,int len,int secs)?

b. execl, execlp, execle, execv, execvp, execvpe , popen, system() 有何差別?

( Linux 如有需要, 最好使用 popen() 而不要用 system())

請自行架設環境 練習

注意 有BUG, FIXIT

selectexe.c
注意 FIXIT

/* Important syytem call: select() I/O re-direction popen application WhoAmI(cddb.tw@gmail.com) 20191210 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <sys/wait.h> #define PANIC(msg) { perror(msg); exit(EXIT_FAILURE); } #define STDIN 0 static void sig_handler(int signo) { pid_t pid; int stat; switch(signo) { case SIGCHLD: printf("SIGCHLD=%d\n",signo); pid=waitpid(0,&stat,WNOHANG); break; case SIGINT: printf("SIGINT=%d\n",signo); break; case SIGALRM: printf("Got SIGALRM=%d, exit!\n",signo); exit( EXIT_FAILURE); break; case SIGPIPE: printf("Got SIGPIPE=%d, exit!\n",signo); //exit( EXIT_FAILURE); default: printf("signal=%d\n",signo); } return; } #define MY_LENTH 1023 int writet(int fd,char *buf,int len,int secs) { fd_set w_fds; struct timeval tv; int n; int m,j; tv.tv_sec = secs; tv.tv_usec = 0; FD_ZERO(&w_fds); FD_SET(fd,&w_fds); m=0; j=0; do{ /* BUG! why?*/ n = select(fd+1, NULL, &w_fds, NULL, &tv ); switch(n){ case 0: errno = ETIMEDOUT; printf("Write timeout!\n"); return -1; break; case -1: return -1; default: //FIXIT! why? m=write(fd,buf+j,len-j); j=j+m; break; } }while(m>0); } static int run(int ofd, char *buf,int n) { FILE *fp; int fd; unsigned char *p; int i,len; char obuf[MY_LENTH+1]; for(p=buf;*p>=' ';p++){ } *p=0; printf("%s\n",buf); // fp=popen("ls -l","r"); fp = popen(buf,"r"); fd=fileno(fp); do{ memset(obuf,0,MY_LENTH+1); p=fgets(obuf, MY_LENTH , fp); obuf[MY_LENTH]=0; printf("%s",obuf); if(ofd>0){ if(p)writet(ofd,p,strlen(p),1); } }while(p!=NULL); pclose(fp); } int main(int argc, char *argv[]) { int server_fd; int client_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; fd_set master_fds; fd_set read_fds; int fdmax; struct timeval tv; int port; int len; int i, j; char buf[1024],ch; int nbytes; int yes=1; int retval; char cmd[512]; int n; int timeout; if(argc>1)port=atoi(argv[1]); else port=9999; if(argc>2)timeout=atoi(argv[2]); else timeout=160; printf("Server start port=%d timeout=%d\n",port,timeout); signal (SIGPIPE, sig_handler); // signal (SIGPIPE,SIG_IGN); FD_ZERO(&master_fds); FD_ZERO(&read_fds); if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) PANIC("socket"); if (setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) PANIC("setsockopt"); memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(port); if (bind(server_fd,(struct sockaddr *)&server_addr,sizeof(server_addr))==-1) PANIC("bind"); if (listen(server_fd,10) == -1) PANIC("listen"); FD_SET(server_fd,&master_fds); FD_SET(STDIN,&master_fds); fdmax = server_fd; // Server Loop for(;;) { read_fds=master_fds; tv.tv_sec = 160; tv.tv_usec = 0; retval = select(fdmax+1,&read_fds,NULL,NULL,&tv); switch(retval){ case -1: perror("select"); continue; case 0: printf("Time Out..."); for(i=3; i<= fdmax; i++) { if (FD_ISSET(i,&master_fds)) close(i); } exit(0); } for(i=0; i<=fdmax; i++) { if (FD_ISSET(i,&read_fds)) { if (i==server_fd) { //Handle New Connection len = sizeof(client_addr); if ((client_fd=accept(server_fd,(struct sockaddr *)&client_addr,&len)) == -1) { perror("accept"); continue; } else { FD_SET(client_fd, &master_fds); if (client_fd > fdmax) { fdmax = client_fd; } printf("New connection from %s on socket %d\n",inet_ntoa(client_addr.sin_addr),client_fd); n=sprintf(cmd,"Welcome new connection from IP:%s on socket %d\n",inet_ntoa(client_addr.sin_addr),client_fd); write(client_fd,cmd,n); } }else { // Handle data from the clients and the STDIN if ((nbytes=read(i, buf, sizeof(buf))) > 0) { if(buf[0]=='!'){ run(i, &buf[1],nbytes-1); //close connection close(i); FD_CLR(i, &master_fds); }if(buf[0]=='@'){ //Don't close connction run(i, &buf[1],nbytes-1); }else{ } write(1,buf,nbytes);// for(j=0; j<=fdmax; j++) { if (FD_ISSET(j, &master_fds)) { if (j!=server_fd && j!=i &&j!=0) { if (send(j, buf, nbytes, 0) == -1) { perror("send"); } } } }//for } else { perror("recv"); close(i); FD_CLR(i, &master_fds); } } //for loop }//if } //for scan all IO }//for server loop return 0; }

run.php

<!DOCTYPE html> <html> <body> <h2>PHP TCP Client</h2> <?php $myaction=$_SERVER['PHP_SELF']; echo $myaction; //set the default values $idnumber=0; //Check GET method if($_SERVER['REQUEST_METHOD'] == 'GET'){ if(isset($idnumber)){ if($idnumber==0){ //set the default values $ip="127.0.0.1"; $port=9999; $cmd="ls -al"; $host="www.org"; $idnumber=$idnumber+1; }else{ //get from FORM $ip=$_GET["IP"]; $port=$_GET["PORT"]; $cmd= $_GET["CMD"]; $host=$_GET["HOST"]; $idnumber=$_GET["idnumber"]; $idnumber=$idnumber+1; } }else{ //set the default values $idnumber=0; $ip="127.0.0.1"; $port=9999; $cmd="ls -al"; $host="www.org"; } } //Check POST method if($_SERVER['REQUEST_METHOD'] == 'POST'){ $ip=$_POST["IP"]; $port=$_POST["PORT"]; $cmd= $_POST["CMD"]; $host=$_POST["HOST"]; $idnumber=$_POST["idnumber"]; $idnumber=$idnumber+1; } ?> <p style="color:green" >POST Method </p> <form action="<?php echo $myaction; ?>" method="POST"> IP:PORT<br> <input type="text" name="IP" value="<?php echo $ip; ?>"> <input type="text" name="PORT" value="<?php echo $port; ?>"> <br>CMD:<br> <input type="text" name="CMD" value="<?php echo $cmd; ?>"> <br><br> <input type="hidden" name="idnumber" value="<?php echo $idnumber; ?>" > <input type="submit" style="color:green" value="Submit (POST)"> </form> <p style="color:blue" >If you click the "Submit" button, the form-data will be sent to a page called "<?php echo $url; ?>".</p> <?PHP $idnumber=0; $host="www.org"; //FIXIT if($idnumber>=0){ echo "<p style='color:blue'>idnumber=$idnumber<BR>IP= $ip: PORT=$port:CMD=$cmd:HOST:$host </p><BR>"; //$message = "GET $url HTTP/1.1\r\nHOST: $host\r\n\r\n\r\n"; $message = "!$cmd\0"; echo "<p style='color:red' >Demo HTTP Client:$message <BR></p>"; echo "<p style='color:red' >Send TCP command...<BR>[".$message."]<BR><BR></p>"; $socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("from Client: Could not create socket\n"); $result = socket_connect($socket, $ip, $port) or die("from Client: Unable to connect to server\n"); socket_write($socket, $message, strlen($message)); $input = socket_read($socket, 1024); echo $input; ?> <?php echo "<p style='color:red' >Respones... <BR></p>"; $r_data=""; $data = ""; $done = false; $total=0; $bb=1; do{ socket_clear_error($socket); $bytes = socket_recv($socket, $r_data, 1256, MSG_WAITALL);//MSG_DONTWAIT $lastError = socket_last_error($socket); $bb=intval($bytes); $total=$total+$bb; if ($lastError != 11 && $lastError > 0) { // something went wrong! do something echo "Wrong"; $done = true; } else if ($bb==0){ continue; } else if ($bb > 0) { $data=$data.$r_data; //echo $data; } else { usleep(2000); // prevent "CPU burn" } }while($bb>0); echo "<p style='color:red' >Total=$total bytes<BR></p>"; echo nl2br($data); echo "<BR>"; sleep(1); socket_close($socket); date_default_timezone_set('Asia/Taipei'); $today=date('m/d/Y h:i:s a', time());; echo "\n<BR><p style='color:red' > Bye from Client...[$today]</p>"; } ?> </body> </html>

不要認為 PHP 很難, 我的經驗是當時我當最後一關 面試委員, 候選 3 人都沒學過PHP, 我早上同時 教3人, 下午考~就有一人 可以, 因為他 基礎好, 所以基礎很重要, 尤其 團隊合作, 計概(含 c 語言), 微處理機, 資料結構

PHP 請自學

PHP 很多網路上的例子~很多 方便 學習, 實務上要考量 美工與前端 JavaScript 的 配合~因此 要 考慮 很多, 很多例子要 修改別亂抄!