xref: /original-bsd/usr.bin/telnet/network.c (revision 823023b8)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)network.c	1.13 (Berkeley) 06/29/88";
20 #endif /* not lint */
21 
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/time.h>
25 
26 #include <errno.h>
27 
28 #include <arpa/telnet.h>
29 
30 #include "ring.h"
31 
32 #include "defines.h"
33 #include "externs.h"
34 #include "fdset.h"
35 
36 Ring	netoring, netiring;
37 char	netobuf[2*BUFSIZ], netibuf[BUFSIZ];
38 
39 /*
40  * Initialize internal network data structures.
41  */
42 
43 init_network()
44 {
45     if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) {
46 	exit(1);
47     }
48     if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) {
49 	exit(1);
50     }
51     NetTrace = stdout;
52 }
53 
54 
55 /*
56  * Check to see if any out-of-band data exists on a socket (for
57  * Telnet "synch" processing).
58  */
59 
60 int
61 stilloob()
62 {
63     static struct timeval timeout = { 0 };
64     fd_set	excepts;
65     int value;
66 
67     do {
68 	FD_ZERO(&excepts);
69 	FD_SET(net, &excepts);
70 	value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
71     } while ((value == -1) && (errno == EINTR));
72 
73     if (value < 0) {
74 	perror("select");
75 	(void) quit();
76     }
77     if (FD_ISSET(net, &excepts)) {
78 	return 1;
79     } else {
80 	return 0;
81     }
82 }
83 
84 
85 /*
86  *  setneturg()
87  *
88  *	Sets "neturg" to the current location.
89  */
90 
91 void
92 setneturg()
93 {
94     ring_mark(&netoring);
95 }
96 
97 
98 /*
99  *  netflush
100  *		Send as much data as possible to the network,
101  *	handling requests for urgent data.
102  *
103  *		The return value indicates whether we did any
104  *	useful work.
105  */
106 
107 
108 int
109 netflush()
110 {
111     register int n, n1;
112 
113     if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
114 	if (!ring_at_mark(&netoring)) {
115 	    n = send(net, netoring.consume, n, 0);	/* normal write */
116 	} else {
117 	    /*
118 	     * In 4.2 (and 4.3) systems, there is some question about
119 	     * what byte in a sendOOB operation is the "OOB" data.
120 	     * To make ourselves compatible, we only send ONE byte
121 	     * out of band, the one WE THINK should be OOB (though
122 	     * we really have more the TCP philosophy of urgent data
123 	     * rather than the Unix philosophy of OOB data).
124 	     */
125 	    n = send(net, netoring.consume, 1, MSG_OOB);/* URGENT data */
126 	}
127     }
128     if (n < 0) {
129 	if (errno != ENOBUFS && errno != EWOULDBLOCK) {
130 	    setcommandmode();
131 	    perror(hostname);
132 	    NetClose(net);
133 	    ring_clear_mark(&netoring);
134 	    longjmp(peerdied, -1);
135 	    /*NOTREACHED*/
136 	}
137 	n = 0;
138     }
139     if (netdata && n) {
140 	Dump('>', netoring.consume, n);
141     }
142     if (n) {
143 	ring_consumed(&netoring, n);
144 	/*
145 	 * If we sent all, and more to send, then recurse to pick
146 	 * up the other half.
147 	 */
148 	if ((n1 == n) && ring_full_consecutive(&netoring)) {
149 	    (void) netflush();
150 	}
151 	return 1;
152     } else {
153 	return 0;
154     }
155 }
156