ttyrex

ttyrec with more options
git clone https://a3nm.net/git/ttyrex/
Log | Files | Refs | README

commit 6c3c9a304c570c4c3852dfb6db37e13573bdbcd7
parent 73b825713a0dd7be02a387423b032f940a5cf15f
Author: Antoine Amarilli <a3nm@a3nm.net>
Date:   Wed,  3 Oct 2012 00:24:18 +0200

+debian

Diffstat:
Makefile | 8+++++++-
io.c | 57+++++++++++++++++++--------------------------------------
io.h | 1+
ttyplay.1 | 3+++
ttyplay.c | 47++++++++++++++++++++++++++++++++++++++---------
ttyrec.1 | 2+-
ttyrec.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
7 files changed, 121 insertions(+), 65 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,7 +1,10 @@ CC = gcc -CFLAGS = -O2 +DEFS= -DSVR4 -D_GNU_SOURCE +CFLAGS = -O2 -g -fomit-frame-pointer -Wall $(DEFS) VERSION = 1.0.8 +DESTDIR= + TARGET = ttyrec ttyplay ttytime DIST = ttyrec.c ttyplay.c ttyrec.h io.c io.h ttytime.c\ @@ -18,6 +21,9 @@ ttyplay: ttyplay.o io.o ttytime: ttytime.o io.o $(CC) $(CFLAGS) -o ttytime ttytime.o io.o +install: + install ttyrec ttyplay ttytime $(DESTDIR)/usr/bin + clean: rm -f *.o $(TARGET) ttyrecord *~ diff --git a/io.c b/io.c @@ -33,6 +33,8 @@ #include <assert.h> #include <errno.h> +#include <endian.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -40,50 +42,28 @@ #include "ttyrec.h" -#define SWAP_ENDIAN(val) ((unsigned int) ( \ - (((unsigned int) (val) & (unsigned int) 0x000000ffU) << 24) | \ - (((unsigned int) (val) & (unsigned int) 0x0000ff00U) << 8) | \ - (((unsigned int) (val) & (unsigned int) 0x00ff0000U) >> 8) | \ - (((unsigned int) (val) & (unsigned int) 0xff000000U) >> 24))) +#define SWAP_ENDIAN(val) ((uint32_t) ( \ + (((uint32_t) (val) & (uint32_t) 0x000000ffU) << 24) | \ + (((uint32_t) (val) & (uint32_t) 0x0000ff00U) << 8) | \ + (((uint32_t) (val) & (uint32_t) 0x00ff0000U) >> 8) | \ + (((uint32_t) (val) & (uint32_t) 0xff000000U) >> 24))) -static int -is_little_endian () +static uint32_t +convert_to_little_endian (uint32_t x) { - static int retval = -1; - - if (retval == -1) { - int n = 1; - char *p = (char *)&n; - char x[] = {1, 0, 0, 0}; - - assert(sizeof(int) == 4); - - if (memcmp(p, x, 4) == 0) { - retval = 1; - } else { - retval = 0; - } - } - - return retval; -} - -static int -convert_to_little_endian (int x) -{ - if (is_little_endian()) { - return x; - } else { - return SWAP_ENDIAN(x); - } +#if BYTE_ORDER == LITTLE_ENDIAN + return x; +#else + return SWAP_ENDIAN(x); +#endif } int read_header (FILE *fp, Header *h) { - int buf[3]; + uint32_t buf[3]; - if (fread(buf, sizeof(int), 3, fp) == 0) { + if (fread(buf, sizeof(uint32_t), 3, fp) == 0) { return 0; } @@ -97,13 +77,13 @@ read_header (FILE *fp, Header *h) int write_header (FILE *fp, Header *h) { - int buf[3]; + uint32_t buf[3]; buf[0] = convert_to_little_endian(h->tv.tv_sec); buf[1] = convert_to_little_endian(h->tv.tv_usec); buf[2] = convert_to_little_endian(h->len); - if (fwrite(buf, sizeof(int), 3, fp) == 0) { + if (fwrite(buf, sizeof(uint32_t), 3, fp) == 0) { return 0; } @@ -158,4 +138,5 @@ efdopen (int fd, const char *mode) fprintf(stderr, "%s: fdopen failed: %s\n", progname, strerror(errno)); exit(EXIT_FAILURE); } + return fp; } diff --git a/io.h b/io.h @@ -9,5 +9,6 @@ FILE* efopen (const char *path, const char *mode); int edup (int oldfd); int edup2 (int oldfd, int newfd); FILE* efdopen (int fd, const char *mode); +void set_progname (const char *name); #endif diff --git a/ttyplay.1 b/ttyplay.1 @@ -38,6 +38,9 @@ Additionally, there are some special keys defined: .BI \- " or " s halve the speed of playback. .TP +.BI 0 +set playback speed to 0, pausing playback. +.TP .BI 1 set playback to speed 1.0 again. diff --git a/ttyplay.c b/ttyplay.c @@ -83,16 +83,21 @@ ttywait (struct timeval prev, struct timeval cur, double speed) static struct timeval drift = {0, 0}; struct timeval start; struct timeval diff = timeval_diff(prev, cur); + struct timeval *diffp = &diff; fd_set readfs; gettimeofday(&start, NULL); - assert(speed != 0); - diff = timeval_diff(drift, timeval_div(diff, speed)); + if (speed == 0.0) + diffp = NULL; + else + diff = timeval_diff(drift, timeval_div(diff, speed)); + if (diff.tv_sec < 0) { diff.tv_sec = diff.tv_usec = 0; } + FD_ZERO(&readfs); FD_SET(STDIN_FILENO, &readfs); /* * We use select() for sleeping with subsecond precision. @@ -101,9 +106,10 @@ ttywait (struct timeval prev, struct timeval cur, double speed) * Save "diff" since select(2) may overwrite it to {0, 0}. */ struct timeval orig_diff = diff; - select(1, &readfs, NULL, NULL, &diff); + int r; + r = select(1, &readfs, NULL, NULL, diffp); /* skip if a user hits any key */ diff = orig_diff; /* Restore the original diff value. */ - if (FD_ISSET(0, &readfs)) { /* a user hits a character? */ + if (r > 0 && FD_ISSET(0, &readfs)) { /* a user hits a character? */ char c; read(STDIN_FILENO, &c, 1); /* drain the character */ switch (c) { @@ -118,6 +124,9 @@ ttywait (struct timeval prev, struct timeval cur, double speed) case '1': speed = 1.0; break; + case '0': + speed = 0.0; + break; } drift.tv_sec = drift.tv_usec = 0; } else { @@ -136,14 +145,21 @@ double ttynowait (struct timeval prev, struct timeval cur, double speed) { /* do nothing */ - return 0; /* Speed isn't important. */ + return 1.0; /* Speed isn't important. */ } int ttyread (FILE *fp, Header *h, char **buf) { + fpos_t pos; + int can_seek=0; + if (fgetpos(fp, &pos) == 0) { + can_seek=1; + } + clearerr(fp); + if (read_header(fp, h) == 0) { - return 0; + goto err; } *buf = malloc(h->len); @@ -152,9 +168,21 @@ ttyread (FILE *fp, Header *h, char **buf) } if (fread(*buf, 1, h->len, fp) == 0) { - perror("fread"); + goto err; } return 1; + +err: + if (ferror(fp)) { + perror("fread"); + } + else { + /* Short read. Seek back to before header, to set up for retry. */ + if (can_seek) { + fsetpos(fp, &pos); + } + } + return 0; } int @@ -202,7 +230,9 @@ ttyplay (FILE *fp, double speed, ReadFunc read_func, } if (!first_time) { - speed = wait_func(prev, h.tv, speed); + do { + speed = wait_func(prev, h.tv, speed); + } while (speed == 0.0); } first_time = 0; @@ -252,7 +282,6 @@ usage (void) FILE * input_from_stdin (void) { - FILE *fp; int fd = edup(STDIN_FILENO); edup2(STDOUT_FILENO, STDIN_FILENO); return efdopen(fd, "r"); diff --git a/ttyrec.1 b/ttyrec.1 @@ -7,7 +7,7 @@ ttyrec \- a tty recorder .SH SYNOPSIS .br .B ttyrec -.I "[\-a][\-u] [file]" +.I "[\-a] [\-u] [\-e command] [file]" .br .SH DESCRIPTION .B Ttyrec diff --git a/ttyrec.c b/ttyrec.c @@ -113,11 +113,19 @@ char line[] = "/dev/ptyXX"; int aflg; int uflg; +static void +resize(int dummy) { + /* transmit window change information to the child */ + (void) ioctl(0, TIOCGWINSZ, (char *)&win); + (void) ioctl(master, TIOCSWINSZ, (char *)&win); +} + int main(argc, argv) int argc; char *argv[]; { + struct sigaction sa; extern int optind; int ch; void finish(); @@ -161,7 +169,10 @@ main(argc, argv) getmaster(); fixtty(); - (void) signal(SIGCHLD, finish); + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = finish; + sigaction(SIGCHLD, &sa, NULL); child = fork(); if (child < 0) { perror("fork"); @@ -173,11 +184,16 @@ main(argc, argv) perror("fork"); fail(); } - if (child) + if (child) { + sa.sa_flags = SA_RESTART; + sigaction(SIGCHLD, &sa, NULL); dooutput(); - else + } else doshell(command); } + sa.sa_handler = resize; + sa.sa_flags = SA_RESTART; + sigaction(SIGWINCH, &sa, NULL); doinput(); return 0; @@ -209,14 +225,10 @@ finish() union wait status; #endif /* !SVR4 */ register int pid; - register int die = 0; while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0) if (pid == child) - die = 1; - - if (die) - done(); + break; } struct linebuf { @@ -250,8 +262,8 @@ check_line (const char *line) } } -void -check_output(const char *str, int len) +static void +uu_check_output(const char *str, int len) { static struct linebuf lbuf = {"", 0}; int i; @@ -276,6 +288,23 @@ check_output(const char *str, int len) } } +static int +check_output(char *str, int len) +{ + char *p; + + /* If we see query string, remove it */ + /* ESC [ > 0 c : Send Device Attributes */ + if (len >= 5 && (p = strstr(str, "\e[>0c")) != NULL) { + if (len == 5) + return 0; + memmove(p, p+5, len-5+1-(p-str)); + return len-5; + } + + return len; +} + void dooutput() { @@ -294,12 +323,14 @@ dooutput() if (cc <= 0) break; if (uflg) - check_output(obuf, cc); + uu_check_output(obuf, cc); h.len = cc; gettimeofday(&h.tv, NULL); (void) write(1, obuf, cc); - (void) write_header(fscript, &h); - (void) fwrite(obuf, 1, cc, fscript); + if ((cc = check_output(obuf, cc))) { + (void) write_header(fscript, &h); + (void) fwrite(obuf, 1, cc, fscript); + } } done(); } @@ -325,9 +356,9 @@ doshell(const char* command) (void) close(slave); if (!command) { - execl(shell, strrchr(shell, '/') + 1, "-i", 0); + execl(shell, strrchr(shell, '/') + 1, "-i", NULL); } else { - execl(shell, strrchr(shell, '/') + 1, "-c", command, 0); + execl(shell, strrchr(shell, '/') + 1, "-c", command, NULL); } perror(shell); fail(); @@ -340,6 +371,9 @@ fixtty() rtt = tt; #if defined(SVR4) +#if !defined(XCASE) +#define XCASE 0 +#endif rtt.c_iflag = 0; rtt.c_lflag &= ~(ISIG|ICANON|XCASE|ECHO|ECHOE|ECHOK|ECHONL); rtt.c_oflag = OPOST; @@ -464,8 +498,10 @@ getslave() fail(); } #endif - (void) ioctl(0, TIOCGWINSZ, (char *)&win); } + (void) tcsetattr(slave, TCSAFLUSH, &tt); + (void) ioctl(slave, TIOCSWINSZ, (char *)&win); + (void) ioctl(slave, TIOCSCTTY, 0); #else /* !SVR4 */ #ifndef HAVE_openpty line[strlen("/dev/")] = 't';