X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/21226fd7e6d5e69dab830cc745e2dc59ed4a00cc..3fe551b2cde6cbc1946b48c311f45310de416cc5:/unix/uxplink.c diff --git a/unix/uxplink.c b/unix/uxplink.c index db881997..8027b6f8 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -27,14 +27,19 @@ void *logctx; +static struct termios orig_termios; + void fatalbox(char *p, ...) { + struct termios cf; va_list ap; + premsg(&cf); fprintf(stderr, "FATAL ERROR: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); + postmsg(&cf); if (logctx) { log_free(logctx); logctx = NULL; @@ -43,12 +48,15 @@ void fatalbox(char *p, ...) } void modalfatalbox(char *p, ...) { + struct termios cf; va_list ap; + premsg(&cf); fprintf(stderr, "FATAL ERROR: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); + postmsg(&cf); if (logctx) { log_free(logctx); logctx = NULL; @@ -57,12 +65,15 @@ void modalfatalbox(char *p, ...) } void connection_fatal(void *frontend, char *p, ...) { + struct termios cf; va_list ap; + premsg(&cf); fprintf(stderr, "FATAL ERROR: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); + postmsg(&cf); if (logctx) { log_free(logctx); logctx = NULL; @@ -71,17 +82,19 @@ void connection_fatal(void *frontend, char *p, ...) } void cmdline_error(char *p, ...) { + struct termios cf; va_list ap; + premsg(&cf); fprintf(stderr, "plink: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); + postmsg(&cf); exit(1); } static int local_tty = FALSE; /* do we have a local tty? */ -static struct termios orig_termios; static Backend *back; static void *backhandle; @@ -94,8 +107,8 @@ char *platform_default_s(const char *name) { if (!strcmp(name, "TermType")) return dupstr(getenv("TERM")); - if (!strcmp(name, "UserName")) - return get_username(); + if (!strcmp(name, "UserName")) + return get_username(); if (!strcmp(name, "SerialLine")) return dupstr("/dev/ttyS0"); return NULL; @@ -371,43 +384,44 @@ void cleanup_termios(void) bufchain stdout_data, stderr_data; -void try_output(int is_stderr) +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; + int sendlen, ret, fl; 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 && errno != EWOULDBLOCK) { + return bufchain_size(&stdout_data) + bufchain_size(&stderr_data); + + fl = fcntl(fd, F_GETFL); + if (fl != -1 && !(fl & O_NONBLOCK)) + fcntl(fd, F_SETFL, fl | O_NONBLOCK); + 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 (ret < 0 && errno != EAGAIN) { perror(is_stderr ? "stderr: write" : "stdout: write"); exit(1); } + return bufchain_size(&stdout_data) + bufchain_size(&stderr_data); } 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(TRUE); + return try_output(TRUE); } else { bufchain_add(&stdout_data, data, len); - try_output(FALSE); + return try_output(FALSE); } - - osize = bufchain_size(&stdout_data); - esize = bufchain_size(&stderr_data); - - return osize + esize; } int from_backend_untrusted(void *frontend_handle, const char *data, int len) @@ -499,7 +513,8 @@ int signalpipe[2]; void sigwinch(int signum) { - write(signalpipe[1], "x", 1); + if (write(signalpipe[1], "x", 1) <= 0) + /* not much we can do about it */; } /* @@ -523,7 +538,7 @@ static void usage(void) printf(" -pgpfp print PGP key fingerprints and exit\n"); printf(" -v show verbose messages\n"); printf(" -load sessname Load settings from saved session\n"); - printf(" -ssh -telnet -rlogin -raw\n"); + printf(" -ssh -telnet -rlogin -raw -serial\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"); @@ -550,6 +565,8 @@ static void usage(void) 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); } @@ -582,7 +599,9 @@ int main(int argc, char **argv) default_protocol = PROT_SSH; default_port = 22; - flags = FLAG_STDERR; + flags = FLAG_STDERR | FLAG_STDERR_TTY; + + stderr_tty_init(); /* * Process the command line. */ @@ -853,6 +872,14 @@ int main(int argc, char **argv) uxsel_init(); /* + * Unix Plink doesn't provide any way to add forwardings after the + * connection is set up, so if there are none now, we can safely set + * the "simple" flag. + */ + if (cfg.protocol == PROT_SSH && !cfg.x11_forward && !cfg.agentfwd && + cfg.portfwd[0] == '\0' && cfg.portfwd[1] == '\0') + cfg.ssh_simple = TRUE; + /* * Start up the connection. */ logctx = log_init(NULL, &cfg); @@ -883,23 +910,6 @@ int main(int argc, char **argv) local_tty = (tcgetattr(STDIN_FILENO, &orig_termios) == 0); atexit(cleanup_termios); ldisc_update(NULL, 1, 1); - - { - int fl; - /* - * Make sure that stdout/err are non-blocking. - */ - if ((fl = fcntl(STDOUT_FILENO, F_GETFL)) == -1 || - fcntl(STDOUT_FILENO, F_SETFL, fl | O_NONBLOCK) == -1) { - perror("stdout"); - exit(1); - } - if ((fl = fcntl(STDERR_FILENO, F_GETFL)) == -1 || - fcntl(STDERR_FILENO, F_SETFL, fl | O_NONBLOCK) == -1) { - perror("stderr"); - exit(1); - } - } sending = FALSE; now = GETTICKCOUNT(); @@ -1023,7 +1033,9 @@ int main(int argc, char **argv) if (FD_ISSET(signalpipe[0], &rset)) { char c[1]; struct winsize size; - read(signalpipe[0], c, 1); /* ignore its value; it'll be `x' */ + if (read(signalpipe[0], c, 1) <= 0) + /* ignore error */; + /* ignore its value; it'll be `x' */ if (ioctl(0, TIOCGWINSZ, (void *)&size) >= 0) back->size(backhandle, size.ws_col, size.ws_row); } @@ -1050,11 +1062,11 @@ int main(int argc, char **argv) } if (FD_ISSET(STDOUT_FILENO, &wset)) { - try_output(FALSE); + back->unthrottle(backhandle, try_output(FALSE)); } if (FD_ISSET(STDERR_FILENO, &wset)) { - try_output(TRUE); + back->unthrottle(backhandle, try_output(TRUE)); } if ((!connopen || !back->connected(backhandle)) &&