rlogin.c 5.47 KB
Newer Older
deuce's avatar
deuce committed
1
2
/* Copyright (C), 2007 by Stephen Hurd */

3
/* $Id: rlogin.c,v 1.38 2020/06/27 00:04:50 deuce Exp $ */
4
5
6
7
8

#include <stdlib.h>

#include "bbslist.h"
#include "conn.h"
Deucе's avatar
Deucе committed
9
#include "sockwrap.h"
10
11
#include "uifcinit.h"

Deucе's avatar
Deucе committed
12
SOCKET rlogin_sock = INVALID_SOCKET;
13

14
#ifdef __BORLANDC__
Deucе's avatar
Deucе committed
15
 #pragma argsused
16
#endif
17

Deucе's avatar
Deucе committed
18
void
19
rlogin_input_thread(void *args)
20
{
Deucе's avatar
Deucе committed
21
22
23
	int    rd = 0;
	int    buffered;
	size_t buffer;
24

deuce's avatar
deuce committed
25
	SetThreadName("RLogin Input");
Deucе's avatar
Deucе committed
26
27
	conn_api.input_thread_running = 1;
	while (rlogin_sock != INVALID_SOCKET && !conn_api.terminate) {
28
		if (socket_readable(rlogin_sock, -1)) {
Deucе's avatar
Deucе committed
29
30
			rd = recv(rlogin_sock, conn_api.rd_buf, conn_api.rd_buf_size, 0);
			if (rd <= 0)
31
32
				break;
		}
Deucе's avatar
Deucе committed
33
34
		buffered = 0;
		while (buffered < rd) {
35
			pthread_mutex_lock(&(conn_inbuf.mutex));
Deucе's avatar
Deucе committed
36
37
			buffer = conn_buf_wait_free(&conn_inbuf, rd - buffered, 1000);
			buffered += conn_buf_put(&conn_inbuf, conn_api.rd_buf + buffered, buffer);
38
39
40
			pthread_mutex_unlock(&(conn_inbuf.mutex));
		}
	}
Deucе's avatar
Deucе committed
41
	conn_api.input_thread_running = 2;
42
43
}

44
#ifdef __BORLANDC__
Deucе's avatar
Deucе committed
45
 #pragma argsused
46
#endif
47

Deucе's avatar
Deucе committed
48
void
49
rlogin_output_thread(void *args)
50
{
Deucе's avatar
Deucе committed
51
52
53
	int wr;
	int ret;
	int sent;
54

deuce's avatar
deuce committed
55
	SetThreadName("RLogin Output");
Deucе's avatar
Deucе committed
56
57
	conn_api.output_thread_running = 1;
	while (rlogin_sock != INVALID_SOCKET && !conn_api.terminate) {
58
		pthread_mutex_lock(&(conn_outbuf.mutex));
Deucе's avatar
Deucе committed
59
60
61
62
		ret = 0;
		wr = conn_buf_wait_bytes(&conn_outbuf, 1, 100);
		if (wr) {
			wr = conn_buf_get(&conn_outbuf, conn_api.wr_buf, conn_api.wr_buf_size);
63
			pthread_mutex_unlock(&(conn_outbuf.mutex));
Deucе's avatar
Deucе committed
64
65
			sent = 0;
			while (sent < wr) {
66
				if (socket_writable(rlogin_sock, -1)) {
Deucе's avatar
Deucе committed
67
68
					ret = sendsocket(rlogin_sock, conn_api.wr_buf + sent, wr - sent);
					if (ret == -1)
69
						break;
Deucе's avatar
Deucе committed
70
					sent += ret;
71
72
73
				}
			}
		}
Deucе's avatar
Deucе committed
74
		else {
75
			pthread_mutex_unlock(&(conn_outbuf.mutex));
Deucе's avatar
Deucе committed
76
77
		}
		if (ret == -1)
78
79
			break;
	}
Deucе's avatar
Deucе committed
80
	conn_api.output_thread_running = 2;
81
82
}

Deucе's avatar
Deucе committed
83
int
84
rlogin_connect(struct bbslist *bbs)
85
{
86
87
	char *ruser;
	char *passwd;
88

89
	if (!bbs->hidepopups)
90
		init_uifc(true, true);
91

Deucе's avatar
Deucе committed
92
93
94
95
96
	ruser = bbs->user;
	passwd = bbs->password;
	if (bbs->conn_type == CONN_TYPE_RLOGIN_REVERSED) {
		passwd = bbs->user;
		ruser = bbs->password;
97
98
	}

Deucе's avatar
Deucе committed
99
100
101
	rlogin_sock = conn_socket_connect(bbs);
	if (rlogin_sock == INVALID_SOCKET)
		return -1;
102

Deucе's avatar
Deucе committed
103
104
105
	if (!create_conn_buf(&conn_inbuf, BUFFER_SIZE))
		return -1;
	if (!create_conn_buf(&conn_outbuf, BUFFER_SIZE)) {
106
		destroy_conn_buf(&conn_inbuf);
Deucе's avatar
Deucе committed
107
		return -1;
108
	}
109
	if (!(conn_api.rd_buf = (unsigned char *)malloc(BUFFER_SIZE))) {
110
111
		destroy_conn_buf(&conn_inbuf);
		destroy_conn_buf(&conn_outbuf);
Deucе's avatar
Deucе committed
112
		return -1;
113
	}
Deucе's avatar
Deucе committed
114
	conn_api.rd_buf_size = BUFFER_SIZE;
115
	if (!(conn_api.wr_buf = (unsigned char *)malloc(BUFFER_SIZE))) {
deuce's avatar
deuce committed
116
		FREE_AND_NULL(conn_api.rd_buf);
117
118
		destroy_conn_buf(&conn_inbuf);
		destroy_conn_buf(&conn_outbuf);
Deucе's avatar
Deucе committed
119
		return -1;
120
	}
Deucе's avatar
Deucе committed
121
122
123
124
125
126
127
128
129
	conn_api.wr_buf_size = BUFFER_SIZE;

	if ((bbs->conn_type == CONN_TYPE_RLOGIN) || (bbs->conn_type == CONN_TYPE_RLOGIN_REVERSED)) {
		conn_send("", 1, 1000);
		conn_send(passwd, strlen(passwd) + 1, 1000);
		conn_send(ruser, strlen(ruser) + 1, 1000);
		if (bbs->bpsrate) {
			char sbuf[30];

130
131
			sprintf(sbuf, "%s/%d", get_emulation_str(get_emulation(bbs)), bbs->bpsrate);

Deucе's avatar
Deucе committed
132
			conn_send(sbuf, strlen(sbuf) + 1, 1000);
133
134
		}
		else {
Deucе's avatar
Deucе committed
135
136
			char sbuf[30];

137
			sprintf(sbuf, "%s/115200", get_emulation_str(get_emulation(bbs)));
138

Deucе's avatar
Deucе committed
139
			conn_send(sbuf, strlen(sbuf) + 1, 1000);
140
141
142
		}
	}

Deucе's avatar
Deucе committed
143
144
145
146
147
        /* Negotiate with GHost and bail if there's apparently no GHost listening. */
	if (bbs->conn_type == CONN_TYPE_MBBS_GHOST) {
		char sbuf[80];
		char rbuf[10];
		int  idx, ret;
148

Deucе's avatar
Deucе committed
149
                /* Check to make sure GHost is actually listening */
150
		sendsocket(rlogin_sock, "\r\nMBBS: PING\r\n", 14);
151
152

		idx = 0;
153
		while (socket_readable(rlogin_sock, 1000)) {
Deucе's avatar
Deucе committed
154
			ret = recv(rlogin_sock, rbuf + idx, 1, 0);
155
156
			if (ret == -1)
				break;
157
158
			rbuf[++idx] = 0;

Deucе's avatar
Deucе committed
159
160
                        /* It says ERROR, but this is a good response to PING. */
			if (strstr(rbuf, "ERROR\r\n"))
161
162
				break;

Deucе's avatar
Deucе committed
163
164
165
                        /* We didn't receive the desired response in time, so bail. */
			if (idx >= sizeof(rbuf))
				return -1;
166
167
		}

Deucе's avatar
Deucе committed
168
169
170
		if (ret < 1)
			return -1;

171
172
173
174
175
176
		sprintf(sbuf, "MBBS: %s %d '%s' %d %s\r\n",
		    (bbs->ghost_program[0]) ? bbs->ghost_program : bbs->password,  /* Program name */
		    2,                                                             /* GHost protocol version */
		    bbs->user,                                                     /* User's full name */
		    999,                                                           /* Time remaining */
		    "GR"                                                           /* GR = ANSI, NG = ASCII */
Deucе's avatar
Deucе committed
177
		    );
178
		sendsocket(rlogin_sock, sbuf, strlen(sbuf));
179
180

		idx = 0;
181
		while (socket_readable(rlogin_sock, 1000)) {
Deucе's avatar
Deucе committed
182
			ret = recv(rlogin_sock, rbuf + idx, 1, 0);
183
184
			if (ret == -1)
				break;
185
186
			rbuf[++idx] = 0;

Deucе's avatar
Deucе committed
187
188
                        /* GHost says it's launching the program, so pass terminal to user. */
			if (strstr(rbuf, "OK\r\n"))
189
190
				break;

Deucе's avatar
Deucе committed
191
192
193
                        /* We didn't receive the desired response in time, so bail. */
			if (idx >= sizeof(rbuf))
				return -1;
194
195
		}

Deucе's avatar
Deucе committed
196
197
		if (ret < 1)
			return -1;
198
199
	}

200
201
202
	_beginthread(rlogin_output_thread, 0, NULL);
	_beginthread(rlogin_input_thread, 0, NULL);

Deucе's avatar
Deucе committed
203
	if (!bbs->hidepopups)
204
		uifc.pop(NULL);
205

Deucе's avatar
Deucе committed
206
	return 0;
207
208
}

Deucе's avatar
Deucе committed
209
210
int
rlogin_close(void)
211
{
212
213
	char garbage[1024];

Deucе's avatar
Deucе committed
214
	conn_api.terminate = 1;
215
	closesocket(rlogin_sock);
Deucе's avatar
Deucе committed
216
	while (conn_api.input_thread_running == 1 || conn_api.output_thread_running == 1) {
217
		conn_recv_upto(garbage, sizeof(garbage), 0);
218
		SLEEP(1);
219
	}
220
221
222
223
	destroy_conn_buf(&conn_inbuf);
	destroy_conn_buf(&conn_outbuf);
	FREE_AND_NULL(conn_api.rd_buf);
	FREE_AND_NULL(conn_api.wr_buf);
Deucе's avatar
Deucе committed
224
	return 0;
225
}