Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

rlogin.c 5.07 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 9 10 11 12

#include <stdlib.h>

#include "sockwrap.h"

#include "bbslist.h"
#include "conn.h"
#include "uifcinit.h"

13
SOCKET rlogin_sock=INVALID_SOCKET;
14

15 16 17
#ifdef __BORLANDC__
#pragma argsused
#endif
18 19 20
void rlogin_input_thread(void *args)
{
	int		rd;
21
	int	buffered;
22 23
	size_t	buffer;

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

43 44 45
#ifdef __BORLANDC__
#pragma argsused
#endif
46 47 48 49 50
void rlogin_output_thread(void *args)
{
	fd_set	wds;
	int		wr;
	int		ret;
51
	int	sent;
52

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

int rlogin_connect(struct bbslist *bbs)
{
	char	*ruser;
	char	*passwd;

85 86
	if (!bbs->hidepopups)
		init_uifc(TRUE, TRUE);
87 88 89

	ruser=bbs->user;
	passwd=bbs->password;
90
	if(bbs->conn_type==CONN_TYPE_RLOGIN_REVERSED) {
91 92 93 94
		passwd=bbs->user;
		ruser=bbs->password;
	}

95 96
	rlogin_sock=conn_socket_connect(bbs);
	if(rlogin_sock==INVALID_SOCKET)
97 98
		return(-1);

99 100 101 102 103 104 105 106 107 108 109
	if(!create_conn_buf(&conn_inbuf, BUFFER_SIZE))
		return(-1);
	if(!create_conn_buf(&conn_outbuf, BUFFER_SIZE)) {
		destroy_conn_buf(&conn_inbuf);
		return(-1);
	}
	if(!(conn_api.rd_buf=(unsigned char *)malloc(BUFFER_SIZE))) {
		destroy_conn_buf(&conn_inbuf);
		destroy_conn_buf(&conn_outbuf);
		return(-1);
	}
110
	conn_api.rd_buf_size=BUFFER_SIZE;
111
	if(!(conn_api.wr_buf=(unsigned char *)malloc(BUFFER_SIZE))) {
deuce's avatar
deuce committed
112
		FREE_AND_NULL(conn_api.rd_buf);
113 114 115 116
		destroy_conn_buf(&conn_inbuf);
		destroy_conn_buf(&conn_outbuf);
		return(-1);
	}
117 118
	conn_api.wr_buf_size=BUFFER_SIZE;

119
	if(bbs->conn_type == CONN_TYPE_RLOGIN || bbs->conn_type == CONN_TYPE_RLOGIN_REVERSED) {
120 121 122 123 124
		conn_send("",1,1000);
		conn_send(passwd,strlen(passwd)+1,1000);
		conn_send(ruser,strlen(ruser)+1,1000);
		if(bbs->bpsrate) {
			char	sbuf[30];
125 126 127 128 129 130 131
			sprintf(sbuf, "%s/%d", get_emulation_str(get_emulation(bbs)), bbs->bpsrate);

			conn_send(sbuf, strlen(sbuf)+1,1000);
		}
		else {
			char	sbuf[30];
			sprintf(sbuf, "%s/115200", get_emulation_str(get_emulation(bbs)));
132 133 134 135 136

			conn_send(sbuf, strlen(sbuf)+1,1000);
		}
	}

137 138 139 140 141 142 143
	/* 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;

		/* Check to make sure GHost is actually listening */
144
		sendsocket(rlogin_sock, "\r\nMBBS: PING\r\n", 14);
145 146

		idx = 0;
147 148 149 150
		while (socket_readable(rlogin_sock, 1000)) {
			ret = recv(rlogin_sock, rbuf+idx, 1, 0);
			if (ret == -1)
				break;
151 152 153
			rbuf[++idx] = 0;

			/* It says ERROR, but this is a good response to PING. */
154
			if (strstr(rbuf,"ERROR\r\n")) {
155 156 157 158 159 160 161 162 163 164 165 166 167 168
				break;
			}

			/* We didn't receive the desired response in time, so bail. */
			if (idx >= sizeof(rbuf)) {
				return(-1);
			}
		}

		if (ret < 1) {
			return(-1);
		}

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

		idx = 0;
178 179 180 181
		while (socket_readable(rlogin_sock, 1000)) {
			ret = recv(rlogin_sock, rbuf+idx, 1, 0);
			if (ret == -1)
				break;
182 183 184
			rbuf[++idx] = 0;

			/* GHost says it's launching the program, so pass terminal to user. */
185
			if (strstr(rbuf,"OK\r\n")) {
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
				break;
			}

			/* We didn't receive the desired response in time, so bail. */
			if (idx >= sizeof(rbuf)) {
				return(-1);
			}
		}

		if (ret < 1) {
			return(-1);
		}

	}

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

204 205 206
	if (!bbs->hidepopups) {
		uifc.pop(NULL);
	}
207 208 209 210 211 212

	return(0);
}

int rlogin_close(void)
{
213 214
	char garbage[1024];

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