APUE Learning Example Source Code
Guo Wenxue
2018-11-08 d4a286bdfd61be9381b0c5199c0a637b8372df1c
Add Ch3_fork sample code
6 files added
525 ■■■■■ changed files
ch3_fork/fork.c 28 ●●●●● patch | view | raw | blame | history
ch3_fork/fork_exec.c 96 ●●●●● patch | view | raw | blame | history
ch3_fork/fork_var.c 109 ●●●●● patch | view | raw | blame | history
ch3_fork/memory_layout.c 42 ●●●●● patch | view | raw | blame | history
ch3_fork/popen.c 88 ●●●●● patch | view | raw | blame | history
ch3_fork/socket_server.c 162 ●●●●● patch | view | raw | blame | history
ch3_fork/fork.c
New file
@@ -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;
    }
}
ch3_fork/fork_exec.c
New file
@@ -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;
}
ch3_fork/fork_var.c
New file
@@ -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;
}
ch3_fork/memory_layout.c
New file
@@ -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;
}
ch3_fork/popen.c
New file
@@ -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;
}
ch3_fork/socket_server.c
New file
@@ -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;
}