X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=unix%2Fuxplink.c;h=d4230935edfcfe1bf059c245dbf1e23f0ebaa8e9;hb=d23c0972cd850c77871f9a314e0520d7023c8b62;hp=fc8100c0608abf7d983550523abc57b2f56a5616;hpb=9c75fe9a3fa5e6b709f1c210795d1140ca1be2e8;p=PuTTY.git diff --git a/unix/uxplink.c b/unix/uxplink.c index fc8100c0..d4230935 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -63,6 +63,18 @@ void modalfatalbox(char *p, ...) } cleanup_exit(1); } +void nonfatal(char *p, ...) +{ + struct termios cf; + va_list ap; + premsg(&cf); + fprintf(stderr, "ERROR: "); + va_start(ap, p); + vfprintf(stderr, p, ap); + va_end(ap); + fputc('\n', stderr); + postmsg(&cf); +} void connection_fatal(void *frontend, char *p, ...) { struct termios cf; @@ -116,12 +128,6 @@ char *platform_default_s(const char *name) int platform_default_i(const char *name, int def) { - if (!strcmp(name, "TermWidth") || - !strcmp(name, "TermHeight")) { - struct winsize size; - if (ioctl(STDIN_FILENO, TIOCGWINSZ, (void *)&size) >= 0) - return (!strcmp(name, "TermWidth") ? size.ws_col : size.ws_row); - } return def; } @@ -130,14 +136,12 @@ FontSpec *platform_default_fontspec(const char *name) return fontspec_new(""); } -Filename platform_default_filename(const char *name) +Filename *platform_default_filename(const char *name) { - Filename ret; if (!strcmp(name, "LogFileName")) - strcpy(ret.path, "putty.log"); + return filename_from_str("putty.log"); else - *ret.path = '\0'; - return ret; + return filename_from_str(""); } char *x_get_default(const char *key) @@ -148,7 +152,7 @@ int term_ldisc(Terminal *term, int mode) { return FALSE; } -void ldisc_update(void *frontend, int echo, int edit) +void frontend_echoedit_update(void *frontend, int echo, int edit) { /* Update stdin read mode to reflect changes in line discipline. */ struct termios mode; @@ -174,8 +178,9 @@ void ldisc_update(void *frontend, int echo, int edit) mode.c_cc[VMIN] = 1; mode.c_cc[VTIME] = 0; /* FIXME: perhaps what we do with IXON/IXOFF should be an - * argument to ldisc_update(), to allow implementation of SSH-2 - * "xon-xoff" and Rlogin's equivalent? */ + * argument to frontend_echoedit_update(), to allow + * implementation of SSH-2 "xon-xoff" and Rlogin's + * equivalent? */ mode.c_iflag &= ~IXON; mode.c_iflag &= ~IXOFF; } @@ -200,7 +205,7 @@ static char *get_ttychar(struct termios *t, int index) cc_t c = t->c_cc[index]; #if defined(_POSIX_VDISABLE) if (c == _POSIX_VDISABLE) - return dupprintf(""); + return dupstr(""); #endif return dupprintf("^<%d>", c); } @@ -388,20 +393,18 @@ int try_output(int is_stderr) bufchain *chain = (is_stderr ? &stderr_data : &stdout_data); int fd = (is_stderr ? STDERR_FILENO : STDOUT_FILENO); void *senddata; - int sendlen, ret, fl; + int sendlen, ret; if (bufchain_size(chain) > 0) { - fl = fcntl(fd, F_GETFL); - if (fl != -1 && !(fl & O_NONBLOCK)) - fcntl(fd, F_SETFL, fl | O_NONBLOCK); + int prev_nonblock = nonblock(fd); do { bufchain_prefix(chain, &senddata, &sendlen); ret = write(fd, senddata, sendlen); if (ret > 0) bufchain_consume(chain, ret); } while (ret == sendlen && bufchain_size(chain) != 0); - if (fl != -1 && !(fl & O_NONBLOCK)) - fcntl(fd, F_SETFL, fl); + if (!prev_nonblock) + no_nonblock(fd); if (ret < 0 && errno != EAGAIN) { perror(is_stderr ? "stderr: write" : "stdout: write"); exit(1); @@ -540,7 +543,7 @@ void uxsel_input_remove(int id) { } */ static void usage(void) { - printf("PuTTY Link: command-line connection utility\n"); + printf("Plink: 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"); @@ -554,6 +557,8 @@ static void usage(void) printf(" -P port connect to specified port\n"); printf(" -l user connect with specified username\n"); printf(" -batch disable all interactive prompts\n"); + printf(" -sercfg configuration-string (e.g. 19200,8,n,1,X)\n"); + printf(" Specify the serial configuration (serial only)\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"); @@ -568,16 +573,16 @@ static void usage(void) printf(" -1 -2 force use of particular protocol version\n"); printf(" -4 -6 force use of IPv4 or IPv6\n"); printf(" -C enable compression\n"); - printf(" -i key private key file for authentication\n"); + printf(" -i key private key file for user authentication\n"); printf(" -noagent disable use of Pageant\n"); printf(" -agent enable use of Pageant\n"); + printf(" -hostkey aa:bb:cc:...\n"); + printf(" manually specify a host key (may be repeated)\n"); printf(" -m file read remote command(s) from file\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"); printf(" -nc host:port\n"); printf(" open tunnel in place of session (SSH-2 only)\n"); - printf(" -sercfg configuration-string (e.g. 19200,8,n,1,X)\n"); - printf(" Specify the serial configuration (serial only)\n"); exit(1); } @@ -587,6 +592,11 @@ static void version(void) exit(1); } +void frontend_net_error_pending(void) {} + +const int share_can_be_downstream = TRUE; +const int share_can_be_upstream = TRUE; + int main(int argc, char **argv) { int sending; @@ -599,7 +609,8 @@ int main(int argc, char **argv) int errors; int use_subsystem = 0; int got_host = FALSE; - long now; + unsigned long now; + struct winsize size; fdlist = NULL; fdcount = fdsize = 0; @@ -659,8 +670,11 @@ int main(int argc, char **argv) } else if (!strcmp(p, "-s")) { /* Save status to write to conf later. */ use_subsystem = 1; - } else if (!strcmp(p, "-V")) { + } else if (!strcmp(p, "-V") || !strcmp(p, "--version")) { version(); + } else if (!strcmp(p, "--help")) { + usage(); + exit(0); } else if (!strcmp(p, "-pgpfp")) { pgp_fingerprints(); exit(1); @@ -694,8 +708,7 @@ int main(int argc, char **argv) q += 2; conf_set_int(conf, CONF_protocol, PROT_TELNET); p = q; - while (*p && *p != ':' && *p != '/') - p++; + p += host_strcspn(p, ":/"); c = *p; if (*p) *p++ = '\0'; @@ -833,10 +846,21 @@ int main(int argc, char **argv) } } - /* - * Trim off a colon suffix if it's there. - */ - host[strcspn(host, ":")] = '\0'; + /* + * Trim a colon suffix off the hostname if it's there. In + * order to protect unbracketed IPv6 address literals + * against this treatment, we do not do this if there's + * _more_ than one colon. + */ + { + char *c = host_strchr(host, ':'); + + if (c) { + char *d = host_strchr(c+1, ':'); + if (!d) + *c = '\0'; + } + } /* * Remove any remaining whitespace. @@ -887,6 +911,12 @@ int main(int argc, char **argv) if (portnumber != -1) conf_set_int(conf, CONF_port, portnumber); + /* + * Block SIGPIPE, so that we'll get EPIPE individually on + * particular network connections that go wrong. + */ + putty_signal(SIGPIPE, SIG_IGN); + /* * Set up the pipe we'll use to tell us about SIGWINCH. */ @@ -896,6 +926,15 @@ int main(int argc, char **argv) } putty_signal(SIGWINCH, sigwinch); + /* + * Now that we've got the SIGWINCH handler installed, try to find + * out the initial terminal size. + */ + if (ioctl(STDIN_FILENO, TIOCGWINSZ, &size) >= 0) { + conf_set_int(conf, CONF_width, size.ws_col); + conf_set_int(conf, CONF_height, size.ws_row); + } + sk_init(); uxsel_init(); @@ -943,7 +982,7 @@ int main(int argc, char **argv) */ local_tty = (tcgetattr(STDIN_FILENO, &orig_termios) == 0); atexit(cleanup_termios); - ldisc_update(NULL, 1, 1); + frontend_echoedit_update(NULL, 1, 1); sending = FALSE; now = GETTICKCOUNT(); @@ -952,6 +991,7 @@ int main(int argc, char **argv) int maxfd; int rwx; int ret; + unsigned long next; FD_ZERO(&rset); FD_ZERO(&wset); @@ -1005,44 +1045,34 @@ int main(int argc, char **argv) FD_SET_MAX(fd, maxfd, xset); } - do { - long next, ticks; - struct timeval tv, *ptv; - - if (run_timers(now, &next)) { - ticks = next - GETTICKCOUNT(); - if (ticks < 0) ticks = 0; /* just in case */ + if (toplevel_callback_pending()) { + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + ret = select(maxfd, &rset, &wset, &xset, &tv); + } else if (run_timers(now, &next)) { + do { + unsigned long then; + long ticks; + struct timeval tv; + + then = now; + now = GETTICKCOUNT(); + if (now - then > next - then) + ticks = 0; + else + ticks = next - now; tv.tv_sec = ticks / 1000; tv.tv_usec = ticks % 1000 * 1000; - ptv = &tv; - } else { - ptv = NULL; - } - ret = select(maxfd, &rset, &wset, &xset, ptv); - if (ret == 0) - now = next; - else { - long newnow = GETTICKCOUNT(); - /* - * Check to see whether the system clock has - * changed massively during the select. - */ - if (newnow - now < 0 || newnow - now > next - now) { - /* - * If so, look at the elapsed time in the - * select and use it to compute a new - * tickcount_offset. - */ - long othernow = now + tv.tv_sec * 1000 + tv.tv_usec / 1000; - /* So we'd like GETTICKCOUNT to have returned othernow, - * but instead it return newnow. Hence ... */ - tickcount_offset += othernow - newnow; - now = othernow; - } else { - now = newnow; - } - } - } while (ret < 0 && errno == EINTR); + ret = select(maxfd, &rset, &wset, &xset, &tv); + if (ret == 0) + now = next; + else + now = GETTICKCOUNT(); + } while (ret < 0 && errno == EINTR); + } else { + ret = select(maxfd, &rset, &wset, &xset, NULL); + } if (ret < 0) { perror("select"); @@ -1070,7 +1100,7 @@ int main(int argc, char **argv) if (read(signalpipe[0], c, 1) <= 0) /* ignore error */; /* ignore its value; it'll be `x' */ - if (ioctl(0, TIOCGWINSZ, (void *)&size) >= 0) + if (ioctl(STDIN_FILENO, TIOCGWINSZ, (void *)&size) >= 0) back->size(backhandle, size.ws_col, size.ws_row); } @@ -1103,6 +1133,8 @@ int main(int argc, char **argv) back->unthrottle(backhandle, try_output(TRUE)); } + run_toplevel_callbacks(); + if ((!connopen || !back->connected(backhandle)) && bufchain_size(&stdout_data) == 0 && bufchain_size(&stderr_data) == 0)