Try to move system dependent stuff to system dependent files.
[unix-history] / usr / src / usr.bin / telnet / network.c
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <errno.h>
#include <arpa/telnet.h>
#include "ring.h"
#include "defines.h"
#include "externs.h"
Ring netoring, netiring;
char netobuf[2*BUFSIZ], netibuf[BUFSIZ];
/*
* Initialize internal network data structures.
*/
init_network()
{
ring_init(&netoring, netobuf, sizeof netobuf);
ring_init(&netiring, netibuf, sizeof netibuf);
NetTrace = stdout;
}
/*
* Check to see if any out-of-band data exists on a socket (for
* Telnet "synch" processing).
*/
int
stilloob(s)
int s; /* socket number */
{
static struct timeval timeout = { 0 };
fd_set excepts;
int value;
do {
FD_ZERO(&excepts);
FD_SET(s, &excepts);
value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
} while ((value == -1) && (errno == EINTR));
if (value < 0) {
perror("select");
quit();
}
if (FD_ISSET(s, &excepts)) {
return 1;
} else {
return 0;
}
}
/*
* setneturg()
*
* Sets "neturg" to the current location.
*/
void
setneturg()
{
ring_mark(&netoring);
}
/*
* netflush
* Send as much data as possible to the network,
* handling requests for urgent data.
*
* The return value indicates whether we did any
* useful work.
*/
int
netflush()
{
int n;
if ((n = ring_full_consecutive(&netoring)) > 0) {
if (!ring_at_mark(&netoring)) {
n = send(net, netoring.consume, n, 0); /* normal write */
} else {
/*
* In 4.2 (and 4.3) systems, there is some question about
* what byte in a sendOOB operation is the "OOB" data.
* To make ourselves compatible, we only send ONE byte
* out of band, the one WE THINK should be OOB (though
* we really have more the TCP philosophy of urgent data
* rather than the Unix philosophy of OOB data).
*/
n = send(net, netoring.consume, 1, MSG_OOB);/* URGENT data */
}
}
if (n < 0) {
if (errno != ENOBUFS && errno != EWOULDBLOCK) {
setcommandmode();
perror(hostname);
NetClose(net);
ring_clear_mark(&netoring);
longjmp(peerdied, -1);
/*NOTREACHED*/
}
n = 0;
}
if (netdata && n) {
Dump('>', netoring.consume, n);
}
ring_consumed(&netoring, n);
return n > 0;
}
\f
/*
* nextitem()
*
* Return the address of the next "item" in the TELNET data
* stream. This will be the address of the next character if
* the current address is a user data character, or it will
* be the address of the character following the TELNET command
* if the current address is a TELNET IAC ("I Am a Command")
* character.
*/
static char *
nextitem(current)
char *current;
{
if ((*current&0xff) != IAC) {
return current+1;
}
switch (*(current+1)&0xff) {
case DO:
case DONT:
case WILL:
case WONT:
return current+3;
case SB: /* loop forever looking for the SE */
{
register char *look = current+2;
for (;;) {
if ((*look++&0xff) == IAC) {
if ((*look++&0xff) == SE) {
return look;
}
}
}
}
default:
return current+2;
}
}
/*
* netclear()
*
* We are about to do a TELNET SYNCH operation. Clear
* the path to the network.
*
* Things are a bit tricky since we may have sent the first
* byte or so of a previous TELNET command into the network.
* So, we have to scan the network buffer from the beginning
* until we are up to where we want to be.
*
* A side effect of what we do, just to keep things
* simple, is to clear the urgent data pointer. The principal
* caller should be setting the urgent data pointer AFTER calling
* us in any case.
*/
void
netclear()
{
#if 0 /* XXX */
register char *thisitem, *next;
char *good;
#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
thisitem = netobuf;
while ((next = nextitem(thisitem)) <= netobuf.send) {
thisitem = next;
}
/* Now, thisitem is first before/at boundary. */
good = netobuf; /* where the good bytes go */
while (netoring.add > thisitem) {
if (wewant(thisitem)) {
int length;
next = thisitem;
do {
next = nextitem(next);
} while (wewant(next) && (nfrontp > next));
length = next-thisitem;
memcpy(good, thisitem, length);
good += length;
thisitem = next;
} else {
thisitem = nextitem(thisitem);
}
}
#endif /* 0 */
ring_init(&netoring, netobuf, sizeof netobuf);
}
#include <varargs.h>
void
netoprint(va_alist)
va_dcl
{
va_list ap;
char buffer[100]; /* where things go */
char *ptr;
char *format;
char *string;
int i;
va_start(ap);
format = va_arg(ap, char *);
ptr = buffer;
while ((i = *format++) != 0) {
if (i == '%') {
i = *format++;
switch (i) {
case 'c':
*ptr++ = va_arg(ap, int);
break;
case 's':
string = va_arg(ap, char *);
ring_supply_data(&netoring, buffer, ptr-buffer);
ring_supply_data(&netoring, string, strlen(string));
ptr = buffer;
break;
case 0:
ExitString("netoprint: trailing %%.\n", 1);
/*NOTREACHED*/
default:
ExitString("netoprint: unknown format character.\n", 1);
/*NOTREACHED*/
}
} else {
*ptr++ = i;
}
}
ring_supply_data(&netoring, buffer, ptr-buffer);
}