mirror of
git://projects.qi-hardware.com/wernermisc.git
synced 2024-11-15 10:10:39 +02:00
neocon.c: copyright update and whitespace cleanup
Now conforms to Linux kernel style.
This commit is contained in:
parent
7d0683b335
commit
f3e1f925c4
495
neocon/neocon.c
495
neocon/neocon.c
@ -2,7 +2,8 @@
|
|||||||
* neocon.c - An interface for changing tty devices
|
* neocon.c - An interface for changing tty devices
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2008 by OpenMoko, Inc.
|
* Copyright (C) 2007, 2008 by OpenMoko, Inc.
|
||||||
* Written by Werner Almesberger <werner@openmoko.org>
|
* Copyright 2011 by Werner Almesberger
|
||||||
|
* Written by Werner Almesberger <werner@almesberger.net>
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -46,86 +47,86 @@ static char escape = '~';
|
|||||||
|
|
||||||
|
|
||||||
static struct bps {
|
static struct bps {
|
||||||
speed_t speed;
|
speed_t speed;
|
||||||
int bps;
|
int bps;
|
||||||
} bps_tab[] = {
|
} bps_tab[] = {
|
||||||
{ B300, 300 },
|
{ B300, 300 },
|
||||||
{ B1200, 1200 },
|
{ B1200, 1200 },
|
||||||
{ B2400, 2400 },
|
{ B2400, 2400 },
|
||||||
{ B9600, 9600 },
|
{ B9600, 9600 },
|
||||||
{ B19200, 19200 },
|
{ B19200, 19200 },
|
||||||
{ B38400, 38400 },
|
{ B38400, 38400 },
|
||||||
{ B115200, 115200 },
|
{ B115200, 115200 },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static speed_t bps_to_speed(int bps)
|
static speed_t bps_to_speed(int bps)
|
||||||
{
|
{
|
||||||
const struct bps *p;
|
const struct bps *p;
|
||||||
|
|
||||||
for (p = bps_tab; p->bps; p++)
|
for (p = bps_tab; p->bps; p++)
|
||||||
if (p->bps == bps)
|
if (p->bps == bps)
|
||||||
return p->speed;
|
return p->speed;
|
||||||
fprintf(stderr, "no such speed: %d bps\n", bps);
|
fprintf(stderr, "no such speed: %d bps\n", bps);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void make_raw(int fd, struct termios *old)
|
static void make_raw(int fd, struct termios *old)
|
||||||
{
|
{
|
||||||
struct termios t;
|
struct termios t;
|
||||||
long flags;
|
long flags;
|
||||||
|
|
||||||
if (tcgetattr(fd, &t) < 0) {
|
if (tcgetattr(fd, &t) < 0) {
|
||||||
perror("tcgetattr");
|
perror("tcgetattr");
|
||||||
exit(1);
|
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) {
|
if (old)
|
||||||
perror("cfsetospeed");
|
*old = t;
|
||||||
exit(1);
|
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)
|
static int open_next_tty(void)
|
||||||
{
|
{
|
||||||
int i, fd = -1;
|
int i, fd = -1;
|
||||||
|
|
||||||
for (i = 0; i != num_ttys; i++) {
|
for (i = 0; i != num_ttys; i++) {
|
||||||
curr_tty = (curr_tty+1) % num_ttys;
|
curr_tty = (curr_tty+1) % num_ttys;
|
||||||
fd = open(ttys[curr_tty], O_RDWR | O_NDELAY);
|
fd = open(ttys[curr_tty], O_RDWR | O_NDELAY);
|
||||||
|
if (fd >= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
break;
|
make_raw(fd, &tty);
|
||||||
}
|
return fd;
|
||||||
if (fd >= 0)
|
|
||||||
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 scan(const char *s, size_t len)
|
||||||
{
|
{
|
||||||
static int state = 0;
|
static int state = 0;
|
||||||
const char *p;
|
const char *p;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
for (p = s; p != s+len; p++)
|
for (p = s; p != s+len; p++)
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 0:
|
case 0:
|
||||||
if (*p == escape)
|
if (*p == escape)
|
||||||
state++;
|
state++;
|
||||||
else
|
else
|
||||||
state = 0;
|
state = 0;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (*p == '.')
|
if (*p == '.')
|
||||||
exit(0);
|
exit(0);
|
||||||
if (*p == 'n')
|
if (*p == 'n')
|
||||||
res = 1;
|
res = 1;
|
||||||
state = 0;
|
state = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int write_log(const char *buf, ssize_t len)
|
static int write_log(const char *buf, ssize_t len)
|
||||||
{
|
{
|
||||||
size_t wrote;
|
size_t wrote;
|
||||||
|
|
||||||
wrote = fwrite(buf, 1, len, log);
|
wrote = fwrite(buf, 1, len, log);
|
||||||
if (wrote == len)
|
if (wrote == len)
|
||||||
return 1;
|
return 1;
|
||||||
fprintf(stderr, "write failed. closing log file.\n");
|
fprintf(stderr, "write failed. closing log file.\n");
|
||||||
fclose(log);
|
fclose(log);
|
||||||
log = NULL;
|
log = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int add_timestamp(void)
|
static int add_timestamp(void)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
char buf[40]; /* be generous */
|
char buf[40]; /* be generous */
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (gettimeofday(&tv, NULL) < 0) {
|
if (gettimeofday(&tv, NULL) < 0) {
|
||||||
perror("gettimeofday");
|
perror("gettimeofday");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
len = sprintf(buf, "%lu.%06lu ",
|
len = sprintf(buf, "%lu.%06lu ",
|
||||||
(unsigned long) tv.tv_sec, (unsigned long) tv.tv_usec);
|
(unsigned long) tv.tv_sec, (unsigned long) tv.tv_usec);
|
||||||
return write_log(buf, len);
|
return write_log(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void do_log(const char *buf, ssize_t len)
|
static void do_log(const char *buf, ssize_t len)
|
||||||
{
|
{
|
||||||
static int nl = 1; /* we're at the beginning of a new line */
|
static int nl = 1; /* we're at the beginning of a new line */
|
||||||
char tmp[MAX_BUF];
|
char tmp[MAX_BUF];
|
||||||
const char *from;
|
const char *from;
|
||||||
char *to;
|
char *to;
|
||||||
|
|
||||||
assert(len <= MAX_BUF);
|
assert(len <= MAX_BUF);
|
||||||
from = buf;
|
from = buf;
|
||||||
to = tmp;
|
to = tmp;
|
||||||
while (from != buf+len) {
|
while (from != buf+len) {
|
||||||
if (*from == '\r') {
|
if (*from == '\r') {
|
||||||
from++;
|
from++;
|
||||||
continue;
|
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)
|
write_log(tmp, to-tmp);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int copy(int in, int out, int from_user, int single)
|
static int copy(int in, int out, int from_user, int single)
|
||||||
{
|
{
|
||||||
char buffer[MAX_BUF];
|
char buffer[MAX_BUF];
|
||||||
ssize_t got, wrote, pos;
|
ssize_t got, wrote, pos;
|
||||||
|
|
||||||
got = read(in, buffer, single ? 1 : sizeof(buffer));
|
got = read(in, buffer, single ? 1 : sizeof(buffer));
|
||||||
if (got <= 0)
|
if (got <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (from_user) {
|
if (from_user) {
|
||||||
if (scan(buffer, got))
|
if (scan(buffer, got))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else {
|
||||||
else {
|
if (log)
|
||||||
if (log)
|
do_log(buffer, got);
|
||||||
do_log(buffer, got);
|
}
|
||||||
}
|
for (pos = 0; pos != got; pos += wrote) {
|
||||||
for (pos = 0; pos != got; pos += wrote) {
|
wrote = write(out, buffer+pos, got-pos);
|
||||||
wrote = write(out, buffer+pos, got-pos);
|
if (wrote < 0)
|
||||||
if (wrote < 0)
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
return 1;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void write_string(const char *s)
|
static void write_string(const char *s)
|
||||||
{
|
{
|
||||||
int len = strlen(s);
|
int len = strlen(s);
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
ssize_t wrote;
|
ssize_t wrote;
|
||||||
|
|
||||||
wrote = write(1, s, len);
|
wrote = write(1, s, len);
|
||||||
if (wrote < 0) {
|
if (wrote < 0) {
|
||||||
perror("write");
|
perror("write");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
}
|
||||||
|
s += wrote;
|
||||||
|
len -= wrote;
|
||||||
}
|
}
|
||||||
s += wrote;
|
|
||||||
len -= wrote;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void cleanup(void)
|
static void cleanup(void)
|
||||||
{
|
{
|
||||||
if (tcsetattr(0, TCSANOW, &console) < 0)
|
if (tcsetattr(0, TCSANOW, &console) < 0)
|
||||||
perror("tcsetattr");
|
perror("tcsetattr");
|
||||||
write(1, "\n", 1);
|
write(1, "\n", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void usage(const char *name)
|
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"
|
"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"
|
" -a append to the log file if it already exists\n"
|
||||||
" -b bps set the TTY to the specified bit rate\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"
|
" -l logfile log all output to the specified file\n"
|
||||||
" -t delay_ms wait the specified amount of time between input characters\n"
|
" -t delay_ms wait the specified amount of time between input characters\n"
|
||||||
" -T add timestamps to the log file\n"
|
" -T add timestamps to the log file\n"
|
||||||
, name);
|
, name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *const *argv)
|
int main(int argc, char *const *argv)
|
||||||
{
|
{
|
||||||
char *end;
|
char *end;
|
||||||
int c, bps;
|
int c, bps;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
int append = 0;
|
int append = 0;
|
||||||
const char *logfile = NULL;
|
const char *logfile = NULL;
|
||||||
int throttle_us = 0;
|
int throttle_us = 0;
|
||||||
int throttle = 0;
|
int throttle = 0;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "ab:e:l:t:T")) != EOF)
|
while ((c = getopt(argc, argv, "ab:e:l:t:T")) != EOF)
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'a':
|
case 'a':
|
||||||
append = 1;
|
append = 1;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
bps = strtoul(optarg, &end, 0);
|
bps = strtoul(optarg, &end, 0);
|
||||||
if (*end)
|
if (*end)
|
||||||
usage(*argv);
|
usage(*argv);
|
||||||
speed = bps_to_speed(bps);
|
speed = bps_to_speed(bps);
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
if (strlen(optarg) != 1)
|
if (strlen(optarg) != 1)
|
||||||
usage(*argv);
|
usage(*argv);
|
||||||
escape = *optarg;
|
escape = *optarg;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
logfile = optarg;
|
logfile = optarg;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
throttle_us = strtoul(optarg, &end, 0)*1000;
|
throttle_us = strtoul(optarg, &end, 0)*1000;
|
||||||
if (*end)
|
if (*end)
|
||||||
usage(*argv);
|
usage(*argv);
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
timestamp = 1;
|
timestamp = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage(*argv);
|
usage(*argv);
|
||||||
}
|
}
|
||||||
num_ttys = argc-optind;
|
num_ttys = argc-optind;
|
||||||
ttys = argv+optind;
|
ttys = argv+optind;
|
||||||
|
|
||||||
if (logfile) {
|
if (logfile) {
|
||||||
log = fopen(logfile, append ? "a" : "w");
|
log = fopen(logfile, append ? "a" : "w");
|
||||||
if (!log) {
|
if (!log) {
|
||||||
perror(logfile);
|
perror(logfile);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
}
|
||||||
|
setlinebuf(log);
|
||||||
}
|
}
|
||||||
setlinebuf(log);
|
|
||||||
}
|
|
||||||
|
|
||||||
make_raw(0, &console);
|
make_raw(0, &console);
|
||||||
atexit(cleanup);
|
atexit(cleanup);
|
||||||
while (1) {
|
while (1) {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
fd_set set;
|
fd_set set;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fd = open_next_tty();
|
fd = open_next_tty();
|
||||||
if (fd > 0) {
|
if (fd > 0) {
|
||||||
char buf[1024]; /* enough :-) */
|
char buf[1024]; /* enough :-) */
|
||||||
|
|
||||||
sprintf(buf, "\r\r[Open %s]\r\n", ttys[curr_tty]);
|
sprintf(buf, "\r\r[Open %s]\r\n",
|
||||||
write_string(buf);
|
ttys[curr_tty]);
|
||||||
}
|
write_string(buf);
|
||||||
}
|
}
|
||||||
FD_ZERO(&set);
|
}
|
||||||
if (!throttle)
|
FD_ZERO(&set);
|
||||||
FD_SET(0, &set);
|
if (!throttle)
|
||||||
if (fd >= 0)
|
FD_SET(0, &set);
|
||||||
FD_SET(fd, &set);
|
if (fd >= 0)
|
||||||
tv.tv_sec = 0;
|
FD_SET(fd, &set);
|
||||||
tv.tv_usec = throttle ? throttle_us : 100000;
|
tv.tv_sec = 0;
|
||||||
res = select(fd < 0 ? 1 : fd+1, &set, NULL, NULL, &tv);
|
tv.tv_usec = throttle ? throttle_us : 100000;
|
||||||
if (res < 0) {
|
res = select(fd < 0 ? 1 : fd+1, &set, NULL, NULL, &tv);
|
||||||
perror("select");
|
if (res < 0) {
|
||||||
return 1;
|
perror("select");
|
||||||
}
|
return 1;
|
||||||
if (!res)
|
}
|
||||||
throttle = 0;
|
if (!res)
|
||||||
if (FD_ISSET(0, &set)) {
|
throttle = 0;
|
||||||
if (throttle_us)
|
if (FD_ISSET(0, &set)) {
|
||||||
throttle = 1;
|
if (throttle_us)
|
||||||
if (!copy(0, fd, 1, throttle_us != 0))
|
throttle = 1;
|
||||||
goto failed;
|
if (!copy(0, fd, 1, throttle_us != 0))
|
||||||
}
|
goto failed;
|
||||||
if (fd >= 0 && FD_ISSET(fd, &set))
|
}
|
||||||
if (!copy(fd, 1, 0, 0))
|
if (fd >= 0 && FD_ISSET(fd, &set))
|
||||||
goto failed;
|
if (!copy(fd, 1, 0, 0))
|
||||||
continue;
|
goto failed;
|
||||||
|
continue;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
write_string("\r\n[Closed]\r\n");
|
write_string("\r\n[Closed]\r\n");
|
||||||
(void) close(fd);
|
(void) close(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user