|
|
1.1 root 1: #include <signal.h>
2: #include <sgtty.h>
3: #include <sys/stat.h>
4: #include <sys/types.h>
5:
6: /*
7: * Conditionalized by steve 6/10/92 for _I386.
8: * I didn't bother to clean up the way the i8086 version works;
9: * it too would be vastly more efficient if it passed both the
10: * character and attribute to a single call rather than calling sout() twice.
11: */
12: #if _I386
13: char outbuf[2]; /* character and attribute */
14: #define atrb(a) {outbuf[1] = (a);}
15: #define bufchr(c) {outbuf[0] = (c); sout2();}
16: #else
17: int a_n;
18: #define atrb(a) {a_n=a;}
19: #define bufchr(c) {sout(caddr++, (c)); sout(caddr++, (a_n));}
20: #endif
21:
22: #define bflush()
23: #define bufstr(s) {register char *pc; pc=s; while (*pc) bufchr(*pc++);}
24: #define beep() write(2, "\7", 1)
25:
26: struct sgttyb sgttyb, oldsgttyb;
27: struct stat sbuf;
28: int pv[3];
29:
30: #if _I386
31: /*
32: * Write character and attribute to display memory directly.
33: * The character and attribute are in outbuf[].
34: * The display memory offset is in caddr, which gets bumped.
35: * This presumes that the process can write /dev/mem.
36: */
37: sout2()
38: {
39: static unsigned int offset;
40: static int mfd;
41: extern unsigned int scrbase;
42:
43: if (mfd == 0) {
44: /* First time, open /dev/mem. */
45: if ((mfd = open("/dev/mem", 1)) == -1)
46: error("cannot open /dev/mem");
47: if (lseek(mfd, scrbase, 0) != scrbase)
48: error("seek failed");
49: }
50: if (caddr != offset && lseek(mfd, scrbase + caddr, 0) == -1)
51: error("seek failed");
52: if (write(mfd, outbuf, 2) != 2)
53: error("write failed");
54: offset = caddr += 2;
55: }
56: #endif
57:
58: cls()
59: {
60: #if _I386
61: outbuf[0] = ' ';
62: outbuf[1] = 7;
63: for (caddr = 0; caddr < 4000; )
64: sout2();
65: #else
66: register int c;
67:
68: for (c = 0; c < 4000; ) {
69: sout (c++, ' ');
70: sout (c++, 7);
71: }
72: #endif
73: }
74:
75: reset()
76: {
77:
78: ioctl(1, TIOCSETP, &oldsgttyb);
79: kill (pv[2], SIGTERM);
80: cls();
81: exit (0);
82: }
83:
84: setup()
85: {
86: struct stat cstat, ostat;
87:
88: /* Make sure the user is running from the console keyboard. */
89: if (stat("/dev/console", &cstat) == -1)
90: error("cannot stat /dev/console");
91: else if (fstat(1, &ostat) == -1)
92: error("cannot stat standard output");
93: else if (cstat.st_dev != ostat.st_dev
94: || cstat.st_mode != ostat.st_mode
95: || cstat.st_rdev != ostat.st_rdev)
96: error("Sorry, you can only play from the console keyboard.");
97: if (pipe(pv) < 0)
98: error("cannot create pipe");
99: if ((pv[2]=fork()) < 0)
100: error("cannot fork");
101: if (pv[2] == 0) {
102: dup2(pv[1], 1);
103: close(pv[0]);
104: close(pv[1]);
105: chdir("/tmp");
106: execl("/bin/cat", "", "-u", 0);
107: exit (1);
108: }
109: signal(SIGINT, reset);
110: dup2(pv[0], 0);
111: close(pv[0]);
112: close(pv[1]);
113: ioctl(1, TIOCGETP, &oldsgttyb);
114: sgttyb = oldsgttyb;
115: sgttyb.sg_flags &= ~ECHO;
116: sgttyb.sg_flags |= CBREAK | RAWOUT;
117: ioctl(1, TIOCSETP, &sgttyb);
118: cls();
119: }
120:
121: static char crlf[2] = { '\r', '\n' };
122: error(s)
123: char *s;
124: {
125: register int i;
126: register char *t;
127:
128: for (i=0, t = s; *t++; )
129: ++i;
130: write(2, s, i);
131: write(2, crlf, 2);
132: exit (1);
133: }
134:
135: input(c)
136: register char *c;
137: {
138: register n;
139:
140: fstat(0, &sbuf);
141: n = (int)sbuf.st_size;
142: if (n <= 0)
143: return (0);
144: while (n--)
145: read(0, c, 1);
146: return (1);
147: }
148:
149: inputecho(c)
150: register char *c;
151: {
152: while (input(c) == 0)
153: ;
154: if (*c == '\n')
155: return;
156: bufchr(*c);
157: bflush();
158: }
159:
160: delay(t)
161: register t;
162: {
163: extern int ndelay;
164: register i;
165:
166: if (ndelay)
167: t *= ndelay;
168: while (t--)
169: for (i=0; i<4096; ++i)
170: ;
171: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.