Package Details: ttyrec 1.0.8-2

Git Clone URL: https://aur.archlinux.org/ttyrec.git (read-only, click to copy)
Package Base: ttyrec
Description: A tty recorder and player
Upstream URL: http://0xcc.net/ttyrec/index.html.en
Licenses: BSD
Submitter: dseg
Maintainer: dseg
Last Packager: dseg
Votes: 13
Popularity: 0.000000
First Submitted: 2016-03-14 12:14
Last Updated: 2016-03-14 12:17

Latest Comments

workonfire commented on 2021-02-14 21:02

Here's the patch file that you need to apply in order to compile this:

diff --git a/Makefile b/Makefile
index 44417aa..9ba4d76 100644
--- 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
index b5dde0c..82e7aab 100644
--- 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
index 5549c9c..8a0bf44 100644
--- 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
index c3d1d83..58cfcdd 100644
--- 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
index 787dfa9..c1acf59 100644
--- 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
index a28a326..c890b9c 100644
--- 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
index 3392f70..4f360e0 100644
--- a/ttyrec.c
+++ b/ttyrec.c
@@ -57,7 +57,9 @@

 #if defined(SVR4)
 #include <fcntl.h>
+#if HAVE_STROPTS_H
 #include <stropts.h>
+#endif
 #endif /* SVR4 */

 #include <sys/time.h>
@@ -113,11 +115,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 +171,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 +186,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 +227,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 +264,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 +290,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 +325,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 +358,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 +373,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;
@@ -449,23 +485,25 @@ getslave()
        perror("open(fd, O_RDWR)");
        fail();
    }
-   if (isastream(slave)) {
-       if (ioctl(slave, I_PUSH, "ptem") < 0) {
+   if (fcntl(slave, F_GETFD)) {
+       if (ioctl(slave, TIOCPKT, "ptem") < 0) {
            perror("ioctl(fd, I_PUSH, ptem)");
            fail();
        }
-       if (ioctl(slave, I_PUSH, "ldterm") < 0) {
-           perror("ioctl(fd, I_PUSH, ldterm)");
+       if (ioctl(slave, TIOCPKT, "ldterm") < 0) {
+           perror("ioctl(fd, TIOCPKT, ldterm)");
            fail();
        }
 #ifndef _HPUX_SOURCE
-       if (ioctl(slave, I_PUSH, "ttcompat") < 0) {
-           perror("ioctl(fd, I_PUSH, ttcompat)");
+       if (ioctl(slave, TIOCPKT, "ttcompat") < 0) {
+           perror("ioctl(fd, TIOCPKT, ttcompat)");
            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';

I don't know whether the if (fcntl(slave, F_GETFD)) { line is correct, but it works.

Most of the patches are taken from https://sources.debian.org/patches/ttyrec/1.0.8-5/

hugo commented on 2019-11-07 22:01

Got an error trying to compile:

ttyrec.c:60:10: fatal error: stropts.h: No such file or directory 60 | #include <stropts.h>