📄 tty.c
字号:
}#endif /* __linux__ */ close(real_ttyfd); real_ttyfd = -1;}/* * maybe_relock - our PID has changed, maybe update the lock file. */static voidmaybe_relock(arg, pid) void *arg; int pid;{ if (locked) relock(pid);}/* * open_socket - establish a stream socket connection to the nominated * host and port. */static intopen_socket(dest) char *dest;{ char *sep, *endp = NULL; int sock, port = -1; u_int32_t host; struct hostent *hent; struct sockaddr_in sad; /* parse host:port and resolve host to an IP address */ sep = strchr(dest, ':'); if (sep != NULL) port = strtol(sep+1, &endp, 10); if (port < 0 || endp == sep+1 || sep == dest) { error("Can't parse host:port for socket destination"); return -1; } *sep = 0; host = inet_addr(dest); if (host == (u_int32_t) -1) { hent = gethostbyname(dest); if (hent == NULL) { error("%s: unknown host in socket option", dest); *sep = ':'; return -1; } host = *(u_int32_t *)(hent->h_addr_list[0]); } *sep = ':'; /* get a socket and connect it to the other end */ sock = socket(PF_INET, SOCK_STREAM, 0); if (sock < 0) { error("Can't create socket: %m"); return -1; } memset(&sad, 0, sizeof(sad)); sad.sin_family = AF_INET; sad.sin_port = htons(port); sad.sin_addr.s_addr = host; if (connect(sock, (struct sockaddr *)&sad, sizeof(sad)) < 0) { error("Can't connect to %s: %m", dest); close(sock); return -1; } return sock;}/* * start_charshunt - create a child process to run the character shunt. */static intstart_charshunt(ifd, ofd) int ifd, ofd;{ int cpid; cpid = safe_fork(ifd, ofd, (log_to_fd >= 0? log_to_fd: 2)); if (cpid == -1) { error("Can't fork process for character shunt: %m"); return 0; } if (cpid == 0) { /* child */ reopen_log(); if (!nodetach) log_to_fd = -1; else if (log_to_fd >= 0) log_to_fd = 2; setgid(getgid()); setuid(uid); if (getuid() != uid) fatal("setuid failed"); charshunt(0, 1, record_file); exit(0); } charshunt_pid = cpid; record_child(cpid, "pppd (charshunt)", charshunt_done, NULL); return 1;}static voidcharshunt_done(arg) void *arg;{ charshunt_pid = 0;}static voidstop_charshunt(arg, sig) void *arg; int sig;{ if (charshunt_pid) kill(charshunt_pid, (sig == SIGINT? sig: SIGTERM));}/* * charshunt - the character shunt, which passes characters between * the pty master side and the serial port (or stdin/stdout). * This runs as the user (not as root). * (We assume ofd >= ifd which is true the way this gets called. :-). */static voidcharshunt(ifd, ofd, record_file) int ifd, ofd; char *record_file;{ int n, nfds; fd_set ready, writey; u_char *ibufp, *obufp; int nibuf, nobuf; int flags; int pty_readable, stdin_readable; struct timeval lasttime; FILE *recordf = NULL; int ilevel, olevel, max_level; struct timeval levelt, tout, *top; extern u_char inpacket_buf[]; /* * Reset signal handlers. */ signal(SIGHUP, SIG_IGN); /* Hangup */ signal(SIGINT, SIG_DFL); /* Interrupt */ signal(SIGTERM, SIG_DFL); /* Terminate */ signal(SIGCHLD, SIG_DFL); signal(SIGUSR1, SIG_DFL); signal(SIGUSR2, SIG_DFL); signal(SIGABRT, SIG_DFL); signal(SIGALRM, SIG_DFL); signal(SIGFPE, SIG_DFL); signal(SIGILL, SIG_DFL); signal(SIGPIPE, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGSEGV, SIG_DFL);#ifdef SIGBUS signal(SIGBUS, SIG_DFL);#endif#ifdef SIGEMT signal(SIGEMT, SIG_DFL);#endif#ifdef SIGPOLL signal(SIGPOLL, SIG_DFL);#endif#ifdef SIGPROF signal(SIGPROF, SIG_DFL);#endif#ifdef SIGSYS signal(SIGSYS, SIG_DFL);#endif#ifdef SIGTRAP signal(SIGTRAP, SIG_DFL);#endif#ifdef SIGVTALRM signal(SIGVTALRM, SIG_DFL);#endif#ifdef SIGXCPU signal(SIGXCPU, SIG_DFL);#endif#ifdef SIGXFSZ signal(SIGXFSZ, SIG_DFL);#endif /* * Check that the fds won't overrun the fd_sets */ if (ifd >= FD_SETSIZE || ofd >= FD_SETSIZE || pty_master >= FD_SETSIZE) fatal("internal error: file descriptor too large (%d, %d, %d)", ifd, ofd, pty_master); /* * Open the record file if required. */ if (record_file != NULL) { recordf = fopen(record_file, "a"); if (recordf == NULL) error("Couldn't create record file %s: %m", record_file); } /* set all the fds to non-blocking mode */ flags = fcntl(pty_master, F_GETFL); if (flags == -1 || fcntl(pty_master, F_SETFL, flags | O_NONBLOCK) == -1) warn("couldn't set pty master to nonblock: %m"); flags = fcntl(ifd, F_GETFL); if (flags == -1 || fcntl(ifd, F_SETFL, flags | O_NONBLOCK) == -1) warn("couldn't set %s to nonblock: %m", (ifd==0? "stdin": "tty")); if (ofd != ifd) { flags = fcntl(ofd, F_GETFL); if (flags == -1 || fcntl(ofd, F_SETFL, flags | O_NONBLOCK) == -1) warn("couldn't set stdout to nonblock: %m"); } nibuf = nobuf = 0; ibufp = obufp = NULL; pty_readable = stdin_readable = 1; ilevel = olevel = 0; gettimeofday(&levelt, NULL); if (max_data_rate) { max_level = max_data_rate / 10; if (max_level < 100) max_level = 100; } else max_level = PPP_MRU + PPP_HDRLEN + 1; nfds = (ofd > pty_master? ofd: pty_master) + 1; if (recordf != NULL) { gettimeofday(&lasttime, NULL); putc(7, recordf); /* put start marker */ putc(lasttime.tv_sec >> 24, recordf); putc(lasttime.tv_sec >> 16, recordf); putc(lasttime.tv_sec >> 8, recordf); putc(lasttime.tv_sec, recordf); lasttime.tv_usec = 0; } while (nibuf != 0 || nobuf != 0 || pty_readable || stdin_readable) { top = 0; tout.tv_sec = 0; tout.tv_usec = 10000; FD_ZERO(&ready); FD_ZERO(&writey); if (nibuf != 0) { if (ilevel >= max_level) top = &tout; else FD_SET(pty_master, &writey); } else if (stdin_readable) FD_SET(ifd, &ready); if (nobuf != 0) { if (olevel >= max_level) top = &tout; else FD_SET(ofd, &writey); } else if (pty_readable) FD_SET(pty_master, &ready); if (select(nfds, &ready, &writey, NULL, top) < 0) { if (errno != EINTR) fatal("select"); continue; } if (max_data_rate) { double dt; int nbt; struct timeval now; gettimeofday(&now, NULL); dt = (now.tv_sec - levelt.tv_sec + (now.tv_usec - levelt.tv_usec) / 1e6); nbt = (int)(dt * max_data_rate); ilevel = (nbt < 0 || nbt > ilevel)? 0: ilevel - nbt; olevel = (nbt < 0 || nbt > olevel)? 0: olevel - nbt; levelt = now; } else ilevel = olevel = 0; if (FD_ISSET(ifd, &ready)) { ibufp = inpacket_buf; nibuf = read(ifd, ibufp, PPP_MRU + PPP_HDRLEN); if (nibuf < 0 && errno == EIO) nibuf = 0; if (nibuf < 0) { if (!(errno == EINTR || errno == EAGAIN)) { error("Error reading standard input: %m"); break; } nibuf = 0; } else if (nibuf == 0) { /* end of file from stdin */ stdin_readable = 0; if (recordf) if (!record_write(recordf, 4, NULL, 0, &lasttime)) recordf = NULL; } else { FD_SET(pty_master, &writey); if (recordf) if (!record_write(recordf, 2, ibufp, nibuf, &lasttime)) recordf = NULL; } } if (FD_ISSET(pty_master, &ready)) { obufp = outpacket_buf; nobuf = read(pty_master, obufp, PPP_MRU + PPP_HDRLEN); if (nobuf < 0 && errno == EIO) nobuf = 0; if (nobuf < 0) { if (!(errno == EINTR || errno == EAGAIN)) { error("Error reading pseudo-tty master: %m"); break; } nobuf = 0; } else if (nobuf == 0) { /* end of file from the pty - slave side has closed */ pty_readable = 0; stdin_readable = 0; /* pty is not writable now */ nibuf = 0; close(ofd); if (recordf) if (!record_write(recordf, 3, NULL, 0, &lasttime)) recordf = NULL; } else { FD_SET(ofd, &writey); if (recordf) if (!record_write(recordf, 1, obufp, nobuf, &lasttime)) recordf = NULL; } } else if (!stdin_readable) pty_readable = 0; if (FD_ISSET(ofd, &writey)) { n = nobuf; if (olevel + n > max_level) n = max_level - olevel; n = write(ofd, obufp, n); if (n < 0) { if (errno == EIO) { pty_readable = 0; nobuf = 0; } else if (errno != EAGAIN && errno != EINTR) { error("Error writing standard output: %m"); break; } } else { obufp += n; nobuf -= n; olevel += n; } } if (FD_ISSET(pty_master, &writey)) { n = nibuf; if (ilevel + n > max_level) n = max_level - ilevel; n = write(pty_master, ibufp, n); if (n < 0) { if (errno == EIO) { stdin_readable = 0; nibuf = 0; } else if (errno != EAGAIN && errno != EINTR) { error("Error writing pseudo-tty master: %m"); break; } } else { ibufp += n; nibuf -= n; ilevel += n; } } } exit(0);}static intrecord_write(f, code, buf, nb, tp) FILE *f; int code; u_char *buf; int nb; struct timeval *tp;{ struct timeval now; int diff; gettimeofday(&now, NULL); now.tv_usec /= 100000; /* actually 1/10 s, not usec now */ diff = (now.tv_sec - tp->tv_sec) * 10 + (now.tv_usec - tp->tv_usec); if (diff > 0) { if (diff > 255) { putc(5, f); putc(diff >> 24, f); putc(diff >> 16, f); putc(diff >> 8, f); putc(diff, f); } else { putc(6, f); putc(diff, f); } *tp = now; } putc(code, f); if (buf != NULL) { putc(nb >> 8, f); putc(nb, f); fwrite(buf, nb, 1, f); } fflush(f); if (ferror(f)) { error("Error writing record file: %m"); return 0; } return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -