free_bookz_player
    by using a central repository. You have been
    hired to implement the necessary changes/additions.
  adz_server
    must be multi-threaded. Specifically, each request must be
    handled in its own thread.
    adz_server must use one exogenous,
    circular, single-linked data structure to hold the repository in
    memory.  (Note: This structure will be shared by the threads that
    handle the requests.)
    free_bookz_player 
    must accept a second command-line argument containing the IP address
    of the adz_server. If no such argument is provided,
    it must use 127.0.0.1 as the default. (Note: There is no need to
    error-check the argument since it will only be provided by
    qualified testers.)
    
When the node contains the data itself it is said to be an endogenous structure and when the node contains a pointer to the data it is said to be an exogenous structure.
When the node contains only one pointer to another node (either the next node in the structure or the previous node in the structure) it is said to be single-linked. On the other hand, when the node contains a pointer to both the next node in the structure and the previous node in the structure it is said to be doubly-linked.
    Finally, when the "last" node in the structure points
    to NULL it is said to be a linear structure
    and when the "last" node in the structure points to the "first"
    node in the structure, it is said to be a circular
    structure.
    
So, the structure that you must use for this assignment can be visualized as follows.
adz, which consists of 
    both a delay and text. So, it can be encapsulated as follows.
struct adz {
  int  delay;
  char text[38];
};
    The elegant way to encapsulate a node is to use a void
    * so that it can be used with any kind of data (though a
    typecast will be required). This might be done as follows.
    
struct node {
  void *data;
  struct node *next;
};
    The less elegant approach is to create a node structure that is appropriate
    only for use with an adz.
    
struct adz_node {
  struct adz *data;
  struct adz_node *next;
};
adz you will want to:
    adz).To that end, when populating the structure, you will want to have a pointer to the "first" node and a pointer to the "last" node.
Initially, the "current" node must be the "first" node. Then, as you move through the structure the "current" node will become the "current's next" node.
However, since the request-handler threads all must use the data structure, the operations/variables associated with iterating over the structure must be thread-safe.
adz_lib currently reads adz information from
  the local file system (probably in a while() loop that
  makes use of keep_going in its condition).
  For this version it must instead send a request to the adz_serve.
  
  Fortunately, since read() is already being called in a
  helper thread, the additional latency won't have any deleterious
  impacts on the display of the
  bookz.
  
  (Note: It would have been better if we had included a get_adz()
  function in the original design that called read(). Then,
  the only function we would need to change in this version would be
  get_adz().)
  
sleep()) in an effort to identify any race
    conditions.
    free_bookz_player and the server (i.e.,
    the adz_server). When you've completed both and begin
    testing you should:
    
    repository.adz and one of the 
      earlier adz files.
      sleep() to ensure that 
      it is handling multiple connections simultaneously.)
      adz_server dynamically allocates memory (for the
  linked structure) and, so, should deallocate that memory at some point.
  Unfortunately, to keep the server as simple as possible, it does not
  terminate normally (i.e., it must be interrupted from the keyboard using
  Ctrl+C).
  
  You might think that you could change the disposition of SIGINT
  and deallocate memory in the handler. However, the disposition of
  SIGINT can't be changed (to ensure that processes can always
  be interrupted).
  
  You might also think that you could register an exit handler using
  atexit(). However, exit handlers are only invoke when a
  process terminates normally.
  
makefile) needed to build both
  the free_bookz_player and the adz_server.
  
  Though you must keep an "old" version of the adz_lib
  module, you do not need be able to build both v2 and v3 of
  the free_bookz_player from the same source code.  (You
  should, however, understand why it would be beneficial to be able to
  do so and how you would do so.)
  
Copyright 2017