📄 sys-svr4.c
字号:
{ close(ipfd);#if defined(INET6) && defined(SOL2) close(ip6fd);#endif /* defined(INET6) && defined(SOL2) */ if (pppfd >= 0) close(pppfd);}/* * sys_check_options - check the options that the user specified */intsys_check_options(){ return 1;}#if 0/* * daemon - Detach us from controlling terminal session. */intdaemon(nochdir, noclose) int nochdir, noclose;{ int pid; if ((pid = fork()) < 0) return -1; if (pid != 0) exit(0); /* parent dies */ setsid(); if (!nochdir) chdir("/"); if (!noclose) { fclose(stdin); /* don't need stdin, stdout, stderr */ fclose(stdout); fclose(stderr); } return 0;}#endif/* * ppp_available - check whether the system has any ppp interfaces */intppp_available(){ struct stat buf; return stat(PPP_DEV_NAME, &buf) >= 0;}/* * establish_ppp - Turn the serial port into a ppp interface. */intestablish_ppp(fd) int fd;{ int i; /* Pop any existing modules off the tty stream. */ for (i = 0;; ++i) if (ioctl(fd, I_LOOK, tty_modules[i]) < 0 || strcmp(tty_modules[i], "ptem") == 0 || ioctl(fd, I_POP, 0) < 0) break; tty_nmodules = i; /* Push the async hdlc module and the compressor module. */ tty_npushed = 0; if(!sync_serial) { if (ioctl(fd, I_PUSH, AHDLC_MOD_NAME) < 0) { error("Couldn't push PPP Async HDLC module: %m"); return -1; } ++tty_npushed; } if (kdebugflag & 4) { i = PPPDBG_LOG + PPPDBG_AHDLC; strioctl(pppfd, PPPIO_DEBUG, &i, sizeof(int), 0); } if (ioctl(fd, I_PUSH, COMP_MOD_NAME) < 0) error("Couldn't push PPP compression module: %m"); else ++tty_npushed; if (kdebugflag & 2) { i = PPPDBG_LOG + PPPDBG_COMP; strioctl(pppfd, PPPIO_DEBUG, &i, sizeof(int), 0); } /* Link the serial port under the PPP multiplexor. */ if ((fdmuxid = ioctl(pppfd, I_LINK, fd)) < 0) { error("Can't link tty to PPP mux: %m"); return -1; } return pppfd;}/* * restore_loop - reattach the ppp unit to the loopback. * This doesn't need to do anything because disestablish_ppp does it. */voidrestore_loop(){}/* * disestablish_ppp - Restore the serial port to normal operation. * It attempts to reconstruct the stream with the previously popped * modules. This shouldn't call die() because it's called from die(). */voiddisestablish_ppp(fd) int fd;{ int i; if (fdmuxid >= 0) { if (ioctl(pppfd, I_UNLINK, fdmuxid) < 0) { if (!hungup) error("Can't unlink tty from PPP mux: %m"); } fdmuxid = -1; if (!hungup) { while (tty_npushed > 0 && ioctl(fd, I_POP, 0) >= 0) --tty_npushed; for (i = tty_nmodules - 1; i >= 0; --i) if (ioctl(fd, I_PUSH, tty_modules[i]) < 0) error("Couldn't restore tty module %s: %m", tty_modules[i]); } if (hungup && default_device && tty_sid > 0) { /* * If we have received a hangup, we need to send a SIGHUP * to the terminal's controlling process. The reason is * that the original stream head for the terminal hasn't * seen the M_HANGUP message (it went up through the ppp * driver to the stream head for our fd to /dev/ppp). */ kill(tty_sid, SIGHUP); } }}/* * Check whether the link seems not to be 8-bit clean. */voidclean_check(){ int x; char *s; if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof(x)) < 0) return; s = NULL; switch (~x) { case RCV_B7_0: s = "bit 7 set to 1"; break; case RCV_B7_1: s = "bit 7 set to 0"; break; case RCV_EVNP: s = "odd parity"; break; case RCV_ODDP: s = "even parity"; break; } if (s != NULL) { warn("Serial link is not 8-bit clean:"); warn("All received characters had %s", s); }}/* * List of valid speeds. */struct speed { int speed_int, speed_val;} speeds[] = {#ifdef B50 { 50, B50 },#endif#ifdef B75 { 75, B75 },#endif#ifdef B110 { 110, B110 },#endif#ifdef B134 { 134, B134 },#endif#ifdef B150 { 150, B150 },#endif#ifdef B200 { 200, B200 },#endif#ifdef B300 { 300, B300 },#endif#ifdef B600 { 600, B600 },#endif#ifdef B1200 { 1200, B1200 },#endif#ifdef B1800 { 1800, B1800 },#endif#ifdef B2000 { 2000, B2000 },#endif#ifdef B2400 { 2400, B2400 },#endif#ifdef B3600 { 3600, B3600 },#endif#ifdef B4800 { 4800, B4800 },#endif#ifdef B7200 { 7200, B7200 },#endif#ifdef B9600 { 9600, B9600 },#endif#ifdef B19200 { 19200, B19200 },#endif#ifdef B38400 { 38400, B38400 },#endif#ifdef EXTA { 19200, EXTA },#endif#ifdef EXTB { 38400, EXTB },#endif#ifdef B57600 { 57600, B57600 },#endif#ifdef B76800 { 76800, B76800 },#endif#ifdef B115200 { 115200, B115200 },#endif#ifdef B153600 { 153600, B153600 },#endif#ifdef B230400 { 230400, B230400 },#endif#ifdef B307200 { 307200, B307200 },#endif#ifdef B460800 { 460800, B460800 },#endif { 0, 0 }};/* * Translate from bits/second to a speed_t. */static inttranslate_speed(bps) int bps;{ struct speed *speedp; if (bps == 0) return 0; for (speedp = speeds; speedp->speed_int; speedp++) if (bps == speedp->speed_int) return speedp->speed_val; warn("speed %d not supported", bps); return 0;}/* * Translate from a speed_t to bits/second. */static intbaud_rate_of(speed) int speed;{ struct speed *speedp; if (speed == 0) return 0; for (speedp = speeds; speedp->speed_int; speedp++) if (speed == speedp->speed_val) return speedp->speed_int; return 0;}/* * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity, * at the requested speed, etc. If `local' is true, set CLOCAL * regardless of whether the modem option was specified. */voidset_up_tty(fd, local) int fd, local;{ int speed; struct termios tios;#if !defined (CRTSCTS) struct termiox tiox;#endif if (!sync_serial && tcgetattr(fd, &tios) < 0) fatal("tcgetattr: %m");#ifndef CRTSCTS termiox_ok = 1; if (ioctl (fd, TCGETX, &tiox) < 0) { termiox_ok = 0; if (errno != ENOTTY) error("TCGETX: %m"); }#endif if (!restore_term) { inittermios = tios;#ifndef CRTSCTS inittermiox = tiox;#endif ioctl(fd, TIOCGWINSZ, &wsinfo); } tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);#ifdef CRTSCTS if (crtscts > 0) tios.c_cflag |= CRTSCTS; else if (crtscts < 0) tios.c_cflag &= ~CRTSCTS;#else if (crtscts != 0 && !termiox_ok) { error("Can't set RTS/CTS flow control"); } else if (crtscts > 0) { tiox.x_hflag |= RTSXOFF|CTSXON; } else if (crtscts < 0) { tiox.x_hflag &= ~(RTSXOFF|CTSXON); }#endif tios.c_cflag |= CS8 | CREAD | HUPCL; if (local || !modem) tios.c_cflag |= CLOCAL; tios.c_iflag = IGNBRK | IGNPAR; tios.c_oflag = 0; tios.c_lflag = 0; tios.c_cc[VMIN] = 1; tios.c_cc[VTIME] = 0; if (crtscts == -2) { tios.c_iflag |= IXON | IXOFF; tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ } speed = translate_speed(inspeed); if (speed) { cfsetospeed(&tios, speed); cfsetispeed(&tios, speed); } else { speed = cfgetospeed(&tios); /* * We can't proceed if the serial port speed is 0, * since that implies that the serial port is disabled. */ if (speed == B0) fatal("Baud rate for %s is 0; need explicit baud rate", devnam); } if (!sync_serial && tcsetattr(fd, TCSAFLUSH, &tios) < 0) fatal("tcsetattr: %m");#ifndef CRTSCTS if (termiox_ok && ioctl (fd, TCSETXF, &tiox) < 0){ error("TCSETXF: %m"); }#endif baud_rate = inspeed = baud_rate_of(speed); restore_term = 1;}/* * restore_tty - restore the terminal to the saved settings. */voidrestore_tty(fd) int fd;{ if (restore_term) { if (!default_device) { /* * Turn off echoing, because otherwise we can get into * a loop with the tty and the modem echoing to each other. * We presume we are the sole user of this tty device, so * when we close it, it will revert to its defaults anyway. */ inittermios.c_lflag &= ~(ECHO | ECHONL); } if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) if (!hungup && errno != ENXIO) warn("tcsetattr: %m");#ifndef CRTSCTS if (ioctl (fd, TCSETXF, &inittermiox) < 0){ if (!hungup && errno != ENXIO) error("TCSETXF: %m"); }#endif ioctl(fd, TIOCSWINSZ, &wsinfo); restore_term = 0; }}/* * setdtr - control the DTR line on the serial port. * This is called from die(), so it shouldn't call die(). */voidsetdtr(fd, on)int fd, on;{ int modembits = TIOCM_DTR; ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);}/* * open_loopback - open the device we use for getting packets * in demand mode. Under Solaris 2, we use our existing fd * to the ppp driver. */intopen_ppp_loopback(){ return pppfd;}/* * output - Output PPP packet. */voidoutput(unit, p, len) int unit; u_char *p; int len;{ struct strbuf data; int retries; struct pollfd pfd; if (debug) dbglog("sent %P", p, len); data.len = len; data.buf = (caddr_t) p; retries = 4; while (putmsg(pppfd, NULL, &data, 0) < 0) { if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) { if (errno != ENXIO) error("Couldn't send packet: %m"); break; } pfd.fd = pppfd; pfd.events = POLLOUT; poll(&pfd, 1, 250); /* wait for up to 0.25 seconds */ }}/* * wait_input - wait until there is data available, * for the length of time specified by *timo (indefinite * if timo is NULL). */voidwait_input(timo) struct timeval *timo;{ int t; t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000; if (poll(pollfds, n_pollfds, t) < 0 && errno != EINTR) fatal("poll: %m");}/* * add_fd - add an fd to the set that wait_input waits for. */void add_fd(fd) int fd;{ int n; for (n = 0; n < n_pollfds; ++n) if (pollfds[n].fd == fd) return; if (n_pollfds < MAX_POLLFDS) { pollfds[n_pollfds].fd = fd; pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP; ++n_pollfds; } else error("Too many inputs!");}/* * remove_fd - remove an fd from the set that wait_input waits for. */void remove_fd(fd) int fd;{ int n; for (n = 0; n < n_pollfds; ++n) { if (pollfds[n].fd == fd) { while (++n < n_pollfds) pollfds[n-1] = pollfds[n]; --n_pollfds; break; } }}#if 0/* * wait_loop_output - wait until there is data available on the * loopback, for the length of time specified by *timo (indefinite * if timo is NULL). */voidwait_loop_output(timo) struct timeval *timo;{ wait_input(timo);}/* * wait_time - wait for a given length of time or until a * signal is received. */voidwait_time(timo) struct timeval *timo;{ int n; n = select(0, NULL, NULL, NULL, timo); if (n < 0 && errno != EINTR) fatal("select: %m");}#endif/* * read_packet - get a PPP packet from the serial device. */intread_packet(buf) u_char *buf;{ struct strbuf ctrl, data; int flags, len; unsigned char ctrlbuf[sizeof(union DL_primitives) + 64]; for (;;) { data.maxlen = PPP_MRU + PPP_HDRLEN; data.buf = (caddr_t) buf; ctrl.maxlen = sizeof(ctrlbuf); ctrl.buf = (caddr_t) ctrlbuf; flags = 0; len = getmsg(pppfd, &ctrl, &data, &flags); if (len < 0) { if (errno == EAGAIN || errno == EINTR) return -1; fatal("Error reading packet: %m"); } if (ctrl.len <= 0) return data.len; /* * Got a M_PROTO or M_PCPROTO message. Interpret it * as a DLPI primitive?? */ if (debug) dbglog("got dlpi prim 0x%x, len=%d", ((union DL_primitives *)ctrlbuf)->dl_primitive, ctrl.len); }}/* * get_loop_output - get outgoing packets from the ppp device, * and detect when we want to bring the real link up. * Return value is 1 if we need to bring up the link, 0 otherwise. */intget_loop_output(){ int len; int rv = 0; while ((len = read_packet(inpacket_buf)) > 0) { if (loop_frame(inpacket_buf, len)) rv = 1; } return rv;}/* * ppp_send_config - configure the transmit characteristics of * the ppp interface. */voidppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -