summaryrefslogtreecommitdiff
path: root/sys/src/cmd/postscript/postio/ifdef.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/postscript/postio/ifdef.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/postscript/postio/ifdef.c')
-rwxr-xr-xsys/src/cmd/postscript/postio/ifdef.c867
1 files changed, 867 insertions, 0 deletions
diff --git a/sys/src/cmd/postscript/postio/ifdef.c b/sys/src/cmd/postscript/postio/ifdef.c
new file mode 100755
index 000000000..1d7be0905
--- /dev/null
+++ b/sys/src/cmd/postscript/postio/ifdef.c
@@ -0,0 +1,867 @@
+/*
+ *
+ * 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 SYSV
+setupline()
+
+{
+
+ 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
+ * mesg[]. The string in mesg[] is terminated with a '\0' and TRUE is returned to
+ * the caller when we find a newline, EOF, or reach the end of the mesg[] array.
+ * If nothing is available on ttyi we return FALSE if a single process is being
+ * used for reads and writes, while in the two process implementation we force a
+ * one character read. Interactive mode loops here forever, except during start(),
+ * echoing everything that comes back on ttyi to stdout. The performance of a
+ * simple getc/putc loop for interactive mode was unacceptable when run under mux
+ * and has been replaced by more complicated code. When layers wasn't involved
+ * the getc/putc loop worked well.
+ *
+ */
+
+ if ( interactive == FALSE ) {
+ while ( 1 ) {
+ while ( nptr < eptr ) { /* grab characters from tbuf */
+ *ptr = *nptr++;
+ if ( *ptr == '\r' ) continue;
+ 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 for */
+
+ nptr = eptr = tbuf;
+ if ( ioctl(ttyi, FIONREAD, &n) < 0 )
+ if ( errno == EINTR )
+ continue;
+ else error(FATAL, "ioctl error - FIONREAD");
+ if ( n <= 0 )
+ if ( canwrite == TRUE )
+ return(FALSE);
+ n = ((n < 1) ? 1 : ((n < sizeof(tbuf)) ? n : sizeof(tbuf)));
+ if ( (n = read(ttyi, tbuf, n)) < 0 )
+ if ( errno == EINTR )
+ continue;
+ else error(FATAL, "error reading line %s", line);
+ else eptr = nptr + n;
+ } /* End while */
+ } /* End if */
+
+ if ( canwrite == TRUE ) /* don't block during start() */
+ return(FALSE);
+
+ while ( 1 ) { /* only interactive mode gets here */
+ if ( ioctl(ttyi, FIONREAD, &n) < 0 )
+ error(FATAL, "ioctl error - FIONREAD");
+ n = ((n < 1) ? 1 : ((n < sizeof(tbuf)) ? n : sizeof(tbuf)));
+ if ( (n = read(ttyi, tbuf, n)) < 0 )
+ error(FATAL, "error reading line %s", line);
+ else if ( n == 0 ) /* should not happen */
+ error(FATAL, "end of file in interactive mode");
+ if ( write(1, tbuf, n) != n )
+ error(FATAL, "error writing to stdout");
+ } /* End while */
+
+ return(FALSE);
+
+} /* End of readline */
+#endif
+
+/*****************************************************************************/
+
+#ifdef BSD4_2
+setupline()
+
+{
+
+ struct sgttyb sgtty;
+ static struct tchars tchar = { '\377', /* interrupt */
+ '\377', /* quit */
+ '\021', /* start output */
+ '\023', /* stop output */
+ '\377', /* end-of-file */
+ '\377' /* input delimiter */
+ };
+ long lmodes;
+ int disc = NTTYDISC;
+
+/*
+ *
+ * Line initialization for BSD4_2. As in the System V code, if no line is given
+ * (ie. line == NULL) we continue on as before using stdout as ttyi and ttyo.
+ *
+ */
+
+ 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 (ioctl(ttyi, TIOCSETD, &disc) == -1 )
+ error(FATAL, "ioctl error - TIOCSETD");
+
+ if ( ioctl(ttyi, TIOCGETP, &sgtty) == -1 )
+ error(FATAL, "ioctl error - TIOCGETP");
+
+ if ( ioctl(ttyi, TIOCLGET, &lmodes) == -1 )
+ error(FATAL, "ioctl error - TIOCLGET");
+
+ sgtty.sg_flags &= ~ECHO;
+ sgtty.sg_flags &= ~CRMOD;
+ sgtty.sg_flags |= CBREAK;
+ sgtty.sg_ispeed = baudrate;
+ sgtty.sg_ospeed = baudrate;
+ lmodes |= LDECCTQ;
+
+ if ( ioctl(ttyi, TIOCSETP, &sgtty) == -1 )
+ error(FATAL, "ioctl error - TIOCSETP");
+
+ if ( ioctl(ttyi, TIOCSETC, &tchar) == -1 )
+ error(FATAL, "ioctl error - TIOCSETC");
+
+ if ( ioctl(ttyi, TIOCLSET, &lmodes) == -1 )
+ error(FATAL, "ioctl error - TIOCLSET");
+
+ 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 Berkeley 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 ( isatty(0) != 1 )
+ error(FATAL, "stdin not a terminal - can't run interactive mode");
+ 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 ttyo 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. Probably should read
+ * everything available on ttyi into a temporary buffer and work from there rather
+ * than reading one character at a time.
+ *
+ */
+
+ if ( interactive == FALSE ) {
+ while ( 1 ) {
+ if ( ioctl(ttyi, FIONREAD, &n) < 0 )
+ if ( errno == EINTR )
+ continue;
+ else error(FATAL, "ioctl error - FIONREAD");
+ if ( n <= 0 )
+ if ( canwrite == TRUE )
+ return(FALSE);
+ else n = 1;
+ for ( ; n > 0; n-- ) {
+ /*if ( read(ttyi, ptr, 1) < 0 )*/
+ if ( (*ptr = getc(fp_ttyi)) == EOF )
+ if ( errno == EINTR )
+ continue;
+ else error(FATAL, "error reading %s", line);
+ if ( *ptr == '\r' ) continue;
+ 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 for */
+ } /* End while */
+ } /* 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 */
+
+/*****************************************************************************/
+
+/* @(#)strspn.c 1.2 */
+/*LINTLIBRARY*/
+/*
+ * Return the number of characters in the maximum leading segment
+ * of string which consists solely of characters from charset.
+ */
+int
+strspn(string, charset)
+char *string;
+register char *charset;
+{
+ register char *p, *q;
+
+ for(q=string; *q != '\0'; ++q) {
+ for(p=charset; *p != '\0' && *p != *q; ++p)
+ ;
+ if(*p == '\0')
+ break;
+ }
+ return(q-string);
+}
+
+/* @(#)strpbrk.c 1.2 */
+/*LINTLIBRARY*/
+/*
+ * Return ptr to first occurance of any character from `brkset'
+ * in the character string `string'; NULL if none exists.
+ */
+
+char *
+strpbrk(string, brkset)
+register char *string, *brkset;
+{
+ register char *p;
+
+ do {
+ for(p=brkset; *p != '\0' && *p != *string; ++p)
+ ;
+ if(*p != '\0')
+ return(string);
+ }
+ while(*string++);
+ return((char*)0);
+}
+
+/* @(#)strtok.c 1.2 */
+/* 3.0 SID # 1.2 */
+/*LINTLIBRARY*/
+/*
+ * uses strpbrk and strspn to break string into tokens on
+ * sequentially subsequent calls. returns NULL when no
+ * non-separator characters remain.
+ * `subsequent' calls are calls with first argument NULL.
+ */
+
+
+extern int strspn();
+extern char *strpbrk();
+
+char *
+strtok(string, sepset)
+char *string, *sepset;
+{
+ register char *p, *q, *r;
+ static char *savept;
+
+ /*first or subsequent call*/
+ p = (string == (char*)0)? savept: string;
+
+ if(p == 0) /* return if no tokens remaining */
+ return((char*)0);
+
+ q = p + strspn(p, sepset); /* skip leading separators */
+
+ if(*q == '\0') /* return if no tokens remaining */
+ return((char*)0);
+
+ if((r = strpbrk(q, sepset)) == (char*)0) /* move past token */
+ savept = 0; /* indicate this is last token */
+ else {
+ *r = '\0';
+ savept = ++r;
+ }
+ return(q);
+}
+#endif
+
+/*****************************************************************************/
+
+#ifdef DKHOST
+
+#ifndef DKSTREAMS
+short dkrmode[3] = {DKR_TIME, 0, 0};
+#endif
+
+dkhost_connect()
+
+{
+
+ int ofd; /* for saving and restoring stderr */
+ int dfd;
+ int retrytime = 5;
+
+/*
+ *
+ * Tries to connect to a Datakit destination. The extra stuff I've added to save
+ * and later restore stderr is primarily for our spooling setup at Murray Hill.
+ * postio is usually called with stderr directed to a file that will be returned
+ * to the user when the job finishes printing. Problems encountered by dkdial(),
+ * like busy messages, go to stderr but don't belong in the user's mail. They'll
+ * be temporarily directed to the log file. After we've connected stderr will be
+ * restored.
+ *
+ */
+
+ if ( *line == '\0' )
+ error(FATAL, "incomplete Datakit line");
+
+ if ( fp_log != NULL && fp_log != stderr ) { /* redirect dkdial errors */
+ ofd = dup(2);
+ close(2);
+ dup(fileno(fp_log));
+ } /* End if */
+
+ while ( (dfd = ttyi = dkdial(line)) < 0 ) {
+ if ( retrytime < 0 )
+ error(FATAL, "can't connect to %s", line);
+ sleep(retrytime++);
+ if ( retrytime > 60 )
+ retrytime = 60;
+ } /* End while */
+
+ if ( fp_log != NULL && fp_log != stderr ) { /* restore stderr */
+ close(2);
+ dup(ofd);
+ close(ofd);
+ } /* End if */
+
+#ifndef DKSTREAMS
+ if ( ioctl(ttyi, DIOCRMODE, dkrmode) == -1 )
+ error(FATAL, "ioctl error - DIOCRMODE");
+
+#ifdef DIOURPWD
+ if ( window_size > 0 ) {
+ short dkparm[3];
+
+ dkparm[0] = dkminor(ttyi);
+ dkparm[1] = 1;
+ dkparm[2] = window_size;
+ if ( ioctl(ttyi, DIOURPWD, dkparm) < 0 || ioctl(ttyi, DIOCFLUSH, 0) < 0 )
+ error(NON_FATAL, "WSA failed");
+ } /* End if */
+#endif
+
+ line = dtnamer(dkminor(ttyi));
+
+ if ( (ttyi = open(line, O_RDWR)) == -1 )
+ error(FATAL, "can't open %s", line);
+
+ close(dfd);
+#endif
+
+} /* End of dkhost_connect */
+#endif
+
+/*****************************************************************************/
+