📄 winplink.c
字号:
else
cfg.port = -1;
strncpy(cfg.host, q, sizeof(cfg.host) - 1);
cfg.host[sizeof(cfg.host) - 1] = '\0';
} else {
char *r, *user, *host;
/*
* Before we process the [user@]host string, we
* first check for the presence of a protocol
* prefix (a protocol name followed by ",").
*/
r = strchr(p, ',');
if (r) {
int i, j;
for (i = 0; backends[i].backend != NULL; i++) {
j = strlen(backends[i].name);
if (j == r - p &&
!memcmp(backends[i].name, p, j)) {
default_protocol = cfg.protocol =
backends[i].protocol;
portnumber =
backends[i].backend->default_port;
p = r + 1;
break;
}
}
}
/*
* A nonzero length string followed by an @ is treated
* as a username. (We discount an _initial_ @.) The
* rest of the string (or the whole string if no @)
* is treated as a session name and/or hostname.
*/
r = strrchr(p, '@');
if (r == p)
p++, r = NULL; /* discount initial @ */
if (r) {
*r++ = '\0';
user = p, host = r;
} else {
user = NULL, host = p;
}
/*
* Now attempt to load a saved session with the
* same name as the hostname.
*/
{
Config cfg2;
do_defaults(host, &cfg2);
if (loaded_session || !cfg_launchable(&cfg2)) {
/* No settings for this host; use defaults */
/* (or session was already loaded with -load) */
strncpy(cfg.host, host, sizeof(cfg.host) - 1);
cfg.host[sizeof(cfg.host) - 1] = '\0';
cfg.port = default_port;
} else {
cfg = cfg2;
}
}
if (user) {
/* Patch in specified username. */
strncpy(cfg.username, user,
sizeof(cfg.username) - 1);
cfg.username[sizeof(cfg.username) - 1] = '\0';
}
}
} else {
char *command;
int cmdlen, cmdsize;
cmdlen = cmdsize = 0;
command = NULL;
while (argc) {
while (*p) {
if (cmdlen >= cmdsize) {
cmdsize = cmdlen + 512;
command = sresize(command, cmdsize, char);
}
command[cmdlen++]=*p++;
}
if (cmdlen >= cmdsize) {
cmdsize = cmdlen + 512;
command = sresize(command, cmdsize, char);
}
command[cmdlen++]=' '; /* always add trailing space */
if (--argc) p = *++argv;
}
if (cmdlen) command[--cmdlen]='\0';
/* change trailing blank to NUL */
cfg.remote_cmd_ptr = command;
cfg.remote_cmd_ptr2 = NULL;
cfg.nopty = TRUE; /* command => no terminal */
break; /* done with cmdline */
}
}
}
if (errors)
return 1;
if (!cfg_launchable(&cfg)) {
usage();
}
/*
* Trim leading whitespace off the hostname if it's there.
*/
{
int space = strspn(cfg.host, " \t");
memmove(cfg.host, cfg.host+space, 1+strlen(cfg.host)-space);
}
/* See if host is of the form user@host */
if (cfg_launchable(&cfg)) {
char *atsign = strrchr(cfg.host, '@');
/* Make sure we're not overflowing the user field */
if (atsign) {
if (atsign - cfg.host < sizeof cfg.username) {
strncpy(cfg.username, cfg.host, atsign - cfg.host);
cfg.username[atsign - cfg.host] = '\0';
}
memmove(cfg.host, atsign + 1, 1 + strlen(atsign + 1));
}
}
/*
* Perform command-line overrides on session configuration.
*/
cmdline_run_saved(&cfg);
/*
* Apply subsystem status.
*/
if (use_subsystem)
cfg.ssh_subsys = TRUE;
/*
* Trim a colon suffix off the hostname if it's there.
*/
cfg.host[strcspn(cfg.host, ":")] = '\0';
/*
* Remove any remaining whitespace from the hostname.
*/
{
int p1 = 0, p2 = 0;
while (cfg.host[p2] != '\0') {
if (cfg.host[p2] != ' ' && cfg.host[p2] != '\t') {
cfg.host[p1] = cfg.host[p2];
p1++;
}
p2++;
}
cfg.host[p1] = '\0';
}
if (!cfg.remote_cmd_ptr && !*cfg.remote_cmd && !*cfg.ssh_nc_host)
flags |= FLAG_INTERACTIVE;
/*
* Select protocol. This is farmed out into a table in a
* separate file to enable an ssh-free variant.
*/
{
int i;
back = NULL;
for (i = 0; backends[i].backend != NULL; i++)
if (backends[i].protocol == cfg.protocol) {
back = backends[i].backend;
break;
}
if (back == NULL) {
fprintf(stderr,
"Internal fault: Unsupported protocol found\n");
return 1;
}
}
/*
* Select port.
*/
if (portnumber != -1)
cfg.port = portnumber;
sk_init();
if (p_WSAEventSelect == NULL) {
fprintf(stderr, "Plink requires WinSock 2\n");
return 1;
}
logctx = log_init(NULL, &cfg);
console_provide_logctx(logctx);
/*
* Start up the connection.
*/
netevent = CreateEvent(NULL, FALSE, FALSE, NULL);
{
const char *error;
char *realhost;
/* nodelay is only useful if stdin is a character device (console) */
int nodelay = cfg.tcp_nodelay &&
(GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
error = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port,
&realhost, nodelay, cfg.tcp_keepalives);
if (error) {
fprintf(stderr, "Unable to open connection:\n%s", error);
return 1;
}
back->provide_logctx(backhandle, logctx);
sfree(realhost);
}
connopen = 1;
inhandle = GetStdHandle(STD_INPUT_HANDLE);
outhandle = GetStdHandle(STD_OUTPUT_HANDLE);
errhandle = GetStdHandle(STD_ERROR_HANDLE);
/*
* Turn off ECHO and LINE input modes. We don't care if this
* call fails, because we know we aren't necessarily running in
* a console.
*/
GetConsoleMode(inhandle, &orig_console_mode);
SetConsoleMode(inhandle, ENABLE_PROCESSED_INPUT);
/*
* Pass the output handles to the handle-handling subsystem.
* (The input one we leave until we're through the
* authentication process.)
*/
stdout_handle = handle_output_new(outhandle, stdouterr_sent, NULL, 0);
stderr_handle = handle_output_new(errhandle, stdouterr_sent, NULL, 0);
main_thread_id = GetCurrentThreadId();
sending = FALSE;
now = GETTICKCOUNT();
while (1) {
int nhandles;
HANDLE *handles;
int n;
DWORD ticks;
if (!sending && back->sendok(backhandle)) {
stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL,
0);
sending = TRUE;
}
if (run_timers(now, &next)) {
ticks = next - GETTICKCOUNT();
if (ticks < 0) ticks = 0; /* just in case */
} else {
ticks = INFINITE;
}
handles = handle_get_events(&nhandles);
handles = sresize(handles, nhandles+1, HANDLE);
handles[nhandles] = netevent;
n = MsgWaitForMultipleObjects(nhandles+1, handles, FALSE, ticks,
QS_POSTMESSAGE);
if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) {
handle_got_event(handles[n - WAIT_OBJECT_0]);
} else if (n == WAIT_OBJECT_0 + nhandles) {
WSANETWORKEVENTS things;
SOCKET socket;
extern SOCKET first_socket(int *), next_socket(int *);
extern int select_result(WPARAM, LPARAM);
int i, socketstate;
/*
* We must not call select_result() for any socket
* until we have finished enumerating within the tree.
* This is because select_result() may close the socket
* and modify the tree.
*/
/* Count the active sockets. */
i = 0;
for (socket = first_socket(&socketstate);
socket != INVALID_SOCKET;
socket = next_socket(&socketstate)) i++;
/* Expand the buffer if necessary. */
if (i > sksize) {
sksize = i + 16;
sklist = sresize(sklist, sksize, SOCKET);
}
/* Retrieve the sockets into sklist. */
skcount = 0;
for (socket = first_socket(&socketstate);
socket != INVALID_SOCKET;
socket = next_socket(&socketstate)) {
sklist[skcount++] = socket;
}
/* Now we're done enumerating; go through the list. */
for (i = 0; i < skcount; i++) {
WPARAM wp;
socket = sklist[i];
wp = (WPARAM) socket;
if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) {
static const struct { int bit, mask; } eventtypes[] = {
{FD_CONNECT_BIT, FD_CONNECT},
{FD_READ_BIT, FD_READ},
{FD_CLOSE_BIT, FD_CLOSE},
{FD_OOB_BIT, FD_OOB},
{FD_WRITE_BIT, FD_WRITE},
{FD_ACCEPT_BIT, FD_ACCEPT},
};
int e;
noise_ultralight(socket);
noise_ultralight(things.lNetworkEvents);
for (e = 0; e < lenof(eventtypes); e++)
if (things.lNetworkEvents & eventtypes[e].mask) {
LPARAM lp;
int err = things.iErrorCode[eventtypes[e].bit];
lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err);
connopen &= select_result(wp, lp);
}
}
}
} else if (n == WAIT_OBJECT_0 + nhandles + 1) {
MSG msg;
while (PeekMessage(&msg, INVALID_HANDLE_VALUE,
WM_AGENT_CALLBACK, WM_AGENT_CALLBACK,
PM_REMOVE)) {
struct agent_callback *c = (struct agent_callback *)msg.lParam;
c->callback(c->callback_ctx, c->data, c->len);
sfree(c);
}
}
if (n == WAIT_TIMEOUT) {
now = next;
} else {
now = GETTICKCOUNT();
}
sfree(handles);
if (sending)
handle_unthrottle(stdin_handle, back->sendbuffer(backhandle));
if ((!connopen || !back->connected(backhandle)) &&
handle_backlog(stdout_handle) + handle_backlog(stderr_handle) == 0)
break; /* we closed the connection */
}
exitcode = back->exitcode(backhandle);
if (exitcode < 0) {
fprintf(stderr, "Remote process exit code unavailable\n");
exitcode = 1; /* this is an error condition */
}
cleanup_exit(exitcode);
return 0; /* placate compiler warning */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -