1 /*
2 * follow.c -- interactively print an ASCII file.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <signal.h>
15 #include <time.h>
16 #include <unistd.h>
17 #include <sys/time.h>
18 #include <sys/types.h>
19
20 #ifdef POSIX
21 # include <termios.h>
22 #elif !defined(USE_SGTTY)
23 # ifdef APOLLO
24 # include "/sys5.3/usr/include/sys/termio.h"
25 # else
26 /*
27 * including both termio.h and termios.h might be an overkill, and gives
28 * many warnings, but seems to be necessary at times. works anyway.
29 */
30 # include <termios.h>
31 # include <termio.h>
32 # endif
33 /* #else USE_SGTTY */
34 #endif
35
36 /*
37 * SunOS 4 doesn't have function headers and has the defs needed from
38 * ioctl.h in termios.h. Does it compile with USE_SGTTY?
39 */
40 #if (defined(sun) && defined(sparc) && ! defined(__SVR4))
41 extern int printf();
42 #else
43 # include <sys/ioctl.h>
44 #endif
45
46 #ifdef BSD_LIKE
47 # include <sys/ioctl_compat.h>
48 # define O_RAW RAW
49 # define O_ECHO ECHO
50 # define O_CBREAK CBREAK
51 #endif
52
53 #ifdef POSIX
54 typedef struct termios termiostruct;
55 #else
56 #if defined(TCSETS) || defined(TCSETATTR)
57 # ifndef TCSETS /* cc for HP-UX SHOULD define this... */
58 # define TCSETS TCSETATTR
59 # define TCGETS TCGETATTR
60 # endif
61 typedef struct termios termiostruct;
62 #else
63 # define TCSETS TCSETA
64 # define TCGETS TCGETA
65 typedef struct termio termiostruct;
66 #endif
67 #endif /* POSIX */
68
69 #ifdef VSUSP
70 # define O_SUSP VSUSP
71 #else
72 # ifdef SWTCH
73 # define O_SUSP SWTCH
74 # else
75 # define O_SUSP SUSP
76 # endif
77 #endif
78
79 /*int ioctl();*/
80
81 #ifdef USE_SGTTY
82 static struct sgttyb ttybsave;
83 static struct tchars tcsave;
84 static struct ltchars ltcsave;
85 #else /* not USE_SGTTY */
86 static termiostruct ttybsave;
87 #endif /* USE_SGTTY */
88
89 /*
90 * Terminal handling routines:
91 * These are one big mess of left-justified chicken scratches.
92 * It should be handled more cleanly...but unix portability is what it is.
93 */
94
95 /*
96 * Set the terminal to character-at-a-time-without-echo mode, and save the
97 * original state in ttybsave
98 */
set_terminal()99 void set_terminal()
100 {
101 #ifdef USE_SGTTY
102 struct sgttyb ttyb;
103 struct ltchars ltc;
104 ioctl(0, TIOCGETP, &ttybsave);
105 ioctl(0, TIOCGETC, &tcsave);
106 ioctl(0, TIOCGLTC, <csave);
107 ttyb = ttybsave;
108 ttyb.sg_flags = (ttyb.sg_flags|O_CBREAK) & ~O_ECHO;
109 ioctl(0, TIOCSETP, &ttyb);
110 ltc = ltcsave;
111 ltc.t_suspc = -1;
112 ioctl(0, TIOCSLTC, <c);
113 #else /* not USE_SGTTY */
114 termiostruct ttyb;
115 #if POSIX
116 tcgetattr(0, &ttyb);
117 #else
118 ioctl(0, TCGETS, &ttyb);
119 #endif
120 ttybsave = ttyb;
121 ttyb.c_lflag &= ~(ECHO|ICANON);
122 ttyb.c_cc[VTIME] = 0;
123 ttyb.c_cc[VMIN] = 1;
124 /* disable the special handling of the suspend key (handle it ourselves) */
125 ttyb.c_cc[O_SUSP] = 0;
126 #if POSIX
127 tcsetattr(0, TCSANOW, &ttyb);
128 #else
129 ioctl(0, TCSETS, &ttyb);
130 #endif
131 #endif /* USE_SGTTY */
132 }
133
134 /*
135 * Reset the terminal to its original state
136 */
reset_terminal()137 void reset_terminal()
138 {
139 #ifdef USE_SGTTY
140 ioctl(0, TIOCSETP, &ttybsave);
141 ioctl(0, TIOCSETC, &tcsave);
142 ioctl(0, TIOCSLTC, <csave);
143 #else /* not USE_SGTTY */
144 #if POSIX
145 tcsetattr(0, TCSANOW, &ttybsave);
146 #else
147 ioctl(0, TCSETS, &ttybsave);
148 #endif
149 #endif /* USE_SGTTY */
150 }
151
main(int argc,char * argv[])152 int main(int argc, char *argv[]) {
153 FILE *f;
154 char c = 0, buf[512];
155 int d;
156
157 if (argc < 2) {
158 fprintf(stderr, "needed a file name\n");
159 exit(0);
160 }
161 f = fopen(argv[1], "r");
162 if (!f) {
163 fprintf(stderr, "unable to open %s\n", argv[1]);
164 exit(0);
165 }
166
167 set_terminal();
168 while(c!=0x1b) {
169 read(0, &c, 1);
170 if (c == 0x0a || c == 0x0d) {
171 if (fgets(buf, 512, f))
172 fputs(buf, stdout);
173 else
174 break;
175 }
176 else {
177 if ((d = fgetc(f)) != EOF)
178 putchar(d);
179 else
180 break;
181 }
182 fflush(stdout);
183 }
184 reset_terminal();
185 fputs("\033[0m\n", stdout);
186 return 0;
187 }
188
189