📄 term.c
字号:
/*
* usage: term [-s speed] [-l line] [-e escape-char] [-c callscript]
* defaults:
* speed: 38400 or 2400
* line : /dev/tty2a
* escape: ~
* escape char may be specified as three octal digits
*
* term escapes:
* escape-. or escape-CTRLD terminate
* escape-! escape to shell
* escape-# send break
* escape-escape send escape char
*/
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include <malloc.h>
#include <setjmp.h>
#ifdef V7
# include <sgtty.h>
#else
# if defined(__linux__) || defined(HAVE_TERMIOS)
# include <termios.h>
# ifndef HAVE_TERMIOS
# define HAVE_TERMIOS
# endif
# else
# include <termio.h>
# endif
# ifndef SYSV
# define SYSV
# endif
#endif
#define XSCRIPT
#define XLOGFILE
#define XCHARXLATE
#ifdef B38400
#define SPEED B38400 /* default speed */
#else
#define SPEED B2400 /* default speed */
#endif
#define LINE "/dev/ttyS0" /* the default line */
#define ESC '~' /* default esc char */
#define EOT '\004' /* ^D */
#ifndef R_OK /* access() modes */
#define R_OK 4
#define W_OK 2
#endif
char esc[2] = { ESC, '\0' };
extern void s_line(); /* set & save line characteristics */
extern void r_line(); /* reset saved line characteristics */
int wr_pid = 0; /* writer process id */
int line_fd; /* comm line file desc */
int tty_fd; /* console file desc */
char line_device[64];
#ifdef CHARXLATE
int Termtype = 2;
#else
int Termtype = 0;
#endif
int Bit_mask = 0xFF; /* Strip high bit from line */
int Parity = 0; /* Add parity to line */
#ifdef LOGFILE
FILE * lfile = 0;
char logfname[64] = "tty/ttylog%d";
char ltbuf[10240];
char * ltptr = 0;
#endif
#ifdef SCRIPT
int in_script = 0;
char script_name[128];
char script_args[128];
struct script_sv
{
struct script_sv * next;
FILE * scrfd;
char script_args[128];
}
* saved_sc = 0;
int verbose = 0;
#endif
int cleanup()
{
int status;
r_line();
if( wr_pid ) kill(wr_pid, SIGTERM);
wait(&status);
uucp_unlock(line_device);
#ifdef LOGFILE
if( lfile ) fclose(lfile);
lfile = 0;
#endif
if( wr_pid ) fprintf(stderr, "Disconnected\r\n");
exit(0);
}
void main(argc, argv)
int argc;
char **argv;
{
int done, status;
int speed = SPEED;
extern char *optarg;
extern int optind;
extern int getopt(), conv_speed(), conv_esc(), access();
extern open_timeout();
strcpy(line_device, LINE);
while((status = getopt(argc, argv,"s:l:e:rdm7pv")) != EOF)
{
switch(status)
{
case 's':
if((speed = conv_speed(optarg)) == EOF)
{
fprintf(stderr,"%s: invalid speed\n", optarg);
exit(1);
}
break;
case 'l':
strncpy(line_device, optarg, sizeof(line_device));
if(access(line_device, R_OK|W_OK) == -1)
{
perror(optarg);
exit(2);
}
break;
case 'e': esc[0] = conv_esc(optarg); break;
case 'p': Parity = 1; /* FALL */
case '7': Bit_mask = 0x7F; break;
case 'd': Termtype = 1; break;
#ifdef CHARXLATE
case 'r': Termtype = 0; break;
#endif
#ifdef SCRIPT
case 'v': verbose++; break;
#endif
default:
fprintf(stderr,
"usage: %s [-s speed] [-l line] [-e escape-char]\n", *argv);
exit(3);
}
}
if( optind < argc )
{
#ifdef SCRIPT
strcpy(script_name, argv[optind]);
strcat(script_name, ".sct");
if(access(script_name, R_OK) == -1)
{
strcpy(script_name, "sct/");
strcat(script_name, argv[optind]);
strcat(script_name, ".sct");
if(access(script_name, R_OK) == -1)
{
fprintf(stderr, "Cannot open '%s.sct'\n", argv[optind]);
exit(4);
}
}
strcpy(script_name, argv[optind]);
in_script = 1;
for(optind++, script_args[0] = '\0'; optind<argc; optind++)
{
if(*script_args) strcat(script_args, " ");
strcat(script_args, argv[optind]);
}
#else
fprintf(stderr,
"usage: %s [-s speed] [-l line] [-e escape-char]\n", *argv);
exit(3);
#endif
}
if( !uucp_check(line_device) )
{
fprintf(stderr, "Device in use\n");
exit(1);
}
signal(SIGALRM, open_timeout);
alarm(5);
if((line_fd = open(line_device, O_RDWR)) < 0)
{
perror(line_device);
exit(4);
}
alarm(0);
signal(SIGALRM, SIG_DFL);
tty_fd = fileno(stdin);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
s_line(speed);
signal(SIGTERM, cleanup);
#ifdef SCRIPT
if( in_script )
fprintf(stderr, "Running script\r\n");
else
#endif
fprintf(stderr, "Connected\r\n");
signal(SIGCHLD, cleanup);
fork_writer(); /* launch writer process */
read_tty();
cleanup();
}
open_timeout()
{
fprintf(stderr, "Cannot open port -- No carrier\n");
cleanup();
}
#ifdef LOGFILE
open_logfile()
{
char file[150];
char file2[160];
char file3[160];
char *p;
int lnumber;
FILE * fd;
if( lfile ) return;
if( strchr(logfname, '%') == 0 )
{
strcpy(file, logfname);
lfile = fopen(file, "a");
if( lfile == 0 ) return;
}
else
{
strcpy(file, logfname);
p = strchr(file, '%');
while(*p) { if(*p == 'd') { *p='s'; break; } else p++; }
sprintf(file3, file, "cnt");
lnumber=1;
fd = fopen(file3, "r");
if(fd) { fscanf(fd, "%d", &lnumber); fclose(fd); }
for(;;lnumber++)
{
sprintf(file, logfname, lnumber);
strcpy(file2, file);
strcat(file2, ".Z");
if( access(file, 0) != -1 || access(file2, 0) != -1 )
{
if( lnumber>=1000 )
{
lfile = 0;
break;;
}
continue;
}
lfile = fopen(file, "w");
fd = fopen(file3, "w");
if(fd) { fprintf(fd, "%d\n", lnumber+1); fclose(fd); }
break;
}
}
if( lfile )
fprintf(stderr, "Logfile %s\r\n", file);
else
fprintf(stderr, "Cannot open Logfile %s\r\n", file);
if( ltptr && ltbuf != ltptr )
{
fwrite(ltbuf, 1, ltptr-ltbuf, lfile);
ltptr = 0;
}
}
#endif
typedef struct
{
char *str;
int spd;
} vspeeds;
static vspeeds valid_speeds[] =
{
{ "110", B110 },
{ "300", B300 },
{ "1200", B1200 },
{ "2400", B2400 },
{ "4800", B4800 },
{ "9600", B9600 },
#ifdef B19200
{ "19200", B19200 },
#endif
#ifdef B38400
{ "38400", B38400 },
#endif
#ifdef B57600
{ "57600", B57600 },
#endif
#ifdef B115200
{ "115200", B115200 },
#endif
{ (char *)0, 0 }
};
/*
* given a desired speed string, if valid return its Bspeed value
* else EOF
*/
int conv_speed(s)
register char *s;
{
register vspeeds *p = &valid_speeds[0];
if(*s == 0) return EOF;
for(; p->str != (char *)0; p++)
if(strncmp(s, p->str, strlen(s)) == 0)
return p->spd;
return EOF;
}
/*
* convert given string to char
* string maybe a char, or octal digits
*/
int conv_esc(s)
register char *s;
{
register int val = 0;
if(!isdigit(*s))
return *s; /* ! octal */
/* convert octal digs */
do
{
if(*s > '7' || *s < '0')
{
fprintf(stderr,"escape char must be character/octal digits\n");
exit(4);
}
val = (val << 3) + (*s++ - '0');
} while(isdigit(*s));
return val;
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
#ifdef V7
/* This is Version 7 unix code it should work on any unix machine */
/* If you believe that you'll believe anything :-) */
struct sgttyb tty_save, line_save, tty;
int tty_mode = -1;
int got_line = 0;
void s_line(speed)
{
set_mode(2);
if(!got_line)
{
got_line = 1;
ioctl(line_fd, TIOCGETP, &line_save);
}
tty = line_save;
tty.sg_ospeed = speed; /* Set new speed */
tty.sg_ispeed = speed; /* Set new speed */
tty.sg_flags |= RAW;
tty.sg_flags &= ~ECHO;
/* Parity doesn't appear to work with Xenix tty.sg_flags |= EVENP; */
/* So xmit parity is done in software */
ioctl(line_fd, TIOCSETP, &tty);
}
void r_line()
{
set_mode(0);
if(!got_line) return;
ioctl(line_fd, TIOCSETP, &line_save);
}
set_mode(which)
int which;
{
if( tty_mode == -1 )
{
if(ioctl(tty_fd, TIOCGETP, &tty))
{
perror("Unable to sense terminal");
exit(1);
}
tty_save = tty;
tty_mode = 0;
}
tty = tty_save;
switch(which)
{
default: /* Normal cooked */
which = 0;
break;
case 1: /* CBREAK */
tty.sg_flags &= ~ECHO;
tty.sg_flags |= CBREAK; /* Allow break & cr/nl mapping */
break;
case 2: /* RAW */
tty.sg_flags &= ~ECHO;
tty.sg_flags |= RAW;
break;
}
if(ioctl(tty_fd, TIOCSETP, &tty))
{
perror("Unable to change terminal mode");
}
else tty_mode = which;
}
#endif
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
#ifdef SYSV
/* This is System V unix code */
#ifdef HAVE_TERMIOS
struct termios tty_save, line_save, tty;
#else
struct termio tty_save, line_save, tty;
#endif
static int tty_mode = -1;
int got_line = 0;
void s_line(speed)
int speed;
{
set_mode(2);
if(!got_line)
{
got_line = 1;
#ifndef HAVE_TERMIOS
ioctl(line_fd, TCGETA, &line_save);
#else
tcgetattr(line_fd, &line_save);
#endif
}
tty = line_save;
tty.c_iflag &= ~(IXON|IXANY|IXOFF|ISTRIP|INLCR|ICRNL|IGNCR|IUCLC);
tty.c_oflag &= ~(OLCUC|ONLCR|OCRNL|ONOCR|ONLRET);
tty.c_cflag &= ~(CBAUD|PARENB);
tty.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHONL|ISIG);
tty.c_iflag |= IXOFF; /* X/Y modem will clear this */
tty.c_cflag |= (speed);
tty.c_cc[VTIME] = 0;
tty.c_cc[VMIN] = 1;
#ifndef HAVE_TERMIOS
ioctl(line_fd, TCSETA, &tty);
#else
tcsetattr(line_fd, TCSANOW, &tty);
#endif
}
void r_line()
{
set_mode(0);
if(!got_line) return;
#ifndef HAVE_TERMIOS
ioctl(line_fd, TCSETA, &line_save);
#else
tcsetattr(line_fd, TCSANOW, &line_save);
#endif
}
set_mode(which)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -