lpc4/lib/
lpc4/lib/doc/efun/
lpc4/lib/doc/lfun/
lpc4/lib/doc/operators/
lpc4/lib/doc/simul_efuns/
lpc4/lib/doc/types/
lpc4/lib/etc/
lpc4/lib/include/
lpc4/lib/include/arpa/
lpc4/lib/obj/d/
lpc4/lib/save/
lpc4/lib/secure/
lpc4/lib/std/
lpc4/lib/std/living/
/*
 *  comm.c -- communications functions and more.
 *            Dwayne Fontenot (Jacques@TMI)
 */
#include "global.h"
/* #include <varargs.h> */
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#define TELOPTS
#include <arpa/telnet.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_SOCKETVAR_H
#include <sys/socketvar.h>
#endif

#include "interpret.h"
#include "comm.h"
#include "socket_efuns.h"
#include "object.h"
#include "sent.h"
#include "debug.h"
#include "comm1.h"
#include "main.h"
#include "stralloc.h"
#include "simulate.h"
#include "exec.h"

/*
 * external function prototypes.
 */
extern char *xalloc(), *string_copy(), *unshared_str_copy();
extern int parse_command();
extern void call_heart_beat();

int total_users = 0;

/*
 * local function prototypes.
 */
RETSIGTYPE sigpipe_handler();
RETSIGTYPE sigalrm_handler();
void hname_handler();
void stdin_handler();

char *query_host_name();


/*
 * external variables.
 */
extern int port_number;
extern int errno;
extern int d_flag;
extern int current_time;
extern struct object *command_giver;
extern struct lpc_socket lpc_socks[];
extern int heart_beat_flag;
extern char *default_fail_message;
int stdin_closed=0;
int stdinisatty=0;
int stdin_is_sock=0;

/*
 * public local variables.
 */
fd_set readmask, writemask;

/*
 * SIGALRM handler.
 */
RETSIGTYPE sigalrm_handler()
{
  heart_beat_flag = 1;
  debug(512,("sigalrm_handler: SIGALRM\n"));
}

INLINE void make_selectmasks()
{
  int i;

  /*
   * generate readmask and writemask for select() call.
   */
  FD_ZERO(&readmask);
  FD_ZERO(&writemask);
  /*
   * set new user accept fd in readmask.
   */
  if(!stdin_closed)
    FD_SET(0,&readmask);

  /*
   * set fd's for efun sockets.
   */
  for(i=0;i<MAX_EFUN_SOCKS;i++)
  {
    if(lpc_socks[i].state != CLOSED)
    {
      if (!(lpc_socks[i].flags & (S_WACCEPT|S_CLOSING)))
	FD_SET(lpc_socks[i].fd,&readmask);
      if (lpc_socks[i].flags & S_BLOCKED)
	FD_SET(lpc_socks[i].fd,&writemask);
    }
  }
}

/*
 * Process I/O.
 */
INLINE void process_io()
{
  int i;

  debug(256,("@"));
  /*
   * check for data pending on efun socket connections.
   */
  for(i=0;i<MAX_EFUN_SOCKS;i++)
  {
    if(lpc_socks[i].state != CLOSED)
      if(FD_ISSET(lpc_socks[i].fd,&readmask))
	socket_read_select_handler(i);

    if(lpc_socks[i].state != CLOSED)
      if(FD_ISSET(lpc_socks[i].fd,&writemask))
	socket_write_select_handler(i);

  }
  handle_line_sockets();

  if(!stdin_closed && FD_ISSET(0,&readmask))
  {
    stdin_handler();
  }
}

#define STDIN_BUF_SIZE 1000
void init_stdin_handler()
{
  stdinisatty=isatty(0);
}

void stdin_handler()
{
  char buf[STDIN_BUF_SIZE];
  int num_bytes;

  if(stdinisatty)
  {
    if(set_socket_nonblocking(0, 1) == -1){
      perror("stdin_handler: set_socket_nonblocking 1");
      return;
    }
  }
  num_bytes = read(0,buf,STDIN_BUF_SIZE);
  if(stdinisatty)
  {
    if(set_socket_nonblocking(0, 0) == -1)
    {
      perror("stdin_handler: set_socket_nonblocking 0");
      return;
    }
  }
  switch(num_bytes)
  {
  case -1:
    switch(errno){
    case EWOULDBLOCK:
      debug(512,("Stdin: Operation would block.\n"));
      break;
    default:
      perror("Stdin read error");
      return;
    }
    break;
  case 0:
    close(0);
    stdin_closed=1;
    break;

  default:
    buf[num_bytes] = '\0';
    push_new_shared_string(buf);
    APPLY_MASTER_OB((void),"stdin",1);
  }
}

#ifndef INET_NTOA_OK
/*
 * Note: if the address string is "a.b.c.d" the address number is
 *       a * 256^3 + b * 256^2 + c * 256 + d
 */
char *inet_ntoa(struct in_addr ad)
{
  u_long s_ad;
  int a, b, c, d;
  static char addr[20]; /* 16 + 1 should be enough */

  s_ad = ad.s_addr;
  d = s_ad % 256;
  s_ad /= 256;
  c = s_ad % 256;
  s_ad /= 256;
  b = s_ad % 256;
  a = s_ad / 256;
  sprintf(addr, "%d.%d.%d.%d", a, b, c, d);
  return(addr);
}
#endif /* INET_NTOA_OK */