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, &ltcsave);
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, &ltc);
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, &ltcsave);
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