📄 uxplink.c
字号:
/* * PLink - a command-line (stdin/stdout) variant of PuTTY. */#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <assert.h>#include <stdarg.h>#include <signal.h>#include <unistd.h>#include <fcntl.h>#include <termios.h>#include <pwd.h>#include <sys/ioctl.h>#define PUTTY_DO_GLOBALS /* actually _define_ globals */#include "putty.h"#include "storage.h"#include "tree234.h"#define MAX_STDIN_BACKLOG 4096void fatalbox(char *p, ...){ va_list ap; fprintf(stderr, "FATAL ERROR: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); cleanup_exit(1);}void modalfatalbox(char *p, ...){ va_list ap; fprintf(stderr, "FATAL ERROR: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); cleanup_exit(1);}void connection_fatal(void *frontend, char *p, ...){ va_list ap; fprintf(stderr, "FATAL ERROR: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); cleanup_exit(1);}void cmdline_error(char *p, ...){ va_list ap; fprintf(stderr, "plink: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); exit(1);}struct termios orig_termios;static Backend *back;static void *backhandle;static Config cfg;/* * Default settings that are specific to pterm. */char *platform_default_s(const char *name){ if (!strcmp(name, "TermType")) return dupstr(getenv("TERM")); if (!strcmp(name, "UserName")) return get_username(); return NULL;}int platform_default_i(const char *name, int def){ if (!strcmp(name, "TermWidth") || !strcmp(name, "TermHeight")) { struct winsize size; if (ioctl(0, TIOCGWINSZ, (void *)&size) >= 0) return (!strcmp(name, "TermWidth") ? size.ws_col : size.ws_row); } return def;}FontSpec platform_default_fontspec(const char *name){ FontSpec ret; *ret.name = '\0'; return ret;}Filename platform_default_filename(const char *name){ Filename ret; if (!strcmp(name, "LogFileName")) strcpy(ret.path, "putty.log"); else *ret.path = '\0'; return ret;}char *x_get_default(const char *key){ return NULL; /* this is a stub */}int term_ldisc(Terminal *term, int mode){ return FALSE;}void ldisc_update(void *frontend, int echo, int edit){ /* Update stdin read mode to reflect changes in line discipline. */ struct termios mode; mode = orig_termios; if (echo) mode.c_lflag |= ECHO; else mode.c_lflag &= ~ECHO; if (edit) mode.c_lflag |= ISIG | ICANON; else mode.c_lflag &= ~(ISIG | ICANON); tcsetattr(0, TCSANOW, &mode);}void cleanup_termios(void){ tcsetattr(0, TCSANOW, &orig_termios);}bufchain stdout_data, stderr_data;void try_output(int is_stderr){ bufchain *chain = (is_stderr ? &stderr_data : &stdout_data); int fd = (is_stderr ? 2 : 1); void *senddata; int sendlen, ret; if (bufchain_size(chain) == 0) return; bufchain_prefix(chain, &senddata, &sendlen); ret = write(fd, senddata, sendlen); if (ret > 0) bufchain_consume(chain, ret); else if (ret < 0) { perror(is_stderr ? "stderr: write" : "stdout: write"); exit(1); }}int from_backend(void *frontend_handle, int is_stderr, const char *data, int len){ int osize, esize; if (is_stderr) { bufchain_add(&stderr_data, data, len); try_output(1); } else { bufchain_add(&stdout_data, data, len); try_output(0); } osize = bufchain_size(&stdout_data); esize = bufchain_size(&stderr_data); return osize + esize;}int signalpipe[2];void sigwinch(int signum){ write(signalpipe[1], "x", 1);}/* * In Plink our selects are synchronous, so these functions are * empty stubs. */int uxsel_input_add(int fd, int rwx) { return 0; }void uxsel_input_remove(int id) { }/* * Short description of parameters. */static void usage(void){ printf("PuTTY Link: command-line connection utility\n"); printf("%s\n", ver); printf("Usage: plink [options] [user@]host [command]\n"); printf(" (\"host\" can also be a PuTTY saved session name)\n"); printf("Options:\n"); printf(" -V print version information\n"); printf(" -v show verbose messages\n"); printf(" -load sessname Load settings from saved session\n"); printf(" -ssh -telnet -rlogin -raw\n"); printf(" force use of a particular protocol\n"); printf(" -P port connect to specified port\n"); printf(" -l user connect with specified username\n"); printf(" -m file read remote command(s) from file\n"); printf(" -batch disable all interactive prompts\n"); printf("The following options only apply to SSH connections:\n"); printf(" -pw passw login with specified password\n"); printf(" -D [listen-IP:]listen-port\n"); printf(" Dynamic SOCKS-based port forwarding\n"); printf(" -L [listen-IP:]listen-port:host:port\n"); printf(" Forward local port to remote address\n"); printf(" -R [listen-IP:]listen-port:host:port\n"); printf(" Forward remote port to local address\n"); printf(" -X -x enable / disable X11 forwarding\n"); printf(" -A -a enable / disable agent forwarding\n"); printf(" -t -T enable / disable pty allocation\n"); printf(" -1 -2 force use of particular protocol version\n"); printf(" -C enable compression\n"); printf(" -i key private key file for authentication\n"); printf(" -s remote command is an SSH subsystem (SSH-2 only)\n"); printf(" -N don't start a shell/command (SSH-2 only)\n"); exit(1);}static void version(void){ printf("plink: %s\n", ver); exit(1);}int main(int argc, char **argv){ int sending; int portnumber = -1; int *fdlist; int fd; int i, fdcount, fdsize, fdstate; int connopen; int exitcode; int errors; int use_subsystem = 0; void *ldisc, *logctx; ssh_get_line = console_get_line; fdlist = NULL; fdcount = fdsize = 0; /* * Initialise port and protocol to sensible defaults. (These * will be overridden by more or less anything.) */ default_protocol = PROT_SSH; default_port = 22; flags = FLAG_STDERR; /* * Process the command line. */ do_defaults(NULL, &cfg); loaded_session = FALSE; default_protocol = cfg.protocol; default_port = cfg.port; errors = 0; { /* * Override the default protocol if PLINK_PROTOCOL is set. */ char *p = getenv("PLINK_PROTOCOL"); int i; if (p) { for (i = 0; backends[i].backend != NULL; i++) { if (!strcmp(backends[i].name, p)) { default_protocol = cfg.protocol = backends[i].protocol; default_port = cfg.port = backends[i].backend->default_port; break; } } } } while (--argc) { char *p = *++argv; if (*p == '-') { int ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL), 1, &cfg); if (ret == -2) { fprintf(stderr, "plink: option \"%s\" requires an argument\n", p); errors = 1; } else if (ret == 2) { --argc, ++argv; } else if (ret == 1) { continue; } else if (!strcmp(p, "-batch")) { console_batch_mode = 1; } else if (!strcmp(p, "-s")) { /* Save status to write to cfg later. */ use_subsystem = 1; } else if (!strcmp(p, "-V")) { version(); } else if (!strcmp(p, "-o")) { if (argc <= 1) { fprintf(stderr, "plink: option \"-o\" requires an argument\n"); errors = 1; } else { --argc; provide_xrm_string(*++argv); } } else { fprintf(stderr, "plink: unknown option \"%s\"\n", p); errors = 1; } } else if (*p) { if (!*cfg.host) { char *q = p; do_defaults(NULL, &cfg); /* * If the hostname starts with "telnet:", set the * protocol to Telnet and process the string as a * Telnet URL. */ if (!strncmp(q, "telnet:", 7)) { char c; q += 7; if (q[0] == '/' && q[1] == '/') q += 2; cfg.protocol = PROT_TELNET; p = q; while (*p && *p != ':' && *p != '/') p++; c = *p; if (*p) *p++ = '\0'; if (c == ':') cfg.port = atoi(p); 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -