Superservers
#include "funcs.h"        /******  Skeleton for a superserver based
                          ******  on using exec to provide service.
                          ******/

#define PASSIVE_MAX 2
sigjmp_buf env;

main()
{
      int passive[2], i;
      short curport = 3071;
      fd_set rds, savefds;
      struct sigaction sa;
      void reaper(int signum);
      int set_up_socket(short port);
      void callexec(int *passive, fd_set ready);
 
      FD_ZERO(&savefds);
      for (i = 0; i < PASSIVE_MAX; i++, curport++)
      {
           passive[i] =  set_up_socket(curport);
           FD_SET(passive[i], &savefds);
      }

      sa.sa_handler = reaper;
      sa.sa_flags   = 0;
      Sigfillset(&sa.sa_mask);
      Sigaction(SIGCHLD, &sa, NULL);

      while (1)
      {
           sigsetjmp(env,1);
           memcpy(&rds, &savefds, sizeof(fd_set));
           if (select(FD_SETSIZE, &rds, NULL, NULL, NULL) < 0)
           {
               perror("Select");
               exit(1);
           }
           callexec(passive, rds);
      }
}




int set_up_socket(short port)
{
     long flags;
     int sd, size;
     struct sockaddr_in sin;

     sd = Socket(AF_INET, SOCK_STREAM, 0);

     memset(&sin, 0, sizeof(sin));
     sin.sin_port = htons(port);
     sin.sin_family = AF_INET;
     sin.sin_addr.s_addr = htonl(INADDR_ANY);

     Bind(sd, (struct sockaddr *) &sin,  sizeof(sin));
     Listen(sd, 5);

     if ((flags = fcntl(sd, F_GETFL, 0)) < 0)
     {
         perror("Get flags");
         exit(1);
     }
     if (fcntl(sd, F_SETFL, flags | O_NONBLOCK) < 0)
     {
         perror("Set flags");
         exit(1);
     }

     return sd;
}

void callexec(int *passive, fd_set rds)
{
     int i, j, sock;
     int active, size;
     char actives[10];
     struct sockaddr_in cli;
     socklen_t len;
     pid_t pid;

     for (i = 0; i < PASSIVE_MAX; i++)
     {
         if (FD_ISSET(passive[i], &rds))
          {
              if ((active = accept(passive[i], (struct sockaddr *) &cli,
                                   (socklen_t *) &len)) < 0)
              {
                  continue;  /**  Something bad happened to passive socket **/
              }
           }
           else continue;    /** passive[i] has no clients  **/

           pid = Fork();
         
           if (pid > 0)   /***  Parent  ***/
           {
               Close(active);
           }
           else   /****  Child  ****/
           {
               for (j = 0; j < PASSIVE_MAX; j++)
                   Close(passive[j]);

               sprintf(actives,"%d", active);
               switch (passive[i])
               {
                  case 3: if (execl("echos","echos", actives, NULL) < 0)
                          {
                              perror("Exec echos");
                              exit(1);
                          };  
                  case 4: if (execl("times2","times2", actives, NULL) < 0)
                          {
                              perror("Exec times2");
                              exit(1);
                          };  
               }
           }
      }
}


void reaper(int signum)
{
     pid_t kid;
     int status;

     while ((kid = waitpid(-1, &status, WNOHANG)) > 0) ;
     siglongjmp(env, 1);
}
#include "funcs.h"     /**  Echo client for super server  **/

int active;
#define MAXBUF 256

main()
{
     struct sockaddr_in sin; 
     char s[MAXBUF];
     struct sigaction sa;
     void handler(int), term_handler(int);
   
     Sigfillset(&sa.sa_mask);
     sa.sa_handler = handler;
     sa.sa_flags   = 0;
     Sigaction(SIGPIPE, &sa, NULL);
     sa.sa_handler = term_handler;
     Sigaction(SIGQUIT, &sa, NULL);
     Sigaction(SIGINT,  &sa, NULL);
   
     active = Socket(PF_INET, SOCK_STREAM, 0);

     memset(&sin, 0, sizeof(struct sockaddr_in));
     sin.sin_port = htons(3071); 
     sin.sin_family = AF_INET;
     sin.sin_addr.s_addr = inet_addr("153.18.17.12");
     Connect(active, (struct sockaddr *) &sin, sizeof(sin));

     while(printf("Enter string: "), fgets(s, MAXBUF, stdin),
           strncmp(s,"quit", 4))
     {
           writen(active,s, MAXBUF); 
           memset(s, 0, MAXBUF);
           readn(active, s, MAXBUF);
           printf("From server: %s\n", s);
     }

     writen(active, "quit", 4);
     Close(active);
}


/****************************  SIGPIPE handler  *****************************/
void handler(int signum)
{
    writen(active, "quit", 4);
    printf("Server died\n");
    Close(active);
    exit(0);
}


/*************************  Terminal signal handler  ************************/
void term_handler(int signum)
{
    writen(active, "quit", 4);
    Close(active);
    exit(0);
}



/******************  Incremental Read/Write Code   ***********************/
/******************  Works on fixed-length packets.***********************/

int readn(int fd, char *buf, int bytes)
{
     int nleft;
     int nread;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nread = read(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         else if (nread == 0)
              break;      /****  EOF!   ****/
         nleft -= nread;
         mover += nread;
     }
     return (bytes - nleft);
}


int writen(int fd, char *buf, int bytes)
{
     int nleft;
     int nwritten;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nwritten = write(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         nleft -= nwritten;
         mover += nwritten;
     }
     return bytes;
}
#include "funcs.h"   /**********  This is the echo server.  *********/
                     /**********  VERY "bare bones".        *********/

#define MAXBUF 256
int active;
sigjmp_buf env;

main(int argc, char **argv)
{
     int readclient(int active, char *buffer, int buffer_size);
     int active;
     char buf[MAXBUF];

     active = atoi(argv[1]);
     while(alarm(45), memset(buf, 0, MAXBUF), readn(active, buf, MAXBUF),
           strncmp(buf, "quit", 4))
     {
           alarm(0);
           writen(active, buf, MAXBUF) ;
     }         
}

/******************  Incremental Read/Write Code   ***********************/
/******************  Works on fixed-length packets.***********************/

int readn(int fd, char *buf, int bytes)
{
     int nleft;
     int nread;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nread = read(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         else if (nread == 0)
              break;      /****  EOF!   ****/
         nleft -= nread;
         mover += nread;
     }
     return (bytes - nleft);
}


int writen(int fd, char *buf, int bytes)
{
     int nleft;
     int nwritten;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nwritten = write(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         nleft -= nwritten;
         mover += nwritten;
     }
     return bytes;
}


#include "funcs.h"  /****  Time client for superserver  ****/

#define MAXBUF 256


main()
{
     struct sockaddr_in sin; 
     char s[256];
     struct sigaction sa;
     void handler(void), set_no_linger(void), term_handler(void);
     int active;
   
   
     active = socket(PF_INET, SOCK_STREAM, 0);
     memset(&sin, 0, sizeof(struct sockaddr_in));
     sin.sin_port = htons(3072); 
     sin.sin_family = AF_INET;
     sin.sin_addr.s_addr = inet_addr("153.18.17.12");

     Connect(active, (struct sockaddr *) &sin, sizeof(sin));

     memset(s, 0, MAXBUF);
     readn(active, s, MAXBUF);
     printf("Time is %s", s);
}

/******************  Incremental Read/Write Code   ***********************/
/******************  Works on fixed-length packets.***********************/

int readn(int fd, char *buf, int bytes)
{
     int nleft;
     int nread;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nread = read(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         else if (nread == 0)
              break;      /****  EOF!   ****/
         nleft -= nread;
         mover += nread;
     }
     return (bytes - nleft);
}



#include <time.h>      /******  Time server for superserver  ******/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

main(int argc, char **argv)
{
     int active;
     char *timeptr;
     time_t now;

     active = atoi(argv[1]);
     now = time(NULL);
     timeptr = ctime(&now);
     writen(active, timeptr, strlen(timeptr)) ;
}


int writen(int fd, char *buf, int bytes)
{
     int nleft;
     int nwritten;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nwritten = write(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         nleft -= nwritten;
         mover += nwritten;
     }
     return bytes;
}






/**********************  Sessions with Superserver  ********************/

$ supers&
[1]     6491

$ echoc                ######  Echo client talks to echo server.
Enter string: hello
From server: hello

Enter string: what
From server: what

Enter string: quit

$ timec                ######  Time client talks to time server.
Time is Wed Feb 24 23:18:31 1999

$ echoc    ######  New echo client.
Enter string: when
From server: when

Enter string:  ######  Suspended this echo client with CTRL-Z
[2] + Stopped                  echoc

$ echoc        ######  A second echo client.
Enter string: when
From server: when

Enter string: why
From server: why

Enter string: quit

$ fg    ######  Bring back old echo client.
echoc
what
Server died   ######  Echo server timed echo client out.

$ timec       ######  New time client.