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
Learn More →
特別注意 PHP 網路 IO 與 c 語言方法, 再使用 popen (與 system() 有何不同?)之間的差異!
Linux mkfifo Command Tutorial for Beginners (with Examples)
Learn More →
Learn More →
Learn More →
PHP 基本語言使用可參閱 PHP Tutorial( w3schools)
Learn More →
Learn More →
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?
Learn More →
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 的 配合~因此 要 考慮 很多, 很多例子要 修改別亂抄!
Authors: CrazyDog, CrazyMonkeyemail: kccddb@gmail.comDate: 20230222
Mar 14, 2025Author: \mathcal{CrazyDog}, Ph.D. in Electrical Engineering, NCTUemail: kccddb@gmail.comDate: 20230910
Nov 4, 2024Author: WhoAmI Date: 20230523 email:kccddb@gmail.com Copyright: CC BY-NC-SA 《荀子‧勸學》不積跬步,無以至千里;不積小流,無以成江海。 I. Mutex variables MUST be declared with type pthread_mutex_t, and must be initialized before they can be used. II. 了解 pthread_mutex_lock / pthread_mutex_unlock 與可能問題和代價 III. 程式執行效率與startvation 等問題
Jul 11, 2024Author: WhoAmIemail: kccddb@gmail.com
Dec 6, 2023or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up