ttyrecのfork. Original: http://0xcc.net/ttyrec/
修訂 | b684765cd88bdbfb09262ed904bbc41b9942af3d (tree) |
---|---|
時間 | 2019-12-09 16:16:31 |
作者 | IWAMOTO Kouichi <sue@iwmt...> |
Commiter | IWAMOTO Kouichi |
update to ttyrec-1.0.6
@@ -1,11 +1,11 @@ | ||
1 | 1 | CC = gcc |
2 | 2 | CFLAGS = -O2 |
3 | -VERSION = 1.0.5 | |
3 | +VERSION = 1.0.6 | |
4 | 4 | |
5 | 5 | TARGET = ttyrec ttyplay ttytime |
6 | 6 | |
7 | 7 | DIST = ttyrec.c ttyplay.c ttyrec.h io.c io.h ttytime.c\ |
8 | - README Makefile ttyrec.1 ttyplay.1 | |
8 | + README Makefile ttyrec.1 ttyplay.1 ttytime.1 | |
9 | 9 | |
10 | 10 | all: $(TARGET) |
11 | 11 |
@@ -109,12 +109,19 @@ write_header (FILE *fp, Header *h) | ||
109 | 109 | return 1; |
110 | 110 | } |
111 | 111 | |
112 | +static char *progname = ""; | |
113 | +void | |
114 | +set_progname (const char *name) | |
115 | +{ | |
116 | + progname = strdup(name); | |
117 | +} | |
118 | + | |
112 | 119 | FILE * |
113 | 120 | efopen (const char *path, const char *mode) |
114 | 121 | { |
115 | 122 | FILE *fp = fopen(path, mode); |
116 | 123 | if (fp == NULL) { |
117 | - fprintf(stderr, "ttyplay: %s: %s\n", path, strerror(errno)); | |
124 | + fprintf(stderr, "%s: %s: %s\n", progname, path, strerror(errno)); | |
118 | 125 | exit(EXIT_FAILURE); |
119 | 126 | } |
120 | 127 | return fp; |
@@ -1,6 +1,9 @@ | ||
1 | +.\" | |
2 | +.\" This manual page is written by NAKANO Takeo <nakano@webmasters.gr.jp> | |
3 | +.\" | |
1 | 4 | .TH TTYPLAY 1 |
2 | 5 | .SH NAME |
3 | -ttyplay \- a player of the tty session recorded by ttyrec | |
6 | +ttyplay \- player of the tty session recorded by ttyrec | |
4 | 7 | .SH SYNOPSIS |
5 | 8 | .br |
6 | 9 | .B ttyplay |
@@ -22,6 +25,22 @@ output the | ||
22 | 25 | as it grows. |
23 | 26 | It means that you can see the "live" shell session |
24 | 27 | running by another user. |
28 | +.PP | |
29 | +If you hit any key during playback, it will go right to the next | |
30 | +character typed. This is handy when examining sessions where a user | |
31 | +spends a lot of time at a prompt. | |
32 | +.PP | |
33 | +Additionally, there are some special keys defined: | |
34 | +.TP | |
35 | +.BI + " or " f | |
36 | + double the speed of playback. | |
37 | +.TP | |
38 | +.BI \- " or " s | |
39 | + halve the speed of playback. | |
40 | +.TP | |
41 | +.BI 1 | |
42 | +set playback to speed 1.0 again. | |
43 | + | |
25 | 44 | .SH OPTIONS |
26 | 45 | .TP |
27 | 46 | .BI \-s " SPEED" |
@@ -38,8 +57,6 @@ Ignore the timing information in | ||
38 | 57 | peek another person's tty session. |
39 | 58 | .SH "SEE ALSO" |
40 | 59 | .BR script (1), |
41 | -.BR ttyrec (1) | |
42 | -.SH AUTHOR | |
43 | -This manual page is written by NAKANO Takeo <nakano@webmasters.gr.jp> | |
44 | -for the Debian GNU/Linux system (but may be used by others). | |
60 | +.BR ttyrec (1), | |
61 | +.BR ttytime (1) | |
45 | 62 |
@@ -35,13 +35,14 @@ | ||
35 | 35 | #include <stdlib.h> |
36 | 36 | #include <assert.h> |
37 | 37 | #include <unistd.h> |
38 | +#include <termios.h> | |
38 | 39 | #include <sys/time.h> |
39 | 40 | #include <string.h> |
40 | 41 | |
41 | 42 | #include "ttyrec.h" |
42 | 43 | #include "io.h" |
43 | 44 | |
44 | -typedef void (*WaitFunc) (struct timeval prev, | |
45 | +typedef double (*WaitFunc) (struct timeval prev, | |
45 | 46 | struct timeval cur, |
46 | 47 | double speed); |
47 | 48 | typedef int (*ReadFunc) (FILE *fp, Header *h, char **buf); |
@@ -52,38 +53,66 @@ typedef void (*ProcessFunc) (FILE *fp, double speed, | ||
52 | 53 | struct timeval |
53 | 54 | timeval_diff (struct timeval tv1, struct timeval tv2) |
54 | 55 | { |
55 | - struct timeval tv; | |
56 | + struct timeval diff; | |
56 | 57 | |
57 | - tv.tv_sec = tv2.tv_sec - tv1.tv_sec; | |
58 | - tv.tv_usec = tv2.tv_usec - tv1.tv_usec; | |
59 | - if (tv.tv_usec < 0) { | |
60 | - tv.tv_sec--; | |
61 | - tv.tv_usec += 1000000; | |
58 | + diff.tv_sec = tv2.tv_sec - tv1.tv_sec; | |
59 | + diff.tv_usec = tv2.tv_usec - tv1.tv_usec; | |
60 | + if (diff.tv_usec < 0) { | |
61 | + diff.tv_sec--; | |
62 | + diff.tv_usec += 1000000; | |
62 | 63 | } |
63 | 64 | |
64 | - return tv; | |
65 | + return diff; | |
65 | 66 | } |
66 | 67 | |
67 | -void | |
68 | +struct timeval | |
69 | +timeval_div (struct timeval tv1, double n) | |
70 | +{ | |
71 | + double x = ((double)tv1.tv_sec + (double)tv1.tv_usec / 1000000.0) / n; | |
72 | + struct timeval div; | |
73 | + | |
74 | + div.tv_sec = (int)x; | |
75 | + div.tv_usec = (x - (int)x) * 1000000; | |
76 | + | |
77 | + return div; | |
78 | +} | |
79 | + | |
80 | +double | |
68 | 81 | ttywait (struct timeval prev, struct timeval cur, double speed) |
69 | 82 | { |
70 | 83 | struct timeval diff = timeval_diff(prev, cur); |
84 | + fd_set readfs; | |
71 | 85 | |
72 | 86 | assert(speed != 0); |
87 | + diff = timeval_div(diff, speed); | |
73 | 88 | |
74 | - /* | |
75 | - * Use select instead of sleep and usleep because some | |
76 | - * systems don't support usleep. | |
77 | - */ | |
78 | - diff.tv_sec /= speed; | |
79 | - diff.tv_usec /= speed; | |
80 | - select(0, NULL, NULL, NULL, &diff); | |
89 | + FD_SET(STDIN_FILENO, &readfs); | |
90 | + select(1, &readfs, NULL, NULL, &diff); /* skip if a user hits any key */ | |
91 | + if (FD_ISSET(0, &readfs)) { /* a user hits a character? */ | |
92 | + char c; | |
93 | + read(STDIN_FILENO, &c, 1); /* drain the character */ | |
94 | + switch (c) { | |
95 | + case '+': | |
96 | + case 'f': | |
97 | + speed *= 2; | |
98 | + break; | |
99 | + case '-': | |
100 | + case 's': | |
101 | + speed /= 2; | |
102 | + break; | |
103 | + case '1': | |
104 | + speed = 1.0; | |
105 | + break; | |
106 | + } | |
107 | + } | |
108 | + return speed; | |
81 | 109 | } |
82 | 110 | |
83 | -void | |
111 | +double | |
84 | 112 | ttynowait (struct timeval prev, struct timeval cur, double speed) |
85 | 113 | { |
86 | 114 | /* do nothing */ |
115 | + return 0; /* Speed isn't important. */ | |
87 | 116 | } |
88 | 117 | |
89 | 118 | int |
@@ -149,7 +178,7 @@ ttyplay (FILE *fp, double speed, ReadFunc read_func, | ||
149 | 178 | } |
150 | 179 | |
151 | 180 | if (!first_time) { |
152 | - wait_func(prev, h.tv, speed); | |
181 | + speed = wait_func(prev, h.tv, speed); | |
153 | 182 | } |
154 | 183 | first_time = 0; |
155 | 184 |
@@ -200,7 +229,9 @@ main (int argc, char **argv) | ||
200 | 229 | WaitFunc wait_func = ttywait; |
201 | 230 | ProcessFunc process = ttyplayback; |
202 | 231 | FILE *input = stdin; |
232 | + struct termios old, new; | |
203 | 233 | |
234 | + set_progname(argv[0]); | |
204 | 235 | while (1) { |
205 | 236 | int ch = getopt(argc, argv, "s:np"); |
206 | 237 | if (ch == EOF) { |
@@ -229,7 +260,13 @@ main (int argc, char **argv) | ||
229 | 260 | input = efopen(argv[optind], "r"); |
230 | 261 | } |
231 | 262 | |
263 | + tcgetattr(0, &old); /* Get current terminal state */ | |
264 | + new = old; /* Make a copy */ | |
265 | + new.c_lflag &= ~(ICANON | ECHO | ECHONL); /* unbuffered, no echo */ | |
266 | + tcsetattr(0, TCSANOW, &new); /* Make it current */ | |
267 | + | |
232 | 268 | process(input, speed, read_func, wait_func); |
269 | + tcsetattr(0, TCSANOW, &old); /* Return terminal state */ | |
233 | 270 | |
234 | 271 | return 0; |
235 | 272 | } |
@@ -1,10 +1,13 @@ | ||
1 | +.\" | |
2 | +.\" This manual page is written by NAKANO Takeo <nakano@webmasters.gr.jp> | |
3 | +.\" | |
1 | 4 | .TH TTYREC 1 |
2 | 5 | .SH NAME |
3 | 6 | ttyrec \- a tty recorder |
4 | 7 | .SH SYNOPSIS |
5 | 8 | .br |
6 | 9 | .B ttyrec |
7 | -.I "[\-a] [file]" | |
10 | +.I "[\-a][\-u] [file]" | |
8 | 11 | .br |
9 | 12 | .SH DESCRIPTION |
10 | 13 | .B Ttyrec |
@@ -32,6 +35,27 @@ Append the output to | ||
32 | 35 | or |
33 | 36 | .IR ttyrecord , |
34 | 37 | rather than overwriting it. |
38 | +.TP | |
39 | +.B \-u | |
40 | +With this option, | |
41 | +.B ttyrec | |
42 | +automatically calls | |
43 | +.BR uudecode (1) | |
44 | +and saves its output when uuencoded data appear on the session. | |
45 | +It allow you to transfer files from remote host. | |
46 | +You can call | |
47 | +.B ttyrec | |
48 | +with this option, login to the remote host | |
49 | +and invoke | |
50 | +.BR uuencode (1) | |
51 | +on it for the file you want to transfer. | |
52 | +.TP | |
53 | +.BI \-e " command" | |
54 | +Invoke | |
55 | +.I command | |
56 | +when ttyrec starts. | |
57 | + | |
58 | + | |
35 | 59 | .SH ENVIRONMENT |
36 | 60 | .TP |
37 | 61 | .I SHELL |
@@ -45,8 +69,8 @@ the Bourne shell is assumed. | ||
45 | 69 | (Most shells set this variable automatically). |
46 | 70 | .SH "SEE ALSO" |
47 | 71 | .BR script (1), |
48 | -.BR ttyplay (1) | |
49 | -.SH AUTHOR | |
50 | -This manual page is written by NAKANO Takeo <nakano@webmasters.gr.jp> | |
51 | -for the Debian GNU/Linux system (but may be used by others). | |
72 | +.BR ttyplay (1), | |
73 | +.BR ttytime (1), | |
74 | +.BR uuencode (1), | |
75 | +.BR uudecode (1) | |
52 | 76 |
@@ -50,19 +50,15 @@ | ||
50 | 50 | #include <sys/file.h> |
51 | 51 | #include <sys/signal.h> |
52 | 52 | #include <stdio.h> |
53 | +#include <unistd.h> | |
54 | +#include <string.h> | |
53 | 55 | |
54 | 56 | #if defined(SVR4) |
55 | 57 | #include <stdlib.h> |
56 | -#include <unistd.h> | |
57 | 58 | #include <fcntl.h> |
58 | 59 | #include <stropts.h> |
59 | 60 | #endif /* SVR4 */ |
60 | 61 | |
61 | -#ifdef __linux__ | |
62 | -#include <unistd.h> | |
63 | -#include <string.h> | |
64 | -#endif | |
65 | - | |
66 | 62 | #include <sys/time.h> |
67 | 63 | #include "ttyrec.h" |
68 | 64 | #include "io.h" |
@@ -94,7 +90,7 @@ void getmaster(void); | ||
94 | 90 | void getslave(void); |
95 | 91 | void doinput(void); |
96 | 92 | void dooutput(void); |
97 | -void doshell(void); | |
93 | +void doshell(const char*); | |
98 | 94 | |
99 | 95 | char *shell; |
100 | 96 | FILE *fscript; |
@@ -125,8 +121,9 @@ main(argc, argv) | ||
125 | 121 | int ch; |
126 | 122 | void finish(); |
127 | 123 | char *getenv(); |
124 | + char *command = NULL; | |
128 | 125 | |
129 | - while ((ch = getopt(argc, argv, "auh?")) != EOF) | |
126 | + while ((ch = getopt(argc, argv, "aue:h?")) != EOF) | |
130 | 127 | switch((char)ch) { |
131 | 128 | case 'a': |
132 | 129 | aflg++; |
@@ -134,10 +131,13 @@ main(argc, argv) | ||
134 | 131 | case 'u': |
135 | 132 | uflg++; |
136 | 133 | break; |
134 | + case 'e': | |
135 | + command = strdup(optarg); | |
136 | + break; | |
137 | 137 | case 'h': |
138 | 138 | case '?': |
139 | 139 | default: |
140 | - fprintf(stderr, _("usage: ttyrec [-u] [-a] [file]\n")); | |
140 | + fprintf(stderr, _("usage: ttyrec [-u] [-e command] [-a] [file]\n")); | |
141 | 141 | exit(1); |
142 | 142 | } |
143 | 143 | argc -= optind; |
@@ -175,7 +175,7 @@ main(argc, argv) | ||
175 | 175 | if (child) |
176 | 176 | dooutput(); |
177 | 177 | else |
178 | - doshell(); | |
178 | + doshell(command); | |
179 | 179 | } |
180 | 180 | doinput(); |
181 | 181 |
@@ -306,7 +306,7 @@ dooutput() | ||
306 | 306 | } |
307 | 307 | |
308 | 308 | void |
309 | -doshell() | |
309 | +doshell(const char* command) | |
310 | 310 | { |
311 | 311 | /*** |
312 | 312 | int t; |
@@ -325,8 +325,11 @@ doshell() | ||
325 | 325 | (void) dup2(slave, 2); |
326 | 326 | (void) close(slave); |
327 | 327 | |
328 | - execl(shell, strrchr(shell, '/') + 1, "-i", 0); | |
329 | - | |
328 | + if (!command) { | |
329 | + execl(shell, strrchr(shell, '/') + 1, "-i", 0); | |
330 | + } else { | |
331 | + execl(shell, strrchr(shell, '/') + 1, "-c", command, 0); | |
332 | + } | |
330 | 333 | perror(shell); |
331 | 334 | fail(); |
332 | 335 | } |
@@ -0,0 +1,27 @@ | ||
1 | +.\" | |
2 | +.\" This manual page is written by NAKANO Takeo <nakano@webmasters.gr.jp> | |
3 | +.\" | |
4 | +.TH TTYTIME 1 | |
5 | +.SH NAME | |
6 | +ttytime \- print the time of the recorded session data by ttyrec(1) | |
7 | +.SH SYNOPSIS | |
8 | +.br | |
9 | +.B ttytime | |
10 | +.I file... | |
11 | +.SH DESCRIPTION | |
12 | +.B Ttytime | |
13 | +tells you the time of recorded data in seconds. | |
14 | +For example: | |
15 | +.sp | |
16 | +.RS | |
17 | +.nf | |
18 | +% ttytime *.tty | |
19 | + 173 foo.tty | |
20 | + 1832 bar.tty | |
21 | +.fi | |
22 | +.RE | |
23 | +.SH "SEE ALSO" | |
24 | +.BR script (1), | |
25 | +.BR ttyrec (1), | |
26 | +.BR ttyplay (1) | |
27 | + |
@@ -61,6 +61,7 @@ int | ||
61 | 61 | main (int argc, char **argv) |
62 | 62 | { |
63 | 63 | int i; |
64 | + set_progname(argv[0]); | |
64 | 65 | for (i = 1; i < argc; i++) { |
65 | 66 | char *filename = argv[i]; |
66 | 67 | printf("%7d %s\n", calc_time(filename), filename); |