[BACK]Return to clientloop.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/clientloop.c, Revision 1.1

1.1     ! deraadt     1: /*
        !             2:
        !             3: clientloop.c
        !             4:
        !             5: Author: Tatu Ylonen <ylo@cs.hut.fi>
        !             6:
        !             7: Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
        !             8:                    All rights reserved
        !             9:
        !            10:
        !            11: Created: Sat Sep 23 12:23:57 1995 ylo
        !            12:
        !            13: The main loop for the interactive session (client side).
        !            14:
        !            15: */
        !            16:
        !            17: #include "includes.h"
        !            18: RCSID("$Id: clientloop.c,v 1.4 1999/05/04 11:58:37 bg Exp $");
        !            19:
        !            20: #include "xmalloc.h"
        !            21: #include "randoms.h"
        !            22: #include "ssh.h"
        !            23: #include "packet.h"
        !            24: #include "buffer.h"
        !            25: #include "authfd.h"
        !            26:
        !            27: /* Flag indicating whether quiet mode is on. */
        !            28: extern int quiet_flag;
        !            29:
        !            30: /* Flag indicating that stdin should be redirected from /dev/null. */
        !            31: extern int stdin_null_flag;
        !            32:
        !            33: /* Name of the host we are connecting to.  This is the name given on the
        !            34:    command line, or the HostName specified for the user-supplied name
        !            35:    in a configuration file. */
        !            36: extern char *host;
        !            37:
        !            38: #ifdef SIGWINCH
        !            39: /* Flag to indicate that we have received a window change signal which has
        !            40:    not yet been processed.  This will cause a message indicating the new
        !            41:    window size to be sent to the server a little later.  This is volatile
        !            42:    because this is updated in a signal handler. */
        !            43: static volatile int received_window_change_signal = 0;
        !            44: #endif /* SIGWINCH */
        !            45:
        !            46: /* Terminal modes, as saved by enter_raw_mode. */
        !            47: #ifdef USING_TERMIOS
        !            48: static struct termios saved_tio;
        !            49: #endif
        !            50: #ifdef USING_SGTTY
        !            51: static struct sgttyb saved_tio;
        !            52: #endif
        !            53:
        !            54: /* Flag indicating whether we are in raw mode.  This is used by enter_raw_mode
        !            55:    and leave_raw_mode. */
        !            56: static int in_raw_mode = 0;
        !            57:
        !            58: /* Flag indicating whether the user\'s terminal is in non-blocking mode. */
        !            59: static int in_non_blocking_mode = 0;
        !            60:
        !            61: /* Common data for the client loop code. */
        !            62: static int escape_pending;  /* Last character was the escape character */
        !            63: static int last_was_cr; /* Last character was a newline. */
        !            64: static int exit_status; /* Used to store the exit status of the command. */
        !            65: static int stdin_eof; /* EOF has been encountered on standard error. */
        !            66: static Buffer stdin_buffer;  /* Buffer for stdin data. */
        !            67: static Buffer stdout_buffer; /* Buffer for stdout data. */
        !            68: static Buffer stderr_buffer; /* Buffer for stderr data. */
        !            69: static unsigned int buffer_high; /* Soft max buffer size. */
        !            70: static int max_fd; /* Maximum file descriptor number in select(). */
        !            71: static int connection_in; /* Connection to server (input). */
        !            72: static int connection_out; /* Connection to server (output). */
        !            73: static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
        !            74: static int quit_pending; /* Set to non-zero to quit the client loop. */
        !            75: static int escape_char; /* Escape character. */
        !            76:
        !            77: /* Returns the user\'s terminal to normal mode if it had been put in raw
        !            78:    mode. */
        !            79:
        !            80: void leave_raw_mode()
        !            81: {
        !            82:   if (!in_raw_mode)
        !            83:     return;
        !            84:   in_raw_mode = 0;
        !            85: #ifdef USING_TERMIOS
        !            86:   if (tcsetattr(fileno(stdin), TCSADRAIN, &saved_tio) < 0)
        !            87:     perror("tcsetattr");
        !            88: #endif /* USING_TERMIOS */
        !            89: #ifdef USING_SGTTY
        !            90:   if (ioctl(fileno(stdin), TIOCSETP, &saved_tio) < 0)
        !            91:     perror("ioctl(stdin, TIOCSETP, ...)");
        !            92: #endif /* USING_SGTTY */
        !            93:
        !            94:   fatal_remove_cleanup((void (*)(void *))leave_raw_mode, NULL);
        !            95: }
        !            96:
        !            97: /* Puts the user\'s terminal in raw mode. */
        !            98:
        !            99: void enter_raw_mode()
        !           100: {
        !           101: #ifdef USING_TERMIOS
        !           102:   struct termios tio;
        !           103:
        !           104:   if (tcgetattr(fileno(stdin), &tio) < 0)
        !           105:     perror("tcgetattr");
        !           106:   saved_tio = tio;
        !           107:   tio.c_iflag |= IGNPAR;
        !           108:   tio.c_iflag &= ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF);
        !           109:   tio.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL);
        !           110: #ifdef IEXTEN
        !           111:   tio.c_lflag &= ~IEXTEN;
        !           112: #endif /* IEXTEN */
        !           113:   tio.c_oflag &= ~OPOST;
        !           114:   tio.c_cc[VMIN] = 1;
        !           115:   tio.c_cc[VTIME] = 0;
        !           116:   if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0)
        !           117:     perror("tcsetattr");
        !           118:   in_raw_mode = 1;
        !           119: #endif /* USING_TERMIOS */
        !           120: #ifdef USING_SGTTY
        !           121:   struct sgttyb tio;
        !           122:
        !           123:   if (ioctl(fileno(stdin), TIOCGETP, &tio) < 0)
        !           124:     perror("ioctl(stdin, TIOCGETP, ...)");
        !           125:   saved_tio = tio;
        !           126:   tio.sg_flags &= ~(CBREAK | ECHO | CRMOD | LCASE | TANDEM);
        !           127:   tio.sg_flags |= (RAW | ANYP);
        !           128:   if (ioctl(fileno(stdin), TIOCSETP, &tio) < 0)
        !           129:     perror("ioctl(stdin, TIOCSETP, ...)");
        !           130:   in_raw_mode = 1;
        !           131: #endif /* USING_SGTTY */
        !           132:
        !           133:   fatal_add_cleanup((void (*)(void *))leave_raw_mode, NULL);
        !           134: }
        !           135:
        !           136: /* Puts stdin terminal in non-blocking mode. */
        !           137:
        !           138: /* Restores stdin to blocking mode. */
        !           139:
        !           140: void leave_non_blocking()
        !           141: {
        !           142:   if (in_non_blocking_mode)
        !           143:     {
        !           144:       (void)fcntl(fileno(stdin), F_SETFL, 0);
        !           145:       in_non_blocking_mode = 0;
        !           146:       fatal_remove_cleanup((void (*)(void *))leave_non_blocking, NULL);
        !           147:     }
        !           148: }
        !           149:
        !           150: void enter_non_blocking()
        !           151: {
        !           152:   in_non_blocking_mode = 1;
        !           153: #if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN)
        !           154:   (void)fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
        !           155: #else /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
        !           156:   (void)fcntl(fileno(stdin), F_SETFL, O_NDELAY);
        !           157: #endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
        !           158:   fatal_add_cleanup((void (*)(void *))leave_non_blocking, NULL);
        !           159: }
        !           160:
        !           161: #ifdef SIGWINCH
        !           162: /* Signal handler for the window change signal (SIGWINCH).  This just
        !           163:    sets a flag indicating that the window has changed. */
        !           164:
        !           165: RETSIGTYPE window_change_handler(int sig)
        !           166: {
        !           167:   received_window_change_signal = 1;
        !           168:   signal(SIGWINCH, window_change_handler);
        !           169: }
        !           170: #endif /* SIGWINCH */
        !           171:
        !           172: /* Signal handler for signals that cause the program to terminate.  These
        !           173:    signals must be trapped to restore terminal modes. */
        !           174:
        !           175: RETSIGTYPE signal_handler(int sig)
        !           176: {
        !           177:   if (in_raw_mode)
        !           178:     leave_raw_mode();
        !           179:   if (in_non_blocking_mode)
        !           180:     leave_non_blocking();
        !           181:   channel_stop_listening();
        !           182:   packet_close();
        !           183:   fatal("Killed by signal %d.", sig);
        !           184: }
        !           185:
        !           186: /* Returns current time in seconds from Jan 1, 1970 with the maximum available
        !           187:    resolution. */
        !           188:
        !           189: double get_current_time()
        !           190: {
        !           191: #ifdef HAVE_GETTIMEOFDAY
        !           192:   struct timeval tv;
        !           193:   gettimeofday(&tv, NULL);
        !           194:   return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
        !           195: #else /* HAVE_GETTIMEOFDAY */
        !           196:   return (double)time(NULL);
        !           197: #endif /* HAVE_GETTIMEOFDAY */
        !           198: }
        !           199:
        !           200: /* This is called when the interactive is entered.  This checks if there
        !           201:    is an EOF coming on stdin.  We must check this explicitly, as select()
        !           202:    does not appear to wake up when redirecting from /dev/null. */
        !           203:
        !           204: void client_check_initial_eof_on_stdin()
        !           205: {
        !           206:   int len;
        !           207:   char buf[1];
        !           208:
        !           209:   /* If standard input is to be "redirected from /dev/null", we simply
        !           210:      mark that we have seen an EOF and send an EOF message to the server.
        !           211:      Otherwise, we try to read a single character; it appears that for some
        !           212:      files, such /dev/null, select() never wakes up for read for this
        !           213:      descriptor, which means that we never get EOF.  This way we will get
        !           214:      the EOF if stdin comes from /dev/null or similar. */
        !           215:   if (stdin_null_flag)
        !           216:     {
        !           217:       /* Fake EOF on stdin. */
        !           218:       debug("Sending eof.");
        !           219:       stdin_eof = 1;
        !           220:       packet_start(SSH_CMSG_EOF);
        !           221:       packet_send();
        !           222:     }
        !           223:   else
        !           224:     {
        !           225:       /* Enter non-blocking mode for stdin. */
        !           226:       enter_non_blocking();
        !           227:
        !           228:       /* Check for immediate EOF on stdin. */
        !           229:       len = read(fileno(stdin), buf, 1);
        !           230:       if (len == 0)
        !           231:        {
        !           232:          /* EOF.  Record that we have seen it and send EOF to server. */
        !           233:          debug("Sending eof.");
        !           234:          stdin_eof = 1;
        !           235:          packet_start(SSH_CMSG_EOF);
        !           236:          packet_send();
        !           237:        }
        !           238:       else
        !           239:        if (len > 0)
        !           240:          {
        !           241:            /* Got data.  We must store the data in the buffer, and also
        !           242:               process it as an escape character if appropriate. */
        !           243:            if ((unsigned char)buf[0] == escape_char)
        !           244:              escape_pending = 1;
        !           245:            else
        !           246:              {
        !           247:                buffer_append(&stdin_buffer, buf, 1);
        !           248:                stdin_bytes += 1;
        !           249:              }
        !           250:          }
        !           251:
        !           252:       /* Leave non-blocking mode. */
        !           253:       leave_non_blocking();
        !           254:     }
        !           255: }
        !           256:
        !           257: /* Get packets from the connection input buffer, and process them as long
        !           258:    as there are packets available. */
        !           259:
        !           260: void client_process_buffered_input_packets()
        !           261: {
        !           262:   int type;
        !           263:   char *data;
        !           264:   unsigned int data_len;
        !           265:   int payload_len;
        !           266:
        !           267:   /* Process any buffered packets from the server. */
        !           268:   while (!quit_pending && (type = packet_read_poll(&payload_len)) != SSH_MSG_NONE)
        !           269:     {
        !           270:       switch (type)
        !           271:        {
        !           272:
        !           273:        case SSH_SMSG_STDOUT_DATA:
        !           274:          data = packet_get_string(&data_len);
        !           275:          packet_integrity_check(payload_len, 4 + data_len, type);
        !           276:          buffer_append(&stdout_buffer, data, data_len);
        !           277:          stdout_bytes += data_len;
        !           278:          memset(data, 0, data_len);
        !           279:          xfree(data);
        !           280:          break;
        !           281:
        !           282:        case SSH_SMSG_STDERR_DATA:
        !           283:          data = packet_get_string(&data_len);
        !           284:          packet_integrity_check(payload_len, 4 + data_len, type);
        !           285:          buffer_append(&stderr_buffer, data, data_len);
        !           286:          stdout_bytes += data_len;
        !           287:          memset(data, 0, data_len);
        !           288:          xfree(data);
        !           289:          break;
        !           290:
        !           291:        case SSH_SMSG_EXITSTATUS:
        !           292:          packet_integrity_check(payload_len, 4, type);
        !           293:          exit_status = packet_get_int();
        !           294:          /* Acknowledge the exit. */
        !           295:          packet_start(SSH_CMSG_EXIT_CONFIRMATION);
        !           296:          packet_send();
        !           297:          /* Must wait for packet to be sent since we are exiting the
        !           298:             loop. */
        !           299:          packet_write_wait();
        !           300:          /* Flag that we want to exit. */
        !           301:          quit_pending = 1;
        !           302:          break;
        !           303:
        !           304:        case SSH_SMSG_X11_OPEN:
        !           305:          x11_input_open(payload_len);
        !           306:          break;
        !           307:
        !           308:        case SSH_MSG_PORT_OPEN:
        !           309:          channel_input_port_open(payload_len);
        !           310:          break;
        !           311:
        !           312:        case SSH_SMSG_AGENT_OPEN:
        !           313:          packet_integrity_check(payload_len, 4, type);
        !           314:          auth_input_open_request();
        !           315:          break;
        !           316:
        !           317:        case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
        !           318:          packet_integrity_check(payload_len, 4 + 4, type);
        !           319:          channel_input_open_confirmation();
        !           320:          break;
        !           321:
        !           322:        case SSH_MSG_CHANNEL_OPEN_FAILURE:
        !           323:          packet_integrity_check(payload_len, 4, type);
        !           324:          channel_input_open_failure();
        !           325:          break;
        !           326:
        !           327:        case SSH_MSG_CHANNEL_DATA:
        !           328:          channel_input_data(payload_len);
        !           329:          break;
        !           330:
        !           331:        case SSH_MSG_CHANNEL_CLOSE:
        !           332:          packet_integrity_check(payload_len, 4, type);
        !           333:          channel_input_close();
        !           334:          break;
        !           335:
        !           336:        case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
        !           337:          packet_integrity_check(payload_len, 4, type);
        !           338:          channel_input_close_confirmation();
        !           339:          break;
        !           340:
        !           341:        default:
        !           342:          /* Any unknown packets received during the actual session
        !           343:             cause the session to terminate.  This is intended to make
        !           344:             debugging easier since no confirmations are sent.  Any
        !           345:             compatible protocol extensions must be negotiated during
        !           346:             the preparatory phase. */
        !           347:          packet_disconnect("Protocol error during session: type %d",
        !           348:                            type);
        !           349:        }
        !           350:     }
        !           351: }
        !           352:
        !           353: /* Make packets from buffered stdin data, and buffer them for sending to
        !           354:    the connection. */
        !           355:
        !           356: void client_make_packets_from_stdin_data()
        !           357: {
        !           358:   unsigned int len;
        !           359:
        !           360:   /* Send buffered stdin data to the server. */
        !           361:   while (buffer_len(&stdin_buffer) > 0 &&
        !           362:         packet_not_very_much_data_to_write())
        !           363:     {
        !           364:       len = buffer_len(&stdin_buffer);
        !           365:       if (len > 32768)
        !           366:        len = 32768;  /* Keep the packets at reasonable size. */
        !           367:       packet_start(SSH_CMSG_STDIN_DATA);
        !           368:       packet_put_string(buffer_ptr(&stdin_buffer), len);
        !           369:       packet_send();
        !           370:       buffer_consume(&stdin_buffer, len);
        !           371:       /* If we have a pending EOF, send it now. */
        !           372:       if (stdin_eof && buffer_len(&stdin_buffer) == 0)
        !           373:        {
        !           374:          packet_start(SSH_CMSG_EOF);
        !           375:          packet_send();
        !           376:        }
        !           377:     }
        !           378: }
        !           379:
        !           380: /* Checks if the client window has changed, and sends a packet about it to
        !           381:    the server if so.  The actual change is detected elsewhere (by a software
        !           382:    interrupt on Unix); this just checks the flag and sends a message if
        !           383:    appropriate. */
        !           384:
        !           385: void client_check_window_change()
        !           386: {
        !           387: #ifdef SIGWINCH
        !           388:   /* Send possible window change message to the server. */
        !           389:   if (received_window_change_signal)
        !           390:     {
        !           391:       struct winsize ws;
        !           392:
        !           393:       /* Clear the window change indicator. */
        !           394:       received_window_change_signal = 0;
        !           395:
        !           396:       /* Read new window size. */
        !           397:       if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0)
        !           398:        {
        !           399:          /* Successful, send the packet now. */
        !           400:          packet_start(SSH_CMSG_WINDOW_SIZE);
        !           401:          packet_put_int(ws.ws_row);
        !           402:          packet_put_int(ws.ws_col);
        !           403:          packet_put_int(ws.ws_xpixel);
        !           404:          packet_put_int(ws.ws_ypixel);
        !           405:          packet_send();
        !           406:        }
        !           407:     }
        !           408: #endif /* SIGWINCH */
        !           409: }
        !           410:
        !           411: /* Waits until the client can do something (some data becomes available on
        !           412:    one of the file descriptors). */
        !           413:
        !           414: void client_wait_until_can_do_something(fd_set *readset, fd_set *writeset)
        !           415: {
        !           416:   /* Initialize select masks. */
        !           417:   FD_ZERO(readset);
        !           418:
        !           419:   /* Read from the connection, unless our buffers are full. */
        !           420:   if (buffer_len(&stdout_buffer) < buffer_high &&
        !           421:       buffer_len(&stderr_buffer) < buffer_high &&
        !           422:       channel_not_very_much_buffered_data())
        !           423:     FD_SET(connection_in, readset);
        !           424:
        !           425:   /* Read from stdin, unless we have seen EOF or have very much buffered
        !           426:      data to send to the server. */
        !           427:   if (!stdin_eof && packet_not_very_much_data_to_write())
        !           428:     FD_SET(fileno(stdin), readset);
        !           429:
        !           430:   FD_ZERO(writeset);
        !           431:
        !           432:   /* Add any selections by the channel mechanism. */
        !           433:   channel_prepare_select(readset, writeset);
        !           434:
        !           435:   /* Select server connection if have data to write to the server. */
        !           436:   if (packet_have_data_to_write())
        !           437:     FD_SET(connection_out, writeset);
        !           438:
        !           439:   /* Select stdout if have data in buffer. */
        !           440:   if (buffer_len(&stdout_buffer) > 0)
        !           441:     FD_SET(fileno(stdout), writeset);
        !           442:
        !           443:   /* Select stderr if have data in buffer. */
        !           444:   if (buffer_len(&stderr_buffer) > 0)
        !           445:     FD_SET(fileno(stderr), writeset);
        !           446:
        !           447:   /* Update maximum file descriptor number, if appropriate. */
        !           448:   if (channel_max_fd() > max_fd)
        !           449:     max_fd = channel_max_fd();
        !           450:
        !           451:   /* Wait for something to happen.  This will suspend the process until
        !           452:      some selected descriptor can be read, written, or has some other
        !           453:      event pending.  Note: if you want to implement SSH_MSG_IGNORE
        !           454:      messages to fool traffic analysis, this might be the place to do
        !           455:      it: just have a random timeout for the select, and send a random
        !           456:      SSH_MSG_IGNORE packet when the timeout expires. */
        !           457:   if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0)
        !           458:     {
        !           459:       char buf[100];
        !           460:       /* Some systems fail to clear these automatically. */
        !           461:       FD_ZERO(readset);
        !           462:       FD_ZERO(writeset);
        !           463:       if (errno == EINTR)
        !           464:        return;
        !           465:       /* Note: we might still have data in the buffers. */
        !           466:       sprintf(buf, "select: %.100s\r\n", strerror(errno));
        !           467:       buffer_append(&stderr_buffer, buf, strlen(buf));
        !           468:       stderr_bytes += strlen(buf);
        !           469:       quit_pending = 1;
        !           470:     }
        !           471: }
        !           472:
        !           473: void client_suspend_self()
        !           474: {
        !           475: #ifdef SIGWINCH
        !           476:   struct winsize oldws, newws;
        !           477: #endif /* SIGWINCH */
        !           478:
        !           479:   /* Flush stdout and stderr buffers. */
        !           480:   if (buffer_len(&stdout_buffer) > 0)
        !           481:     write(fileno(stdout),
        !           482:          buffer_ptr(&stdout_buffer),
        !           483:          buffer_len(&stdout_buffer));
        !           484:   if (buffer_len(&stderr_buffer) > 0)
        !           485:     write(fileno(stderr),
        !           486:          buffer_ptr(&stderr_buffer),
        !           487:          buffer_len(&stderr_buffer));
        !           488:
        !           489:   /* Leave raw mode. */
        !           490:   leave_raw_mode();
        !           491:
        !           492:   /* Free (and clear) the buffer to reduce the
        !           493:      amount of data that gets written to swap. */
        !           494:   buffer_free(&stdin_buffer);
        !           495:   buffer_free(&stdout_buffer);
        !           496:   buffer_free(&stderr_buffer);
        !           497:
        !           498: #ifdef SIGWINCH
        !           499:   /* Save old window size. */
        !           500:   ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
        !           501: #endif /* SIGWINCH */
        !           502:
        !           503:   /* Send the suspend signal to the program
        !           504:      itself. */
        !           505:   kill(getpid(), SIGTSTP);
        !           506:
        !           507: #ifdef SIGWINCH
        !           508:   /* Check if the window size has changed. */
        !           509:   if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 &&
        !           510:       (oldws.ws_row != newws.ws_row || oldws.ws_col != newws.ws_col ||
        !           511:        oldws.ws_xpixel != newws.ws_xpixel ||
        !           512:        oldws.ws_ypixel != newws.ws_ypixel))
        !           513:     received_window_change_signal = 1;
        !           514: #endif /* SIGWINCH */
        !           515:
        !           516:   /* OK, we have been continued by the user.
        !           517:      Reinitialize buffers. */
        !           518:   buffer_init(&stdin_buffer);
        !           519:   buffer_init(&stdout_buffer);
        !           520:   buffer_init(&stderr_buffer);
        !           521:
        !           522:   /* Re-enter raw mode. */
        !           523:   enter_raw_mode();
        !           524: }
        !           525:
        !           526: void client_process_input(fd_set *readset)
        !           527: {
        !           528:   int len, pid;
        !           529:   char buf[8192], *s;
        !           530:
        !           531:   /* Read input from the server, and add any such data to the buffer of the
        !           532:      packet subsystem. */
        !           533:   if (FD_ISSET(connection_in, readset))
        !           534:     {
        !           535:       /* Read as much as possible. */
        !           536:       len = read(connection_in, buf, sizeof(buf));
        !           537:       if (len == 0)
        !           538:        {
        !           539:          /* Received EOF.  The remote host has closed the connection. */
        !           540:          sprintf(buf, "Connection to %.300s closed by remote host.\r\n",
        !           541:                  host);
        !           542:          buffer_append(&stderr_buffer, buf, strlen(buf));
        !           543:          stderr_bytes += strlen(buf);
        !           544:          quit_pending = 1;
        !           545:          return;
        !           546:        }
        !           547:
        !           548:       /* There is a kernel bug on Solaris that causes select to sometimes
        !           549:         wake up even though there is no data available. */
        !           550:       if (len < 0 && errno == EAGAIN)
        !           551:        len = 0;
        !           552:
        !           553:       if (len < 0)
        !           554:        {
        !           555:          /* An error has encountered.  Perhaps there is a network
        !           556:             problem. */
        !           557:          sprintf(buf, "Read from remote host %.300s: %.100s\r\n",
        !           558:                  host, strerror(errno));
        !           559:          buffer_append(&stderr_buffer, buf, strlen(buf));
        !           560:          stderr_bytes += strlen(buf);
        !           561:          quit_pending = 1;
        !           562:          return;
        !           563:        }
        !           564:       packet_process_incoming(buf, len);
        !           565:     }
        !           566:
        !           567:   /* Read input from stdin. */
        !           568:   if (FD_ISSET(fileno(stdin), readset))
        !           569:     {
        !           570:       /* Read as much as possible. */
        !           571:       len = read(fileno(stdin), buf, sizeof(buf));
        !           572:       if (len <= 0)
        !           573:        {
        !           574:          /* Received EOF or error.  They are treated similarly,
        !           575:             except that an error message is printed if it was
        !           576:             an error condition. */
        !           577:          if (len < 0)
        !           578:            {
        !           579:              sprintf(buf, "read: %.100s\r\n", strerror(errno));
        !           580:              buffer_append(&stderr_buffer, buf, strlen(buf));
        !           581:              stderr_bytes += strlen(buf);
        !           582:            }
        !           583:          /* Mark that we have seen EOF. */
        !           584:          stdin_eof = 1;
        !           585:          /* Send an EOF message to the server unless there is data
        !           586:             in the buffer.  If there is data in the buffer, no message
        !           587:             will be sent now.  Code elsewhere will send the EOF
        !           588:             when the buffer becomes empty if stdin_eof is set. */
        !           589:          if (buffer_len(&stdin_buffer) == 0)
        !           590:            {
        !           591:              packet_start(SSH_CMSG_EOF);
        !           592:              packet_send();
        !           593:            }
        !           594:        }
        !           595:       else
        !           596:        if (escape_char == -1)
        !           597:          {
        !           598:            /* Normal successful read, and no escape character.  Just
        !           599:               append the data to buffer. */
        !           600:            buffer_append(&stdin_buffer, buf, len);
        !           601:            stdin_bytes += len;
        !           602:          }
        !           603:        else
        !           604:          {
        !           605:            /* Normal, successful read.  But we have an escape character
        !           606:               and have to process the characters one by one. */
        !           607:            unsigned int i;
        !           608:            for (i = 0; i < len; i++)
        !           609:              {
        !           610:                unsigned char ch;
        !           611:                /* Get one character at a time. */
        !           612:                ch = buf[i];
        !           613:
        !           614:                /* Check if we have a pending escape character. */
        !           615:                if (escape_pending)
        !           616:                  {
        !           617:                    /* We have previously seen an escape character. */
        !           618:                    /* Clear the flag now. */
        !           619:                    escape_pending = 0;
        !           620:                    /* Process the escaped character. */
        !           621:                    switch (ch)
        !           622:                      {
        !           623:                      case '.':
        !           624:                        /* Terminate the connection. */
        !           625:                        sprintf(buf, "%c.\r\n", escape_char);
        !           626:                        buffer_append(&stderr_buffer, buf, strlen(buf));
        !           627:                        stderr_bytes += strlen(buf);
        !           628:                        quit_pending = 1;
        !           629:                        return;
        !           630:
        !           631:                      case 'Z' - 64:
        !           632:                          /* Suspend the program. */
        !           633:                          /* Print a message to that effect to the user. */
        !           634:                          sprintf(buf, "%c^Z\r\n", escape_char);
        !           635:                          buffer_append(&stderr_buffer, buf, strlen(buf));
        !           636:                          stderr_bytes += strlen(buf);
        !           637:
        !           638:                          /* Restore terminal modes and suspend. */
        !           639:                          client_suspend_self();
        !           640:
        !           641:                          /* We have been continued. */
        !           642:                          continue;
        !           643:
        !           644:                      case '&':
        !           645:                        /* Detach the program (continue to serve connections,
        !           646:                           but put in background and no more new
        !           647:                           connections). */
        !           648:                        if (!stdin_eof)
        !           649:                          {
        !           650:                            /* Sending SSH_CMSG_EOF alone does not always
        !           651:                               appear to be enough.  So we try to send an
        !           652:                               EOF character first. */
        !           653:                            packet_start(SSH_CMSG_STDIN_DATA);
        !           654:                            packet_put_string("\004", 1);
        !           655:                            packet_send();
        !           656:                            /* Close stdin. */
        !           657:                            stdin_eof = 1;
        !           658:                            if (buffer_len(&stdin_buffer) == 0)
        !           659:                              {
        !           660:                                packet_start(SSH_CMSG_EOF);
        !           661:                                packet_send();
        !           662:                              }
        !           663:                          }
        !           664:                        /* Restore tty modes. */
        !           665:                        leave_raw_mode();
        !           666:
        !           667:                        /* Stop listening for new connections. */
        !           668:                        channel_stop_listening();
        !           669:
        !           670:                        printf("%c& [backgrounded]\n", escape_char);
        !           671:
        !           672:                        /* Fork into background. */
        !           673:                        pid = fork();
        !           674:                        if (pid < 0)
        !           675:                          {
        !           676:                            error("fork: %.100s", strerror(errno));
        !           677:                            continue;
        !           678:                          }
        !           679:                        if (pid != 0)
        !           680:                          { /* This is the parent. */
        !           681:                            /* The parent just exits. */
        !           682:                            exit(0);
        !           683:                          }
        !           684:
        !           685:                        /* The child continues serving connections. */
        !           686:                        continue;
        !           687:
        !           688:                      case '?':
        !           689:                        sprintf(buf, "%c?\r\n\
        !           690: Supported escape sequences:\r\n\
        !           691: ~.  - terminate connection\r\n\
        !           692: ~^Z - suspend ssh\r\n\
        !           693: ~#  - list forwarded connections\r\n\
        !           694: ~&  - background ssh (when waiting for connections to terminate)\r\n\
        !           695: ~?  - this message\r\n\
        !           696: ~~  - send the escape character by typing it twice\r\n\
        !           697: (Note that escapes are only recognized immediately after newline.)\r\n",
        !           698:                                escape_char);
        !           699:                        buffer_append(&stderr_buffer, buf, strlen(buf));
        !           700:                        continue;
        !           701:
        !           702:                      case '#':
        !           703:                        sprintf(buf, "%c#\r\n", escape_char);
        !           704:                        buffer_append(&stderr_buffer, buf, strlen(buf));
        !           705:                        s = channel_open_message();
        !           706:                        buffer_append(&stderr_buffer, s, strlen(s));
        !           707:                        xfree(s);
        !           708:                        continue;
        !           709:
        !           710:                      default:
        !           711:                        if (ch != escape_char)
        !           712:                          {
        !           713:                            /* Escape character followed by non-special
        !           714:                               character.  Append both to the input
        !           715:                               buffer. */
        !           716:                            buf[0] = escape_char;
        !           717:                            buf[1] = ch;
        !           718:                            buffer_append(&stdin_buffer, buf, 2);
        !           719:                            stdin_bytes += 2;
        !           720:                            continue;
        !           721:                          }
        !           722:                        /* Note that escape character typed twice falls through
        !           723:                           here; the latter gets processed as a normal
        !           724:                           character below. */
        !           725:                        break;
        !           726:                      }
        !           727:                  }
        !           728:                else
        !           729:                  {
        !           730:                    /* The previous character was not an escape char.
        !           731:                       Check if this is an escape. */
        !           732:                    if (last_was_cr && ch == escape_char)
        !           733:                      {
        !           734:                        /* It is. Set the flag and continue to next
        !           735:                           character. */
        !           736:                        escape_pending = 1;
        !           737:                        continue;
        !           738:                      }
        !           739:                  }
        !           740:
        !           741:                /* Normal character.  Record whether it was a newline,
        !           742:                   and append it to the buffer. */
        !           743:                last_was_cr = (ch == '\r' || ch == '\n');
        !           744:                buf[0] = ch;
        !           745:                buffer_append(&stdin_buffer, buf, 1);
        !           746:                stdin_bytes += 1;
        !           747:                continue;
        !           748:              }
        !           749:          }
        !           750:     }
        !           751: }
        !           752:
        !           753: void client_process_output(fd_set *writeset)
        !           754: {
        !           755:   int len;
        !           756:   char buf[100];
        !           757:
        !           758:   /* Write buffered output to stdout. */
        !           759:   if (FD_ISSET(fileno(stdout), writeset))
        !           760:     {
        !           761:       /* Write as much data as possible. */
        !           762:       len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
        !           763:                  buffer_len(&stdout_buffer));
        !           764:       if (len <= 0)
        !           765:        {
        !           766:          if (errno == EAGAIN)
        !           767:            len = 0;
        !           768:          else
        !           769:            {
        !           770:              /* An error or EOF was encountered.  Put an error message
        !           771:                 to stderr buffer. */
        !           772:              sprintf(buf, "write stdout: %.50s\r\n", strerror(errno));
        !           773:              buffer_append(&stderr_buffer, buf, strlen(buf));
        !           774:              stderr_bytes += strlen(buf);
        !           775:              quit_pending = 1;
        !           776:              return;
        !           777:            }
        !           778:        }
        !           779:       /* Consume printed data from the buffer. */
        !           780:       buffer_consume(&stdout_buffer, len);
        !           781:     }
        !           782:
        !           783:   /* Write buffered output to stderr. */
        !           784:   if (FD_ISSET(fileno(stderr), writeset))
        !           785:     {
        !           786:       /* Write as much data as possible. */
        !           787:       len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
        !           788:                  buffer_len(&stderr_buffer));
        !           789:       if (len <= 0)
        !           790:        if (errno == EAGAIN)
        !           791:          len = 0;
        !           792:        else
        !           793:          {
        !           794:            /* EOF or error, but can't even print error message. */
        !           795:            quit_pending = 1;
        !           796:            return;
        !           797:          }
        !           798:       /* Consume printed characters from the buffer. */
        !           799:       buffer_consume(&stderr_buffer, len);
        !           800:     }
        !           801: }
        !           802:
        !           803: /* Implements the interactive session with the server.  This is called
        !           804:    after the user has been authenticated, and a command has been
        !           805:    started on the remote host.  If escape_char != -1, it is the character
        !           806:    used as an escape character for terminating or suspending the
        !           807:    session. */
        !           808:
        !           809: int client_loop(int have_pty, int escape_char_arg)
        !           810: {
        !           811:   double start_time, total_time;
        !           812:   int len;
        !           813:   char buf[100];
        !           814:
        !           815:   debug("Entering interactive session.");
        !           816:
        !           817:   start_time = get_current_time();
        !           818:
        !           819:   /* Initialize variables. */
        !           820:   escape_pending = 0;
        !           821:   last_was_cr = 1;
        !           822:   exit_status = -1;
        !           823:   stdin_eof = 0;
        !           824:   buffer_high = 64 * 1024;
        !           825:   connection_in = packet_get_connection_in();
        !           826:   connection_out = packet_get_connection_out();
        !           827:   max_fd = connection_in;
        !           828:   if (connection_out > max_fd)
        !           829:     max_fd = connection_out;
        !           830:   stdin_bytes = 0;
        !           831:   stdout_bytes = 0;
        !           832:   stderr_bytes = 0;
        !           833:   quit_pending = 0;
        !           834:   escape_char = escape_char_arg;
        !           835:
        !           836:   /* Initialize buffers. */
        !           837:   buffer_init(&stdin_buffer);
        !           838:   buffer_init(&stdout_buffer);
        !           839:   buffer_init(&stderr_buffer);
        !           840:
        !           841:   /* Set signal handlers to restore non-blocking mode.  */
        !           842:   signal(SIGINT, signal_handler);
        !           843:   signal(SIGQUIT, signal_handler);
        !           844:   signal(SIGTERM, signal_handler);
        !           845:   signal(SIGPIPE, SIG_IGN);
        !           846: #ifdef SIGWINCH
        !           847:   if (have_pty)
        !           848:     signal(SIGWINCH, window_change_handler);
        !           849: #endif /* SIGWINCH */
        !           850:
        !           851:   /* Enter raw mode if have a pseudo terminal. */
        !           852:   if (have_pty)
        !           853:     enter_raw_mode();
        !           854:
        !           855:   /* Check if we should immediately send of on stdin. */
        !           856:   client_check_initial_eof_on_stdin();
        !           857:
        !           858:   /* Main loop of the client for the interactive session mode. */
        !           859:   while (!quit_pending)
        !           860:     {
        !           861:       fd_set readset, writeset;
        !           862:
        !           863:       /* Precess buffered packets sent by the server. */
        !           864:       client_process_buffered_input_packets();
        !           865:
        !           866:       /* Make packets of buffered stdin data, and buffer them for sending
        !           867:         to the server. */
        !           868:       client_make_packets_from_stdin_data();
        !           869:
        !           870:       /* Make packets from buffered channel data, and buffer them for sending
        !           871:         to the server. */
        !           872:       if (packet_not_very_much_data_to_write())
        !           873:        channel_output_poll();
        !           874:
        !           875:       /* Check if the window size has changed, and buffer a message about
        !           876:         it to the server if so. */
        !           877:       client_check_window_change();
        !           878:
        !           879:       if (quit_pending)
        !           880:        break;
        !           881:
        !           882:       /* Wait until we have something to do (something becomes available
        !           883:         on one of the descriptors). */
        !           884:       client_wait_until_can_do_something(&readset, &writeset);
        !           885:
        !           886:       if (quit_pending)
        !           887:        break;
        !           888:
        !           889:       /* Do channel operations. */
        !           890:       channel_after_select(&readset, &writeset);
        !           891:
        !           892:       /* Process input from the connection and from stdin.  Buffer any data
        !           893:          that is available. */
        !           894:       client_process_input(&readset);
        !           895:
        !           896:       /* Process output to stdout and stderr.   Output to the connection
        !           897:          is processed elsewhere (above). */
        !           898:       client_process_output(&writeset);
        !           899:
        !           900:       /* Send as much buffered packet data as possible to the sender. */
        !           901:       if (FD_ISSET(connection_out, &writeset))
        !           902:        packet_write_poll();
        !           903:     }
        !           904:
        !           905:   /* Terminate the session. */
        !           906:
        !           907: #ifdef SIGWINCH
        !           908:   /* Stop watching for window change. */
        !           909:   if (have_pty)
        !           910:     signal(SIGWINCH, SIG_DFL);
        !           911: #endif /* SIGWINCH */
        !           912:
        !           913:   /* Stop listening for connections. */
        !           914:   channel_stop_listening();
        !           915:
        !           916:   /* In interactive mode (with pseudo tty) display a message indicating that
        !           917:      the connection has been closed. */
        !           918:   if (have_pty && !quiet_flag)
        !           919:     {
        !           920:       sprintf(buf, "Connection to %.64s closed.\r\n", host);
        !           921:       buffer_append(&stderr_buffer, buf, strlen(buf));
        !           922:       stderr_bytes += strlen(buf);
        !           923:     }
        !           924:
        !           925:   /* Output any buffered data for stdout. */
        !           926:   while (buffer_len(&stdout_buffer) > 0)
        !           927:     {
        !           928:       len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
        !           929:                  buffer_len(&stdout_buffer));
        !           930:       if (len <= 0)
        !           931:        {
        !           932:          error("Write failed flushing stdout buffer.");
        !           933:          break;
        !           934:        }
        !           935:       buffer_consume(&stdout_buffer, len);
        !           936:     }
        !           937:
        !           938:   /* Output any buffered data for stderr. */
        !           939:   while (buffer_len(&stderr_buffer) > 0)
        !           940:     {
        !           941:       len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
        !           942:                  buffer_len(&stderr_buffer));
        !           943:       if (len <= 0)
        !           944:        {
        !           945:          error("Write failed flushing stderr buffer.");
        !           946:          break;
        !           947:        }
        !           948:       buffer_consume(&stderr_buffer, len);
        !           949:     }
        !           950:
        !           951:   /* Leave raw mode. */
        !           952:   if (have_pty)
        !           953:     leave_raw_mode();
        !           954:
        !           955:   /* Clear and free any buffers. */
        !           956:   memset(buf, 0, sizeof(buf));
        !           957:   buffer_free(&stdin_buffer);
        !           958:   buffer_free(&stdout_buffer);
        !           959:   buffer_free(&stderr_buffer);
        !           960:
        !           961:   /* Report bytes transferred, and transfer rates. */
        !           962:   total_time = get_current_time() - start_time;
        !           963:   debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds",
        !           964:        stdin_bytes, stdout_bytes, stderr_bytes, total_time);
        !           965:   if (total_time > 0)
        !           966:     debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f",
        !           967:          stdin_bytes / total_time, stdout_bytes / total_time,
        !           968:          stderr_bytes / total_time);
        !           969:
        !           970:   /* Return the exit status of the program. */
        !           971:   debug("Exit status %d", exit_status);
        !           972:   return exit_status;
        !           973: }