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

📄 ifdef.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * * Conditionally compiled routines for setting up and reading the line. Things * were getting out of hand with all the ifdefs, and even though this defeats * part of the purpose of conditional complilation directives, I think it's easier * to follow this way. Thanks to Alan Buckwalter for the System V DKHOST code. * * postio now can be run as separate read and write processes, but requires that * you write a procedure called resetline() and perhaps modify readline() some. * I've already tested the code on System V and it seems to work. Ninth Edition * and BSD code may be missing. * * By request I've changed the way some of the setupline() procedures (eg. in the * System V implementation) handle things when no line has been given. If line is * NULL the new setupline() procedures try to continue, assuming whoever called * postio connected stdout to the printer. Things will only work if we can read * and write stdout! * */#include <stdio.h>#include <ctype.h>#include <fcntl.h>#include <signal.h>#include <sys/types.h>#include <errno.h>#include "ifdef.h"			/* conditional header file inclusion */#include "gen.h"			/* general purpose definitions */FILE	*fp_ttyi, *fp_ttyo;char	*ptr = mesg;extern int	window_size;/*****************************************************************************/#ifdef SYSVsetupline(){    struct termio	termio;/* * * Line initialization for SYSV. For now if no line is given (ie. line == NULL ) * we continue on as before using stdout as ttyi and ttyo. Doesn't work when we're * running in interactive mode or forcing stuff that comes back from the printer * to stdout. Both cases are now caught by a test that's been added to routine * initialize(). The change is primarily for the version of lp that's available * with SVR3.2. * */#ifdef DKHOST    if ( line != NULL && *line != '/' )  {	if ( strncmp(line, "DK:", 3) == 0 )	    line += 3;	dkhost_connect();#ifdef DKSTREAMS	if ( ioctl(ttyi, I_PUSH, DKSTREAMS) == -1 )	    error(FATAL, "ioctl error - %s", DKSTREAMS);	if ( ioctl(ttyi, I_PUSH, "ldterm") == -1 )	    error(FATAL, "ioctl error - ldterm");#endif    } else#endif    if ( line == NULL )	ttyi = fileno(stdout);    else if ( (ttyi = open(line, O_RDWR)) == -1 )	error(FATAL, "can't open %s", line);    if ( (ttyo = dup(ttyi)) == -1 )	error(FATAL, "can't dup file descriptor for %s", line);    if ( stopbits == 1 )	stopbits = 0;    else stopbits = CSTOPB;    if ( fcntl(ttyi, F_SETFL, O_NDELAY) == -1 )	error(FATAL, "fcntl error - F_SETFL");    if ( ioctl(ttyi, TCGETA, &termio) == -1 )	error(FATAL, "ioctl error - TCGETA");    termio.c_iflag = IXON | IGNCR;    termio.c_oflag = 0;    termio.c_cflag = HUPCL | CREAD | CS8 | stopbits | baudrate;    termio.c_lflag = 0;    termio.c_cc[VMIN] = termio.c_cc[VTIME] = 0;    if ( ioctl(ttyi, TCSETA, &termio) == -1 )	error(FATAL, "ioctl error - TCSETA");    if ( ioctl(ttyi, TCFLSH, 2) == -1 )	error(FATAL, "ioctl error - TCFLSH");    fp_ttyi = fdopen(ttyi, "r");}   /* End of setupline *//*****************************************************************************/resetline(){    int			flags;		/* for turning O_NDELAY off */    struct termio	termio;		/* so we can reset flow control *//* * * Only used if we're running the program as separate read and write processes. * Called from split() after the initial connection has been made and returns * TRUE if two processes should work. Don't know if the O_NDELAY stuff is really * needed, but setting c_cc[VMIN] to 1 definitely is. If we leave it be (as a 0) * the read in readline() won't block! * */    if ( (flags = fcntl(ttyi, F_GETFL, 0)) == -1 )	error(FATAL, "fcntl error - F_GETFL");    flags &= ~O_NDELAY;    if ( fcntl(ttyi, F_SETFL, flags) == -1 )	error(FATAL, "fcntl error - F_SETFL");    if ( ioctl(ttyi, TCGETA, &termio) == -1 )	error(FATAL, "ioctl error - TCGETA");    termio.c_iflag &= ~IXANY;    termio.c_iflag |= IXON | IXOFF;    termio.c_cc[VMIN] = 1;    termio.c_cc[VTIME] = 0;    if ( ioctl(ttyi, TCSETA, &termio) == -1 )	error(FATAL, "ioctl error - TCSETA");    return(TRUE);}   /* End of resetline *//*****************************************************************************/setupstdin(mode)    int		mode;			/* what to do with stdin settings */{    struct termio		termio;    static int			saved = FALSE;    static struct termio	oldtermio;/* * * Save (mode = 0), reset (mode = 1), or restore (mode = 2) the tty settings for * stdin. Expect something like raw mode with no echo will be set up. Explicit * code to ensure blocking reads probably isn't needed because blocksize is set * to 1 when we're in interactive mode, but I've included it anyway. * */    if ( interactive == TRUE )	switch ( mode )  {	    case 0:		if ( isatty(0) != 1 )		    error(FATAL, "stdin not a terminal - can't run interactive mode");		if ( ioctl(0, TCGETA, &oldtermio) == -1 )		    error(FATAL, "can't save terminal settings");		saved = TRUE;		break;	    case 1:		termio = oldtermio;		termio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);		termio.c_cc[VMIN] = 1;		termio.c_cc[VTIME] = 0;		ioctl(0, TCSETA, &termio);		break;	    case 2:		if ( saved == TRUE )		    ioctl(0, TCSETA, &oldtermio);		break;	}   /* End switch */}   /* End of setupstdin *//*****************************************************************************/readline(){    int		n;			/* read() return value */    int		ch;			/* for interactive mode */    static int	tries = 0;		/* consecutive times read returned 0 *//* * * Reads characters coming back from the printer on ttyi up to a newline (or EOF) * or until no more characters are available. Characters are put in mesg[], the * string is terminated with '\0' when we're done with a line and TRUE is returned * to the caller. If complete line wasn't available FALSE is returned. Interactive * mode should loop here forever, except during start(), echoing characters to * stdout. If it happens to leave FALSE should be returned. The non-blocking read * gets us out until split() is called. * * Some users (apparently just on 3B2 DKHOST systems) have had problems with the * two process implementation that's forced me to kludge things up some. When a * printer (on those systems) is turned off while postio is transmitting files * the write process hangs in writeblock() (postio.c) - it's typically in the * middle of a write() call, while the read() call (below) continually returns 0. * In the original code readline() returned FALSE when read() returned 0 and we * get into a loop that never ends - because the write process is hung. In the * one process implementation having read return 0 is legitimate because the line * is opened for no delay, but with two processes the read() blocks and a return * value of 0 should never occur. From my point of view the real problem is that * the write() call hangs on 3B2 DKHOST systems and apparently doesn't anywhere * else. If the write returned anything less than or equal to 0 writeblock() would * shut things down. The kludge I've implemented counts the number of consecutive * times read() returns a 0 and if it exceeds a limit (100) the read process will * shut things down. In fact one return of 0 from read() when we're in the two * process mode is undoubtedly sufficient and no counting should be necessary!!! * Moving the check to getstatus() should also work and is probably where things * belong. * */    if ( interactive == FALSE )  {	while ( (n = read(ttyi, ptr, 1)) != 0 )  {	    if ( n < 0 )		if ( errno == EINTR )		    continue;		else error(FATAL, "error reading %s", line);	    tries = 0;	    if ( *ptr == '\n' || *ptr == '\004' || ptr >= endmesg )  {		*(ptr+1) = '\0';		if ( *ptr == '\004' )		    strcpy(ptr, "%%[ status: endofjob ]%%\n");		ptr = mesg;		return(TRUE);	    }   /* End if */	    ptr++;	}   /* End while */	if ( canread == TRUE && canwrite == FALSE )	/* read process kludge */	    if ( ++tries > 100 )		error(FATAL, "printer appears to be offline - shutting down");	return(FALSE);    }	/* End if */    if ( canwrite == TRUE )		/* don't block during start() */	return(FALSE);    while ( (ch = getc(fp_ttyi)) != EOF )	putc(ch, stdout);    return(FALSE);}   /* End of readline */#endif/*****************************************************************************/#ifdef V9#include <ipc.h>char	tbuf[256];			/* temporary input buffer */char	*nptr = tbuf;			/* next character comes from here */char	*eptr = tbuf;			/* one past the last character in tbuf */setupline(){    struct sgttyb	sgtty;    struct ttydevb	ttydev;		/* for setting up the line */    static struct tchars	tchar = { '\377',	/* interrupt */					  '\377',	/* quit */					  '\021',	/* start output */					  '\023',	/* stop output */					  '\377',	/* end-of-file */					  '\377'	/* input delimiter */					};/* * * Line initialization for V9. * */    if ( line == NULL )  {	ttyi = ttyo = 1;	return;    }	/* End if */    alarm(120);			/* watch for hanging opens */    if ( line[0] == '/' ) {	if ( (ttyi = open(line, O_RDWR)) == -1 )	error(FATAL, "can't open %s", line);    } else if ((ttyi = ipcopen(ipcpath(line, "dk", 0), "")) < 0) {		sleep(5);	/* wait for Datakit to hangup */		if ((ttyi = ipcopen(ipcpath(line, "dk", 0), "")) < 0) {			fprintf(stderr, "%s", errstr);			error(FATAL, "can't ipcopen %s", line);		}    }    alarm(0);    if ( (ttyo = dup(ttyi)) == -1 )	error(FATAL, "can't dup file descriptor for %s", line);    if ( ioctl(ttyi, FIOPUSHLD, &tty_ld) == -1 )	error(FATAL, "ioctl error - FIOPUSHLD");    if ( ioctl(ttyi, TIOCGDEV, &ttydev) == -1 )	error(FATAL, "ioctl error - TIOCGDEV");    if ( ioctl(ttyi, TIOCGETP, &sgtty) == -1 )	error(FATAL, "ioctl error - TIOCGETP");    sgtty.sg_flags &= ~ECHO;    sgtty.sg_flags &= ~CRMOD;    sgtty.sg_flags |= CBREAK;    ttydev.ispeed = baudrate;    ttydev.ospeed = baudrate;    if ( ioctl(ttyi, TIOCSDEV, &ttydev) == -1 )	error(FATAL, "ioctl error - TIOCSDEV");    if ( ioctl(ttyi, TIOCSETP, &sgtty) == -1 )	error(FATAL, "ioctl error - TIOCSETP");    if ( ioctl(ttyi, TIOCSETC, &tchar) == -1 )	error(FATAL, "ioctl error - TIOCSETC");    fp_ttyi = fdopen(ttyi, "r");}   /* End of setupline *//*****************************************************************************/resetline(){    struct sgttyb	sgtty;/* * * Only used if we're running the program as separate read and write processes. * Called from split() after the initial connection has been made and returns * TRUE if two processes should work. Haven't tested or even compiled the stuff * for separate read and write processes on Ninth Edition systems - no guarantees * even though we return TRUE! * */    if ( ioctl(ttyi, TIOCGETP, &sgtty) == -1 )	error(FATAL, "ioctl error - TIOCGETP");    sgtty.sg_flags |= TANDEM;    if ( ioctl(ttyi, TIOCSETP, &sgtty) == -1 )	error(FATAL, "ioctl error - TIOCSETP");    return(TRUE);}   /* End of resetline *//*****************************************************************************/setupstdin(mode)    int		mode;			/* what to do with stdin settings */{    struct sgttyb		sgtty;    static int			saved = FALSE;    static struct sgttyb	oldsgtty;/* * * Save (mode = 0), reset (mode = 1), or restore (mode = 2) the tty settings for * stdin. Expect something like raw mode with no echo will be set up. Need to make * sure interrupt and quit still work - they're the only good way to exit when * we're running interactive mode. I haven't tested or even compiled this code * so there are no guarantees. * */    if ( interactive == TRUE )	switch ( mode )  {	    case 0:		if ( ioctl(0, TIOCGETP, &oldsgtty) == -1 )		    error(FATAL, "can't save terminal settings");		saved = TRUE;		break;	    case 1:		sgtty = oldsgtty;		sgtty.sg_flags &= ~ECHO;		sgtty.sg_flags |= CBREAK;		ioctl(0, TIOCSETP, &sgtty);		break;	    case 2:		if ( saved == TRUE )		    ioctl(0, TIOCSETP, &oldsgtty);		break;	}   /* End switch */}   /* End of setupstdin *//*****************************************************************************/readline(){    int		n;			/* read() return value */    int		ch;			/* for interactive mode *//* * * Reads characters coming back from the printer on ttyi up to a newline (or EOF) * and transfers each line to the mesg[] array. Everything available on ttyi is * initially stored in tbuf[] and a line at a time is transferred from there to

⌨️ 快捷键说明

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