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

📄 tip.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1983, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1983, 1993\n\	The Regents of the University of California.  All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)tip.c	8.1 (Berkeley) 6/6/93";#endif /* not lint *//* * tip - UNIX link to other systems *  tip [-v] [-speed] system-name * or *  cu phone-number [-s speed] [-l line] [-a acu] */#include "tip.h"#include "pathnames.h"/* * Baud rate mapping table */int bauds[] = {	0, 50, 75, 110, 134, 150, 200, 300, 600,	1200, 1800, 2400, 4800, 9600, 19200, -1};int	disc = OTTYDISC;		/* tip normally runs this way */void	intprompt();void	timeout();void	cleanup();char	*sname();char	PNbuf[256];			/* This limits the size of a number */main(argc, argv)	char *argv[];{	char *system = NOSTR;	register int i;	register char *p;	char sbuf[12];	gid = getgid();	egid = getegid();	uid = getuid();	euid = geteuid();	if (equal(sname(argv[0]), "cu")) {		cumode = 1;		cumain(argc, argv);		goto cucommon;	}	if (argc > 4) {		fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");		exit(1);	}	if (!isatty(0)) {		fprintf(stderr, "tip: must be interactive\n");		exit(1);	}	for (; argc > 1; argv++, argc--) {		if (argv[1][0] != '-')			system = argv[1];		else switch (argv[1][1]) {		case 'v':			vflag++;			break;		case '0': case '1': case '2': case '3': case '4':		case '5': case '6': case '7': case '8': case '9':			BR = atoi(&argv[1][1]);			break;		default:			fprintf(stderr, "tip: %s, unknown option\n", argv[1]);			break;		}	}	if (system == NOSTR)		goto notnumber;	if (isalpha(*system))		goto notnumber;	/*	 * System name is really a phone number...	 * Copy the number then stomp on the original (in case the number	 *	is private, we don't want 'ps' or 'w' to find it).	 */	if (strlen(system) > sizeof PNbuf - 1) {		fprintf(stderr, "tip: phone number too long (max = %d bytes)\n",			sizeof PNbuf - 1);		exit(1);	}	strncpy( PNbuf, system, sizeof PNbuf - 1 );	for (p = system; *p; p++)		*p = '\0';	PN = PNbuf;	(void)sprintf(sbuf, "tip%d", BR);	system = sbuf;notnumber:	(void)signal(SIGINT, cleanup);	(void)signal(SIGQUIT, cleanup);	(void)signal(SIGHUP, cleanup);	(void)signal(SIGTERM, cleanup);	if ((i = hunt(system)) == 0) {		printf("all ports busy\n");		exit(3);	}	if (i == -1) {		printf("link down\n");		(void)uu_unlock(uucplock);		exit(3);	}	setbuf(stdout, NULL);	loginit();	/*	 * Kludge, their's no easy way to get the initialization	 *   in the right order, so force it here	 */	if ((PH = getenv("PHONES")) == NOSTR)		PH = _PATH_PHONES;	vinit();				/* init variables */	setparity("even");			/* set the parity table */	if ((i = speed(number(value(BAUDRATE)))) == NULL) {		printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));		(void)uu_unlock(uucplock);		exit(3);	}	/*	 * Now that we have the logfile and the ACU open	 *  return to the real uid and gid.  These things will	 *  be closed on exit.  Swap real and effective uid's	 *  so we can get the original permissions back	 *  for removing the uucp lock.	 */	user_uid();	/*	 * Hardwired connections require the	 *  line speed set before they make any transmissions	 *  (this is particularly true of things like a DF03-AC)	 */	if (HW)		ttysetup(i);	if (p = connect()) {		printf("\07%s\n[EOT]\n", p);		daemon_uid();		(void)uu_unlock(uucplock);		exit(1);	}	if (!HW)		ttysetup(i);cucommon:	/*	 * From here down the code is shared with	 * the "cu" version of tip.	 */	ioctl(0, TIOCGETP, (char *)&defarg);	ioctl(0, TIOCGETC, (char *)&defchars);	ioctl(0, TIOCGLTC, (char *)&deflchars);	ioctl(0, TIOCGETD, (char *)&odisc);	arg = defarg;	arg.sg_flags = ANYP | CBREAK;	tchars = defchars;	tchars.t_intrc = tchars.t_quitc = -1;	ltchars = deflchars;	ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc		= ltchars.t_lnextc = -1;	raw();	pipe(fildes); pipe(repdes);	(void)signal(SIGALRM, timeout);	/*	 * Everything's set up now:	 *	connection established (hardwired or dialup)	 *	line conditioned (baud rate, mode, etc.)	 *	internal data structures (variables)	 * so, fork one process for local side and one for remote.	 */	printf(cumode ? "Connected\r\n" : "\07connected\r\n");	if (pid = fork())		tipin();	else		tipout();	/*NOTREACHED*/}voidcleanup(){	daemon_uid();	(void)uu_unlock(uucplock);	if (odisc)		ioctl(0, TIOCSETD, (char *)&odisc);	exit(0);}/* * Muck with user ID's.  We are setuid to the owner of the lock * directory when we start.  user_uid() reverses real and effective * ID's after startup, to run with the user's permissions. * daemon_uid() switches back to the privileged uid for unlocking. * Finally, to avoid running a shell with the wrong real uid, * shell_uid() sets real and effective uid's to the user's real ID. */static int uidswapped;user_uid(){	if (uidswapped == 0) {		seteuid(uid);		uidswapped = 1;	}}daemon_uid(){	if (uidswapped) {		seteuid(euid);		uidswapped = 0;	}}shell_uid(){	seteuid(uid);}/* * put the controlling keyboard into raw mode */raw(){	ioctl(0, TIOCSETP, &arg);	ioctl(0, TIOCSETC, &tchars);	ioctl(0, TIOCSLTC, &ltchars);	ioctl(0, TIOCSETD, (char *)&disc);}/* * return keyboard to normal mode */unraw(){	ioctl(0, TIOCSETD, (char *)&odisc);	ioctl(0, TIOCSETP, (char *)&defarg);	ioctl(0, TIOCSETC, (char *)&defchars);	ioctl(0, TIOCSLTC, (char *)&deflchars);}static	jmp_buf promptbuf;/* * Print string ``s'', then read a string *  in from the terminal.  Handles signals & allows use of *  normal erase and kill characters. */prompt(s, p)	char *s;	register char *p;{	register char *b = p;	sig_t oint, oquit;	stoprompt = 0;	oint = signal(SIGINT, intprompt);	oquit = signal(SIGQUIT, SIG_IGN);	unraw();	printf("%s", s);	if (setjmp(promptbuf) == 0)		while ((*p = getchar()) != EOF && *p != '\n')			p++;	*p = '\0';	raw();	(void)signal(SIGINT, oint);	(void)signal(SIGQUIT, oquit);	return (stoprompt || p == b);}/* * Interrupt service routine during prompting */voidintprompt(){	(void)signal(SIGINT, SIG_IGN);	stoprompt = 1;	printf("\r\n");	longjmp(promptbuf, 1);}/* * ****TIPIN   TIPIN**** */tipin(){	char gch, bol = 1;	/*	 * Kinda klugey here...	 *   check for scripting being turned on from the .tiprc file,	 *   but be careful about just using setscript(), as we may	 *   send a SIGEMT before tipout has a chance to set up catching	 *   it; so wait a second, then setscript()	 */	if (boolean(value(SCRIPT))) {		sleep(1);		setscript();	}	while (1) {		gch = getchar()&0177;		if ((gch == character(value(ESCAPE))) && bol) {			if (!(gch = escape()))				continue;		} else if (!cumode && gch == character(value(RAISECHAR))) {			boolean(value(RAISE)) = !boolean(value(RAISE));			continue;		} else if (gch == '\r') {			bol = 1;			pwrite(FD, &gch, 1);			if (boolean(value(HALFDUPLEX)))				printf("\r\n");			continue;		} else if (!cumode && gch == character(value(FORCE)))			gch = getchar()&0177;		bol = any(gch, value(EOL));		if (boolean(value(RAISE)) && islower(gch))			gch = toupper(gch);		pwrite(FD, &gch, 1);		if (boolean(value(HALFDUPLEX)))			printf("%c", gch);	}}extern esctable_t etable[];/* * Escape handler -- *  called on recognition of ``escapec'' at the beginning of a line */escape(){	register char gch;	register esctable_t *p;	char c = character(value(ESCAPE));	gch = (getchar()&0177);	for (p = etable; p->e_char; p++)		if (p->e_char == gch) {			if ((p->e_flags&PRIV) && uid)				continue;			printf("%s", ctrl(c));			(*p->e_func)(gch);			return (0);		}	/* ESCAPE ESCAPE forces ESCAPE */	if (c != gch)		pwrite(FD, &c, 1);	return (gch);}speed(n)	int n;{	register int *p;	for (p = bauds; *p != -1;  p++)		if (*p == n)			return (p - bauds);	return (NULL);}any(c, p)	register char c, *p;{	while (p && *p)		if (*p++ == c)			return (1);	return (0);}size(s)	register char	*s;{	register int i = 0;	while (s && *s++)		i++;	return (i);}char *interp(s)	register char *s;{	static char buf[256];	register char *p = buf, c, *q;	while (c = *s++) {		for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)			if (*q++ == c) {				*p++ = '\\'; *p++ = *q;				goto next;			}		if (c < 040) {			*p++ = '^'; *p++ = c + 'A'-1;		} else if (c == 0177) {			*p++ = '^'; *p++ = '?';		} else			*p++ = c;	next:		;	}	*p = '\0';	return (buf);}char *ctrl(c)	char c;{	static char s[3];	if (c < 040 || c == 0177) {		s[0] = '^';		s[1] = c == 0177 ? '?' : c+'A'-1;		s[2] = '\0';	} else {		s[0] = c;		s[1] = '\0';	}	return (s);}/* * Help command */help(c)	char c;{	register esctable_t *p;	printf("%c\r\n", c);	for (p = etable; p->e_char; p++) {		if ((p->e_flags&PRIV) && uid)			continue;		printf("%2s", ctrl(character(value(ESCAPE))));		printf("%-2s %c   %s\r\n", ctrl(p->e_char),			p->e_flags&EXP ? '*': ' ', p->e_help);	}}/* * Set up the "remote" tty's state */ttysetup(speed)	int speed;{	unsigned bits = LDECCTQ;	arg.sg_ispeed = arg.sg_ospeed = speed;	arg.sg_flags = RAW;	if (boolean(value(TAND)))		arg.sg_flags |= TANDEM;	ioctl(FD, TIOCSETP, (char *)&arg);	ioctl(FD, TIOCLBIS, (char *)&bits);}/* * Return "simple" name from a file name, * strip leading directories. */char *sname(s)	register char *s;{	register char *p = s;	while (*s)		if (*s++ == '/')			p = s;	return (p);}static char partab[0200];static int bits8;/* * Do a write to the remote machine with the correct parity. * We are doing 8 bit wide output, so we just generate a character * with the right parity and output it. */pwrite(fd, buf, n)	int fd;	char *buf;	register int n;{	register int i;	register char *bp;	extern int errno;	bp = buf;	if (bits8 == 0)		for (i = 0; i < n; i++) {			*bp = partab[(*bp) & 0177];			bp++;		}	if (write(fd, buf, n) < 0) {		if (errno == EIO)			tipabort("Lost carrier.");		/* this is questionable */		perror("write");	}}/* * Build a parity table with appropriate high-order bit. */setparity(defparity)	char *defparity;{	register int i, flip, clr, set;	char *parity;	extern char evenpartab[];	if (value(PARITY) == NOSTR)		value(PARITY) = defparity;	parity = value(PARITY);	if (equal(parity, "none")) {		bits8 = 1;		return;	}	bits8 = 0;	flip = 0;	clr = 0377;	set = 0;	if (equal(parity, "odd"))		flip = 0200;			/* reverse bit 7 */	else if (equal(parity, "zero"))		clr = 0177;			/* turn off bit 7 */	else if (equal(parity, "one"))		set = 0200;			/* turn on bit 7 */	else if (!equal(parity, "even")) {		(void) fprintf(stderr, "%s: unknown parity value\r\n", parity);		(void) fflush(stderr);	}	for (i = 0; i < 0200; i++)		partab[i] = evenpartab[i] ^ flip | set & clr;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -