Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'UNIX/UXSER.C')
-rw-r--r--UNIX/UXSER.C595
1 files changed, 0 insertions, 595 deletions
diff --git a/UNIX/UXSER.C b/UNIX/UXSER.C
deleted file mode 100644
index d4a1e0ba..00000000
--- a/UNIX/UXSER.C
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- * Serial back end (Unix-specific).
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <limits.h>
-
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <termios.h>
-
-#include "putty.h"
-#include "tree234.h"
-
-#define SERIAL_MAX_BACKLOG 4096
-
-typedef struct Serial Serial;
-struct Serial {
- Seat *seat;
- LogContext *logctx;
- int fd;
- bool finished;
- size_t inbufsize;
- bufchain output_data;
- Backend backend;
-};
-
-/*
- * We store our serial backends in a tree sorted by fd, so that
- * when we get an uxsel notification we know which backend instance
- * is the owner of the serial port that caused it.
- */
-static int serial_compare_by_fd(void *av, void *bv)
-{
- Serial *a = (Serial *)av;
- Serial *b = (Serial *)bv;
-
- if (a->fd < b->fd)
- return -1;
- else if (a->fd > b->fd)
- return +1;
- return 0;
-}
-
-static int serial_find_by_fd(void *av, void *bv)
-{
- int a = *(int *)av;
- Serial *b = (Serial *)bv;
-
- if (a < b->fd)
- return -1;
- else if (a > b->fd)
- return +1;
- return 0;
-}
-
-static tree234 *serial_by_fd = NULL;
-
-static void serial_select_result(int fd, int event);
-static void serial_uxsel_setup(Serial *serial);
-static void serial_try_write(Serial *serial);
-
-static char *serial_configure(Serial *serial, Conf *conf)
-{
- struct termios options;
- int bflag, bval, speed, flow, parity;
- const char *str;
-
- if (serial->fd < 0)
- return dupstr("Unable to reconfigure already-closed "
- "serial connection");
-
- tcgetattr(serial->fd, &options);
-
- /*
- * Find the appropriate baud rate flag.
- */
- speed = conf_get_int(conf, CONF_serspeed);
-#define SETBAUD(x) (bflag = B ## x, bval = x)
-#define CHECKBAUD(x) do { if (speed >= x) SETBAUD(x); } while (0)
- SETBAUD(50);
-#ifdef B75
- CHECKBAUD(75);
-#endif
-#ifdef B110
- CHECKBAUD(110);
-#endif
-#ifdef B134
- CHECKBAUD(134);
-#endif
-#ifdef B150
- CHECKBAUD(150);
-#endif
-#ifdef B200
- CHECKBAUD(200);
-#endif
-#ifdef B300
- CHECKBAUD(300);
-#endif
-#ifdef B600
- CHECKBAUD(600);
-#endif
-#ifdef B1200
- CHECKBAUD(1200);
-#endif
-#ifdef B1800
- CHECKBAUD(1800);
-#endif
-#ifdef B2400
- CHECKBAUD(2400);
-#endif
-#ifdef B4800
- CHECKBAUD(4800);
-#endif
-#ifdef B9600
- CHECKBAUD(9600);
-#endif
-#ifdef B19200
- CHECKBAUD(19200);
-#endif
-#ifdef B38400
- CHECKBAUD(38400);
-#endif
-#ifdef B57600
- CHECKBAUD(57600);
-#endif
-#ifdef B76800
- CHECKBAUD(76800);
-#endif
-#ifdef B115200
- CHECKBAUD(115200);
-#endif
-#ifdef B153600
- CHECKBAUD(153600);
-#endif
-#ifdef B230400
- CHECKBAUD(230400);
-#endif
-#ifdef B307200
- CHECKBAUD(307200);
-#endif
-#ifdef B460800
- CHECKBAUD(460800);
-#endif
-#ifdef B500000
- CHECKBAUD(500000);
-#endif
-#ifdef B576000
- CHECKBAUD(576000);
-#endif
-#ifdef B921600
- CHECKBAUD(921600);
-#endif
-#ifdef B1000000
- CHECKBAUD(1000000);
-#endif
-#ifdef B1152000
- CHECKBAUD(1152000);
-#endif
-#ifdef B1500000
- CHECKBAUD(1500000);
-#endif
-#ifdef B2000000
- CHECKBAUD(2000000);
-#endif
-#ifdef B2500000
- CHECKBAUD(2500000);
-#endif
-#ifdef B3000000
- CHECKBAUD(3000000);
-#endif
-#ifdef B3500000
- CHECKBAUD(3500000);
-#endif
-#ifdef B4000000
- CHECKBAUD(4000000);
-#endif
-#undef CHECKBAUD
-#undef SETBAUD
- cfsetispeed(&options, bflag);
- cfsetospeed(&options, bflag);
- logeventf(serial->logctx, "Configuring baud rate %d", bval);
-
- options.c_cflag &= ~CSIZE;
- switch (conf_get_int(conf, CONF_serdatabits)) {
- case 5: options.c_cflag |= CS5; break;
- case 6: options.c_cflag |= CS6; break;
- case 7: options.c_cflag |= CS7; break;
- case 8: options.c_cflag |= CS8; break;
- default: return dupstr("Invalid number of data bits "
- "(need 5, 6, 7 or 8)");
- }
- logeventf(serial->logctx, "Configuring %d data bits",
- conf_get_int(conf, CONF_serdatabits));
-
- if (conf_get_int(conf, CONF_serstopbits) >= 4) {
- options.c_cflag |= CSTOPB;
- } else {
- options.c_cflag &= ~CSTOPB;
- }
- logeventf(serial->logctx, "Configuring %s",
- (options.c_cflag & CSTOPB ? "2 stop bits" : "1 stop bit"));
-
- options.c_iflag &= ~(IXON|IXOFF);
-#ifdef CRTSCTS
- options.c_cflag &= ~CRTSCTS;
-#endif
-#ifdef CNEW_RTSCTS
- options.c_cflag &= ~CNEW_RTSCTS;
-#endif
- flow = conf_get_int(conf, CONF_serflow);
- if (flow == SER_FLOW_XONXOFF) {
- options.c_iflag |= IXON | IXOFF;
- str = "XON/XOFF";
- } else if (flow == SER_FLOW_RTSCTS) {
-#ifdef CRTSCTS
- options.c_cflag |= CRTSCTS;
-#endif
-#ifdef CNEW_RTSCTS
- options.c_cflag |= CNEW_RTSCTS;
-#endif
- str = "RTS/CTS";
- } else
- str = "no";
- logeventf(serial->logctx, "Configuring %s flow control", str);
-
- /* Parity */
- parity = conf_get_int(conf, CONF_serparity);
- if (parity == SER_PAR_ODD) {
- options.c_cflag |= PARENB;
- options.c_cflag |= PARODD;
- str = "odd";
- } else if (parity == SER_PAR_EVEN) {
- options.c_cflag |= PARENB;
- options.c_cflag &= ~PARODD;
- str = "even";
- } else {
- options.c_cflag &= ~PARENB;
- str = "no";
- }
- logeventf(serial->logctx, "Configuring %s parity", str);
-
- options.c_cflag |= CLOCAL | CREAD;
- options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
- options.c_iflag &= ~(ISTRIP | IGNCR | INLCR | ICRNL
-#ifdef IUCLC
- | IUCLC
-#endif
- );
- options.c_oflag &= ~(OPOST
-#ifdef ONLCR
- | ONLCR
-#endif
-#ifdef OCRNL
- | OCRNL
-#endif
-#ifdef ONOCR
- | ONOCR
-#endif
-#ifdef ONLRET
- | ONLRET
-#endif
- );
- options.c_cc[VMIN] = 1;
- options.c_cc[VTIME] = 0;
-
- if (tcsetattr(serial->fd, TCSANOW, &options) < 0)
- return dupprintf("Configuring serial port: %s", strerror(errno));
-
- return NULL;
-}
-
-/*
- * Called to set up the serial connection.
- *
- * Returns an error message, or NULL on success.
- *
- * Also places the canonical host name into `realhost'. It must be
- * freed by the caller.
- */
-static char *serial_init(const BackendVtable *vt, Seat *seat,
- Backend **backend_handle, LogContext *logctx,
- Conf *conf, const char *host, int port,
- char **realhost, bool nodelay, bool keepalive)
-{
- Serial *serial;
- char *err;
- char *line;
-
- /* No local authentication phase in this protocol */
- seat_set_trust_status(seat, false);
-
- serial = snew(Serial);
- serial->backend.vt = vt;
- *backend_handle = &serial->backend;
-
- serial->seat = seat;
- serial->logctx = logctx;
- serial->finished = false;
- serial->inbufsize = 0;
- bufchain_init(&serial->output_data);
-
- line = conf_get_str(conf, CONF_serline);
- logeventf(serial->logctx, "Opening serial device %s", line);
-
- serial->fd = open(line, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
- if (serial->fd < 0)
- return dupprintf("Opening serial port '%s': %s",
- line, strerror(errno));
-
- cloexec(serial->fd);
-
- err = serial_configure(serial, conf);
- if (err)
- return err;
-
- *realhost = dupstr(line);
-
- if (!serial_by_fd)
- serial_by_fd = newtree234(serial_compare_by_fd);
- add234(serial_by_fd, serial);
-
- serial_uxsel_setup(serial);
-
- /*
- * Specials are always available.
- */
- seat_update_specials_menu(serial->seat);
-
- return NULL;
-}
-
-static void serial_close(Serial *serial)
-{
- if (serial->fd >= 0) {
- uxsel_del(serial->fd);
- close(serial->fd);
- serial->fd = -1;
- }
-}
-
-static void serial_free(Backend *be)
-{
- Serial *serial = container_of(be, Serial, backend);
-
- serial_close(serial);
-
- bufchain_clear(&serial->output_data);
-
- sfree(serial);
-}
-
-static void serial_reconfig(Backend *be, Conf *conf)
-{
- Serial *serial = container_of(be, Serial, backend);
-
- char *err = serial_configure(serial, conf);
- if (err) {
- /*
- * FIXME: apart from freeing the dynamically allocated
- * message, what should we do if this returns an error?
- */
- sfree(err);
- }
-}
-
-static void serial_select_result(int fd, int event)
-{
- Serial *serial;
- char buf[4096];
- int ret;
- bool finished = false;
-
- serial = find234(serial_by_fd, &fd, serial_find_by_fd);
-
- if (!serial)
- return; /* spurious event; keep going */
-
- if (event == 1) {
- ret = read(serial->fd, buf, sizeof(buf));
-
- if (ret == 0) {
- /*
- * Shouldn't happen on a real serial port, but I'm open
- * to the idea that there might be two-way devices we
- * can treat _like_ serial ports which can return EOF.
- */
- finished = true;
- } else if (ret < 0) {
-#ifdef EAGAIN
- if (errno == EAGAIN)
- return; /* spurious */
-#endif
-#ifdef EWOULDBLOCK
- if (errno == EWOULDBLOCK)
- return; /* spurious */
-#endif
- perror("read serial port");
- exit(1);
- } else if (ret > 0) {
- serial->inbufsize = seat_stdout(serial->seat, buf, ret);
- serial_uxsel_setup(serial); /* might acquire backlog and freeze */
- }
- } else if (event == 2) {
- /*
- * Attempt to send data down the pty.
- */
- serial_try_write(serial);
- }
-
- if (finished) {
- serial_close(serial);
-
- serial->finished = true;
-
- seat_notify_remote_exit(serial->seat);
- }
-}
-
-static void serial_uxsel_setup(Serial *serial)
-{
- int rwx = 0;
-
- if (serial->inbufsize <= SERIAL_MAX_BACKLOG)
- rwx |= SELECT_R;
- if (bufchain_size(&serial->output_data))
- rwx |= SELECT_W; /* might also want to write to it */
- uxsel_set(serial->fd, rwx, serial_select_result);
-}
-
-static void serial_try_write(Serial *serial)
-{
- ssize_t ret;
-
- assert(serial->fd >= 0);
-
- while (bufchain_size(&serial->output_data) > 0) {
- ptrlen data = bufchain_prefix(&serial->output_data);
- ret = write(serial->fd, data.ptr, data.len);
-
- if (ret < 0 && (errno == EWOULDBLOCK)) {
- /*
- * We've sent all we can for the moment.
- */
- break;
- }
- if (ret < 0) {
- perror("write serial port");
- exit(1);
- }
- bufchain_consume(&serial->output_data, ret);
- }
-
- serial_uxsel_setup(serial);
-}
-
-/*
- * Called to send data down the serial connection.
- */
-static size_t serial_send(Backend *be, const char *buf, size_t len)
-{
- Serial *serial = container_of(be, Serial, backend);
-
- if (serial->fd < 0)
- return 0;
-
- bufchain_add(&serial->output_data, buf, len);
- serial_try_write(serial);
-
- return bufchain_size(&serial->output_data);
-}
-
-/*
- * Called to query the current sendability status.
- */
-static size_t serial_sendbuffer(Backend *be)
-{
- Serial *serial = container_of(be, Serial, backend);
- return bufchain_size(&serial->output_data);
-}
-
-/*
- * Called to set the size of the window
- */
-static void serial_size(Backend *be, int width, int height)
-{
- /* Do nothing! */
- return;
-}
-
-/*
- * Send serial special codes.
- */
-static void serial_special(Backend *be, SessionSpecialCode code, int arg)
-{
- Serial *serial = container_of(be, Serial, backend);
-
- if (serial->fd >= 0 && code == SS_BRK) {
- tcsendbreak(serial->fd, 0);
- logevent(serial->logctx, "Sending serial break at user request");
- }
-
- return;
-}
-
-/*
- * Return a list of the special codes that make sense in this
- * protocol.
- */
-static const SessionSpecial *serial_get_specials(Backend *be)
-{
- static const struct SessionSpecial specials[] = {
- {"Break", SS_BRK},
- {NULL, SS_EXITMENU}
- };
- return specials;
-}
-
-static bool serial_connected(Backend *be)
-{
- return true; /* always connected */
-}
-
-static bool serial_sendok(Backend *be)
-{
- return true;
-}
-
-static void serial_unthrottle(Backend *be, size_t backlog)
-{
- Serial *serial = container_of(be, Serial, backend);
- serial->inbufsize = backlog;
- serial_uxsel_setup(serial);
-}
-
-static bool serial_ldisc(Backend *be, int option)
-{
- /*
- * Local editing and local echo are off by default.
- */
- return false;
-}
-
-static void serial_provide_ldisc(Backend *be, Ldisc *ldisc)
-{
- /* This is a stub. */
-}
-
-static int serial_exitcode(Backend *be)
-{
- Serial *serial = container_of(be, Serial, backend);
- if (serial->fd >= 0)
- return -1; /* still connected */
- else
- /* Exit codes are a meaningless concept with serial ports */
- return INT_MAX;
-}
-
-/*
- * cfg_info for Serial does nothing at all.
- */
-static int serial_cfg_info(Backend *be)
-{
- return 0;
-}
-
-const BackendVtable serial_backend = {
- .init = serial_init,
- .free = serial_free,
- .reconfig = serial_reconfig,
- .send = serial_send,
- .sendbuffer = serial_sendbuffer,
- .size = serial_size,
- .special = serial_special,
- .get_specials = serial_get_specials,
- .connected = serial_connected,
- .exitcode = serial_exitcode,
- .sendok = serial_sendok,
- .ldisc_option_state = serial_ldisc,
- .provide_ldisc = serial_provide_ldisc,
- .unthrottle = serial_unthrottle,
- .cfg_info = serial_cfg_info,
- .id = "serial",
- .displayname = "Serial",
- .protocol = PROT_SERIAL,
- .serial_parity_mask = ((1 << SER_PAR_NONE) |
- (1 << SER_PAR_ODD) |
- (1 << SER_PAR_EVEN)),
- .serial_flow_mask = ((1 << SER_FLOW_NONE) |
- (1 << SER_FLOW_XONXOFF) |
- (1 << SER_FLOW_RTSCTS)),
-};