|
|
1.1 root 1: /* EMACS_MODES: c !fill */
2: #ifdef v8
3: #include <sys/types.h>
4: #endif
5: #include "emacs_gb.h"
6: #include "emacs_io.h"
7: #ifndef PC
8: #include <signal.h>
9: #endif
10: #ifdef bsd
11: #include <sys/time.h>
12: #else
13: #include <time.h>
14: #endif
15: #include <errno.h>
16: #ifdef ux3
17: #include <termio.h>
18: #else
19: #include <sgtty.h>
20: #endif
21:
22: #ifdef bsd
23:
24: /* The following defines turn on the use of the select system call
25: * and Cbreak mode for berkeley unix. If you are running a version
26: * of berkeley unix without these features, taken them out */
27:
28: #define SELECT
29: #define CBRAKE
30: #define FLIM
31: #endif
32: #ifdef ux3
33: #define FLIM
34: #endif
35:
36:
37: #ifdef COMPRESS
38: long coutc = 0;
39: int DOCOMP=0;
40: char *trtab[128] = {
41:
42: #include "compress.h"
43: };
44:
45: #endif
46:
47: #ifdef NDLAY
48: #include <sys/types.h>
49: #ifdef ux3
50: #include <fcntl.h>
51: #endif ux3
52:
53: int ndfrn; /* file for ndelay I/O */
54: #endif
55:
56: extern int SAVEMD;
57: extern int curbf;
58: extern char *getenv();
59:
60: #ifdef PC
61: #define READM (0)
62: #define APPEM (1)
63: #define WRITEM (1)
64: #else
65: #define READM 0
66: #define APPEM 1
67: #define WRITEM 0666
68:
69: int READ_WAIT = 255;
70: int read_miss;
71: #endif
72: /* TTY buffer */
73:
74: /* if unix3.0 (or later) system with no wait raw-mode I/O, use a big tty */
75: /* buffer to allow type ahead and avoid excessive re-display */
76:
77: #if (defined(ux3) || defined(bsd) || defined(v8))
78: #define TTLOOK 16
79: #else
80: #define TTLOOK 1
81: #endif
82: int ttcnt ;
83: char ttbuf[18]; /* Make large */
84: char *ttptr;
85: int ungc = 0;
86: extern int ttywarp;
87:
88: /* Interrupted system command flag */
89: int irupt = 0;
90: #define MAXIRUPT 100
91:
92: /* controlification stuff */
93:
94: int ctlify;
95: int CONCHAR = 036; /* ^^ */
96: ioinit()
97: {
98: /* Keywords: internal-initialization standard-I/O files:20 */
99: register char *ttname;
100:
101: xclose(3); /* close all files */
102: _stdout._frn = 1;
103: _stdout._cnt = 0;
104: _stdout._flags = _OUTPUT;
105: incnt = inlev = infrn = 0;
106: infrn = NULL;
107: brkflg = 0;
108: inbuf = _inbuf[0];
109: #ifdef NDLAY
110: #ifdef ux3
111:
112: #ifdef pdp11
113: #define PDPTEST (ttywarp<2)
114: #else
115: #define PDPTEST 0
116: #endif
117:
118: /* IF we have NDELAY I/O, close standard error and open it with ndelay */
119:
120: close(2); /* close standard error */
121:
122:
123: if ((ttname=getenv("LOGTTY"))==NULL) ttname="/dev/tty";
124: if (PDPTEST || (open(ttname,O_RDWR+O_NDELAY)<0)) {
125: dup(1);
126: ndfrn = 0;
127: } else ndfrn = 2;
128:
129: /* if we can't get tty, restore frn2 */
130: #endif ux3
131: #ifdef (defined(bsd) || defined(v8))
132: /*
133: * we can see how many chars await us in bsd4.1,
134: * so set ndfrn if the tty is fast enough for us. - CRC
135: */
136: ndfrn = 2; /* CRC */
137:
138: #endif (bsd || v8) /* CRC */
139:
140: #endif /* CRC */
141: }
142: int FLOWMIN=0; /* Mode variable must be present */
143:
144: #ifdef PC
145:
146: cook()
147: {
148: }
149: uncook()
150: {
151: }
152: #else
153: /* into raw mode */
154:
155:
156: /* Terminal I/O modes, sgttyb for before unix 3.0, termio for later */
157:
158:
159: int xon;
160:
161: #ifdef ux3
162: struct termio ttyjunk;
163: struct termio nttyjunk;
164: #else
165: struct sgttyb ttyjunk;
166: struct sgttyb nttyjunk;
167: #endif
168:
169: #ifdef CBRAKE
170: /* Additional goodies for 4.2BSD */
171:
172: int ldisc; /* Line discipline */
173: struct tchars tchars; /* Basic characters */
174: int locmode; /* Local mode */
175: struct ltchars ltchars; /* And at last, local modes */
176: struct ltchars zchars = {
177: -1,-1,-1,-1,-1,-1 }; /* Zero characters for ioctl */
178: struct tchars fcoff = {0,-1,-1,-1,-1,-1};
179: struct tchars fcon = {0,-1,021,023,-1,-1};
180: int mylmode = LLITOUT|LDECCTQ; /* Literal output, ^Q starts ^S */
181: #endif
182:
183:
184: #define NBAUD 16 /* number of baud rates */
185: char charms[NBAUD] = { /* ms per char in various rates */
186: 100,
187: 100, /* 50 */
188: 100, /* 75 */
189: 100, /* 110 */
190: 70, /* 134 */
191: 66, /* 150 */
192: 50, /* 200 */
193: 33, /* 300 */
194: 16, /* 600 */
195: 8, /* 1200 */
196: 5, /* 1800 */
197: 4, /* 2400 */
198: 2, /* 4800 */
199: 1, /* 9600 */
200: 1, /* EXTA */
201: 1, /* EXTB */
202: };
203:
204: uncook()
205: {
206:
207: /* UNIX 3 code thanks to J. Langer and M. Plotnick */
208:
209: /* Keywords: the-terminal internal-initialization:40 terminal-initialization terminal-modes unix-interface:50 */
210: #ifdef ux3
211:
212:
213: ioctl(1, TCGETA, &ttyjunk);
214: nttyjunk=ttyjunk;
215:
216: #ifdef u370
217:
218: nttyjunk.c_iflag |= (BRKINT|ISTRIP|IGNPAR);
219: nttyjunk.c_iflag &=
220: ~(IGNBRK|IGNPAR|PARMRK|IXON|INLCR|IGNCR|ICRNL|INPCK);
221: /* accept break, no crnl mapping, no ^S^Q */
222: nttyjunk.c_oflag = 0; /* no delays, no crlf mapping */
223: /* nttyjunk.c_cflag |= CS8 ;*/
224: nttyjunk.c_lflag &= ~(ISIG|ECHO|ICANON); /* no echo, signals,
225: or erase/kill processing */
226: #else
227: nttyjunk.c_iflag |= (BRKINT|ISTRIP);
228: nttyjunk.c_iflag &= ~(IGNBRK|PARMRK|INLCR|ICRNL|IGNCR|IXON|IXOFF);
229: /* accept break, no crnl mapping, no ^S^Q */
230: nttyjunk.c_oflag = 0; /* no delays, no crlf mapping */
231: nttyjunk.c_lflag &= ~(ISIG|ECHO|ICANON); /* no echo, signals,
232: or erase/kill processing */
233: #endif
234: nttyjunk.c_cc[VMIN] = 0; /* return after every character read */
235:
236: /* Setting VMIN to 0 causes emacs to time out input every 25.5 seconds,
237: * updating the display of time (if time mode is on) and received
238: * mail. Setting it to 1 will cause emacs to wait indefinetely for
239: * input. */
240:
241: nttyjunk.c_cc[VTIME] = READ_WAIT; /* Or after 25.5 seconds */
242: ttywarp = charms[ttyjunk.c_cflag&CBAUD]; /* milliseconds for character */
243:
244: ioctl(1, TCSETAW, &nttyjunk);
245: ioctl(1, TCXONC,1); /* Force tty back on */
246: xon = 0; /* Xon/XOff is now off */
247:
248: #else
249:
250:
251: ioctl(1,TIOCGETP,&ttyjunk);
252: nttyjunk=ttyjunk;
253: #ifdef CBRAKE
254: nttyjunk.sg_flags = CBREAK;
255: ioctl(1,TIOCSETN,&nttyjunk);
256:
257: /* Now for the real fun, get all of the other 4.2BSD goodies */
258:
259: ioctl(1,TIOCGETC,&tchars);
260: ioctl(1,TIOCSETC,&fcoff);
261: ioctl(1,TIOCLGET,&locmode);
262: ioctl(1,TIOCLBIS,&mylmode);
263: ioctl(1,TIOCGLTC,<chars);
264: ioctl(1,TIOCSLTC,&zchars);
265: xon = 0;
266: #else
267: nttyjunk.sg_flags &= (~ECHO); /* it was so SIMPLE in the old days */
268: nttyjunk.sg_flags |= (RAW);
269: ioctl(1,TIOCSETP,&nttyjunk);
270: #endif
271: ttywarp = charms[ttyjunk.sg_ospeed]; /* milliseconds for char */
272: #endif
273:
274: vinit();
275:
276: /* Anything above 2500 baud may cause problems */
277: /* If the user has not selected a limit we'll set one */
278: /* Commented out, remove this line to enable it
279: if ((ttywarp < 4)&&(FLOWMIN==0)) FLOWMIN = 64; /* */
280:
281: }
282:
283: cook()
284: {
285: /* Keywords: the-terminal terminal-modes exit-processing:50 unix-interface:50 */
286: extern int osert,umode;
287:
288: /* First, return the terminal to a sane state */
289:
290: if (no_io) return;
291: if (umode) unline();
292: if (osert) unsert();
293: vexit();
294: mflush(stdout); /* force output */
295: #ifdef ux3
296: ioctl(1,TCSETAW, &ttyjunk);
297: ioctl(1, TCXONC,1); /* Force tty back on */
298: xon = 1; /* XON/XOFF is now ON */
299: #else
300: #ifdef CBRAKE
301: ioctl(1,TIOCSETN,&ttyjunk);
302: ioctl(1,TIOCSETC,&tchars);
303: ioctl(1,TIOCLSET,&locmode);
304: ioctl(1,TIOCLBIC,&mylmode);
305: ioctl(1,TIOCSLTC,<chars);
306: xon = 1;
307: #else
308: ioctl(1,TIOCSETP,&ttyjunk);
309: #endif
310: #endif
311: }
312: #endif
313:
314: /*VARARGS2*/
315:
316: char *
317: nscan(stptr,ret)
318:
319: register char *stptr;
320: register int *ret;
321:
322: /* Keywords: standard-I/O:20 conversions parsing:20 reading:20 */
323: {
324: register int c;
325:
326: *ret = 0;
327: while (((c = *stptr)>='0') && (c <= '9')) {
328: stptr++;
329: *ret = *ret*10+(c-'0');
330: }
331: return(stptr);
332: }
333:
334:
335: seprintf(string,fmt,x)
336: char *string;
337: char *fmt;
338: unsigned x;
339: {
340: sxprintf(string,fmt,&x); /* Depends on arg list format */
341: }
342:
343: /* Internal printf formatter */
344:
345: sxprintf(string,fmt, adx)
346: register char *string;
347: register char *fmt;
348: register unsigned int *adx;
349: {
350: /* Keywords: standard-I/O:50 formatting writing:20 terminal-parameters:20 */
351: int c;
352: int width;
353:
354: extern char *mstrcpy();
355:
356: if (fmt == NULL) fmt = "";
357:
358: loop:
359: while((c = *fmt++) != '%') {
360: *string++ = c;
361: if(c == '\0') {
362: return;
363: }
364: }
365: width = 0;
366: c = *fmt++;
367: if ((c >= '0') && (c <= '9')) {
368: fmt = nscan(fmt-1,&width);
369: c = *fmt++;
370: }
371:
372: switch(c) {
373: case 'd':
374: case 'D':
375: case 'o':
376: case 'O':
377: {
378: register int b;
379: long n;
380: long n1;
381: register int i;
382: char dstack[20];
383:
384: b = (((c=='o') || (c == 'O'))? 8: 10); /* number base */
385: if ((c == 'o') || (c == 'd')) {
386: n = (long) (*adx);
387: if (sizeof(n) != sizeof(i)) {
388: if (n > 32768L) n = n-65536L; /* sign correction */
389: }
390: } else {
391: n = *((long *) adx);
392: adx += ((sizeof(n)-sizeof(i))/sizeof(i));
393: }
394: i = 0;
395: if (n < 0) {
396: n = -n;
397: *string++ = '-';
398: }
399:
400: do {
401: n1 = n/b;
402: dstack[i++] = (short) (n-(n1*b));
403: n = n1;
404: } while (n != 0); /* figure number */
405: if ((b == 8) && ((i !=1 ) || (dstack[0] != 0))) dstack[i++]=0;
406: while (i<width) dstack[i++] = 0;
407: while (i > 0) {
408: #ifdef PC
409: char cq;
410: cq = dstack[--i];
411: cq += '0';
412: *string++ = cq;
413: #else
414: *string++ = (dstack[--i] + '0'); /* print number */
415: #endif
416: }
417: }
418: break;
419: case 'P':
420: width *= SREGION;
421: /* Fall through */
422: case 'p':
423: while (width > 0) {
424: *string++ = *NOP;
425: width -= ttywarp;
426: }
427: adx--;
428: break;
429: case 's':
430: string = mstrcpy(string,(char *)*adx);
431: break;
432: case 'm':
433: case 'M':
434: {
435: char *cp;
436: if (c=='m') {
437: cp = &TMAP[width * (*adx)];
438: } else {
439: cp = &SMAP[width * (*adx)];
440: }
441: for (c = 0; c < width; c++) {
442: if (*cp) *string++ = *cp++;
443: }
444: }
445: break;
446: case 'c':
447: c = *adx + width;
448: if (c) {
449: *string++ = c;
450: } else {
451: *string++ = '^';
452: *string++ = '@'; /* punt */
453: }
454: break;
455: case '%':
456: *string++ ='%';
457: adx--;
458: break;
459: default:
460: error(WARN,70); /* Bad character in printf */
461: }
462: adx++;
463: goto loop;
464: }
465: char *inget()
466: {
467: /* Keywords: command-files:10 */
468: if (infrn < 0)return(inptr);
469: else return(NULL);
470: }
471: inset(newptr)
472: char *newptr;
473: /* Keywords: command-files:10 */
474: {
475: if (infrn < 0) inptr = newptr;
476: }
477:
478: #ifdef SELECT
479: int sreadfd = 1;
480: struct timeval stimeout = {30,0}; /* timeout interval */
481: #endif
482: #ifdef v8
483: fd_set sreadfd;
484: #endif
485: int
486: getchar()
487: {
488: /* Keywords: the-terminal standard-I/O terminal-modes:10 reading mail-processing:20 time-processing:20 prompting:30 conversions:10 PC-only:10 keyboard-macros:20 unix-interface:10 */
489:
490: extern int timemd;
491: extern int newmail;
492: extern int mailcnt;
493: extern int kbdfile;
494: extern char ctype[];
495: extern char cbuf[];
496: register int c;
497:
498:
499: if (no_io) return(CTRLZ); /* Flush I/O */
500: if (brkflg) brkit(); /* handle break interrupt */
501: if (incnt == 0) {
502: while (1) {
503: errno = 0;
504: if (infrn) {
505: inptr = inbuf;
506: incnt = read(infrn,inbuf,INLOOK);
507: } else {
508:
509: /* The following code expects read from a raw mode tty port to
510: * return whenever at least one character has been received or a
511: * timeout expires. It assumes that if it gets 0 characters, the
512: * timer expired, unless it happens too many times in a row. */
513:
514: reread: ttptr = ttbuf+2;
515: #ifdef PC
516: ttcnt = incnt = rawread(ttbuf+2);
517: #else
518:
519: read_miss = 0;
520: if (donttime) goto notime; /* Avoid time and mail */
521:
522: /* First, update time and mail */
523:
524: if (timemd) dtime(0);
525: if ((mailcnt>=0) && (--mailcnt<=0)) {
526: ckmail();
527: }
528:
529: /* Display them if necessary */
530: if (newmail) {
531: int x,y;
532: x = mline;
533: y = mcol;
534: prompt(ECHOL-1,"%s You have mail",cbuf);
535: if (newmail < 0) beep();
536: mgo(x,y);
537: newmail = 1;
538: } else if (disptime) {
539:
540: int x,y;
541: x = mline;
542: y = mcol;
543: prompt(ECHOL-1,cbuf);
544: disptime=0;
545: mgo(x,y);
546: }
547: notime:
548: /* Now try to read some standard input */
549:
550: mflush(stdout);
551: #ifdef FLIM
552: if (xon && (FLOWMIN>=0)) { /* If xon/xoff is on, turn it off */
553: #ifdef CBRAKE
554:
555: quietout();
556: ioctl(1,TIOCSETC,&fcoff);
557: #else
558: nttyjunk.c_iflag &= ~(IXON|IXANY);
559: ioctl(1,TCSETAW,&nttyjunk);
560: #endif
561: xon = 0;
562: }
563: #endif
564: #ifdef SELECT
565: if (inproc){
566: sreadfd = 1+(1<<inproc);
567: ttcnt = select(inproc+1,&sreadfd,NULL,NULL,&stimeout);
568: if (sreadfd > 1) readproc();
569: } else {
570: sreadfd = 1; /* must set up each time since select clobbers it */
571: ttcnt = select(1,&sreadfd,NULL,NULL,&stimeout);
572: }
573: if ((sreadfd & 1) && (brkflg == 0)) ttcnt = incnt = read(0,ttbuf+2,TTLOOK);
574: else {
575: incnt = 0;
576: errno = EINTR; /* Make it look like the read timed out! */
577:
578: }
579: #else
580: #ifdef v8
581: if (inproc){
582: FD_ZERO(sreadfd);
583: FD_SET(0, sreadfd);
584: FD_SET(inproc, sreadfd);
585: ttcnt = select(inproc+1,&sreadfd,NULL,30000);
586: if (FD_ISSET(inproc,sreadfd))
587: readproc();
588: } else {
589: FD_ZERO(sreadfd);
590: FD_SET(0, sreadfd);
591: ttcnt = select(1,&sreadfd,NULL,30000);
592: }
593: if (FD_ISSET(0,sreadfd) && (brkflg == 0))
594: ttcnt = incnt = read(0,ttbuf+2,TTLOOK);
595: else {
596: incnt = 0;
597: errno = EINTR; /* Make it look like the read timed out! */
598:
599: }
600: #else
601: ttcnt = incnt = read(0,ttbuf+2,TTLOOK);
602: if (inproc) readproc(); /* Process any input */
603: #ifdef ux3
604: if (ttcnt) ioset(10);
605: else ioset(READ_WAIT<<1); /* Back off read timeout next time */
606: #endif ux3
607: #endif v8
608: #endif SELECT
609: if (brkflg) {
610: incnt=ttcnt=0;
611: brkit();
612: disup();
613: goto reread; /* Try again for a charactger */
614:
615: }
616:
617: if (incnt == 0) {
618: mailcnt = 0; /* Expire mail timer */
619: if (++read_miss < 1000) goto reread;
620: }
621: #endif PC
622: }
623: ninch+= incnt; /* count for stats */
624: if (incnt >= 0) break;
625: if ((errno != EINTR)|| (++irupt > MAXIRUPT)) break;
626: }
627:
628: }
629:
630: if (infrn < 0) { /* if in macro */
631: incnt++;
632: }
633: if (infrn) {
634: if (incnt-- >0) return(*inptr++ & 0377);
635: } else {
636: if ((incnt= --ttcnt) >= 0) {
637: if (ungc) {
638: ungc--;
639: return(*ttptr++ & 0377);
640: }
641: c = (*ttptr++ & 0177);
642: if (ctlify && (c == CONCHAR)) {
643: ctlify = 0; /* don't controlify again */
644:
645: c = getchar();
646: if ((c>= 'a') && (c <= 'z')) c -= 040;
647: if ((ctype[c] == PLAIN) ||(ctype[c] == UL)) c ^= 0100;
648: ctlify++;
649: }
650: if (kbdfile) {
651: char x;
652: x=c;
653: write(kbdfile,&x,1);
654: }
655: return(c);
656: }
657: }
658: return(CTRLZ);
659: }
660: #ifndef PC
661: #ifdef ux3
662:
663: /* Set non-blocking terminal timeout appropriately */
664:
665: /* Note -- this is a very imperfect simulation of the select system
666: * call in 4.2bsd for system V unix. What is done is that if no
667: * process is running, the timeout is set to 25.5 seconds. If a
668: * process is running, the timeout is decreased after every piece of
669: * input is sent, and rises as reads time out, returning eventually
670: * to 25.5 seconds. Thus quick processes get good results, but slow
671: * ones can get dismal response. Emacs polls the sub-process(s)
672: * each time it reads from the tty, so the timeout just dictates
673: * how often this happens if there is no tty input. */
674:
675:
676: ioset(limit)
677: int limit;
678: {
679: /* Keywords: unix-interface reading shell-escape sub-processes look-ahead: 10*/
680:
681: if (READ_WAIT == 0) return; /* No non-blocking I/O available */
682: if (limit > 255) limit = 255; /* Clamp it */
683:
684: if (READ_WAIT == limit) return;
685: READ_WAIT = limit;
686: nttyjunk.c_cc[VTIME] = READ_WAIT;
687: ioctl(1, TCSETA, &nttyjunk);
688:
689: }
690: #endif
691:
692: /* Process input from process in the window */
693:
694: readproc ()
695: {
696: /* Keywords: unix-interface reading shell-escape sub-processes buffers:50 */
697:
698:
699: char buf[128];
700: int nc,obuf;
701: int cnt;
702:
703: #ifdef v8
704: ioctl(inproc, FIONREAD, &cnt);
705: if(cnt <= 0)
706: return;
707: #endif
708: nc = read(inproc,buf,127);
709: buf[nc]=0;
710: if (nc) {
711: if (curbf != procbuf) {
712: if (procbuf == windbuf()) {
713: owind();
714: stuffproc(buf);
715: disup();
716: owind();
717: disup();
718: } else {
719: obuf=curbf;
720: chbuf(procbuf);
721: stuffproc(buf);
722: chbuf(obuf);
723: }
724: } else {
725: stuffproc(buf);
726: disup(); /* Update display for user */
727: }
728: } else {
729: }
730: }
731:
732: /* stuffproc -- stuff process input into the current buffer */
733:
734: stuffproc(string)
735: char *string;
736: {
737: /* Keywords: unix-interface reading shell-escape sub-processes buffers:50 */
738:
739: bot();
740: putin(string);
741: mark(curbf);
742: }
743:
744: /* sendproc -- send current line to the process */
745:
746: sendproc (ptr,count)
747: char * ptr;
748: int count;
749: {
750: /* Keywords: unix-interface shell-escape buffer-representation:10 buffers:50 writing sub-processes */
751: if (write(outproc,ptr,count)<0) flushproc();
752: #ifdef ux3
753: ioset(1); /* Set back timeout appropriately */
754:
755: #endif
756: }
757:
758: /* brkproc -- send an interrupt to the current sub-process */
759:
760: brkproc(arg)
761:
762: /* Keywords: unix-interface shell-escape break-handling sub-processes */
763:
764:
765: {
766: if (curbf == procbuf) {
767: if (arg== 1) arg = SIGINT;
768: kill(procpid,arg);
769: }
770: }
771:
772: /* flushproc -- rid ourselves of the current sub-process */
773:
774: flushproc()
775: {
776: /* Keywords: unix-interface shell-escape closing sub-processes */
777:
778: int status;
779:
780: if (procpid) {
781: kill (procpid,9);
782: status=wait(&status);
783: close(inproc);
784: close(outproc);
785: procpid=inproc=outproc=0;
786: procbuf= -1;
787: }
788: }
789: #else
790: /* Define some tombstones for this code. It's easier than ifdeffing out all the calls */
791: brkproc()
792: {
793: }
794: #endif
795: /* Fill tty buffer if we have ndelay I/O */
796:
797: ttfill()
798: /* Keywords: the-terminal terminal-modes lookahead reading unix-interface:50 */
799:
800: {
801: #ifdef NDLAY
802: long i;
803: register char *addr;
804:
805: if (no_io || (ndfrn == 0)) return;
806: mflush(stdout); /* flush tty */
807:
808: #if (defined(bsd) || defined(v8)) /* CRC */
809: i = 0; /* CRC */
810: ioctl(2,FIONREAD,&i); /* CRC */
811: if( i <= 0) /* CRC */
812: /* no input awaits us. - CRC */
813: return; /* CRC */
814: #endif (bsd || v8)
815: if (ttcnt) {
816: /* more input, append to it */
817: addr = ttptr+ttcnt;
818: i = read(2,addr,ttbuf+2+TTLOOK-addr);
819: } else {
820: i = read(2,ttbuf+2,TTLOOK);
821: ttptr = ttbuf+2;
822: }
823: if (i < 0) i = 0;
824: ttcnt += i; /* more characters */
825: if (infrn == 0) { /* reading from tty */
826: incnt = ttcnt;
827: inptr = ttptr;
828: }
829: #endif
830: return;
831: }
832: pushin(fp)
833: /* Keywords: command-files:50 keyboard-macros:20 opening unix-interface:10 */
834: register char *fp;
835: {
836: register int frn;
837:
838: if (fp != NULL) {
839: while((frn = open(fp,READM)) <= 0) {
840: if ((errno != EINTR) && (errno != 23))break;
841: }
842: } else frn = 0;
843: if (frn >= 0) {
844: _incnt[inlev] = incnt;
845: _infrn[inlev] = infrn;
846: _inptr[inlev++] = inptr;
847: infrn = frn;
848: if (frn) incnt = 0;
849: else incnt = ttcnt;
850: return(1);
851: } else return(0);
852: }
853:
854: pshmac(pos)
855: /* Keywords: macro-invocation */
856:
857: short pos;
858: {
859:
860: if (inlev>= NINP) error(FATAL,64);
861: _incnt[inlev] = incnt;
862: _infrn[inlev] = infrn;
863: _inptr[inlev++] = inptr;
864: infrn = -1;
865: incnt = 100; /* will never decrease */
866: inptr = &bbuf[0][pos]; /* macro buffer position */
867: return(1);
868: }
869:
870:
871:
872: inpop()
873: /* Keywords: exit-processing:10 macro-invoction:20 command-files:20 */
874: {
875: if (inlev > 0) {
876: --inlev;
877: if (infrn>0) close(infrn);
878: infrn = _infrn[inlev];
879: inptr = _inptr[inlev];
880: inbuf = _inbuf[inlev];
881: if (infrn) incnt = _incnt[inlev];
882: else incnt = ttcnt;
883: return(1);
884: } else return(0);
885: }
886:
887: #ifdef COMPRESS
888:
889: #define CRELOAD 0376
890:
891: translate(buf,count)
892: /* Keywords: standard-I/O:10 compressed-output conversions writing */
893: char *buf;
894: int count;
895: {
896: register char *bp;
897: char *be;
898: register char *bo;
899: register char *mp;
900: register char *tp;
901: bp=bo=buf;
902: be=buf+count;
903:
904: while (bp<be-1) {
905: if (*bp&0200) {
906: *bp = 0; /* PUNT all meta characters to 0 */
907: goto stop;
908: }
909: mp=trtab[*bp];
910: while (*mp) {
911: tp=bp+1;
912: while (*tp++ == *mp++);
913: if ((mp[-1]&0200)){
914: if (tp > be+1) {
915: goto stop;
916: }
917: /* Matched a substring */
918: *bo++ = mp[-1];
919: bp = tp-1;
920: goto out;
921: }
922: while ((*mp++ & 0200) == 0); /* Skip rest of string */
923: }
924: stop: *bo++ = *bp++;
925: out: continue;
926: }
927: if (bp < be) *bo++ = *bp++;
928: return(bo-buf);
929: }
930:
931: loadtbl()
932: /* Load compression table here and remote */
933: /* Keywords: commands the-terminal:90 conversions compressed-output */
934: {
935: extern int macptr;
936: char *nullp;
937: char c;
938: int nc;
939: FILE fbuf;
940: FILE *fp;
941: int i;
942:
943: if (DOCOMP==0) return; /* Can't do compression */
944: nullp = &bbuf[0][macptr];
945: pshchr(0); /* Store a null string for common cases */
946: fp = xopen(&fbuf,expenv(getname("Compression file: ")),"r");
947: if (fp == NULL) return;
948: DOCOMP=0;
949: mflush(stdout); /* Past the point of no return */
950: i = 0;
951: while (getc(fp) != EOF) {
952: nc = 0;
953: while (getc(fp) == '\\') {
954: if (nc == 0) trtab[i] = &bbuf[0][macptr];
955: nc++;
956: c = ((getc(fp)&07)<<6);
957: c += ((getc(fp)&07)<<3);
958: c += (getc(fp)&07);
959: pshchr(c);
960: }
961: c = getc(fp); /* Eat comma */
962: c = getc(fp); /* Eat newline */
963: if (nc) pshchr(0); /* Put in null */
964: else trtab[i]=nullp; /* Null string */
965: i++;
966: }
967: /* OK, host table loaded, now load the blit */
968: mclose(fp);
969: fp = xopen(&fbuf,expenv(getname("Decompression file: ")),"r");
970: if (fp == NULL) return;
971: putchar(CRELOAD); /* Tell blit it's time to reload */
972: while ((c = getc(fp)) != EOF) putchar(c);
973: putchar(CRELOAD); /* Reload done (let's hope!) */
974: mflush(stdout); /* Force output out before we turn on compression */
975: DOCOMP=1; /* Here goes nothing */
976: clear(); /* refresh screen */
977: mclose(fp);
978: }
979: #endif
980: ungetch(c)
981: /* Keywords: the-terminal:90 standard-I/O parsing:10 reading:10 */
982: {
983: if (incnt < 0) return; /* Can't unget an eof */
984: ++incnt;
985: if (infrn==0) {
986: ++ungc;
987: *(--ttptr) = c;
988: ++ttcnt;
989: } else {
990: *(--inptr) = c;
991: }
992: }
993:
994: mflush(p)
995:
996: register FILE *p;
997: /* Keywords: writing the-terminal:10 standard-I/O PC-only:40 unix-interface:20 */
998: {
999: register int bc;
1000: register int bo;
1001:
1002: if (p->_flags & _OUTPUT) {
1003: if (p->_flags & _ERROR) {
1004: p->_cnt = 0;
1005: return;
1006: }
1007: if (p == stdout) {
1008: if (no_io) {
1009: p->_cnt = 0;
1010: return;
1011: }
1012: ntwrite++; /* count for stats */
1013: noutc += p->_cnt;
1014: #ifdef PC
1015: return; /* No output to stdout */
1016: #endif PC
1017: #ifdef COMPRESS
1018: if (DOCOMP&& (p->_cnt > 10)) p->_cnt = translate(p->_buf,p->_cnt);
1019: coutc += p->_cnt;
1020: #endif
1021: #ifdef FLIM
1022: if (FLOWMIN && (p->_cnt > FLOWMIN) && (xon == 0)) {
1023: #ifdef CBRAKE
1024: quietout();
1025: ioctl(1,TIOCSETC,&fcon);
1026: #else
1027: nttyjunk.c_iflag |= IXON+IXANY;
1028: ioctl(1,TCSETA,&nttyjunk);
1029: #endif
1030: xon = 1;
1031: }
1032: #endif
1033: }
1034: #ifdef PC
1035: if (p->_cnt) {
1036: if ((bc = write(p->_frn, p->_buf, p->_cnt)) < p->_cnt) {
1037: error (NORM,errno,"writing");
1038: }
1039: }
1040: #else
1041: bo = 0;
1042: while((bc = write(p->_frn, p->_buf+bo, p->_cnt)) != p->_cnt) {
1043: if (bc >0) {
1044: p->_cnt -= bc;
1045: bo += bc;
1046: }
1047: if ((errno != EINTR)|| (++irupt > MAXIRUPT)) {
1048: if ((p == stdout) || (errno == EPIPE)) break; /* PUNT
1049: * errors on standard output */
1050: p->_flags |= _ERROR;
1051: SAVEMD = 0; /* Give up on autosaving */
1052: error (NORM,errno,"writing");
1053: break;
1054: }
1055: }
1056: #endif PC
1057: p->_cnt = 0;
1058: }
1059: }
1060:
1061: #ifdef CBRAKE
1062: /* Wait for quiet output on berkely systems. This is very imperfect */
1063: /* but it's all we can do. */
1064:
1065: quietout()
1066: {
1067: int outqs;
1068: struct timeval outime;
1069: long timeout;
1070:
1071: ioctl(1,TIOCOUTQ,&outqs);
1072: while (outqs > 0) {
1073:
1074: timeout = outqs*1000 /ttywarp - 3000; /* Microseconds of timeout */
1075: if (timeout > 0) {
1076:
1077: outime.tv_sec = timeout/1000000;
1078: outime.tv_usec = timeout%1000000;
1079: select(0,NULL,NULL,NULL,&outime); /* Wait for something to happen! */
1080: }
1081: ioctl(1,TIOCOUTQ,&outqs);
1082: }
1083: }
1084: #endif
1085: filbuf(p)
1086:
1087: FILE *p;
1088: {
1089: /* Keywords: reading standard-I/O PC-only:40 unix-interface:10 */
1090: #ifdef PC
1091: p->_cnt = read(p->_frn, p->_buf, BUFSIZ);
1092: #else
1093: mflush(stdout); /* Make output come out */
1094: while ((p->_cnt = read(p->_frn, p->_buf, BUFSIZ)) < 0) {
1095: if ((errno != EINTR)|| (++irupt > MAXIRUPT)) break;
1096: }
1097: #endif PC
1098: p->_ptr = &(p->_buf[1]);
1099: if (p->_cnt > 0) {
1100: p->_cnt--;
1101: return(p->_buf[0]&0377);
1102: }
1103: else p->_cnt = 0;
1104: return(EOF);
1105: }
1106:
1107: /*VARARGS1*/
1108:
1109: eprintf(string,a1)
1110:
1111: char *string;
1112: /* Keywords: formatting standard-I/O:50 terminal-parameters:50 */
1113: {
1114: char pbuf[1024];
1115: sxprintf(pbuf,string,&a1);
1116: puts(pbuf,stdout);
1117: }
1118:
1119: puts(cp,p)
1120:
1121: FILE *p;
1122: register char *cp;
1123: /* Keywords standard-I/O writing */
1124: {
1125: while (*cp) {
1126: putc(*cp++,p);
1127: }
1128: }
1129:
1130: mclose(p)
1131:
1132: FILE *p;
1133: /* Keywords: standard-I/O closing files unix-interface */
1134: {
1135: mflush(p);
1136: close(p->_frn);
1137: return(p->_flags & _ERROR);
1138: }
1139:
1140: FILE *
1141:
1142: xopen(p,np,mode)
1143:
1144: FILE *p;
1145: char *np;
1146: char *mode;
1147: /* Keywords: files opening standard-I/O unix-interface */
1148: {
1149: int omode;
1150:
1151: omode = 0;
1152: if (*mode == 'b') {
1153: #ifdef PC
1154: omode = 4;
1155: #endif
1156: mode++;
1157: }
1158: switch(*mode) {
1159: case 'r': /* read file mode */
1160:
1161: while ((p->_frn = open(np,omode+READM)) <0) {
1162: if ((errno != EINTR) && (errno != 23))return(NULL);
1163: }
1164: p->_flags = _INPUT;
1165: break;
1166:
1167: case 'a':
1168: while((p->_frn = open(np,omode+APPEM)) <0) {
1169: if ((errno != EINTR) && (errno != 23))return(NULL);
1170: }
1171: lseek (p->_frn,0L,2); /* at end */
1172: p->_flags = _OUTPUT;
1173: break;
1174: case 'w':
1175:
1176: while((p->_frn = creat(np,omode+WRITEM)) <=0) {
1177: if ((errno != EINTR)&& (errno != 23)) return(NULL);
1178: }
1179: p->_flags = _OUTPUT;
1180: break;
1181: }
1182: p->_cnt = 0;
1183: p->_ptr = 0;
1184: return(p);
1185: }
1186:
1187: FILE *
1188:
1189: fdopen(p,frn,mode)
1190:
1191: FILE *p;
1192: int frn;
1193: char *mode;
1194: /* Keywords: standard-I/O opening unix-interface */
1195:
1196: {
1197: p->_frn = frn;
1198: p->_cnt = 0;
1199: p->_ptr = &(p->_buf[0]);
1200: p->_flags = _DEAD;
1201: switch(*mode) {
1202:
1203: case 'r':
1204: p->_flags = _INPUT;
1205: break;
1206: case 'w':
1207: p->_flags = _OUTPUT;
1208: break;
1209: }
1210: return(p);
1211: }
1212:
1213: /* ascii to integer */
1214:
1215: aint(string)
1216:
1217: register char *string;
1218: /* Keywords: standard-I/O:10 conversions string-handling:10 */
1219: {
1220: register int result;
1221: register int base;
1222:
1223: base = ((*string == '0') ? 8 : 10);
1224: result = 0;
1225: while ((*string >= '0') && (*string <= '9')) {
1226: result = (result * base) + (*string++ - '0');
1227: }
1228: if (*string == 0) return(result);
1229: else return(-1);
1230: }
1231:
1232: xclose(lowfile)
1233:
1234: register int lowfile;
1235: /* Keywords: unix-interface files closing */
1236: {
1237: register int fileno;
1238: #ifndef PC
1239: for (fileno = lowfile; fileno < 20; fileno++) {
1240: close(fileno);
1241: }
1242: #endif PC
1243: }
1244: #ifdef PC
1245: /* All the nice? C routines you don't really need! */
1246: signal()
1247: {
1248: return(0);
1249: }
1250: char *
1251: getenv()
1252: {
1253: return(0);
1254: }
1255: char cbuf[2]; /* Fake character buffer */
1256: #else
1257:
1258: /* ctime stuff */
1259:
1260:
1261:
1262: char cbuf[26];
1263: char dmsize[12] =
1264: {
1265: 31,
1266: 28,
1267: 31,
1268: 30,
1269: 31,
1270: 30,
1271: 31,
1272: 31,
1273: 30,
1274: 31,
1275: 30,
1276: 31
1277: };
1278:
1279: long timez = 0;
1280: int daylite = 1;
1281:
1282: #define dysize(xyear) ((xyear&03) ? 365 : 366)
1283:
1284:
1285: struct tm *gmtime();
1286: struct tm *localtime();
1287: char *ctime();
1288: char *asctime();
1289:
1290: char *
1291: ctime(t)
1292: long *t;
1293: {
1294: /* Keywords: time-processing */
1295: return(asctime(localtime(t)));
1296: }
1297:
1298: #ifdef ux3
1299: void
1300: #endif
1301: tzset()
1302: {
1303: register char *p;
1304: register int n;
1305: int sign;
1306: /* Keywords: time-processing internal-initialization */
1307: if ((p = getenv ("TZ")) && *p) {
1308:
1309: p += 3;
1310: if (sign = *p == '-')
1311: p++;
1312: n = 0;
1313: while (*p >= '0' && *p <= '9')
1314: n = (n * 10) + *p++ - '0';
1315: if (sign)
1316: n = -n;
1317: timez = ((long) (n * 60)) * 60;
1318: if (*p) daylite = 1;
1319: else daylite = 0;
1320: }
1321: }
1322:
1323: struct tm *
1324: localtime(tim)
1325: long *tim;
1326: {
1327: /* Keywords: time-processing */
1328: register int dayno;
1329: register struct tm *ct;
1330: register daylbegin, daylend;
1331: long copyt;
1332:
1333: if (timez == 0) tzset();
1334:
1335: copyt = *tim - timez;
1336: ct = gmtime(©t);
1337: if (!daylite) return(ct);
1338: dayno = ct->tm_yday;
1339: daylbegin = 119; /* last Sun in Apr */
1340: daylend = 303; /* Last Sun in Oct */
1341: daylbegin = sunday(ct, daylbegin);
1342: daylend = sunday(ct, daylend);
1343: if ((dayno>daylbegin || (dayno==daylbegin && ct->tm_hour>=2)) &&
1344: (dayno<daylend || (dayno==daylend && ct->tm_hour<1))) {
1345: copyt += 1*60*60;
1346: ct = gmtime(©t);
1347: }
1348: return(ct);
1349: }
1350:
1351: /*
1352: * The argument is a 0-origin day number.
1353: * The value is the day number of the first
1354: * Sunday on or after the day.
1355: */
1356: sunday(t, d)
1357: register struct tm *t;
1358: register int d;
1359: {
1360: /* Keywords: time-processing */
1361: if ((d >= 58) && ((t->tm_year & 03) == 0)) d+=1; /* leap year */
1362: return(d - (d - t->tm_yday + t->tm_wday + 700) % 7);
1363: }
1364:
1365: struct tm *
1366: gmtime(tim)
1367: long *tim;
1368: {
1369: /* Keywords: time-processing */
1370: register int d0, d1;
1371: int day;
1372: long hms;
1373: static struct tm xtime;
1374:
1375: /*
1376: * break initial number into days
1377: */
1378: day = *tim / 86400;
1379: hms = *tim - (day*86400);
1380:
1381: /*
1382: * generate hours:minutes:seconds
1383: */
1384: d1 = hms/60;
1385: xtime.tm_sec = hms - (((long)d1)*60L);
1386: xtime.tm_min = d1%60;
1387: d1 /= 60;
1388: xtime.tm_hour = d1;
1389:
1390: /*
1391: * day is the day number.
1392: * generate day of the week.
1393: * The addend is 4 mod 7 (1/1/1970 was Thursday)
1394: */
1395:
1396: xtime.tm_wday = (day+4)%7;
1397:
1398: /*
1399: * year number
1400: */
1401: for(d1=70; day >= dysize(d1); d1++)
1402: day -= dysize(d1);
1403: xtime.tm_year = d1;
1404: xtime.tm_yday = d0 = day;
1405:
1406: /*
1407: * generate month
1408: */
1409:
1410: if ((d1&03) == 0)dmsize[1] = 29;
1411: else dmsize[1] = 28;
1412: for(d1=0; d0 >= dmsize[d1]; d1++)
1413: d0 -= dmsize[d1];
1414: xtime.tm_mday= d0+1;
1415: xtime.tm_mon = d1;
1416: return(&xtime);
1417: }
1418:
1419: char *
1420: asctime(t)
1421: register struct tm *t;
1422: {
1423: /* Keywords: time-processing */
1424:
1425: seprintf(cbuf,"%s %s %d %2d:%2d",
1426: &"Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat"[4*t->tm_wday],
1427: &"Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec"[(t->tm_mon)*4],
1428: t->tm_mday,
1429: t->tm_hour,
1430: t->tm_min);
1431: return(cbuf);
1432: }
1433: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.