📄 tip.c
字号:
/*****************************************************************************/
/*
* tip.c -- simple tip/cu program.
*
* (C) Copyright 1999, Greg Ungerer (gerg@lineo.com).
* (C) Copyright 2000, Lineo Inc. (www.lineo.com)
*
* Modified 5 May 2000, Rick Stevenson.
* Added -f option to pass XON/XOFF characters through
* to remote end.
*/
/*****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <getopt.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/termios.h>
#include <sys/time.h>
#ifndef EMBED
#include <sys/select.h>
#endif
/*****************************************************************************/
char *version = "1.0.0";
/*****************************************************************************/
/*
* Define some parity flags, internal use only.
*/
#define PARITY_NONE 0
#define PARITY_EVEN 1
#define PARITY_ODD 2
/*
* Default port settings.
*/
int clocal = 0;
int hardware = 0;
int software = 0;
int passflow = 0;
int parity = PARITY_NONE;
int databits = 8;
unsigned int baud = 9600;
char *devname;
int gotdevice = 0;
/*
* Working termios settings.
*/
struct termios savetio;
/*
* Temporary buffer to use when working.
*/
unsigned char buf[512];
/*****************************************************************************/
/*
* Baud rate table for baud rate conversions.
*/
typedef struct baudmap {
unsigned int baud;
unsigned int flag;
} baudmap_t;
struct baudmap baudtable[] = {
{ 0, B0 },
{ 50, B50 },
{ 75, B75 },
{ 110, B110 },
{ 134, B134 },
{ 150, B150 },
{ 200, B200 },
{ 300, B300 },
{ 600, B600 },
{ 1200, B1200 },
{ 1800, B1800 },
{ 2400, B2400 },
{ 4800, B4800 },
{ 9600, B9600 },
{ 19200, B19200 },
{ 38400, B38400 },
{ 57600, B57600 },
{ 115200, B115200 },
{ 230400, B230400 },
{ 460800, B460800 }
};
#define NRBAUDS (sizeof(baudtable) / sizeof(struct baudmap))
/*****************************************************************************/
/*
* Verify that the supplied baud rate is valid.
*/
int baud2flag(unsigned int speed)
{
int i;
for (i = 0; (i < NRBAUDS); i++) {
if (speed == baudtable[i].baud)
return(baudtable[i].flag);
}
return(-1);
}
/*****************************************************************************/
void restorelocaltermios()
{
if (tcsetattr(1, TCSAFLUSH, &savetio) < 0) {
fprintf(stderr, "ERROR: ioctl(TCSETA) failed, errno=%d\n",
errno);
exit(0);
}
}
/*****************************************************************************/
void savelocaltermios()
{
if (tcgetattr(1, &savetio) < 0) {
fprintf(stderr, "ERROR: ioctl(TCGETA) failed, errno=%d\n",
errno);
exit(0);
}
}
/*****************************************************************************/
/*
* Set local port to raw mode, no input mappings.
*/
int setlocaltermios()
{
struct termios tio;
if (tcgetattr(1, &tio) < 0) {
fprintf(stderr, "ERROR: ioctl(TCGETA) failed, errno=%d\n",
errno);
exit(1);
}
if (passflow)
tio.c_iflag &= ~(ICRNL|IXON);
else
tio.c_iflag &= ~ICRNL;
tio.c_lflag = 0;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
if (tcsetattr(1, TCSAFLUSH, &tio) < 0) {
fprintf(stderr, "ERROR: ioctl(TCSETA) failed, errno=%d\n",
errno);
exit(1);
}
return(0);
}
/*****************************************************************************/
/*
* Set up remote (connect) port termio settings according to
* user specification.
*/
int setremotetermios(int fd)
{
struct termios tio;
memset(&tio, 0, sizeof(tio));
tio.c_cflag = CREAD | HUPCL | baud2flag(baud);
if (clocal)
tio.c_cflag |= CLOCAL;
switch (parity) {
case PARITY_ODD: tio.c_cflag |= PARENB | PARODD; break;
case PARITY_EVEN: tio.c_cflag |= PARENB; break;
default: break;
}
tio.c_cflag |= ((databits == 7) ? CS7 : CS8);
if (software)
tio.c_iflag |= IXON | IXOFF;
if (hardware)
tio.c_cflag |= CRTSCTS;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSAFLUSH, &tio) < 0) {
fprintf(stderr, "ERROR: ioctl(TCSETS) failed\n");
exit(1);
}
return(0);
}
/*****************************************************************************/
/*
* Do the connection session. Pass data between local and remote
* ports.
*/
int loopit(int fd)
{
fd_set infds;
int maxfd, n;
int partialescape = 0;
maxfd = fd + 1;
for (;;) {
FD_ZERO(&infds);
FD_SET(1, &infds);
FD_SET(fd, &infds);
if (select(maxfd, &infds, NULL, NULL, NULL) < 0) {
fprintf(stderr, "ERROR: select() failed, errno=%d\n",
errno);
exit(1);
}
if (FD_ISSET(fd, &infds)) {
if ((n = read(fd, buf, sizeof(buf))) < 0) {
fprintf(stderr, "ERROR: read(fd=%d) failed, "
"errno=%d\n", fd, errno);
exit(1);
}
if (n == 0)
break;
if (write(1, buf, n) < 0) {
fprintf(stderr, "ERROR: write(fd=%d) failed, "
"errno=%d\n", 1, errno);
exit(1);
}
}
if (FD_ISSET(1, &infds)) {
if ((n = read(1, buf, sizeof(buf))) < 0) {
fprintf(stderr, "ERROR: read(fd=%d) failed, "
"errno=%d\n", 1, errno);
exit(1);
}
if (n == 0)
break;
if ((n == 1) && (buf[0] == 0x1d))
break;
if ((n == 1) && (buf[0] == 0x1))
break;
if (partialescape) {
if (buf[0] == '.')
break;
write(fd, "~", 1);
}
partialescape = ((n == 1) && (buf[0] == '~')) ? 1 : 0;
if (write(fd, buf, n) < 0) {
fprintf(stderr, "ERROR: write(fd=%d) failed, "
"errno=%d\n", fd, errno);
exit(1);
}
}
}
}
/*****************************************************************************/
void usage(FILE *fp, int rc)
{
fprintf(fp, "Usage: tip [-h?eonxrc78] [-s speed] [-l device] "
"[device]\n\n");
fprintf(fp, " -h? this help\n");
fprintf(fp, " -7 7 data bits\n");
fprintf(fp, " -8 8 data bits (default)\n");
fprintf(fp, " -e even parity\n");
fprintf(fp, " -o odd parity\n");
fprintf(fp, " -n no parity (default)\n");
fprintf(fp, " -s baud rate (default 9600)\n");
fprintf(fp, " -c use clocal mode (no disconnect)\n");
fprintf(fp, " -l device to use\n");
fprintf(fp, " -x use software flow (xon/xoff)\n");
fprintf(fp, " -r use hardware flow (rts/cts)\n");
fprintf(fp, " -f pass xon/xoff flow control to remote\n");
exit(rc);
}
/*****************************************************************************/
int main(int argc, char *argv[])
{
int fd, c;
gotdevice = 0;
while ((c = getopt(argc, argv, "eonxrcf78h?s:l:")) > 0) {
switch (c) {
case 'v':
printf("%s: version %s\n", argv[0], version);
exit(0);
case '7':
databits = 7;
break;
case '8':
databits = 8;
break;
case 'r':
hardware++;
break;
case 'x':
software++;
break;
case 'f':
passflow++;
break;
case 'o':
parity = PARITY_ODD;
break;
case 'e':
parity = PARITY_EVEN;
break;
case 'n':
parity = PARITY_NONE;
break;
case 's':
baud = atoi(optarg);
if (baud2flag(baud) < 0) {
fprintf(stderr,
"ERROR: baud speed specified %d\n",
baud);
exit(1);
}
break;
case 'c':
clocal++;
break;
case 'l':
gotdevice++;
devname = optarg;
break;
case 'h':
case '?':
usage(stdout, 0);
break;
default:
fprintf(stderr, "ERROR: unkown option '%c'\n", c);
usage(stderr, 1);
break;
}
}
if ((optind < argc) && (gotdevice == 0)) {
gotdevice++;
devname = argv[optind++];
}
if (gotdevice == 0) {
fprintf(stderr, "ERROR: no device specified\n");
usage(stderr, 1);
}
if (optind < argc) {
fprintf(stderr, "ERROR: too many arguments\n");
usage(stderr, 1);
}
/*
* Check device is real, and open it.
*/
if ((fd = open(devname, (O_RDWR | O_NDELAY))) < 0) {
fprintf(stderr, "ERROR: failed to open %s, errno=%d\n",
devname, errno);
exit(0);
}
setremotetermios(fd);
savelocaltermios();
setlocaltermios();
printf("Connected.\n");
loopit(fd);
restorelocaltermios();
close(fd);
printf("Disconnected.\n");
exit(0);
}
/*****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -