From d4a286bdfd61be9381b0c5199c0a637b8372df1c Mon Sep 17 00:00:00 2001
From: Guo Wenxue <guowenxue@gmail.com>
Date: Thu, 08 Nov 2018 11:00:27 +0800
Subject: [PATCH] Add Ch3_fork sample code

---
 ch3_fork/fork_exec.c     |   96 ++++++++++
 ch3_fork/memory_layout.c |   42 ++++
 ch3_fork/socket_server.c |  162 ++++++++++++++++++
 ch3_fork/popen.c         |   88 +++++++++
 ch3_fork/fork.c          |   28 +++
 ch3_fork/fork_var.c      |  109 ++++++++++++
 6 files changed, 525 insertions(+), 0 deletions(-)

diff --git a/ch3_fork/fork.c b/ch3_fork/fork.c
new file mode 100644
index 0000000..4dbb728
--- /dev/null
+++ b/ch3_fork/fork.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+int main(int argc, char **argv)
+{
+	pid_t          pid;
+
+	printf("Parent process PID[%d] start running...\n", getpid() );
+
+	pid = fork();
+	if(pid < 0)
+	{
+		printf("fork() create child process failure: %s\n", strerror(errno));
+		return -1;
+	}
+	else if( pid == 0 )
+	{
+		printf("Child process PID[%d] start running, my parent PID is [%d]\n", getpid(), getppid());
+		return 0;
+	}
+	else // if( pid > 0 )
+	{ 
+		printf("Parent process PID[%d] continue running, and child process PID is [%d]\n", getpid(), pid);
+	       	return 0;
+	}
+}
diff --git a/ch3_fork/fork_exec.c b/ch3_fork/fork_exec.c
new file mode 100644
index 0000000..e009f47
--- /dev/null
+++ b/ch3_fork/fork_exec.c
@@ -0,0 +1,96 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#define TMP_FILE         "/tmp/.ifconfig.log"
+
+int main(int argc, char **argv)
+{
+        pid_t          pid;
+        int            fd;
+        char           buf[1024];
+        int            rv;
+        char          *ptr;
+        FILE          *fp;
+        char          *ip_start;
+        char          *ip_end;
+        char           ipaddr[16];
+
+        if( (fd=open(TMP_FILE, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0 )
+        {
+                printf("Redirect standard output to file failure: %s\n", strerror(errno));
+                return -1;
+        }
+
+        pid = fork();
+        if(pid < 0)
+        {
+                printf("fork() create child process failure: %s\n", strerror(errno));
+                return -1;
+        }
+        else if( pid == 0 )
+        {
+                printf("Child process start excute ifconfig program\n");
+                dup2(fd, STDOUT_FILENO);
+                execl("/sbin/ifconfig", "ifconfig", "eth0", NULL);
+                printf("Child process excute another program, will not return here. Return here means execl() error\n");
+		return -1;
+        }
+        else 
+        {
+                sleep(3);
+        }
+
+        memset(buf, 0, sizeof(buf));
+
+        rv=read(fd, buf, sizeof(buf));
+        printf("Read %d bytes data dierectly read after child process write\n", rv);
+
+        memset(buf, 0, sizeof(buf));
+        lseek(fd, 0, SEEK_SET);
+        rv=read(fd, buf, sizeof(buf));
+        printf("Read %d bytes data after lseek:\n %s", rv, buf);
+
+        fp = fdopen(fd, "r");
+        fseek(fp, 0, SEEK_SET);
+
+        while( fgets(buf, sizeof(buf), fp) )
+        {
+                if( strstr(buf, "netmask") )
+                {
+                        ptr=strstr(buf, "inet");
+                        if( !ptr )
+                        {
+                                break;
+                        }
+                        ptr += strlen("inet");
+
+                        while( isblank(*ptr) )
+                                ptr++;
+
+                        ip_start = ptr;
+
+                        while( !isblank(*ptr) )
+                                ptr++;
+
+                        ip_end = ptr;
+
+                        memset(ipaddr, 0, sizeof(ipaddr));
+                        memcpy(ipaddr, ip_start, ip_end-ip_start);
+
+                        break;
+                }
+        }
+
+        printf("Parser and get IP address: %s\n", ipaddr);
+
+        fclose(fp);
+        unlink(TMP_FILE);
+
+        return 0;
+}
diff --git a/ch3_fork/fork_var.c b/ch3_fork/fork_var.c
new file mode 100644
index 0000000..1489039
--- /dev/null
+++ b/ch3_fork/fork_var.c
@@ -0,0 +1,109 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#define TMP_FILE         "/tmp/.ifconfig.log"
+
+int main(int argc, char **argv)
+{
+        pid_t          pid;
+        int            fd;
+        char           buf[1024];
+        int            rv;
+        char          *ptr;
+        FILE          *fp;
+        char          *ip_start;
+        char          *ip_end;
+        char           ipaddr[16];
+
+        if( (fd=open(TMP_FILE, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0 )
+        {
+                printf("Redirect standard output to file failure: %s\n", strerror(errno));
+                return -1;
+        }
+
+        pid = fork();
+        if(pid < 0)
+        {
+                printf("fork() create child process failure: %s\n", strerror(errno));
+                return -1;
+        }
+        else if( pid == 0 )
+        {
+                printf("Child process start excute ifconfig program\n");
+                dup2(fd, STDOUT_FILENO);
+                execl("/sbin/ifconfig", "ifconfig", "eth0", NULL);
+                printf("Child process start excute ifconfig program over\n");
+                return 0;
+        }
+         else 
+        {
+                sleep(3);
+        }
+
+        memset(buf, 0, sizeof(buf));
+
+        rv=read(fd, buf, sizeof(buf));
+        printf("Read %d bytes data dierectly read after child process write\n", rv);
+
+        lseek(fd, 0, SEEK_SET);
+        rv=read(fd, buf, sizeof(buf));
+        printf("Read %d bytes data after lseek:\n %s\n ", rv, buf);
+
+        fp = fdopen(fd, "r");
+        fseek(fp, 0, SEEK_SET);
+
+        memset(buf, 0, sizeof(buf));
+
+        rv=read(fd, buf, sizeof(buf));
+        printf("Read %d bytes data dierectly read after child process write\n", rv);                                                                                    
+        printf("Read %d bytes data dierectly read after child process write\n", rv);
+
+        lseek(fd, 0, SEEK_SET);
+        rv=read(fd, buf, sizeof(buf));
+        printf("Read %d bytes data after lseek:\n %s\n ", rv, buf);
+
+        fp = fdopen(fd, "r");
+        fseek(fp, 0, SEEK_SET);
+
+        while( fgets(buf, sizeof(buf), fp) )
+        {
+                if( strstr(buf, "netmask") )
+                {
+                        ptr=strstr(buf, "inet");
+                        if( !ptr )
+                        {
+                                break;
+                        }
+                        ptr += strlen("inet");
+
+                        while( isblank(*ptr) )
+                                ptr++;
+
+                        ip_start = ptr;
+
+                        while( !isblank(*ptr) )
+                                ptr++;
+
+                        ip_end = ptr;
+
+                        memset(ipaddr, 0, sizeof(ipaddr));
+                        memcpy(ipaddr, ip_start, ip_end-ip_start);
+
+                        break;
+                }
+        }
+
+        printf("Parser and get IP address: %s\n", ipaddr);
+
+        fclose(fp);
+
+        unlink(TMP_FILE);
+
+        return 0;
+}
diff --git a/ch3_fork/memory_layout.c b/ch3_fork/memory_layout.c
new file mode 100644
index 0000000..5a786cd
--- /dev/null
+++ b/ch3_fork/memory_layout.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int   g_var1;
+int   g_var2=20;
+
+int main(int argc, char **argv)
+{
+	static int   s_var1;
+	static int   s_var2=10;
+       
+	char        *str="Hello";
+	char        *ptr;
+
+	ptr = malloc(100);
+
+	printf("[cmd args]:  argv address: %p\n", argv);
+	printf("\n");
+
+	printf("[ Stack]:     str address: %p\n", &str);
+	printf("[ Stack]:     ptr address: %p\n", &ptr);
+	printf("\n");
+
+	printf("[ Heap ]:  malloc address: %p\n", ptr);
+	printf("\n");
+
+
+	printf("[  bss ]:  s_var1 address: %p value: %d\n", &s_var1, g_var1);
+	printf("[  bss ]:  g_var1 address: %p value: %d\n", &g_var1, g_var1);
+
+	printf("[ data ]:  g_var2 address: %p value: %d\n", &g_var2, g_var2);
+	printf("[ data ]:  s_var2 address: %p value: %d\n", &s_var2, s_var2);
+
+	printf("[rodata]: \"%s\" address: %p \n", str, str);
+	printf("\n");
+
+	printf("[ text ]:  main() address: %p\n", main);
+	printf("\n");
+
+
+	return 0;
+}
diff --git a/ch3_fork/popen.c b/ch3_fork/popen.c
new file mode 100644
index 0000000..6a8e089
--- /dev/null
+++ b/ch3_fork/popen.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+int get_ipaddr(char *interface, char *ipaddr, int ipaddr_size);
+
+int main(int argc, char **argv)
+{
+       char           ipaddr[16];
+       char           *interface="eth0";
+
+        memset(ipaddr, 0, sizeof(ipaddr));
+
+	if( get_ipaddr(interface, ipaddr, sizeof(ipaddr)) < 0 )
+	{
+		printf("ERROR: get IP address failure\n");
+		return -1;
+	}
+
+	printf("get network interface %s IP address [%s]\n", interface, ipaddr);
+        return 0;
+}
+
+int get_ipaddr(char *interface, char *ipaddr, int ipaddr_size)
+{
+        char           buf[1024];
+        char          *ptr;
+        char          *ip_start;
+        char          *ip_end;
+	FILE          *fp;
+	int            len;
+	int            rv;
+ 
+	if( !interface || !ipaddr || ipaddr_size<16 )
+	{
+		printf("Invalid input arguments\n");
+		return -1;
+	}
+
+	memset(buf, 0, sizeof(buf));
+	snprintf(buf, sizeof(buf), "ifconfig %s", interface);
+	if( NULL == (fp=popen(buf, "r")) )
+	{
+		printf("popen() to excute command \"%s\" failure: %s\n", buf, strerror(errno));
+		return -2;
+	}
+	
+	rv = -3; /* Set default return value to -3 means parser failure */
+
+        while( fgets(buf, sizeof(buf), fp) )
+        {
+                if( strstr(buf, "netmask") )
+                {
+                        ptr=strstr(buf, "inet");
+                        if( !ptr )
+                        {
+                                break;
+                        }
+                        ptr += strlen("inet");
+
+                        while( isblank(*ptr) )
+                                ptr++;
+
+                        ip_start = ptr;
+
+                        while( !isblank(*ptr) )
+                                ptr++;
+
+                        ip_end = ptr;
+                        memset(ipaddr, 0, sizeof(ipaddr));
+
+			len = ip_end-ip_start;
+			len = len>ipaddr_size ? ipaddr_size : len;
+                        memcpy(ipaddr, ip_start, len);
+
+			rv = 0; /* Parser IP address OK and set rv to 0 */
+
+                        break;
+                }
+        }
+
+	return rv;
+}
diff --git a/ch3_fork/socket_server.c b/ch3_fork/socket_server.c
new file mode 100644
index 0000000..875386c
--- /dev/null
+++ b/ch3_fork/socket_server.c
@@ -0,0 +1,162 @@
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h> 
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#define MSG_STR "Hello LingYun IoT Studio Client\n"
+
+void print_usage(char *progname)
+{
+	printf("%s usage: \n", progname);
+	printf("-p(--port): sepcify server listen port.\n");
+	printf("-h(--Help): print this help information.\n");
+
+	return ;
+}
+
+int main(int argc, char **argv)
+{
+	int                  sockfd = -1;
+	int                  rv = -1;
+	struct sockaddr_in   servaddr;
+	struct sockaddr_in   cliaddr;
+	socklen_t            len;
+	int                  port = 0;
+	int                  clifd;
+	int                  ch;
+	int                  on = 1;
+	pid_t                pid;
+
+       	struct option        opts[] = {
+		{"port", required_argument, NULL, 'p'},
+		{"help", no_argument, NULL, 'h'},
+		{NULL, 0, NULL, 0}
+	};
+
+	while( (ch=getopt_long(argc, argv, "p:h", opts, NULL)) != -1 ) 
+	{
+		switch(ch)
+		{
+			case 'p':
+				port=atoi(optarg);
+				break;
+
+			case 'h':
+				print_usage(argv[0]);
+				return 0;
+		}
+
+	}
+
+	if( !port )
+	{
+		print_usage(argv[0]);
+		return 0;
+	}
+
+	sockfd=socket(AF_INET, SOCK_STREAM, 0);
+	if(sockfd < 0)
+	{
+		printf("Create socket failure: %s\n", strerror(errno));
+		return -1;
+	}
+	printf("Create socket[%d] successfully!\n", sockfd);
+
+	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+	memset(&servaddr, 0, sizeof(servaddr));
+	servaddr.sin_family=AF_INET;
+	servaddr.sin_port = htons(port);
+	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+	//inet_aton("192.168.0.16", &servaddr.sin_addr);
+
+	rv=bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
+	if(rv < 0)
+	{
+		printf("Socket[%d] bind on port[%d] failure: %s\n", sockfd, port, strerror(errno));
+		return -2;
+	}
+
+	listen(sockfd, 13);
+	printf("Start to listen on port [%d]\n", port);
+
+	while(1)
+	{ 
+		printf("Start accept new client incoming...\n");
+
+		clifd=accept(sockfd, (struct sockaddr *)&cliaddr, &len);
+		if(clifd < 0)
+		{
+			printf("Accept new client failure: %s\n", strerror(errno));
+			continue;
+		}
+
+		printf("Accept new client[%s:%d] successfully\n", 
+				inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
+
+		pid = fork();
+		if( pid < 0 )
+		{
+			printf("fork() create child process failure: %s\n", strerror(errno));
+			close(clifd);
+			continue;
+		}
+		else if( pid > 0 ) 
+		{
+			/* Parent process close client fd and goes to  accept new socket client again */
+			close(clifd);
+			continue;
+		}
+		else if ( 0 == pid )
+		{ 
+			char                 buf[1024];
+
+			/* Child process close the listen socket fd */
+			close(sockfd); 
+		       
+			printf("Child process start to commuicate with socket client...\n");
+			memset(buf, 0, sizeof(buf));
+		       	rv=read(clifd, buf, sizeof(buf));
+		       	if( rv < 0)
+		       	{
+			       	printf("Read data from client sockfd[%d] failure: %s\n", clifd, strerror(errno));
+			       	close(clifd);
+				exit(0);
+		       	}
+		       	else if( rv == 0)
+		       	{ 
+				printf("Socket[%d] get disconnected\n", clifd);
+			       	close(clifd);
+				exit(0);
+			} 
+			else if( rv > 0 ) 
+			{
+			       	printf("Read %d bytes data from Server: %s\n", rv, buf);
+		       	} 
+			
+			rv=write(clifd, MSG_STR, strlen(MSG_STR));
+		       	if(rv < 0)
+		       	{
+			       	printf("Write to client by sockfd[%d] failure: %s\n", sockfd, strerror(errno));
+			       	close(clifd);
+				exit(0);
+		       	}
+
+			sleep(1);
+
+			printf("close client socket[%d] and child process exit\n", clifd);
+		       	close(clifd);
+		       	exit(0);
+		}
+	}
+
+
+	close(sockfd);
+
+	return 0;
+}

--
Gitblit v1.9.1