⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tty.c

📁 经典的ppp程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (!start_charshunt(fd, fd))			return -1;	} else if (notty) {		if (!start_charshunt(0, 1))			return -1;	} else if (record_file != NULL) {		if (!start_charshunt(ttyfd, ttyfd))			return -1;	}	/* run connection script */	if ((connector && connector[0]) || initializer) {		if (real_ttyfd != -1) {			/* XXX do this if doing_callback == CALLBACK_DIALIN? */			if (!default_device && modem) {				setdtr(real_ttyfd, 0);	/* in case modem is off hook */				sleep(1);				setdtr(real_ttyfd, 1);			}		}		if (initializer && initializer[0]) {			if (device_script(initializer, ttyfd, ttyfd, 0) < 0) {				error("Initializer script failed");				status = EXIT_INIT_FAILED;				return -1;			}			if (kill_link) {				disconnect_tty();				return -1;			}			info("Serial port initialized.");		}		error("connector=%s",connector);		if (connector && connector[0]) {			if (device_script(connector, ttyfd, ttyfd, 0) < 0) {				error("Connect script failed");				status = EXIT_CONNECT_FAILED;				return -1;			}			if (kill_link) {				disconnect_tty();				return -1;			}			info("Serial connection established.");		}		/* set line speed, flow control, etc.;		   clear CLOCAL if modem option */		if (real_ttyfd != -1)			set_up_tty(real_ttyfd, 0);		if (doing_callback == CALLBACK_DIALIN)			connector = NULL;	}	/* reopen tty if necessary to wait for carrier */	if (connector == NULL && modem && devnam[0] != 0) {		int i;		for (;;) {			if ((i = open(devnam, O_RDWR)) >= 0)				break;			if (errno != EINTR) {				error("Failed to reopen %s: %m", devnam);				status = EXIT_OPEN_FAILED;			}			if (!persist || errno != EINTR || hungup || kill_link)				return -1;		}		close(i);	}	slprintf(numbuf, sizeof(numbuf), "%d", baud_rate);	script_setenv("SPEED", numbuf, 0);	/* run welcome script, if any */	if (welcomer && welcomer[0]) {		if (device_script(welcomer, ttyfd, ttyfd, 0) < 0)			warn("Welcome script failed");	}	/*	 * If we are initiating this connection, wait for a short	 * time for something from the peer.  This can avoid bouncing	 * our packets off his tty before he has it set up.	 */	if (connector != NULL || ptycommand != NULL)		listen_time = connect_delay;	return ttyfd;}void disconnect_tty(){	if (disconnect_script == NULL || hungup)		return;	if (real_ttyfd >= 0)		set_up_tty(real_ttyfd, 1);	if (device_script(disconnect_script, ttyfd, ttyfd, 0) < 0) {		warn("disconnect script failed");	} else {		info("Serial link disconnected.");	}}void tty_close_fds(){	if (pty_master >= 0)		close(pty_master);	if (pty_slave >= 0)		close(pty_slave);	if (real_ttyfd >= 0) {		close(real_ttyfd);		real_ttyfd = -1;	}	/* N.B. ttyfd will == either pty_slave or real_ttyfd */}void cleanup_tty(){	if (real_ttyfd >= 0)		finish_tty();	tty_close_fds();	if (locked) {		unlock();		locked = 0;	}}/* * tty_do_send_config - set transmit-side PPP configuration. * We set the extended transmit ACCM here as well. */voidtty_do_send_config(mtu, accm, pcomp, accomp)    int mtu;    u_int32_t accm;    int pcomp, accomp;{	tty_set_xaccm(xmit_accm);	tty_send_config(mtu, accm, pcomp, accomp);}/* * finish_tty - restore the terminal device to its original settings */static voidfinish_tty(){	/* drop dtr to hang up */	if (!default_device && modem) {		setdtr(real_ttyfd, 0);		/*		 * This sleep is in case the serial port has CLOCAL set by default,		 * and consequently will reassert DTR when we close the device.		 */		sleep(1);	}	restore_tty(real_ttyfd);	if (tty_mode != (mode_t) -1) {		if (fchmod(real_ttyfd, tty_mode) != 0) {			/* XXX if devnam is a symlink, this will change the link */			chmod(devnam, tty_mode);		}	}	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 = fork();    if (cpid == -1) {	error("Can't fork process for character shunt: %m");	return 0;    }    if (cpid == 0) {	/* child */	close(pty_slave);	setuid(uid);	if (getuid() != uid)	    fatal("setuid failed");	setgid(getgid());	if (!nodetach)	    log_to_fd = -1;	charshunt(ifd, ofd, record_file);	exit(0);    }    charshunt_pid = cpid;    add_notifier(&sigreceived, stop_charshunt, 0);    close(pty_master);    pty_master = -1;    ttyfd = pty_slave;    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    /*     * 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;		/* do a 0-length write, hopefully this will generate		   an EOF (hangup) on the slave side. */		write(pty_master, inpacket_buf, 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;	    }	}	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 + -