📄 x29d.c
字号:
ioctl(pty, TIOCGETA, (char *)&pt); signal(SIGPIPE, SIG_IGN); /* why not cleanup? --kwl */ signal(SIGTSTP, SIG_IGN); signal(SIGCHLD, cleanup); signal(SIGHUP, cleanup); signal(SIGTTOU, SIG_IGN); signal(SIGURG, x25_interrupt); /* for out-of-band data */ if (netp->n_proflen) (void) write(net, netp->n_profile, netp->n_proflen); /* * Show banner that getty never gave. */ if (send_banner) { gethostname(hostname, sizeof (hostname));#ifdef BSD4_3 strcpy(pibuf+1, "\r\n\r\n4.3 BSD UNIX (");#else strcpy(pibuf+1, "\r\n\r\n4.2 BSD UNIX (");#endif strcat(pibuf+1, hostname); strcat(pibuf+1, ")\r\n\r\n"); pcc = strlen(pibuf+1) + 1; } else pcc = 0; fcc = 0; for (;;) { int ibits, obits; ibits = obits = 0; /* * Never look for input if there's still * stuff in the corresponding output buffer */ if (fcc >= 0) /* net connection alive? */ if (fcc && pcc >= 0) /* output pending? */ obits |= (1 << pty); else if (pcc >= 0) /* pty still alive? */ ibits |= (1 << net); if (pcc >= 0) /* pty connection alive? */ if (pcc && fcc >= 0) /* output pending? */ obits |= (1 << net); else if (fcc >= 0) /* net still alive? */ ibits |= (1 << pty); if (ibits == 0 && obits == 0) break; (void) select(16, &ibits, &obits, (int *)0, 0); if (ibits == 0 && obits == 0) { sleep(5); continue; } /* * Something to read from the network... */ if (fcc == 0 && (ibits & (1 << net))) { fcc = read(net, fibuf, BUFSIZ); fbp = fibuf+1; if (fcc < 0 && errno == EWOULDBLOCK) fcc = 0; else if (fcc <= 0) fcc = -1; else { if (tracefn) x29d_trace("netread", fibuf, fcc); if (fibuf[0] & Q_BIT) { x29_qbit(fcc); fcc = 0; } else fcc--; } } /* * Something to read from the pty... */ if (ibits & (1 << pty)) { pcc = read(pty, pibuf, packet_size+1); if (pcc < 0 && errno == EWOULDBLOCK) pcc = 0; else if (pcc <= 0) pcc = -1; else if (pibuf[0] != 0) { /* non-data packet */ if (pibuf[0] & TIOCPKT_IOCTL) { if (--pcc > sizeof(pt)) pcc = sizeof(pt); old_pt = pt; bcopy(pibuf + 1, (char *)&pt, pcc); pcc = set_x29_parameters(); } else pcc = 0; } else /* data packet */ pibuf[0] = 0; } if ((obits & (1<<net)) && pcc > 0) if ((cc = write(net, pibuf, pcc)) == pcc) { if (tracefn) x29d_trace("netwrite", pibuf, pcc); pcc = 0; } else { extern char *sys_errlist[]; if (tracefn) x29d_trace("netwrite", sys_errlist[errno], strlen(sys_errlist[errno])); } if ((obits & (1 << pty)) && fcc > 0) { cc = ptywrite(fbp, fcc); if (cc > 0) { fcc -= cc; fbp += cc; } } } cleanup();}/* * Send interrupt to process on other side of pty. * If it is in raw mode, just write NULL; * otherwise, write intr char. */x25_interrupt(){ struct termios tt; int zero = 0; signal(SIGURG, x25_interrupt); tcgetattr(pty, &tt); if (tt.c_lflag & ISIG) { tcsetattr(pty, TCSAFLUSH, &tt); (void) write(pty, &tt.c_cc[VINTR], 1); } else (void) write(pty, "\0", 1);}cleanup(){ char *p; p = line + sizeof(_PATH_DEV) - 1; if (logout(p)) logwtmp(p, "", ""); (void)chmod(line, 0666); (void)chown(line, 0, 0); *p = 'p'; (void)chmod(line, 0666); (void)chown(line, 0, 0); shutdown(net, 2); exit(1);}/* * Map unix tty modes and special characters * into x29 parameters. */set_x29_parameters(){ register char *p; int f; char *lim = p + sizeof (pt); if (netp->n_type == X25NET) return (0); if ((old_pt.c_lflag & ICANON) != (pt.c_lflag & ICANON)) { f = pt.c_lflag & ICANON; ioctl(pty, TIOCEXT, &f); /* this precipitates more junk of the same * sort that caused our call here, but we can't * turn it off since something may be going on in our progeny. * * Instead, we'll check the next time around to see if nothing * has changed, and skip informing the network. */ } if (bcmp((char *)&pt, (char *)&old_pt, sizeof (pt)) == 0) return; p = pibuf; *p++ = Q_BIT; *p++ = X29_SET_PARMS; /* *p++ = X29_ESCAPE_TO_CMD_CODE; *p++ = (f & (RAW|CBREAK)) == 0;*/ *p++ = X29_ESCAPE_TO_CMD_CODE; *p++ = (pt.c_lflag & ICANON) != 0; *p++ = X29_ECHO_CODE; *p++ = (pt.c_lflag & ECHO) != 0; *p++ = X29_FORWARDING_SIGNAL_CODE; *p++ = (pt.c_lflag & ISIG) ? 0 : 126; /* * The value of 10 (0.5 seconds) for the idle timer when * in raw or cbreak mode is a compromise value. For good * interactive response this value should be as low as * possible; for reasonable efficiency with file transfers * this value should be at fairly high. This number should * be changed to suit local requirements. */ /**p++ = X29_IDLE_TIMER_CODE; *p++ = (f & (RAW|CBREAK)) ? 10 : 0;*/ *p++ = X29_IDLE_TIMER_CODE; *p++ = (pt.c_lflag & ICANON) ? 0 : 10; /**p++ = X29_AUX_DEV_CONTROL_CODE;*p++ = (f & TANDEM) != 0;*/ *p++ = X29_AUX_DEV_CONTROL_CODE;*p++ = (pt.c_iflag & IXOFF) != 0; *p++ = X29_XON_XOFF_CODE; *p++ = (pt.c_iflag & IXON) != 0; if (netp->n_type == CCITT1980) { *p++ = X29_LF_AFTER_CR; /* *p++ = (f & (RAW|CBREAK) || (f & ECHO) == 0) ? 0 : 4; */ *p++ = ((pt.c_lflag & (ICANON | ECHO)) != (ICANON | ECHO)) ? 0 : 4; *p++ = X29_EDITING; *p++ = (pt.c_lflag & ICANON) != 0;#define ctlchar(x) \ (0 == (pt.c_lflag & ICANON) || pt.c_cc[x] == _POSIX_VDISABLE) ? 0 : pt.c_cc[x] *p++ = X29_CHARACTER_DELETE; *p++ = ctlchar(VERASE); *p++ = X29_LINE_DELETE; *p++ = ctlchar(VKILL); *p++ = X29_LINE_DISPLAY; *p++ = ctlchar(VREPRINT); }#undef ctlchar return (p - pibuf);}/* Have to be careful writing to pty. The pad will forward control * characters without necessarily sending an interrupt so if ISIG and * ICANNON are set, must inspect line for quit or interrupt or suspend. */ptywrite(buf, n)char *buf;int n;{ register char *cp, *lim; char *last;#define is_ctl(x) (pt.c_cc[x] == *(cc_t *)cp) if ((pt.c_lflag & EXTPROC) && (pt.c_lflag & ISIG)) { for (cp = buf, lim = buf + n; cp < lim; cp ++) { if (is_ctl(VLNEXT)) { cp++; continue; } if (is_ctl(VSUSP) || is_ctl(VDSUSP) || is_ctl(VINTR) || is_ctl(VQUIT)) { int onoff = 0; tcflag_t old_echo = pt.c_lflag & ECHO; ioctl(pty, TIOCPKT, (char *)&onoff); ioctl(pty, FIONBIO, (char *)&onoff); ioctl(pty, TIOCEXT, (char *)&onoff); if (old_echo) { pt.c_lflag &= ~ECHO; ioctl(pty, TIOCSETA, (char *)&pt); } n = write(pty, buf, n); onoff = 1; if (old_echo) { pt.c_lflag |= ECHO; ioctl(pty, TIOCSETA, (char *)&pt); } ioctl(pty, TIOCEXT, (char *)&onoff); ioctl(pty, FIONBIO, (char *)&onoff); ioctl(pty, TIOCPKT, (char *)&onoff); return (n); } } } return write(pty, buf, n);}/* * Process Q BIT (control) packets from the net. * The only message that we are interested in are * those indicating output is being discarded. */x29_qbit(n){ register char *p; switch (fibuf[1]) { case X29_SET_PARMS: case X29_SET_AND_READ_PARMS: case X29_PARAMETER_INDICATION: case X29_INDICATION_OF_BREAK: for (p = &fibuf[2]; p < fibuf+n; p++) { if (*p == X29_TRANSMISSION_SPEED_CODE) { static char speeds[] = { B110, B0, B300, B1200, B600, B0, B0, B0, B0, B0, B0, B0, B2400, B4800, B9600, EXTA }; if (*++p >= 0 && *p < sizeof(speeds)) { cfsetspeed(&pt, speeds[*p]); tcsetattr(pty, TCSANOW, &pt); } } else if (*p == X29_DISCARD_OUTPUT_CODE && *++p != 0) { char message[4]; /* * Always re-enable normal output */ message[0] = Q_BIT; message[1] = X29_SET_PARMS; message[2] = X29_DISCARD_OUTPUT_CODE; message[3] = 0; (void) write(net, message, sizeof(message)); if (tracefn) x29d_trace("netwrite", message, 4); } } return; default: { register char *p2; char buf[BUFSIZ*4]; static int fd; /* * Bad news - we received an x29 error message or * some other unknown packet. Dump the contents * of the packet on the console. */ p = buf; for (p2 = "x29d: unknown q-bit packet: "; *p++ = *p2++; ); for (p2 = fibuf+1; p2 < fibuf+n; p2++) if (*p2 >= ' ' && *p2 < 0177) *p++ = *p2; else { *p++ = '\\'; *p++ = ((*p2 & 0300) >> 6) + '0'; *p++ = ((*p2 & 070) >> 3) + '0'; *p++ = (*p2 & 07) + '0'; } *p++ = '\n'; if (fd <= 0) fd = open(console, 1); (void) write(fd, buf, p-buf); } }}x29d_trace(s, bp, n)char *s, *bp;{ static int fd; char buf[BUFSIZ*4]; register char *p1, *p2; for (p1 = buf; *s; *p1++ = *s++); *p1++ = ':'; *p1++ = ' '; for (p2=bp; p2 < bp+n; p2++) if (*p2 >= ' ' && *p2 < 0177) *p1++ = *p2; else { *p1++ = '\\'; *p1++ = ((*p2 & 0300) >> 6) + '0'; *p1++ = ((*p2 & 070) >> 3) + '0'; *p1++ = (*p2 & 07) + '0'; } *p1++ = '\n'; if (fd <= 0) fd = creat(tracefn, 0666); (void) write(fd, buf, p1-buf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -