An Example of a Remote Directory Service Using Exec
#include "funcs.h"

#define PACKET   256 
#define DIR_WONT_OPEN  '\01' 
#define ILLEGAL_DIR    '\02' 
#define TERMINATOR     '\06'
#define QUIT           "\07"

int  active;
main()
{
    char *dirname, filename[PACKET], packet[PACKET];
    char *PromptAndGetResponse(void);  
    int MakeSocket(void);
    int readn(int fd, char *buf, int bytes),
        writen(int fd, char *buf, int bytes);
    void SetUpSIGNALS(void);
    void WriteQuit(void);
    FILE *more;

    atexit(WriteQuit);
    active = MakeSocket();
    SetUpSIGNALS();

    while(dirname = PromptAndGetResponse(), 
          dirname ? strcmp(dirname, "quit") : 1)
    {
          if (!dirname) continue;
          
          memset(packet, 0, PACKET);
          strcpy(packet, dirname);
          writen(active, packet, 1);
          writen(active, packet + 1, PACKET - 1);

          more = Popen("more", "w");
          memset(filename, 0, PACKET);
          alarm(50);
          while(readn(active, filename, PACKET), *filename != TERMINATOR)
          {
              switch (*filename)
              {
                  case DIR_WONT_OPEN:
                            fprintf(more, "Could not open %s.\n\n", dirname);
                            break;

                  case ILLEGAL_DIR:
                            fprintf(more, "Illegal search of %s!\n\n", dirname);
                            break;
 
                  default: fprintf(more, "%s\n", filename);
              }
              alarm(0);
              memset(filename, 0, PACKET);
          }
          Pclose(more);
    }
    
    WriteQuit();
}
int MakeSocket(void)
{
    struct sockaddr_in sin;
    int active;

    active = Socket(AF_INET, SOCK_STREAM, 0);

    memset(&sin, 0, sizeof(struct sockaddr_in));
    sin.sin_port   = htons(3123);
    sin.sin_family = AF_INET;
    Inet_aton("153.18.17.12", &sin.sin_addr);

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



void SetUpSIGNALS(void)
{
    void handler(int sigtype);
    struct sigaction sa;

    Sigfillset(&sa.sa_mask);
    sa.sa_flags = 0;
    sa.sa_handler = handler;
    Sigaction(SIGALRM, &sa, NULL);
    Sigaction(SIGPIPE, &sa, NULL);
}


void handler(int signum)
{
     void WriteQuit(void);

     printf("Server disconnected!\n");
     WriteQuit();
     exit(0);
}



char *PromptAndGetResponse(void)
{
    static char buf[PACKET];
    char *token;

    printf("Enter directory: ");
    fgets(buf, PACKET, stdin);

    token = strtok(buf, "\040\t\n");
    if (!token) return NULL;
    if (strtok(NULL, "\040\t\n"))
    {
          printf("Excess parameters!  Try again!\n\n");
          return NULL;
    }
    return token;
}


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

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



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

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



void WriteQuit(void)
{
     char packet[PACKET];

     memset(packet, 0, PACKET);
     strcpy(packet, QUIT);
     writen(active, packet, 1);
     writen(active, packet + 1, PACKET - 1);
}
#include "funcs.h"

#define PACKET   256 

main()
{
      int passive, active, clilen = sizeof(struct sockaddr_in);
      pid_t pid;
      struct sigaction sa;
      struct sockaddr_in client;
      char actives[PACKET];
      int SocketSetup(void);
      void SetUpSIGCHLD(void);
    
      passive = SocketSetup();
      SetUpSIGCHLD();

      for (;;)
      {
           active = accept(passive, (struct sockaddr *) &client,
                           &clilen);
           if (active < 0)
           {
                if (errno == EINTR) continue;
                else
                {
                    perror("accept");
                    exit(0);
                }
           }

           pid = Fork();

           if (pid > 0)   /** Parent **/
           {
                Close(active);
                continue;
           }
           else  /** Child  **/
           {
                Close(passive);

                sprintf(actives, "%d", active);
                if (execlp("getfiles", "getfiles", actives, NULL) < 0)
                {
                     perror("execl");
                     exit(0);
                }
                exit(0);
           }
     }
}


int SocketSetup(void)
{
      int passive;
      struct sockaddr_in sin;

      passive = Socket(AF_INET, SOCK_STREAM, 0);

      sin.sin_port = htons(3123);
      sin.sin_addr.s_addr = htonl(INADDR_ANY);
      sin.sin_family = AF_INET;

      Bind(passive, (struct sockaddr *) &sin, sizeof(sin));
      Listen(passive, 20);

      return passive;
}


void SetUpSIGCHLD(void)
{
      struct sigaction sa;
      void handler(int signum);

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


void handler(int signum)
{
      int status;

      while(waitpid(-1, &status, WNOHANG) > 0) {}
}


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)
              return 0;      /****  EOF!   ****/
         nleft -= nread;
         mover += nread;
     }
     return (bytes - nleft);
}
#include "funcs.h"

#define PACKET   256 

main()
{
      int passive, active, clilen = sizeof(struct sockaddr_in);
      pid_t pid;
      struct sigaction sa;
      struct sockaddr_in client;
      char actives[PACKET];
      int SocketSetup(void);
      void SetUpSIGCHLD(void);
    
      passive = SocketSetup();
      SetUpSIGCHLD();

      for (;;)
      {
           active = accept(passive, (struct sockaddr *) &client,
                           &clilen);
           if (active < 0)
           {
                if (errno == EINTR) continue;
                else
                {
                    perror("accept");
                    exit(0);
                }
           }

           pid = Fork();

           if (pid > 0)   /** Parent **/
           {
                Close(active);
                continue;
           }
           else  /** Child  **/
           {
                Close(passive);

                sprintf(actives, "%d", active);
                if (execlp("getfiles", "getfiles", actives, NULL) < 0)
                {
                     perror("execl");
                     exit(0);
                }
           }
     }
}


int SocketSetup(void)
{
      int passive;
      struct sockaddr_in sin;

      passive = Socket(AF_INET, SOCK_STREAM, 0);

      sin.sin_port = htons(3123);
      sin.sin_addr.s_addr = htonl(INADDR_ANY);
      sin.sin_family = AF_INET;

      Bind(passive, (struct sockaddr *) &sin, sizeof(sin));
      Listen(passive, 20);

      return passive;
}


void SetUpSIGCHLD(void)
{
      struct sigaction sa;
      void handler(int signum);

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


void handler(int signum)
{
      int status;

      while(waitpid(-1, &status, WNOHANG) > 0) {}
}


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)
              return 0;      /****  EOF!   ****/
         nleft -= nread;
         mover += nread;
     }
     return (bytes - nleft);
}

#include "funcs.h"

#define PACKET   256
#define MAXFILES 100000
#define DIR_WONT_OPEN  "\01" 
#define ILLEGAL_DIR    "\02" 
#define TERMINATOR     "\06"
#define QUIT           '\07'

int main(int argc, char **argv)
{
      char **GetFilesInDir(char *dirname), **files, **mover, dirname[PACKET];
      char packet[PACKET];
      int active;
      void SetUpSignals(void);

      active = atoi(argv[1]);
      SetUpSignals();
 
      while(alarm(20), readn(active, dirname, PACKET),
            *dirname != QUIT)
      {
           alarm(0);
           files = GetFilesInDir(dirname); 
           mover = files;

           while (strcmp(*mover, TERMINATOR) != 0)
           {
                memset(packet, 0, PACKET);
                strcpy(packet, *mover);

                writen(active, packet, 1);
                writen(active, packet + 1, PACKET - 1);
                mover++;
           }

           memset(packet, 0, PACKET);
           strcpy(packet, TERMINATOR);
           writen(active, packet, 1);
           writen(active, packet + 1, PACKET - 1);
           
           for (mover = files; strcmp(*mover, TERMINATOR) != 0; mover++)
               free(*mover); 
      }
}



void SetUpSignals(void)
{
      void handler(int signum);
      struct sigaction sa;

      Sigfillset(&sa.sa_mask);
      sa.sa_flags    = 0;
      sa.sa_handler  = handler;
      Sigaction(SIGPIPE, &sa, NULL);
      Sigaction(SIGALRM, &sa, NULL);
}
       
/****  The exec'ed program  ****/

char **GetFilesInDir(char *dirname)
{
      DIR *dptr;
      struct dirent *fname;
      static char *filenames[MAXFILES];
      char **mover = filenames, packet[PACKET], curdir[PACKET], newdir[PACKET];
      int compare(const void *, const void *), count;

      getcwd(curdir, PACKET);   /**  Where I am!!  **/
      if (chdir(dirname) < 0) 
      {
           filenames[0] = (char *) Malloc(2); 
           strcpy(filenames[0], DIR_WONT_OPEN); 
           filenames[1] = (char *) Malloc(2);
           strcpy(filenames[1], TERMINATOR);
           Chdir(curdir);
           return filenames;               
      }
      getcwd(newdir, PACKET);   /**  My new dir after the chdir!!  **/

      if (strstr(newdir, curdir) != newdir || (newdir[strlen(curdir)] != '\0'
                                           &&  newdir[strlen(curdir)] != '/'))
      {
           filenames[0] = (char *) Malloc(2); 
           strcpy(filenames[0], ILLEGAL_DIR); 
           filenames[1] = (char *) Malloc(2);
           strcpy(filenames[1], TERMINATOR);
           Chdir(curdir);
           return filenames;               
      }

      Chdir(curdir);
 
      if ((dptr = opendir(dirname)) == NULL)
      {
           filenames[0] = (char *) Malloc(2); 
           strcpy(filenames[0], DIR_WONT_OPEN);
           filenames[1] = (char *) Malloc(2);
           strcpy(filenames[1], TERMINATOR);
           return filenames;               
      }

      count = 0;
      mover = filenames;
      while(fname = readdir(dptr))
      {
           *mover = (char *) Malloc(strlen(fname->d_name) + 1);
           strcpy(*mover, fname->d_name);
           mover++;
           count++;
      }
      Closedir(dptr);

      qsort(filenames, (size_t) count, sizeof(char *), compare);

      filenames[count] = (char *) Malloc(2);
      strcpy(filenames[count], TERMINATOR);
      return filenames;
}




int compare(const void *fname1, const void *fname2)
{
     char **f1 = (char **) fname1, **f2 = (char **) fname2;

     return strcmp(*f1, *f2);
}




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)
              return 0;      /****  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;
}



void handler(int signum)
{
      exit(0);
}
/****************************  Sessions With Server  **************************/

$ s&
[1] 4943

$ c
Enter directory: 
Enter directory: sub1
Could not open sub1.

Enter directory: sub1dir
.
..
a
b
c

Enter directory: ../demos
Illegal search of ../demos!

Enter directory: ../homework
.
..
2c
2gc
2gc.c
2gs
2gs.c
4c.c
4gc.c
4gs.c
4s.c
a.out
a1.dat
asg1
asg1.answer
asg1.c
asg1.demo
asg1.log
asg1.out
asg1b
asg1b.c
asg1b.demo
[7m--More--[m[K

Enter directory: ../exams
Illegal search of ../exams!

Enter directory: sub2
.
..
d
e
f

Enter directory: 
[2]+  Stopped                 c     /*  CTRL-Z  */



$ c    /*  New client */
Enter directory: sub1
Could not open sub1.   /*  Same old error */

Enter directory: sub1dir
.
..
a
b
c
Enter directory: quit

$ fg
c
foo
Could not open foo.    /*  Old client still alive! */

Enter directory: ../foo
Could not open ../foo.

Enter directory: ../demos
Illegal search of ../demos!

Enter directory: quit

$ c
Enter directory: sub1dir
.
..
a
b
c
Enter directory: hello
Could not open hello.

Enter directory: hello
Server disconnected!   /* Alarmed out by server */