diff --git a/neocon/neocon.c b/neocon/neocon.c index 6766644..570dacb 100644 --- a/neocon/neocon.c +++ b/neocon/neocon.c @@ -2,7 +2,8 @@ * neocon.c - An interface for changing tty devices * * Copyright (C) 2007, 2008 by OpenMoko, Inc. - * Written by Werner Almesberger + * Copyright 2011 by Werner Almesberger + * Written by Werner Almesberger * All Rights Reserved * * This program is free software; you can redistribute it and/or modify @@ -46,86 +47,86 @@ static char escape = '~'; static struct bps { - speed_t speed; - int bps; + speed_t speed; + int bps; } bps_tab[] = { - { B300, 300 }, - { B1200, 1200 }, - { B2400, 2400 }, - { B9600, 9600 }, - { B19200, 19200 }, - { B38400, 38400 }, - { B115200, 115200 }, - { 0, 0 } + { B300, 300 }, + { B1200, 1200 }, + { B2400, 2400 }, + { B9600, 9600 }, + { B19200, 19200 }, + { B38400, 38400 }, + { B115200, 115200 }, + { 0, 0 } }; static speed_t bps_to_speed(int bps) { - const struct bps *p; + const struct bps *p; - for (p = bps_tab; p->bps; p++) - if (p->bps == bps) - return p->speed; - fprintf(stderr, "no such speed: %d bps\n", bps); - exit(1); + for (p = bps_tab; p->bps; p++) + if (p->bps == bps) + return p->speed; + fprintf(stderr, "no such speed: %d bps\n", bps); + exit(1); } static void make_raw(int fd, struct termios *old) { - struct termios t; - long flags; + struct termios t; + long flags; - if (tcgetattr(fd, &t) < 0) { - perror("tcgetattr"); - exit(1); - } - if (old) - *old = t; - cfmakeraw(&t); - if (fd) { - t.c_iflag &= ~(IXON | IXOFF); - t.c_cflag |= CLOCAL; - t.c_cflag &= ~CRTSCTS; - if (cfsetispeed(&t, speed) < 0) { - perror("cfsetispeed"); - exit(1); + if (tcgetattr(fd, &t) < 0) { + perror("tcgetattr"); + exit(1); } - if (cfsetospeed(&t, speed) < 0) { - perror("cfsetospeed"); - exit(1); + if (old) + *old = t; + cfmakeraw(&t); + if (fd) { + t.c_iflag &= ~(IXON | IXOFF); + t.c_cflag |= CLOCAL; + t.c_cflag &= ~CRTSCTS; + if (cfsetispeed(&t, speed) < 0) { + perror("cfsetispeed"); + exit(1); + } + if (cfsetospeed(&t, speed) < 0) { + perror("cfsetospeed"); + exit(1); + } + } + if (tcsetattr(fd, TCSANOW, &t) < 0) { + perror("tcsetattr"); + exit(1); + } + flags = fcntl(fd, F_GETFL); + if (flags < 0) { + perror("fcntl F_GETFL"); + exit(1); + } + if (fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) < 0) { + perror("fcntl F_GETFL"); + exit(1); } - } - if (tcsetattr(fd, TCSANOW, &t) < 0) { - perror("tcsetattr"); - exit(1); - } - flags = fcntl(fd,F_GETFL); - if (flags < 0) { - perror("fcntl F_GETFL"); - exit(1); - } - if (fcntl(fd,F_SETFL,flags & ~O_NONBLOCK) < 0) { - perror("fcntl F_GETFL"); - exit(1); - } } static int open_next_tty(void) { - int i, fd = -1; + int i, fd = -1; - for (i = 0; i != num_ttys; i++) { - curr_tty = (curr_tty+1) % num_ttys; - fd = open(ttys[curr_tty], O_RDWR | O_NDELAY); + for (i = 0; i != num_ttys; i++) { + curr_tty = (curr_tty+1) % num_ttys; + fd = open(ttys[curr_tty], O_RDWR | O_NDELAY); + if (fd >= 0) + break; + } if (fd >= 0) - break; - } - if (fd >= 0) - make_raw(fd, &tty); - return fd; + make_raw(fd, &tty); + return fd; } @@ -136,148 +137,147 @@ static int open_next_tty(void) static int scan(const char *s, size_t len) { - static int state = 0; - const char *p; - int res = 0; + static int state = 0; + const char *p; + int res = 0; - for (p = s; p != s+len; p++) - switch (state) { - case 0: - if (*p == escape) - state++; - else - state = 0; - break; - case 1: - if (*p == '.') - exit(0); - if (*p == 'n') - res = 1; - state = 0; - break; - } - return res; + for (p = s; p != s+len; p++) + switch (state) { + case 0: + if (*p == escape) + state++; + else + state = 0; + break; + case 1: + if (*p == '.') + exit(0); + if (*p == 'n') + res = 1; + state = 0; + break; + } + return res; } static int write_log(const char *buf, ssize_t len) { - size_t wrote; + size_t wrote; - wrote = fwrite(buf, 1, len, log); - if (wrote == len) - return 1; - fprintf(stderr, "write failed. closing log file.\n"); - fclose(log); - log = NULL; - return 0; + wrote = fwrite(buf, 1, len, log); + if (wrote == len) + return 1; + fprintf(stderr, "write failed. closing log file.\n"); + fclose(log); + log = NULL; + return 0; } static int add_timestamp(void) { - struct timeval tv; - char buf[40]; /* be generous */ - int len; + struct timeval tv; + char buf[40]; /* be generous */ + int len; - if (gettimeofday(&tv, NULL) < 0) { - perror("gettimeofday"); - exit(1); - } - len = sprintf(buf, "%lu.%06lu ", - (unsigned long) tv.tv_sec, (unsigned long) tv.tv_usec); - return write_log(buf, len); + if (gettimeofday(&tv, NULL) < 0) { + perror("gettimeofday"); + exit(1); + } + len = sprintf(buf, "%lu.%06lu ", + (unsigned long) tv.tv_sec, (unsigned long) tv.tv_usec); + return write_log(buf, len); } static void do_log(const char *buf, ssize_t len) { - static int nl = 1; /* we're at the beginning of a new line */ - char tmp[MAX_BUF]; - const char *from; - char *to; + static int nl = 1; /* we're at the beginning of a new line */ + char tmp[MAX_BUF]; + const char *from; + char *to; - assert(len <= MAX_BUF); - from = buf; - to = tmp; - while (from != buf+len) { - if (*from == '\r') { - from++; - continue; + assert(len <= MAX_BUF); + from = buf; + to = tmp; + while (from != buf+len) { + if (*from == '\r') { + from++; + continue; + } + if (nl && timestamp) + if (!add_timestamp()) + return; + nl = 0; + if (*from == '\n') { + *to++ = *from++; + if (!write_log(tmp, to-tmp)) + return; + to = tmp; + nl = 1; + continue; + } + *to++ = *from < ' ' || *from > '~' ? '#' : *from; + from++; } - if (nl && timestamp) - if (!add_timestamp()) - return; - nl = 0; - if (*from == '\n') { - *to++ = *from++; - if (!write_log(tmp, to-tmp)) - return; - to = tmp; - nl = 1; - continue; - } - *to++ = *from < ' ' || *from > '~' ? '#' : *from; - from++; - } - write_log(tmp, to-tmp); + write_log(tmp, to-tmp); } static int copy(int in, int out, int from_user, int single) { - char buffer[MAX_BUF]; - ssize_t got, wrote, pos; + char buffer[MAX_BUF]; + ssize_t got, wrote, pos; - got = read(in, buffer, single ? 1 : sizeof(buffer)); - if (got <= 0) - return 0; - if (from_user) { - if (scan(buffer, got)) - return 0; - } - else { - if (log) - do_log(buffer, got); - } - for (pos = 0; pos != got; pos += wrote) { - wrote = write(out, buffer+pos, got-pos); - if (wrote < 0) - return 0; - } - return 1; + got = read(in, buffer, single ? 1 : sizeof(buffer)); + if (got <= 0) + return 0; + if (from_user) { + if (scan(buffer, got)) + return 0; + } else { + if (log) + do_log(buffer, got); + } + for (pos = 0; pos != got; pos += wrote) { + wrote = write(out, buffer+pos, got-pos); + if (wrote < 0) + return 0; + } + return 1; } static void write_string(const char *s) { - int len = strlen(s); + int len = strlen(s); - while (len) { - ssize_t wrote; + while (len) { + ssize_t wrote; - wrote = write(1, s, len); - if (wrote < 0) { - perror("write"); - exit(1); + wrote = write(1, s, len); + if (wrote < 0) { + perror("write"); + exit(1); + } + s += wrote; + len -= wrote; } - s += wrote; - len -= wrote; - } } static void cleanup(void) { - if (tcsetattr(0, TCSANOW, &console) < 0) - perror("tcsetattr"); - write(1, "\n", 1); + if (tcsetattr(0, TCSANOW, &console) < 0) + perror("tcsetattr"); + write(1, "\n", 1); } static void usage(const char *name) { - fprintf(stderr, + fprintf(stderr, "usage: %s [-b bps] [-e escape] [-l logfile [-a] [-T]] [-t delay_ms] tty ...\n\n" " -a append to the log file if it already exists\n" " -b bps set the TTY to the specified bit rate\n" @@ -285,108 +285,109 @@ static void usage(const char *name) " -l logfile log all output to the specified file\n" " -t delay_ms wait the specified amount of time between input characters\n" " -T add timestamps to the log file\n" - , name); - exit(1); + , name); + exit(1); } int main(int argc, char *const *argv) { - char *end; - int c, bps; - int fd = -1; - int append = 0; - const char *logfile = NULL; - int throttle_us = 0; - int throttle = 0; + char *end; + int c, bps; + int fd = -1; + int append = 0; + const char *logfile = NULL; + int throttle_us = 0; + int throttle = 0; - while ((c = getopt(argc, argv, "ab:e:l:t:T")) != EOF) - switch (c) { - case 'a': - append = 1; - break; - case 'b': - bps = strtoul(optarg, &end, 0); - if (*end) - usage(*argv); - speed = bps_to_speed(bps); - break; - case 'e': - if (strlen(optarg) != 1) - usage(*argv); - escape = *optarg; - break; - case 'l': - logfile = optarg; - break; - case 't': - throttle_us = strtoul(optarg, &end, 0)*1000; - if (*end) - usage(*argv); - break; - case 'T': - timestamp = 1; - break; - default: - usage(*argv); + while ((c = getopt(argc, argv, "ab:e:l:t:T")) != EOF) + switch (c) { + case 'a': + append = 1; + break; + case 'b': + bps = strtoul(optarg, &end, 0); + if (*end) + usage(*argv); + speed = bps_to_speed(bps); + break; + case 'e': + if (strlen(optarg) != 1) + usage(*argv); + escape = *optarg; + break; + case 'l': + logfile = optarg; + break; + case 't': + throttle_us = strtoul(optarg, &end, 0)*1000; + if (*end) + usage(*argv); + break; + case 'T': + timestamp = 1; + break; + default: + usage(*argv); } - num_ttys = argc-optind; - ttys = argv+optind; + num_ttys = argc-optind; + ttys = argv+optind; - if (logfile) { - log = fopen(logfile, append ? "a" : "w"); - if (!log) { - perror(logfile); - exit(1); + if (logfile) { + log = fopen(logfile, append ? "a" : "w"); + if (!log) { + perror(logfile); + exit(1); + } + setlinebuf(log); } - setlinebuf(log); - } - make_raw(0, &console); - atexit(cleanup); - while (1) { - struct timeval tv; - fd_set set; - int res; + make_raw(0, &console); + atexit(cleanup); + while (1) { + struct timeval tv; + fd_set set; + int res; - if (fd < 0) { - fd = open_next_tty(); - if (fd > 0) { - char buf[1024]; /* enough :-) */ + if (fd < 0) { + fd = open_next_tty(); + if (fd > 0) { + char buf[1024]; /* enough :-) */ - sprintf(buf, "\r\r[Open %s]\r\n", ttys[curr_tty]); - write_string(buf); - } - } - FD_ZERO(&set); - if (!throttle) - FD_SET(0, &set); - if (fd >= 0) - FD_SET(fd, &set); - tv.tv_sec = 0; - tv.tv_usec = throttle ? throttle_us : 100000; - res = select(fd < 0 ? 1 : fd+1, &set, NULL, NULL, &tv); - if (res < 0) { - perror("select"); - return 1; - } - if (!res) - throttle = 0; - if (FD_ISSET(0, &set)) { - if (throttle_us) - throttle = 1; - if (!copy(0, fd, 1, throttle_us != 0)) - goto failed; - } - if (fd >= 0 && FD_ISSET(fd, &set)) - if (!copy(fd, 1, 0, 0)) - goto failed; - continue; + sprintf(buf, "\r\r[Open %s]\r\n", + ttys[curr_tty]); + write_string(buf); + } + } + FD_ZERO(&set); + if (!throttle) + FD_SET(0, &set); + if (fd >= 0) + FD_SET(fd, &set); + tv.tv_sec = 0; + tv.tv_usec = throttle ? throttle_us : 100000; + res = select(fd < 0 ? 1 : fd+1, &set, NULL, NULL, &tv); + if (res < 0) { + perror("select"); + return 1; + } + if (!res) + throttle = 0; + if (FD_ISSET(0, &set)) { + if (throttle_us) + throttle = 1; + if (!copy(0, fd, 1, throttle_us != 0)) + goto failed; + } + if (fd >= 0 && FD_ISSET(fd, &set)) + if (!copy(fd, 1, 0, 0)) + goto failed; + continue; failed: - write_string("\r\n[Closed]\r\n"); - (void) close(fd); - fd = -1; - } - return 0; + write_string("\r\n[Closed]\r\n"); + (void) close(fd); + fd = -1; + } + return 0; }