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