/***************************************************************************
*                                                                          *
* client.m                                                                 *
* Copyright 1992 by Nik A Gervae                                           *
*                                                                          *
* An example using the Objective-C classes (SktSocketManager, SktSocket,   *
* and SktSocketUser) which implement a convenient interface to Berkeley    *
* stream sockets under NeXTSTEP(r).  See the accompanying class            *
* specifications (files with a .rtf or .spec suffix) for further           *
* information.                                                             *
*                                                                          *
* NeXTSTEP is a registered trademark of NeXT Computer, Inc.                *
*                                                                          *
****************************************************************************
*                                                                          *
* LICENSE                                                                  *
*                                                                          *
* This program is free software; you can redistribute it and/or modify     *
* it under the terms of the GNU General Public License as published by     *
* the Free Software Foundation.                                            *
*                                                                          *
* The program and this makefile are distributed in the hope that it will   *
* be useful, but are provided "AS IS" AND WITHOUT ANY WARRANTY; without    *
* any express or implied warranty of MERCHANTABILITY or FITNESS FOR A      *
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
* Any use or distribution of the program and documentation must include    *
* appropriate copyrights to acknowledge Nik A. Gervae and the Free         *
* Software Foundation, Inc.                                                *
*                                                                          *
* You should have received a copy of the GNU General Public License        *
* along with this program; if not, write to the Free Software              *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                *
*                                                                          *
****************************************************************************
*                                                                          *
* BUILDING WITHOUT A MAKEFILE                                              *
*                                                                          *
* Just cc -c this file, then cc the .o with SktSocket.o, SktSocketUser.o,  *
* and util.o.                                                              *
*                                                                          *
****************************************************************************
*                                                                          *
* VERSION HISTORY                                                          *
*                                                                          *
* Version numbers are simply dates in the form YYYYMMDD.  These represent  *
* the date that version was finished.  Only significantly changed versions *
* are reported here, or those versions requiring explanation of changes.   *
* There may be many interim stages between dated versions.                 *
*                                                                          *
* DateVersion Primary Author  Notes                                        *
* ----------- --------------- -------------------------------------------- *
* 19920327    Nik A Gervae    First released version                       *
*                                                                          *
***************************************************************************/

#import <stdio.h>

#import <fcntl.h>
#import <sys/types.h>
#import <sys/time.h>

#import "SktSocket.h"
#import "SktSocketUser.h"

/***************************************************************************
*                                                                          *
* These are the constant strings used.  Feel free to translate them into   *
* your favorite language.  Do be sure to keep all the % directives in      *
* place, or change the code that accesses these strings.                   *
*                                                                          *
***************************************************************************/
#define STR_Usage            "Usage: %s hostname port#\n"
#define STR_ConnectionClosed "Connection closed\n"


/***************************************************************************
*                                                                          *
* The User class                                                           *
*                                                                          *
* This is a very simple subclass of SktSocketUser, providing only the      *
* minimum of methods to get anything at all done.                          *
*                                                                          *
***************************************************************************/

@interface User : SktSocketUser
{
}
- update;

@end

@implementation User

/***************************************************************************
*                                                                          *
* -update                                                                  *
*                                                                          *
* Flush out any input we have from the server, and see if the user has     *
* typed anything in; if so, send it off to the server.                     *
*                                                                          *
***************************************************************************/
- update
{
  char     *input;            // pending input
  long int  amount;           // amount of that input

  fd_set         readFds;     // for select()
  struct timeval timeout;     // for select()
  char           buffer[80];  // for read from input
  int            readres;     // how much was read

  amount = [self getAllInput:&input];
  if (0 < amount) {
    printf("%.*s", amount, input);
    fflush(stdout);
    free(input);
  }

 /*
  * There is an easier way to get input from the keyboard, but
  * I figured as long as I've been using these functions in the
  * socket classes, go crazy. :-)
  *
  * You'll have to totally replace this part if you want to
  * snag user input to filter it for commands....
  */
  FD_ZERO(&readFds);
  FD_SET(0, &readFds);
  timeout.tv_sec = 0;
  timeout.tv_usec = 0;
  select(1, &readFds, (fd_set *)0, (fd_set *)0, &timeout);

  if (FD_ISSET(0, &readFds)) {
    if ((readres = read(0, buffer, sizeof(buffer))) != -1) {
      [self queueOutput:buffer ofLength:readres];
    }
  }

  return self;
}

@end

/***************************************************************************
*                                                                          *
* main()                                                                   *
*                                                                          *
* Check args, try to init, and go into an infinite loop until the user     *
* types ctrl-C or the server closes the connection.                        *
*                                                                          *
***************************************************************************/
main(int argc, char *argv[])
{
  id   socket;
  id   user;
  char buffer[80];

  if (argc < 3) {
    fprintf(stderr, STR_Usage, argv[0]);
    exit(2);
  }

 /*
  * Make a new socket and a new user,
  * bomb if either fails to get made.
  */
  socket = [[SktSocket alloc] initOnHostname:argv[1] andPort:atoi(argv[2])];
  user = [[User alloc] initWithSocket:socket];

  if (!socket || !user) {
    exit(3);
  }

  while (1) {

   /*
    * This happens when the server closes the connection.
    */
    if (![socket readInput]) {
      fprintf(stderr, STR_ConnectionClosed);
      fflush(stderr);
      exit(0);
    }

   /*
    * Just keep having the user update and the socket printing
    * output to the user.
    */
    [user update];
    [socket flushOutput];
  }

  exit(0);
}

/***************************************************************************
***************************************************************************/
