/* * 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 */