|
|
1.1 root 1: /*
2: *
3: * Conditionally compiled routines for setting up and reading the line. Things
4: * were getting out of hand with all the ifdefs, and even though this defeats
5: * part of the purpose of conditional complilation directives, I think it's easier
6: * to follow this way. Thanks to Alan Buckwalter for the System V DKHOST code.
7: *
8: * postio now can be run as separate read and write processes, but requires that
9: * you write a procedure called resetline() and perhaps modify readline() some.
10: * I've already tested the code on System V and it seems to work. Ninth Edition
11: * and BSD code may be missing.
12: *
13: * By request I've changed the way some of the setupline() procedures (eg. in the
14: * System V implementation) handle things when no line has been given. If line is
15: * NULL the new setupline() procedures try to continue, assuming whoever called
16: * postio connected stdout to the printer. Things will only work if we can read
17: * and write stdout!
18: *
19: */
20:
21: #include <stdio.h>
22: #include <ctype.h>
23: #include <fcntl.h>
24: #include <signal.h>
25: #include <sys/types.h>
26: #include <errno.h>
27:
28: #include "ifdef.h" /* conditional header file inclusion */
29: #include "gen.h" /* general purpose definitions */
30:
31: FILE *fp_ttyi, *fp_ttyo;
32: char *ptr = mesg;
33:
34: extern int window_size;
35:
36: /*****************************************************************************/
37:
38: #ifdef SYSV
39: setupline()
40:
41: {
42:
43: struct termio termio;
44:
45: /*
46: *
47: * Line initialization for SYSV. For now if no line is given (ie. line == NULL )
48: * we continue on as before using stdout as ttyi and ttyo. Doesn't work when we're
49: * running in interactive mode or forcing stuff that comes back from the printer
50: * to stdout. Both cases are now caught by a test that's been added to routine
51: * initialize(). The change is primarily for the version of lp that's available
52: * with SVR3.2.
53: *
54: */
55:
56: #ifdef DKHOST
57: if ( line != NULL && *line != '/' ) {
58: if ( strncmp(line, "DK:", 3) == 0 )
59: line += 3;
60: dkhost_connect();
61: #ifdef DKSTREAMS
62: if ( ioctl(ttyi, I_PUSH, DKSTREAMS) == -1 )
63: error(FATAL, "ioctl error - %s", DKSTREAMS);
64: if ( ioctl(ttyi, I_PUSH, "ldterm") == -1 )
65: error(FATAL, "ioctl error - ldterm");
66: #endif
67: } else
68: #endif
69:
70: if ( line == NULL )
71: ttyi = fileno(stdout);
72: else if ( (ttyi = open(line, O_RDWR)) == -1 )
73: error(FATAL, "can't open %s", line);
74:
75: if ( (ttyo = dup(ttyi)) == -1 )
76: error(FATAL, "can't dup file descriptor for %s", line);
77:
78: if ( stopbits == 1 )
79: stopbits = 0;
80: else stopbits = CSTOPB;
81:
82: if ( fcntl(ttyi, F_SETFL, O_NDELAY) == -1 )
83: error(FATAL, "fcntl error - F_SETFL");
84:
85: if ( ioctl(ttyi, TCGETA, &termio) == -1 )
86: error(FATAL, "ioctl error - TCGETA");
87:
88: termio.c_iflag = IXON | IGNCR;
89: termio.c_oflag = 0;
90: termio.c_cflag = HUPCL | CREAD | CS8 | stopbits | baudrate;
91: termio.c_lflag = 0;
92: termio.c_cc[VMIN] = termio.c_cc[VTIME] = 0;
93:
94: if ( ioctl(ttyi, TCSETA, &termio) == -1 )
95: error(FATAL, "ioctl error - TCSETA");
96:
97: if ( ioctl(ttyi, TCFLSH, 2) == -1 )
98: error(FATAL, "ioctl error - TCFLSH");
99:
100: fp_ttyi = fdopen(ttyi, "r");
101:
102: } /* End of setupline */
103:
104: /*****************************************************************************/
105:
106: resetline()
107:
108: {
109:
110: int flags; /* for turning O_NDELAY off */
111: struct termio termio; /* so we can reset flow control */
112:
113: /*
114: *
115: * Only used if we're running the program as separate read and write processes.
116: * Called from split() after the initial connection has been made and returns
117: * TRUE if two processes should work. Don't know if the O_NDELAY stuff is really
118: * needed, but setting c_cc[VMIN] to 1 definitely is. If we leave it be (as a 0)
119: * the read in readline() won't block!
120: *
121: */
122:
123: if ( (flags = fcntl(ttyi, F_GETFL, 0)) == -1 )
124: error(FATAL, "fcntl error - F_GETFL");
125:
126: flags &= ~O_NDELAY;
127:
128: if ( fcntl(ttyi, F_SETFL, flags) == -1 )
129: error(FATAL, "fcntl error - F_SETFL");
130:
131: if ( ioctl(ttyi, TCGETA, &termio) == -1 )
132: error(FATAL, "ioctl error - TCGETA");
133:
134: termio.c_iflag &= ~IXANY;
135: termio.c_iflag |= IXON | IXOFF;
136: termio.c_cc[VMIN] = 1;
137: termio.c_cc[VTIME] = 0;
138:
139: if ( ioctl(ttyi, TCSETA, &termio) == -1 )
140: error(FATAL, "ioctl error - TCSETA");
141:
142: return(TRUE);
143:
144: } /* End of resetline */
145:
146: /*****************************************************************************/
147:
148: setupstdin(mode)
149:
150: int mode; /* what to do with stdin settings */
151:
152: {
153:
154: struct termio termio;
155:
156: static int saved = FALSE;
157: static struct termio oldtermio;
158:
159: /*
160: *
161: * Save (mode = 0), reset (mode = 1), or restore (mode = 2) the tty settings for
162: * stdin. Expect something like raw mode with no echo will be set up. Explicit
163: * code to ensure blocking reads probably isn't needed because blocksize is set
164: * to 1 when we're in interactive mode, but I've included it anyway.
165: *
166: */
167:
168: if ( interactive == TRUE )
169: switch ( mode ) {
170: case 0:
171: if ( isatty(0) != 1 )
172: error(FATAL, "stdin not a terminal - can't run interactive mode");
173: if ( ioctl(0, TCGETA, &oldtermio) == -1 )
174: error(FATAL, "can't save terminal settings");
175: saved = TRUE;
176: break;
177:
178: case 1:
179: termio = oldtermio;
180: termio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
181: termio.c_cc[VMIN] = 1;
182: termio.c_cc[VTIME] = 0;
183: ioctl(0, TCSETA, &termio);
184: break;
185:
186: case 2:
187: if ( saved == TRUE )
188: ioctl(0, TCSETA, &oldtermio);
189: break;
190: } /* End switch */
191:
192: } /* End of setupstdin */
193:
194: /*****************************************************************************/
195:
196: readline()
197:
198: {
199:
200: int n; /* read() return value */
201: int ch; /* for interactive mode */
202:
203: static int tries = 0; /* consecutive times read returned 0 */
204:
205: /*
206: *
207: * Reads characters coming back from the printer on ttyi up to a newline (or EOF)
208: * or until no more characters are available. Characters are put in mesg[], the
209: * string is terminated with '\0' when we're done with a line and TRUE is returned
210: * to the caller. If complete line wasn't available FALSE is returned. Interactive
211: * mode should loop here forever, except during start(), echoing characters to
212: * stdout. If it happens to leave FALSE should be returned. The non-blocking read
213: * gets us out until split() is called.
214: *
215: * Some users (apparently just on 3B2 DKHOST systems) have had problems with the
216: * two process implementation that's forced me to kludge things up some. When a
217: * printer (on those systems) is turned off while postio is transmitting files
218: * the write process hangs in writeblock() (postio.c) - it's typically in the
219: * middle of a write() call, while the read() call (below) continually returns 0.
220: * In the original code readline() returned FALSE when read() returned 0 and we
221: * get into a loop that never ends - because the write process is hung. In the
222: * one process implementation having read return 0 is legitimate because the line
223: * is opened for no delay, but with two processes the read() blocks and a return
224: * value of 0 should never occur. From my point of view the real problem is that
225: * the write() call hangs on 3B2 DKHOST systems and apparently doesn't anywhere
226: * else. If the write returned anything less than or equal to 0 writeblock() would
227: * shut things down. The kludge I've implemented counts the number of consecutive
228: * times read() returns a 0 and if it exceeds a limit (100) the read process will
229: * shut things down. In fact one return of 0 from read() when we're in the two
230: * process mode is undoubtedly sufficient and no counting should be necessary!!!
231: * Moving the check to getstatus() should also work and is probably where things
232: * belong.
233: *
234: */
235:
236: if ( interactive == FALSE ) {
237: while ( (n = read(ttyi, ptr, 1)) != 0 ) {
238: if ( n < 0 )
239: if ( errno == EINTR )
240: continue;
241: else error(FATAL, "error reading %s", line);
242: tries = 0;
243: if ( *ptr == '\n' || *ptr == '\004' || ptr >= endmesg ) {
244: *(ptr+1) = '\0';
245: if ( *ptr == '\004' )
246: strcpy(ptr, "%%[ status: endofjob ]%%\n");
247: ptr = mesg;
248: return(TRUE);
249: } /* End if */
250: ptr++;
251: } /* End while */
252: if ( canread == TRUE && canwrite == FALSE ) /* read process kludge */
253: if ( ++tries > 100 )
254: error(FATAL, "printer appears to be offline - shutting down");
255: return(FALSE);
256: } /* End if */
257:
258: if ( canwrite == TRUE ) /* don't block during start() */
259: return(FALSE);
260:
261: while ( (ch = getc(fp_ttyi)) != EOF )
262: putc(ch, stdout);
263: return(FALSE);
264:
265: } /* End of readline */
266: #endif
267:
268: /*****************************************************************************/
269:
270: #ifdef V9
271: #include <ipc.h>
272:
273: char tbuf[256]; /* temporary input buffer */
274: char *nptr = tbuf; /* next character comes from here */
275: char *eptr = tbuf; /* one past the last character in tbuf */
276:
277: setupline()
278:
279: {
280:
281: struct sgttyb sgtty;
282: struct ttydevb ttydev; /* for setting up the line */
283: static struct tchars tchar = { '\377', /* interrupt */
284: '\377', /* quit */
285: '\021', /* start output */
286: '\023', /* stop output */
287: '\377', /* end-of-file */
288: '\377' /* input delimiter */
289: };
290:
291: /*
292: *
293: * Line initialization for V9.
294: *
295: */
296:
297: if ( line == NULL ) {
298: ttyi = ttyo = 1;
299: return;
300: } /* End if */
301: alarm(120); /* watch for hanging opens */
302: if ( line[0] == '/' ) {
303: if ( (ttyi = open(line, O_RDWR)) == -1 )
304: error(FATAL, "can't open %s", line);
305: } else if ((ttyi = ipcopen(ipcpath(line, "dk", 0), "")) < 0) {
306: sleep(5); /* wait for Datakit to hangup */
307: if ((ttyi = ipcopen(ipcpath(line, "dk", 0), "")) < 0) {
308: fprintf(stderr, "%s", errstr);
309: error(FATAL, "can't ipcopen %s", line);
310: }
311: }
312: alarm(0);
313:
314: if ( (ttyo = dup(ttyi)) == -1 )
315: error(FATAL, "can't dup file descriptor for %s", line);
316:
317: if ( ioctl(ttyi, FIOPUSHLD, &tty_ld) == -1 )
318: error(FATAL, "ioctl error - FIOPUSHLD");
319:
320: if ( ioctl(ttyi, TIOCGDEV, &ttydev) == -1 )
321: error(FATAL, "ioctl error - TIOCGDEV");
322:
323: if ( ioctl(ttyi, TIOCGETP, &sgtty) == -1 )
324: error(FATAL, "ioctl error - TIOCGETP");
325:
326: sgtty.sg_flags &= ~ECHO;
327: sgtty.sg_flags &= ~CRMOD;
328: sgtty.sg_flags |= CBREAK;
329: ttydev.ispeed = baudrate;
330: ttydev.ospeed = baudrate;
331:
332: if ( ioctl(ttyi, TIOCSDEV, &ttydev) == -1 )
333: error(FATAL, "ioctl error - TIOCSDEV");
334:
335: if ( ioctl(ttyi, TIOCSETP, &sgtty) == -1 )
336: error(FATAL, "ioctl error - TIOCSETP");
337:
338: if ( ioctl(ttyi, TIOCSETC, &tchar) == -1 )
339: error(FATAL, "ioctl error - TIOCSETC");
340:
341: fp_ttyi = fdopen(ttyi, "r");
342:
343: } /* End of setupline */
344:
345: /*****************************************************************************/
346:
347: resetline()
348:
349: {
350:
351: struct sgttyb sgtty;
352:
353: /*
354: *
355: * Only used if we're running the program as separate read and write processes.
356: * Called from split() after the initial connection has been made and returns
357: * TRUE if two processes should work. Haven't tested or even compiled the stuff
358: * for separate read and write processes on Ninth Edition systems - no guarantees
359: * even though we return TRUE!
360: *
361: */
362:
363: if ( ioctl(ttyi, TIOCGETP, &sgtty) == -1 )
364: error(FATAL, "ioctl error - TIOCGETP");
365:
366: sgtty.sg_flags |= TANDEM;
367:
368: if ( ioctl(ttyi, TIOCSETP, &sgtty) == -1 )
369: error(FATAL, "ioctl error - TIOCSETP");
370:
371: return(TRUE);
372:
373: } /* End of resetline */
374:
375: /*****************************************************************************/
376:
377: setupstdin(mode)
378:
379: int mode; /* what to do with stdin settings */
380:
381: {
382:
383: struct sgttyb sgtty;
384:
385: static int saved = FALSE;
386: static struct sgttyb oldsgtty;
387:
388: /*
389: *
390: * Save (mode = 0), reset (mode = 1), or restore (mode = 2) the tty settings for
391: * stdin. Expect something like raw mode with no echo will be set up. Need to make
392: * sure interrupt and quit still work - they're the only good way to exit when
393: * we're running interactive mode. I haven't tested or even compiled this code
394: * so there are no guarantees.
395: *
396: */
397:
398: if ( interactive == TRUE )
399: switch ( mode ) {
400: case 0:
401: if ( ioctl(0, TIOCGETP, &oldsgtty) == -1 )
402: error(FATAL, "can't save terminal settings");
403: saved = TRUE;
404: break;
405:
406: case 1:
407: sgtty = oldsgtty;
408: sgtty.sg_flags &= ~ECHO;
409: sgtty.sg_flags |= CBREAK;
410: ioctl(0, TIOCSETP, &sgtty);
411: break;
412:
413: case 2:
414: if ( saved == TRUE )
415: ioctl(0, TIOCSETP, &oldsgtty);
416: break;
417: } /* End switch */
418:
419: } /* End of setupstdin */
420:
421: /*****************************************************************************/
422:
423: readline()
424:
425: {
426:
427: int n; /* read() return value */
428: int ch; /* for interactive mode */
429:
430: /*
431: *
432: * Reads characters coming back from the printer on ttyi up to a newline (or EOF)
433: * and transfers each line to the mesg[] array. Everything available on ttyi is
434: * initially stored in tbuf[] and a line at a time is transferred from there to
435: * mesg[]. The string in mesg[] is terminated with a '\0' and TRUE is returned to
436: * the caller when we find a newline, EOF, or reach the end of the mesg[] array.
437: * If nothing is available on ttyi we return FALSE if a single process is being
438: * used for reads and writes, while in the two process implementation we force a
439: * one character read. Interactive mode loops here forever, except during start(),
440: * echoing everything that comes back on ttyi to stdout. The performance of a
441: * simple getc/putc loop for interactive mode was unacceptable when run under mux
442: * and has been replaced by more complicated code. When layers wasn't involved
443: * the getc/putc loop worked well.
444: *
445: */
446:
447: if ( interactive == FALSE ) {
448: while ( 1 ) {
449: while ( nptr < eptr ) { /* grab characters from tbuf */
450: *ptr = *nptr++;
451: if ( *ptr == '\r' ) continue;
452: if ( *ptr == '\n' || *ptr == '\004' || ptr >= endmesg ) {
453: *(ptr+1) = '\0';
454: if ( *ptr == '\004' )
455: strcpy(ptr, "%%[ status: endofjob ]%%\n");
456: ptr = mesg;
457: return(TRUE);
458: } /* End if */
459: ++ptr;
460: } /* End for */
461:
462: nptr = eptr = tbuf;
463: if ( ioctl(ttyi, FIONREAD, &n) < 0 )
464: if ( errno == EINTR )
465: continue;
466: else error(FATAL, "ioctl error - FIONREAD");
467: if ( n <= 0 )
468: if ( canwrite == TRUE )
469: return(FALSE);
470: n = ((n < 1) ? 1 : ((n < sizeof(tbuf)) ? n : sizeof(tbuf)));
471: if ( (n = read(ttyi, tbuf, n)) < 0 )
472: if ( errno == EINTR )
473: continue;
474: else error(FATAL, "error reading line %s", line);
475: else eptr = nptr + n;
476: } /* End while */
477: } /* End if */
478:
479: if ( canwrite == TRUE ) /* don't block during start() */
480: return(FALSE);
481:
482: while ( 1 ) { /* only interactive mode gets here */
483: if ( ioctl(ttyi, FIONREAD, &n) < 0 )
484: error(FATAL, "ioctl error - FIONREAD");
485: n = ((n < 1) ? 1 : ((n < sizeof(tbuf)) ? n : sizeof(tbuf)));
486: if ( (n = read(ttyi, tbuf, n)) < 0 )
487: error(FATAL, "error reading line %s", line);
488: else if ( n == 0 ) /* should not happen */
489: error(FATAL, "end of file in interactive mode");
490: if ( write(1, tbuf, n) != n )
491: error(FATAL, "error writing to stdout");
492: } /* End while */
493:
494: return(FALSE);
495:
496: } /* End of readline */
497: #endif
498:
499: /*****************************************************************************/
500:
501: #ifdef BSD4_2
502: setupline()
503:
504: {
505:
506: struct sgttyb sgtty;
507: static struct tchars tchar = { '\377', /* interrupt */
508: '\377', /* quit */
509: '\021', /* start output */
510: '\023', /* stop output */
511: '\377', /* end-of-file */
512: '\377' /* input delimiter */
513: };
514: long lmodes;
515: int disc = NTTYDISC;
516:
517: /*
518: *
519: * Line initialization for BSD4_2. As in the System V code, if no line is given
520: * (ie. line == NULL) we continue on as before using stdout as ttyi and ttyo.
521: *
522: */
523:
524: if ( line == NULL )
525: ttyi = fileno(stdout);
526: else if ( (ttyi = open(line, O_RDWR)) == -1 )
527: error(FATAL, "can't open %s", line);
528:
529: if ( (ttyo = dup(ttyi)) == -1 )
530: error(FATAL, "can't dup file descriptor for %s", line);
531:
532: if (ioctl(ttyi, TIOCSETD, &disc) == -1 )
533: error(FATAL, "ioctl error - TIOCSETD");
534:
535: if ( ioctl(ttyi, TIOCGETP, &sgtty) == -1 )
536: error(FATAL, "ioctl error - TIOCGETP");
537:
538: if ( ioctl(ttyi, TIOCLGET, &lmodes) == -1 )
539: error(FATAL, "ioctl error - TIOCLGET");
540:
541: sgtty.sg_flags &= ~ECHO;
542: sgtty.sg_flags &= ~CRMOD;
543: sgtty.sg_flags |= CBREAK;
544: sgtty.sg_ispeed = baudrate;
545: sgtty.sg_ospeed = baudrate;
546: lmodes |= LDECCTQ;
547:
548: if ( ioctl(ttyi, TIOCSETP, &sgtty) == -1 )
549: error(FATAL, "ioctl error - TIOCSETP");
550:
551: if ( ioctl(ttyi, TIOCSETC, &tchar) == -1 )
552: error(FATAL, "ioctl error - TIOCSETC");
553:
554: if ( ioctl(ttyi, TIOCLSET, &lmodes) == -1 )
555: error(FATAL, "ioctl error - TIOCLSET");
556:
557: fp_ttyi = fdopen(ttyi, "r");
558:
559: } /* End of setupline */
560:
561: /*****************************************************************************/
562:
563: resetline()
564:
565: {
566:
567: struct sgttyb sgtty;
568:
569: /*
570: *
571: * Only used if we're running the program as separate read and write processes.
572: * Called from split() after the initial connection has been made and returns
573: * TRUE if two processes should work. Haven't tested or even compiled the stuff
574: * for separate read and write processes on Berkeley systems - no guarantees
575: * even though we return TRUE!
576: *
577: */
578:
579: if ( ioctl(ttyi, TIOCGETP, &sgtty) == -1 )
580: error(FATAL, "ioctl error - TIOCGETP");
581:
582: sgtty.sg_flags |= TANDEM;
583:
584: if ( ioctl(ttyi, TIOCSETP, &sgtty) == -1 )
585: error(FATAL, "ioctl error - TIOCSETP");
586:
587: return(TRUE);
588:
589: } /* End of resetline */
590:
591: /*****************************************************************************/
592:
593: setupstdin(mode)
594:
595: int mode; /* what to do with stdin settings */
596:
597: {
598:
599: struct sgttyb sgtty;
600:
601: static int saved = FALSE;
602: static struct sgttyb oldsgtty;
603:
604: /*
605: *
606: * Save (mode = 0), reset (mode = 1), or restore (mode = 2) the tty settings for
607: * stdin. Expect something like raw mode with no echo will be set up. Need to make
608: * sure interrupt and quit still work - they're the only good way to exit when
609: * we're running interactive mode. I haven't tested or even compiled this code
610: * so there are no guarantees.
611: *
612: */
613:
614: if ( interactive == TRUE )
615: switch ( mode ) {
616: case 0:
617: if ( isatty(0) != 1 )
618: error(FATAL, "stdin not a terminal - can't run interactive mode");
619: if ( ioctl(0, TIOCGETP, &oldsgtty) == -1 )
620: error(FATAL, "can't save terminal settings");
621: saved = TRUE;
622: break;
623:
624: case 1:
625: sgtty = oldsgtty;
626: sgtty.sg_flags &= ~ECHO;
627: sgtty.sg_flags |= CBREAK;
628: ioctl(0, TIOCSETP, &sgtty);
629: break;
630:
631: case 2:
632: if ( saved == TRUE )
633: ioctl(0, TIOCSETP, &oldsgtty);
634: break;
635: } /* End switch */
636:
637: } /* End of setupstdin */
638:
639: /*****************************************************************************/
640:
641: readline()
642:
643: {
644:
645: int n; /* read() return value */
646: int ch; /* for interactive mode */
647:
648: /*
649: *
650: * Reads characters coming back from the printer on ttyo up to a newline (or EOF)
651: * or until no more characters are available. Characters are put in mesg[], the
652: * string is terminated with '\0' when we're done with a line and TRUE is returned
653: * to the caller. If complete line wasn't available FALSE is returned. Interactive
654: * mode should loop here forever, except during start(), echoing characters to
655: * stdout. If it happens to leave FALSE should be returned. Probably should read
656: * everything available on ttyi into a temporary buffer and work from there rather
657: * than reading one character at a time.
658: *
659: */
660:
661: if ( interactive == FALSE ) {
662: while ( 1 ) {
663: if ( ioctl(ttyi, FIONREAD, &n) < 0 )
664: if ( errno == EINTR )
665: continue;
666: else error(FATAL, "ioctl error - FIONREAD");
667: if ( n <= 0 )
668: if ( canwrite == TRUE )
669: return(FALSE);
670: else n = 1;
671: for ( ; n > 0; n-- ) {
672: /*if ( read(ttyi, ptr, 1) < 0 )*/
673: if ( (*ptr = getc(fp_ttyi)) == EOF )
674: if ( errno == EINTR )
675: continue;
676: else error(FATAL, "error reading %s", line);
677: if ( *ptr == '\r' ) continue;
678: if ( *ptr == '\n' || *ptr == '\004' || ptr >= endmesg ) {
679: *(ptr+1) = '\0';
680: if ( *ptr == '\004' )
681: strcpy(ptr, "%%[ status: endofjob ]%%\n");
682: ptr = mesg;
683: return(TRUE);
684: } /* End if */
685: ++ptr;
686: } /* End for */
687: } /* End while */
688: } /* End if */
689:
690: if ( canwrite == TRUE ) /* don't block during start() */
691: return(FALSE);
692:
693: while ( (ch = getc(fp_ttyi)) != EOF )
694: putc(ch, stdout);
695: return(FALSE);
696:
697: } /* End of readline */
698:
699: /*****************************************************************************/
700:
701: /* @(#)strspn.c 1.2 */
702: /*LINTLIBRARY*/
703: /*
704: * Return the number of characters in the maximum leading segment
705: * of string which consists solely of characters from charset.
706: */
707: int
708: strspn(string, charset)
709: char *string;
710: register char *charset;
711: {
712: register char *p, *q;
713:
714: for(q=string; *q != '\0'; ++q) {
715: for(p=charset; *p != '\0' && *p != *q; ++p)
716: ;
717: if(*p == '\0')
718: break;
719: }
720: return(q-string);
721: }
722:
723: /* @(#)strpbrk.c 1.2 */
724: /*LINTLIBRARY*/
725: /*
726: * Return ptr to first occurance of any character from `brkset'
727: * in the character string `string'; NULL if none exists.
728: */
729:
730: char *
731: strpbrk(string, brkset)
732: register char *string, *brkset;
733: {
734: register char *p;
735:
736: do {
737: for(p=brkset; *p != '\0' && *p != *string; ++p)
738: ;
739: if(*p != '\0')
740: return(string);
741: }
742: while(*string++);
743: return((char*)0);
744: }
745:
746: /* @(#)strtok.c 1.2 */
747: /* 3.0 SID # 1.2 */
748: /*LINTLIBRARY*/
749: /*
750: * uses strpbrk and strspn to break string into tokens on
751: * sequentially subsequent calls. returns NULL when no
752: * non-separator characters remain.
753: * `subsequent' calls are calls with first argument NULL.
754: */
755:
756:
757: extern int strspn();
758: extern char *strpbrk();
759:
760: char *
761: strtok(string, sepset)
762: char *string, *sepset;
763: {
764: register char *p, *q, *r;
765: static char *savept;
766:
767: /*first or subsequent call*/
768: p = (string == (char*)0)? savept: string;
769:
770: if(p == 0) /* return if no tokens remaining */
771: return((char*)0);
772:
773: q = p + strspn(p, sepset); /* skip leading separators */
774:
775: if(*q == '\0') /* return if no tokens remaining */
776: return((char*)0);
777:
778: if((r = strpbrk(q, sepset)) == (char*)0) /* move past token */
779: savept = 0; /* indicate this is last token */
780: else {
781: *r = '\0';
782: savept = ++r;
783: }
784: return(q);
785: }
786: #endif
787:
788: /*****************************************************************************/
789:
790: #ifdef DKHOST
791:
792: #ifndef DKSTREAMS
793: short dkrmode[3] = {DKR_TIME, 0, 0};
794: #endif
795:
796: dkhost_connect()
797:
798: {
799:
800: int ofd; /* for saving and restoring stderr */
801: int dfd;
802: int retrytime = 5;
803:
804: /*
805: *
806: * Tries to connect to a Datakit destination. The extra stuff I've added to save
807: * and later restore stderr is primarily for our spooling setup at Murray Hill.
808: * postio is usually called with stderr directed to a file that will be returned
809: * to the user when the job finishes printing. Problems encountered by dkdial(),
810: * like busy messages, go to stderr but don't belong in the user's mail. They'll
811: * be temporarily directed to the log file. After we've connected stderr will be
812: * restored.
813: *
814: */
815:
816: if ( *line == '\0' )
817: error(FATAL, "incomplete Datakit line");
818:
819: if ( fp_log != NULL && fp_log != stderr ) { /* redirect dkdial errors */
820: ofd = dup(2);
821: close(2);
822: dup(fileno(fp_log));
823: } /* End if */
824:
825: while ( (dfd = ttyi = dkdial(line)) < 0 ) {
826: if ( retrytime < 0 )
827: error(FATAL, "can't connect to %s", line);
828: sleep(retrytime++);
829: if ( retrytime > 60 )
830: retrytime = 60;
831: } /* End while */
832:
833: if ( fp_log != NULL && fp_log != stderr ) { /* restore stderr */
834: close(2);
835: dup(ofd);
836: close(ofd);
837: } /* End if */
838:
839: #ifndef DKSTREAMS
840: if ( ioctl(ttyi, DIOCRMODE, dkrmode) == -1 )
841: error(FATAL, "ioctl error - DIOCRMODE");
842:
843: #ifdef DIOURPWD
844: if ( window_size > 0 ) {
845: short dkparm[3];
846:
847: dkparm[0] = dkminor(ttyi);
848: dkparm[1] = 1;
849: dkparm[2] = window_size;
850: if ( ioctl(ttyi, DIOURPWD, dkparm) < 0 || ioctl(ttyi, DIOCFLUSH, 0) < 0 )
851: error(NON_FATAL, "WSA failed");
852: } /* End if */
853: #endif
854:
855: line = dtnamer(dkminor(ttyi));
856:
857: if ( (ttyi = open(line, O_RDWR)) == -1 )
858: error(FATAL, "can't open %s", line);
859:
860: close(dfd);
861: #endif
862:
863: } /* End of dkhost_connect */
864: #endif
865:
866: /*****************************************************************************/
867:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.