The Open Source Swiss Army Knife

/code/c/unix_c/fork/
/code/c/unix_c/fork/ + sub-categories
http://www.sirfsup.com/
web directory content
    
      

Not logged in
Chat Register Login
return to:  http:/www.sirfsup.com      /code   /c   /unix_c   /fork 
Permalink: child_demo2.c
Title: add
article options : please login   |  raw source view  

#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <limits.h>

#include "child.h"

int debug=1;


int listen_sock;



void child_process_1(
   child_info_t *child_p,
   void *private_p
) {
   int rc;
   int sleep_time;
   int connection;
   struct sockaddr_in remote_addr;
   int addr_size;
   struct hostent *remote_host;
   char buf[1024];
   char *p;
   int requests_remaining = 10;
   int read_fd;
   int write_fd;
   FILE *in;
   FILE *out;
   char s[128];
   assert(child_p);

   requests_remaining = 10;

   /* undo signal settings from parent */
   signal(SIGTERM, SIG_DFL);
   signal(SIGINT, SIG_DFL);
   signal(SIGQUIT, SIG_DFL);

   /* This is child process */
   fprintf(stderr, 
      "Child process #%d starting, pid=%d, parent=%d\n",
       child_p->number, 
       child_p->pid,
       child_p->ppid
   );

   while(requests_remaining--) {

      addr_size=sizeof(remote_addr);

      connection = accept(listen_sock,
	 (struct sockaddr *) &remote_addr,
	 &addr_size);
      fprintf(stderr, "accepted connection\n");
 
      remote_host = gethostbyaddr( (void *) &remote_addr.sin_addr,
	 addr_size, AF_INET);
      /* we never bother to free the remote_host strings */
      /* The man page for gethostbyaddr() fails to mention */
      /* allocation/deallocation or reuse issues */

      /* return values from DNS can be hostile */


      if(remote_host) { 
         assert(strlen(remote_host->h_name)<128);
         assert(remote_host->h_length==4);  /* no IPv6 */

	if(debug) fprintf(stderr, "from: %s\n", remote_host->h_name);
	strncpy(s,remote_host->h_name,sizeof(s));
      } else {
	if(debug) fprintf(stderr, "from: [%s]\n",inet_ntoa(remote_addr
   .sin_addr) );
	strncpy(s,inet_ntoa(remote_addr.sin_addr),sizeof(s));
      }

      #if 0
         fprintf(stderr,"Connection from %s [%s]\n",
	    remote_host->h_name, 
            inet_ntoa(remote_addr.sin_addr));
      #endif


      read_fd = dup(connection);
      write_fd = dup(connection);
      assert(read_fd>=0);
      assert(write_fd>=0);
      in = fdopen(read_fd, "r");
      out = fdopen(write_fd, "w");
      assert(in);
      assert(out);

      /* do some work */

      while(1) {
         buf[0]=0;
	 p=fgets(buf, sizeof(buf), in);
         if(!p) break;  /* connection probably died */
	 buf[sizeof(buf)-1]=0;
	 p=strrchr(buf,'\n');
	 if(p) *p=0;  /* zap newline */
	 p=strrchr(buf,'\r');
	 if(p) *p=0;  /* zap return */

         fprintf(stderr,"buf=<%s>\n",buf);
	 p=strchr(buf,':');
	 if(p) {
            /* we never actually get here because we start */
            /* spewing out a response as soon as we rx GET */
	    /* probably an http: header */
	    /* ignore it */
	    ; 
	 } else if(strstr(buf,"GET")) {
             fprintf(stderr,"GET\n");
	     fprintf(out,"HTTP/1.0 200 OK");
	     fprintf(out,"Content-type: text/html\n");
	     fprintf(out,"\n");
	     fprintf(out,"<HTML>\n");
	     fprintf(out,"  <TITLE>\n");
	     fprintf(out,"  Status Page\n");
	     fprintf(out,"  </TITLE>\n");
	     fprintf(out," <BODY>\n");
	     fprintf(out,"  <H1>\n");
	     fprintf(out,"  Status Page\n");
	     fprintf(out,"  </H1>\n");
	     fprintf(out,"  <BR>number=%d\n",child_p->number);
	     fprintf(out,"  <BR>pid=%d\n",child_p->pid);
	     fprintf(out,"  <BR>ppid=%d\n",child_p->ppid);
	     fprintf(out,"  <BR>requests remaining=%d\n",
                requests_remaining);
	     fprintf(out," </BODY>\n");
	     fprintf(out,"</HTML>\n");
             break;
	 } else {
	    /* ??? */
	 }


      }

      fprintf(stderr,"closing connection\n");
      /* wrap things up */   
      fclose(in);
      fclose(out);
      close(read_fd);
      close(write_fd);
      close(connection);
   } /* while */


   fprintf(stderr, 
      "Child process #%d exiting, pid=%d, parent=%d\n",
       child_p->number,
       child_p->pid,
       child_p->ppid
   );
}

child_group_info_t child_group_1;
jmp_buf jump_env;


void sig_handler(int signal)
{
   fprintf(stderr, "pid %d recieved signal %d\n", 
      getpid(), signal);
   child_restart_children = 0;

   #if 0
      /* wake up the wait() */
      /* doesn't work */
      raise(SIGCHLD);
   #endif

   longjmp(jump_env,1);

   /* We opt not to call signal() again here */
   /* next signal may kill us */
}

int port = 1236;

main()
{
   int i; 
   int child;
   child_group_info_t child_group_1;
   child_groups_t child_groups;
   int rc;
   struct sockaddr_in tcpaddr;
 
   tcpaddr.sin_family = AF_INET;
   tcpaddr.sin_addr.s_addr = INADDR_ANY;
   tcpaddr.sin_port = htons( port );

   listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
   if(listen_sock<0) perror("socket");
   assert(listen_sock>=0);

   fprintf(stderr, "listening on port %d\n",port);

   #if 1
      rc=bind(listen_sock, (struct sockaddr *) &tcpaddr, sizeof(tcpaddr));
   #else
      rc=bind(listen_sock, (struct sockaddr *) &tcpaddr, 4);
   #endif
   if(rc!=0) perror("bind");
   assert(rc==0);
   rc=listen(listen_sock,10);
   if(rc!=0) perror("listen");
   assert(rc==0);

   #if 0
      setvbuf(stderr, NULL, _IOLBF, 0);
   #else
      setbuf(stderr, NULL);
   #endif

   /* Note: children inherit this */
   signal(SIGTERM, sig_handler);
   signal(SIGINT, sig_handler);
   signal(SIGQUIT, sig_handler);

   child_group_create(&child_group_1, 4, 4, child_process_1, NULL );

   child_groups.ngroups = 1;
   child_groups.group[0]=&child_group_1;


   rc=setjmp(jump_env);
   if(rc==0) {
     /* normal program execution */

      child_groups_keepalive(&child_groups);
   } else {
      /* exception handler */
      /* we got here via setjmp() */

      /* restore signal handlers to defaults */
      signal(SIGTERM, SIG_DFL);
      signal(SIGINT, SIG_DFL);
      signal(SIGQUIT, SIG_DFL);

      child_groups_kill(&child_groups);
      exit(0);
   }

}




Leave a Reply
Your Name:     anonymous
Your Email:
Website:  
Comments:

The author will be notified of your reply.
return to top