mirror of
https://github.com/ovh/ovh-ttyrec.git
synced 2023-04-10 17:58:23 +03:00
First public release of ovh-ttyrec (v1.1.5.0)
Signed-off-by: Stéphane Lesimple <stephane.lesimple@corp.ovh.com>
This commit is contained in:
13
AUTHORS
Normal file
13
AUTHORS
Normal file
@@ -0,0 +1,13 @@
|
||||
# This is the official list of ovh-ttyrec authors for copyright purposes.
|
||||
# This file is distinct from the CONTRIBUTORS files
|
||||
# and it lists the copyright holders only.
|
||||
|
||||
# Names should be added to this file as one of
|
||||
# Organization's name
|
||||
# Individual's name <submission email address>
|
||||
# Individual's name <submission email address> <email2> <emailN>
|
||||
# See CONTRIBUTORS for the meaning of multiple email addresses.
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
OVH SAS
|
||||
78
CONTRIBUTING.md
Normal file
78
CONTRIBUTING.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Contributing to ovh-ttyrec
|
||||
|
||||
This project accepts contributions. In order to contribute, you should
|
||||
pay attention to a few things:
|
||||
|
||||
1. your code must follow the coding style rules
|
||||
2. your code must be unit-tested
|
||||
3. your code must be documented
|
||||
4. your work must be signed (see below)
|
||||
5. you may contribute through GitHub Pull Requests
|
||||
|
||||
# Coding and documentation Style
|
||||
|
||||
Please follow the coding style you'll find in the main ttyrec.c file.
|
||||
Ensure you `make style` before comitting.
|
||||
|
||||
# Submitting Modifications
|
||||
|
||||
The contributions should be submitted through Github Pull Requests
|
||||
and follow the DCO which is defined below.
|
||||
|
||||
Note that we want to keep compatibility with ttyrec classic, and as
|
||||
ovh-ttyrec needs to be extremely stable (as it's used in critical
|
||||
environment), deep modifications will probably get rejected.
|
||||
|
||||
For this project, stability will always be preferred over fancy.
|
||||
|
||||
# Licensing for new files
|
||||
|
||||
ovh-ttyrec is licensed under a Modified 3-Clause BSD license. Anything
|
||||
contributed to ovh-ttyrec must be released under this license.
|
||||
|
||||
When introducing a new file into the project, please make sure it has a
|
||||
copyright header making clear under which license it's being released.
|
||||
|
||||
# Developer Certificate of Origin (DCO)
|
||||
|
||||
To improve tracking of contributions to this project we will use a
|
||||
process modeled on the modified DCO 1.1 and use a "sign-off" procedure
|
||||
on patches that are being emailed around or contributed in any other
|
||||
way.
|
||||
|
||||
The sign-off is a simple line at the end of the explanation for the
|
||||
patch, which certifies that you wrote it or otherwise have the right
|
||||
to pass it on as an open-source patch. The rules are pretty simple:
|
||||
if you can certify the below:
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I have
|
||||
the right to submit it under the open source license indicated in
|
||||
the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best of
|
||||
my knowledge, is covered under an appropriate open source License
|
||||
and I have the right under that license to submit that work with
|
||||
modifications, whether created in whole or in part by me, under
|
||||
the same open source license (unless I am permitted to submit
|
||||
under a different license), as indicated in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other person
|
||||
who certified (a), (b) or (c) and I have not modified it.
|
||||
|
||||
(d) The contribution is made free of any other party's intellectual
|
||||
property claims or rights.
|
||||
|
||||
(e) I understand and agree that this project and the contribution are
|
||||
public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
|
||||
|
||||
then you just add a line saying
|
||||
|
||||
Signed-off-by: Random J Developer <random@example.org>
|
||||
|
||||
using your real name (sorry, no pseudonyms or anonymous contributions.)
|
||||
14
CONTRIBUTORS
Normal file
14
CONTRIBUTORS
Normal file
@@ -0,0 +1,14 @@
|
||||
# This is the official list of people who can contribute
|
||||
# (and typically have contributed) code to the <PROJECT> repository.
|
||||
#
|
||||
# Names should be added to this file only after verifying that
|
||||
# the individual or the individual's organization has agreed to
|
||||
# the appropriate CONTRIBUTING.md file.
|
||||
#
|
||||
# Names should be added to this file like so:
|
||||
# Individual's name <submission email address>
|
||||
# Individual's name <submission email address>
|
||||
#
|
||||
# Please keep the list sorted.
|
||||
#
|
||||
Stéphane Lesimple <stephane.lesimple@corp.ovh.com>
|
||||
27
LICENSE
Normal file
27
LICENSE
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright 2001-2019, OVH SAS.
|
||||
All rights reserved.
|
||||
Modified 3-Clause BSD
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of OVH SAS nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY OVH SAS AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL OVH SAS AND CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
12
MAINTAINERS
Normal file
12
MAINTAINERS
Normal file
@@ -0,0 +1,12 @@
|
||||
# This is the official list of the project maintainers.
|
||||
# This is mostly useful for contributors that want to push
|
||||
# significant pull requests or for project management issues.
|
||||
#
|
||||
#
|
||||
# Names should be added to this file like so:
|
||||
# Individual's name <submission email address>
|
||||
# Individual's name <submission email address>
|
||||
#
|
||||
# Please keep the list sorted.
|
||||
#
|
||||
Stéphane Lesimple <stephane.lesimple@corp.ovh.com>
|
||||
46
Makefile
46
Makefile
@@ -1,46 +0,0 @@
|
||||
CC = gcc
|
||||
CFLAGS = -O2 -DSVR4 -D_GNU_SOURCE -Wall -std=gnu99 -D_FORTIFY_SOURCE=1 -Wno-unused-result
|
||||
VERSION = 1.0
|
||||
|
||||
TARGET = ttyrec ttyplay ttytime
|
||||
|
||||
DIST = ttyrec.c ttyplay.c ttyrec.h io.c io.h ttytime.c\
|
||||
README Makefile ttyrec.1 ttyplay.1 ttytime.1
|
||||
|
||||
BIN = $(DESTDIR)/usr/bin
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
patch:
|
||||
quilt push -a
|
||||
touch $@
|
||||
|
||||
ttyrec: patch ttyrec.o io.o
|
||||
$(CC) $(CFLAGS) -o ttyrec ttyrec.o io.o
|
||||
|
||||
ttyplay: patch ttyplay.o io.o
|
||||
$(CC) $(CFLAGS) -o ttyplay ttyplay.o io.o
|
||||
|
||||
ttytime: patch ttytime.o io.o
|
||||
$(CC) $(CFLAGS) -o ttytime ttytime.o io.o
|
||||
|
||||
clean:
|
||||
rm -f *.o $(TARGET) ttyrecord *~
|
||||
quilt pop -a || true
|
||||
rm -f patch
|
||||
|
||||
install:
|
||||
install -d -m 0755 -o root -g root $(BIN)
|
||||
install -m 0755 -o root -g root ttyrec $(BIN)
|
||||
install -m 0755 -o root -g root ttyplay $(BIN)
|
||||
install -m 0755 -o root -g root ttytime $(BIN)
|
||||
install -m 0755 -o root -g root helper/telnetpassfile $(BIN)
|
||||
|
||||
dist:
|
||||
rm -rf ttyrec-$(VERSION)
|
||||
rm -f ttyrec-$(VERSION).tar.gz
|
||||
|
||||
mkdir ttyrec-$(VERSION)
|
||||
cp $(DIST) ttyrec-$(VERSION)
|
||||
tar zcf ttyrec-$(VERSION).tar.gz ttyrec-$(VERSION)
|
||||
rm -rf ttyrec-$(VERSION)
|
||||
47
Makefile.in
Normal file
47
Makefile.in
Normal file
@@ -0,0 +1,47 @@
|
||||
CC = %CC%
|
||||
CFLAGS = -O2 -D_GNU_SOURCE -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -std=gnu99 %WARNINGS% -Werror
|
||||
LIBS = %LIBS%
|
||||
|
||||
BINARIES = ttyrec ttyplay ttytime
|
||||
DOCS = docs/ttyrec.1
|
||||
|
||||
BIN = $(DESTDIR)/usr/bin
|
||||
|
||||
all: prog doc
|
||||
|
||||
deb:
|
||||
dpkg-buildpackage -b -rfakeroot -us -uc
|
||||
|
||||
prog: $(BINARIES)
|
||||
|
||||
doc: $(DOCS)
|
||||
|
||||
ttyrec.o: ttyrec.c configure.h
|
||||
$(CC) $(CFLAGS) -c ttyrec.c
|
||||
|
||||
ttyrec: ttyrec.o io.o
|
||||
$(CC) $(CFLAGS) -pthread -o ttyrec ttyrec.o io.o $(LIBS)
|
||||
|
||||
ttyplay: ttyplay.o io.o
|
||||
$(CC) $(CFLAGS) -o ttyplay ttyplay.o io.o
|
||||
|
||||
ttytime: ttytime.o io.o
|
||||
$(CC) $(CFLAGS) -o ttytime ttytime.o io.o
|
||||
|
||||
docs/ttyrec.1: ttyrec
|
||||
help2man -N --help-option=-h --version-option=-V --no-discard-stderr ./ttyrec > docs/ttyrec.1
|
||||
|
||||
clean:
|
||||
rm -f *.o $(BINARIES) $(DOCS) ttyrecord *~ Makefile configure.h
|
||||
|
||||
style:
|
||||
uncrustify -c uncrustify.cfg -l C --no-backup *.h *.c
|
||||
|
||||
dist:
|
||||
tar cvzf ttyrec.tar.gz *.c *.h docs/ debian/ configure Makefile.in uncrustify.cfg
|
||||
|
||||
install:
|
||||
install -d -m 0755 -o root -g root $(BIN)
|
||||
install -m 0755 -o root -g root ttyrec $(BIN)
|
||||
install -m 0755 -o root -g root ttyplay $(BIN)
|
||||
install -m 0755 -o root -g root ttytime $(BIN)
|
||||
27
README
27
README
@@ -1,27 +0,0 @@
|
||||
ttyrec is a tty recorder. ttyplay is a tty player.
|
||||
|
||||
Installation:
|
||||
|
||||
% make
|
||||
|
||||
or if your system is SVR4 system (Solaris etc.),
|
||||
|
||||
% make CFLAGS=-DSVR4
|
||||
|
||||
or if your system supports getpt(3),
|
||||
|
||||
% make CFLAGS=-DHAVE_getpt
|
||||
|
||||
HAVE_getpt is required if your linux system uses devfs.
|
||||
|
||||
|
||||
Usage:
|
||||
|
||||
% ttyrec
|
||||
(In the excuted shell, do whatever you want and exit)
|
||||
|
||||
% ttyplay ttyrecord
|
||||
|
||||
Have fun!
|
||||
|
||||
-- Satoru Takabayashi <satoru@namazu.org>
|
||||
93
README.md
Normal file
93
README.md
Normal file
@@ -0,0 +1,93 @@
|
||||
ovh-ttyrec
|
||||
==========
|
||||
|
||||
`ttyrec` is a terminal (tty) recorder, it comes with `ttyplay`, which is a tty player.
|
||||
|
||||
The original ttyrec is Copyright (c) 2000 Satoru Takabayashi.
|
||||
|
||||
The original ttyrec is based on the `script` program, Copyright (c) 1980 Regents of the University of California.
|
||||
|
||||
ovh-ttyrec is based (and compatible with) the original ttyrec, and can be used as a drop-in replacement. It is licensed under the 3-clause BSD license (see LICENSE file).
|
||||
|
||||
Efforts have been made to ensure the code is portable. It is known to work under at least:
|
||||
|
||||
- Linux
|
||||
- FreeBSD
|
||||
- NetBSD
|
||||
- OpenBSD
|
||||
- MacOS
|
||||
- OpenSolaris distributions (such as OmniOS)
|
||||
|
||||
It should work under any POSIX OS that support either `openpty()` or the `grantpt()`/`unlockpt() `mechanisms.
|
||||
|
||||
## features
|
||||
|
||||
- Drop-in replacement of the classic ttyrec, additional features don't break compatibility
|
||||
- The code is portable and OS features that can be used are detected at compile time
|
||||
- Supports ttyrec output file rotation without interrupting the session
|
||||
- Supports locking the session after a keyboard input timeout, optionally displaying a custom message
|
||||
- Supports terminating the session after a keyboard input timeout
|
||||
- Supports manually locking or terminating the session via "cheatcodes" (specific keystrokes)
|
||||
- Supports a no-tty mode, relying on pipes instead of pseudottys, while still recording stdout/stderr
|
||||
- Automatically detects whether to use pseudottys or pipes, also overridable from command-line
|
||||
- Supports reporting the number of bytes that were output to the terminal on session exit
|
||||
|
||||
## compilation
|
||||
|
||||
To compile the binaries and build the man pages, just run:
|
||||
|
||||
$ ./configure && make
|
||||
|
||||
If you don't want to build the manpages, or you don't have the required `help2man` tool, you can run `make prog` instead.
|
||||
|
||||
Installation:
|
||||
|
||||
$ make install
|
||||
|
||||
Note that installation is not needed to test the binaries: you can just call `./ttyrec` from the build folder.
|
||||
|
||||
## build a .deb package
|
||||
|
||||
If you want to build a .deb (Debian/Ubuntu) package, just run:
|
||||
|
||||
$ ./configure && make deb
|
||||
|
||||
## usage
|
||||
|
||||
The simplest usage is just calling the binary, it'll execute the users' shell and record the session until exit:
|
||||
|
||||
$ ttyrec
|
||||
To replay this session:
|
||||
|
||||
$ ttyplay ./ttyrecord
|
||||
|
||||
Run some shell commands:
|
||||
|
||||
$ ttyrec -f cmds.ttyrec -- sh -c 'for i in a b c; do echo $i; done'
|
||||
|
||||
Connect to a remote machine interactively, lock the session after 1 minute of inactivity, and kill it after 5 minutes of inactivity:
|
||||
|
||||
$ ttyrec -t 60 -k 300 -- ssh remoteserver
|
||||
|
||||
Execute a local script remotely with the default remote shell:
|
||||
|
||||
$ cat script.sh | ttyrec -- ssh remoteserver
|
||||
|
||||
Record a screen session:
|
||||
|
||||
$ ttyrec screen
|
||||
|
||||
Usage information:
|
||||
|
||||
$ ttyrec -h
|
||||
|
||||
## version scheme
|
||||
|
||||
We follow the version format `A.B.C.D`. The following rules apply:
|
||||
|
||||
- A is incremented when the file format of ttyrec changes, as long as A=1, the format is compatible with the original ttyrec (and original ttyplay)
|
||||
- B is incremented for a breaking change in the way ttyrec can be called (a command-line option was removed for example), which means in that case, other programs or scripts using ttyrec should be checked for compatibility
|
||||
- C is incremented for any non-hotfix change that stays backwards compatible (a new feature that can be enabled with a new command-line option for example)
|
||||
- D is incremented for a quickfix/hotfix, or a change in the build system, docs, etc.
|
||||
|
||||
When a digit is incremented, all the "lower" ones go back to zero, i.e. if we are at version 4.7.1.5, and we implement a breaking change, the version number becomes 4.8.0.0.
|
||||
149
configure
vendored
Executable file
149
configure
vendored
Executable file
@@ -0,0 +1,149 @@
|
||||
#! /bin/sh
|
||||
curdir=$(dirname $0)
|
||||
|
||||
echo '#ifndef CONFIGURE_H' >"$curdir/configure.h"
|
||||
echo '#define CONFIGURE_H' >>"$curdir/configure.h"
|
||||
|
||||
printf "%b" "Looking for compiler... "
|
||||
[ -z "$CC" ] && CC=gcc
|
||||
which $CC >/dev/null 2>&1 || CC=clang
|
||||
which $CC >/dev/null 2>&1 || CC=cc
|
||||
echo "$CC"
|
||||
|
||||
LIBS=''
|
||||
DEFINES_STR='uses:'
|
||||
WARNINGS=''
|
||||
|
||||
srcfile=$(mktemp)
|
||||
mv $srcfile $srcfile.c
|
||||
trap "rm -f $srcfile.c" INT HUP EXIT
|
||||
|
||||
printf "%b" "Looking for isastream()... "
|
||||
cat >$srcfile.c <<EOF
|
||||
#include <stropts.h>
|
||||
int main(void) { return isastream(0); }
|
||||
EOF
|
||||
if $CC $srcfile.c -o /dev/null >/dev/null 2>&1; then
|
||||
echo "yes"
|
||||
echo '#define HAVE_isastream' >>"$curdir/configure.h"
|
||||
DEFINES_STR="$DEFINES_STR isastream"
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
|
||||
printf "%b" "Looking for cfmakeraw()... "
|
||||
cat >$srcfile.c <<EOF
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
int main(void) { cfmakeraw(0); return 0; }
|
||||
EOF
|
||||
if $CC $srcfile.c -o /dev/null >/dev/null 2>&1; then
|
||||
echo "yes"
|
||||
echo '#define HAVE_cfmakeraw' >>"$curdir/configure.h"
|
||||
DEFINES_STR="$DEFINES_STR cfmakeraw"
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
|
||||
printf "%b" "Looking for getpt()... "
|
||||
cat >$srcfile.c <<EOF
|
||||
#include <stdlib.h>
|
||||
int main(void) { return getpt(); }
|
||||
EOF
|
||||
if $CC $srcfile.c -o /dev/null >/dev/null 2>&1; then
|
||||
echo "yes"
|
||||
echo '#define HAVE_getpt' >>"$curdir/configure.h"
|
||||
DEFINES_STR="$DEFINES_STR getpt"
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
|
||||
printf "%b" "Looking for posix_openpt()... "
|
||||
cat >$srcfile.c <<EOF
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
int main(void) { return posix_openpt(0); }
|
||||
EOF
|
||||
if $CC $srcfile.c -o /dev/null >/dev/null 2>&1; then
|
||||
echo "yes"
|
||||
echo '#define HAVE_posix_openpt' >>"$curdir/configure.h"
|
||||
DEFINES_STR="$DEFINES_STR posix_openpt"
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
|
||||
printf "%b" "Looking for grantpt()... "
|
||||
cat >$srcfile.c <<EOF
|
||||
#include <stdlib.h>
|
||||
int main(void) { (void)ptsname(0); return grantpt(0) + unlockpt(0); }
|
||||
EOF
|
||||
if $CC $srcfile.c -o /dev/null >/dev/null 2>&1; then
|
||||
echo "yes"
|
||||
echo '#define HAVE_grantpt' >>"$curdir/configure.h"
|
||||
DEFINES_STR="$DEFINES_STR grantpt"
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
|
||||
printf "%b" "Looking for openpty()... "
|
||||
cat >$srcfile.c <<EOF
|
||||
#include <pty.h>
|
||||
int main(void) { return openpty(0, 0, 0, 0, 0); }
|
||||
EOF
|
||||
if $CC $srcfile.c -lutil -o /dev/null >/dev/null 2>&1; then
|
||||
echo "yes (pty.h)"
|
||||
LIBS="$LIBS -lutil"
|
||||
echo '#define HAVE_openpty' >>"$curdir/configure.h"
|
||||
echo '#define HAVE_openpty_pty_h' >>"$curdir/configure.h"
|
||||
DEFINES_STR="$DEFINES_STR openpty[pty.h]"
|
||||
else
|
||||
cat >$srcfile.c <<EOF
|
||||
#include <util.h>
|
||||
int main(void) { return openpty(0, 0, 0, 0, 0); }
|
||||
EOF
|
||||
if $CC $srcfile.c -lutil -o /dev/null >/dev/null 2>&1; then
|
||||
echo "yes (util.h)"
|
||||
LIBS="$LIBS -lutil"
|
||||
echo '#define HAVE_openpty' >>"$curdir/configure.h"
|
||||
echo '#define HAVE_openpty_util_h' >>"$curdir/configure.h"
|
||||
DEFINES_STR="$DEFINES_STR openpty[util.h]"
|
||||
else
|
||||
cat >$srcfile.c <<EOF
|
||||
#include <libutil.h>
|
||||
int main(void) { return openpty(0, 0, 0, 0, 0); }
|
||||
EOF
|
||||
if $CC $srcfile.c -lutil -o /dev/null >/dev/null 2>&1; then
|
||||
echo "yes (libutil.h)"
|
||||
LIBS="$LIBS -lutil"
|
||||
echo '#define HAVE_openpty' >>"$curdir/configure.h"
|
||||
echo '#define HAVE_openpty_libutil_h' >>"$curdir/configure.h"
|
||||
DEFINES_STR="$DEFINES_STR openpty[libutil.h]"
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Checking for supported compiler options..."
|
||||
for w in -Wall -Wextra -pedantic -Wno-unused-result -Wbad-function-cast -Wmissing-declarations \
|
||||
-Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wstrict-prototypes \
|
||||
-Wpointer-sign -Wmissing-parameter-type -Wold-style-declaration
|
||||
do
|
||||
echo 'int main(void) { return 0; }' >$srcfile.c
|
||||
if [ $($CC $srcfile.c $w -o /dev/null 2>&1 | wc -l) = 0 ]; then
|
||||
echo "... OK $w"
|
||||
WARNINGS="$WARNINGS $w"
|
||||
else
|
||||
echo "... unsupported $w"
|
||||
fi
|
||||
done
|
||||
|
||||
sed "s/%CC%/$CC/g;s/%LIBS%/$LIBS/g;s/%WARNINGS%/$WARNINGS/" $(dirname $0)/Makefile.in > $(dirname $0)/Makefile
|
||||
|
||||
cat >>"$curdir/configure.h" <<EOF
|
||||
#define DEFINES_STR "$DEFINES_STR"
|
||||
#endif
|
||||
EOF
|
||||
|
||||
echo
|
||||
echo "You may run make now"
|
||||
7
debian/README
vendored
Normal file
7
debian/README
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
The Debian Package ovh-ttyrec
|
||||
-----------------------------
|
||||
|
||||
Records terminal sessions.
|
||||
See included README.md for more information.
|
||||
|
||||
-- Stéphane Lesimple <stephane.lesimple@corp.ovh.com> Thu, 09 May 2019 12:56:27 +0200
|
||||
8
debian/README.source
vendored
Normal file
8
debian/README.source
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
ovh-ttyrec for Debian
|
||||
---------------------
|
||||
|
||||
See the included README.md file for more information.
|
||||
|
||||
|
||||
|
||||
|
||||
6
debian/changelog
vendored
Normal file
6
debian/changelog
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
ovh-ttyrec (1.1.5.0) master; urgency=medium
|
||||
|
||||
* First public release
|
||||
* Add -c option to enable cheatcodes, as they're now disabled by default
|
||||
|
||||
-- Stéphane Lesimple (deb packages) <stephane.lesimple@corp.ovh.com> Thu, 09 May 2019 12:55:21 +0200
|
||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
||||
7
|
||||
23
debian/control
vendored
Normal file
23
debian/control
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
Source: ovh-ttyrec
|
||||
Section: ovh
|
||||
Priority: extra
|
||||
Maintainer: Stéphane Lesimple <stephane.lesimple@corp.ovh.com>
|
||||
Build-Depends: debhelper (>= 7.0.50~)
|
||||
Standards-Version: 3.8.4
|
||||
|
||||
Package: ovh-ttyrec
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Conflicts: ttyrec
|
||||
Description: Extended (but compatible) fork of ttyrec
|
||||
ttyrec is a terminal (tty) recorder, it comes with ttyplay, which is a tty player.
|
||||
Some features ov ovh-ttyrec follow:
|
||||
- Drop-in replacement of the classic ttyrec, additional features don't break compatibility
|
||||
- The code is portable and OS features that can be used are detected at compile time
|
||||
- Supports ttyrec output file rotation without interrupting the session
|
||||
- Supports locking the session after a keyboard input timeout, optionally displaying a custom message
|
||||
- Supports terminating the session after a keyboard input timeout
|
||||
- Supports manually locking or terminating the session via "cheatcodes" (specific keystrokes)
|
||||
- Supports a no-tty mode, relying on pipes instead of pseudottys, while still recording stdout/stderr
|
||||
- Automatically detects whether to use pseudottys or pipes, also overridable from command-line
|
||||
- Supports reporting the number of bytes that were output to the terminal on session exit
|
||||
20
debian/copyright
vendored
Normal file
20
debian/copyright
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
This work was packaged for Debian by:
|
||||
|
||||
Stéphane Lesimple <stephane.lesimple@corp.ovh.com> on Fri, 13 Jul 2012 15:16:31 +0200
|
||||
|
||||
Upstream Author(s):
|
||||
|
||||
Stéphane Lesimple <stephane.lesimple@corp.ovh.com>
|
||||
|
||||
Copyright:
|
||||
|
||||
Copyright 2001-2019, OVH SAS.
|
||||
|
||||
License:
|
||||
|
||||
See included LICENSE file.
|
||||
|
||||
The Debian packaging is:
|
||||
|
||||
Under the same terms as the included LICENSE file.
|
||||
|
||||
1
debian/links
vendored
Normal file
1
debian/links
vendored
Normal file
@@ -0,0 +1 @@
|
||||
usr/bin/ttyrec usr/bin/ovh-ttyrec
|
||||
3
debian/manpages
vendored
Normal file
3
debian/manpages
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
docs/ttyplay.1
|
||||
docs/ttyrec.1
|
||||
docs/ttytime.1
|
||||
13
debian/rules
vendored
Executable file
13
debian/rules
vendored
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
# Sample debian/rules that uses debhelper.
|
||||
# This file was originally written by Joey Hess and Craig Small.
|
||||
# As a special exception, when this file is copied by dh-make into a
|
||||
# dh-make output file, you may use that output file without restriction.
|
||||
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
%:
|
||||
dh $@
|
||||
142
io.c
142
io.c
@@ -1,4 +1,10 @@
|
||||
/*
|
||||
/* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
* Copyright 2001-2019 The ovh-ttyrec Authors. All rights reserved.
|
||||
*
|
||||
* This work is based on the original ttyrec, whose license text
|
||||
* can be found below unmodified.
|
||||
*
|
||||
* Copyright (c) 2000 Satoru Takabayashi <satoru@namazu.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -40,51 +46,69 @@
|
||||
|
||||
#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) \
|
||||
((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)))
|
||||
|
||||
static int
|
||||
is_little_endian ()
|
||||
|
||||
int read_header(FILE *fp, Header *h);
|
||||
int write_header(FILE *fp, Header *h);
|
||||
void set_progname(const char *name);
|
||||
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);
|
||||
|
||||
|
||||
static int is_little_endian(void)
|
||||
{
|
||||
static int retval = -1;
|
||||
|
||||
if (retval == -1) {
|
||||
int n = 1;
|
||||
char *p = (char *)&n;
|
||||
char x[] = {1, 0, 0, 0};
|
||||
if (retval == -1)
|
||||
{
|
||||
int n = 1;
|
||||
char *p = (char *)&n;
|
||||
char x[] = { 1, 0, 0, 0 };
|
||||
|
||||
assert(sizeof(int) == 4);
|
||||
assert(sizeof(int) == 4);
|
||||
|
||||
if (memcmp(p, x, 4) == 0) {
|
||||
retval = 1;
|
||||
} else {
|
||||
retval = 0;
|
||||
}
|
||||
if (memcmp(p, x, 4) == 0)
|
||||
{
|
||||
retval = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
convert_to_little_endian (int x)
|
||||
|
||||
static int convert_to_little_endian(int x)
|
||||
{
|
||||
if (is_little_endian()) {
|
||||
return x;
|
||||
} else {
|
||||
return SWAP_ENDIAN(x);
|
||||
if (is_little_endian())
|
||||
{
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SWAP_ENDIAN(x);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
read_header (FILE *fp, Header *h)
|
||||
|
||||
int read_header(FILE *fp, Header *h)
|
||||
{
|
||||
int buf[3];
|
||||
|
||||
if (fread(buf, sizeof(int), 3, fp) == 0) {
|
||||
return 0;
|
||||
if (fread(buf, sizeof(int), 3, fp) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
h->tv.tv_sec = convert_to_little_endian(buf[0]);
|
||||
@@ -94,8 +118,8 @@ read_header (FILE *fp, Header *h)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
write_header (FILE *fp, Header *h)
|
||||
|
||||
int write_header(FILE *fp, Header *h)
|
||||
{
|
||||
int buf[3];
|
||||
|
||||
@@ -103,59 +127,69 @@ write_header (FILE *fp, Header *h)
|
||||
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) {
|
||||
return 0;
|
||||
if (fwrite(buf, sizeof(int), 3, fp) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static char *progname = "";
|
||||
void
|
||||
set_progname (const char *name)
|
||||
void set_progname(const char *name)
|
||||
{
|
||||
progname = strdup(name);
|
||||
}
|
||||
|
||||
FILE *
|
||||
efopen (const char *path, const char *mode)
|
||||
|
||||
FILE *efopen(const char *path, const char *mode)
|
||||
{
|
||||
FILE *fp = fopen(path, mode);
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "%s: %s: %s\n", progname, path, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
fprintf(stderr, "%s: %s: %s\n", progname, path, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
int
|
||||
edup (int oldfd)
|
||||
|
||||
int edup(int oldfd)
|
||||
{
|
||||
int fd = dup(oldfd);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "%s: dup failed: %s\n", progname, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
fprintf(stderr, "%s: dup failed: %s\n", progname, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
int
|
||||
edup2 (int oldfd, int newfd)
|
||||
|
||||
int edup2(int oldfd, int newfd)
|
||||
{
|
||||
int fd = dup2(oldfd, newfd);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "%s: dup2 failed: %s\n", progname, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
fprintf(stderr, "%s: dup2 failed: %s\n", progname, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
FILE *
|
||||
efdopen (int fd, const char *mode)
|
||||
|
||||
FILE *efdopen(int fd, const char *mode)
|
||||
{
|
||||
FILE *fp = fdopen(fd, mode);
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "%s: fdopen failed: %s\n", progname, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
fprintf(stderr, "%s: fdopen failed: %s\n", progname, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
13
io.h
13
io.h
@@ -3,11 +3,12 @@
|
||||
|
||||
#include "ttyrec.h"
|
||||
|
||||
int read_header (FILE *fp, Header *h);
|
||||
int write_header (FILE *fp, Header *h);
|
||||
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);
|
||||
int read_header(FILE *fp, Header *h);
|
||||
int write_header(FILE *fp, Header *h);
|
||||
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
|
||||
|
||||
328
ttyplay.c
328
ttyplay.c
@@ -1,4 +1,11 @@
|
||||
/*
|
||||
// vim: noai:ts=4:sw=4:expandtab:
|
||||
/* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
* Copyright 2001-2019 The ovh-ttyrec Authors. All rights reserved.
|
||||
*
|
||||
* This work is based on the original ttyrec, whose license text
|
||||
* can be found below unmodified.
|
||||
*
|
||||
* Copyright (c) 2000 Satoru Takabayashi <satoru@namazu.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -12,8 +19,8 @@
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
@@ -42,178 +49,217 @@
|
||||
#include "ttyrec.h"
|
||||
#include "io.h"
|
||||
|
||||
typedef double (*WaitFunc) (struct timeval prev,
|
||||
struct timeval cur,
|
||||
double speed);
|
||||
typedef int (*ReadFunc) (FILE *fp, Header *h, char **buf);
|
||||
typedef void (*WriteFunc) (char *buf, int len);
|
||||
typedef void (*ProcessFunc) (FILE *fp, double speed,
|
||||
ReadFunc read_func, WaitFunc wait_func);
|
||||
typedef double (*WaitFunc) (struct timeval prev,
|
||||
struct timeval cur,
|
||||
double speed);
|
||||
typedef int (*ReadFunc) (FILE *fp, Header *h, char **buf);
|
||||
typedef void (*WriteFunc) (char *buf, int len);
|
||||
typedef void (*ProcessFunc) (FILE *fp, double speed,
|
||||
ReadFunc read_func, WaitFunc wait_func);
|
||||
|
||||
struct timeval
|
||||
timeval_diff (struct timeval tv1, struct timeval tv2)
|
||||
struct timeval timeval_diff(struct timeval tv1, struct timeval tv2);
|
||||
struct timeval timeval_div(struct timeval tv1, double n);
|
||||
double ttywait(struct timeval prev, struct timeval cur, double speed);
|
||||
double ttynowait(struct timeval prev, struct timeval cur, double speed);
|
||||
int ttyread(FILE *fp, Header *h, char **buf);
|
||||
int ttypread(FILE *fp, Header *h, char **buf);
|
||||
void ttywrite(char *buf, int len);
|
||||
void ttynowrite(char *buf, int len);
|
||||
void ttyplay(FILE *fp, double speed, ReadFunc read_func, WriteFunc write_func, WaitFunc wait_func);
|
||||
void ttyskipall(FILE *fp);
|
||||
void ttyplayback(FILE *fp, double speed, ReadFunc read_func, WaitFunc wait_func);
|
||||
void ttypeek(FILE *fp, double speed, ReadFunc read_func, WaitFunc wait_func);
|
||||
void usage(void);
|
||||
FILE *input_from_stdin(void);
|
||||
|
||||
|
||||
struct timeval timeval_diff(struct timeval tv1, struct timeval tv2)
|
||||
{
|
||||
struct timeval diff;
|
||||
|
||||
diff.tv_sec = tv2.tv_sec - tv1.tv_sec;
|
||||
diff.tv_sec = tv2.tv_sec - tv1.tv_sec;
|
||||
diff.tv_usec = tv2.tv_usec - tv1.tv_usec;
|
||||
if (diff.tv_usec < 0) {
|
||||
diff.tv_sec--;
|
||||
diff.tv_usec += 1000000;
|
||||
if (diff.tv_usec < 0)
|
||||
{
|
||||
diff.tv_sec--;
|
||||
diff.tv_usec += 1000000;
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
struct timeval
|
||||
timeval_div (struct timeval tv1, double n)
|
||||
|
||||
struct timeval timeval_div(struct timeval tv1, double n)
|
||||
{
|
||||
double x = ((double)tv1.tv_sec + (double)tv1.tv_usec / 1000000.0) / n;
|
||||
double x = ((double)tv1.tv_sec + (double)tv1.tv_usec / 1000000.0) / n;
|
||||
struct timeval div;
|
||||
|
||||
|
||||
div.tv_sec = (int)x;
|
||||
div.tv_usec = (x - (int)x) * 1000000;
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
double
|
||||
ttywait (struct timeval prev, struct timeval cur, double speed)
|
||||
|
||||
double 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);
|
||||
fd_set readfs;
|
||||
static struct timeval drift = { 0, 0 };
|
||||
struct timeval start;
|
||||
struct timeval diff = timeval_diff(prev, cur);
|
||||
fd_set readfs;
|
||||
|
||||
gettimeofday(&start, NULL);
|
||||
|
||||
assert(speed != 0);
|
||||
diff = timeval_diff(drift, timeval_div(diff, speed));
|
||||
if (diff.tv_sec < 0) {
|
||||
diff.tv_sec = diff.tv_usec = 0;
|
||||
if (diff.tv_sec < 0)
|
||||
{
|
||||
diff.tv_sec = diff.tv_usec = 0;
|
||||
}
|
||||
|
||||
FD_SET(STDIN_FILENO, &readfs);
|
||||
/*
|
||||
|
||||
/*
|
||||
* We use select() for sleeping with subsecond precision.
|
||||
* select() is also used to wait user's input from a keyboard.
|
||||
*
|
||||
* Save "diff" since select(2) may overwrite it to {0, 0}.
|
||||
* Save "diff" since select(2) may overwrite it to {0, 0}.
|
||||
*/
|
||||
struct timeval orig_diff = diff;
|
||||
select(1, &readfs, NULL, NULL, &diff);
|
||||
diff = orig_diff; /* Restore the original diff value. */
|
||||
if (FD_ISSET(0, &readfs)) { /* a user hits a character? */
|
||||
diff = orig_diff; /* Restore the original diff value. */
|
||||
if (FD_ISSET(0, &readfs)) /* a user hits a character? */
|
||||
{
|
||||
char c;
|
||||
read(STDIN_FILENO, &c, 1); /* drain the character */
|
||||
switch (c) {
|
||||
case '+':
|
||||
case 'f':
|
||||
speed *= 2;
|
||||
break;
|
||||
case '-':
|
||||
case 's':
|
||||
speed /= 2;
|
||||
break;
|
||||
case '1':
|
||||
speed = 1.0;
|
||||
break;
|
||||
if (read(STDIN_FILENO, &c, 1) == 1)
|
||||
{
|
||||
/* drain the character */
|
||||
switch (c)
|
||||
{
|
||||
case '+':
|
||||
case 'f':
|
||||
speed *= 2;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
case 's':
|
||||
speed /= 2;
|
||||
break;
|
||||
|
||||
case '1':
|
||||
speed = 1.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
drift.tv_sec = drift.tv_usec = 0;
|
||||
} else {
|
||||
struct timeval stop;
|
||||
gettimeofday(&stop, NULL);
|
||||
/* Hack to accumulate the drift */
|
||||
if (diff.tv_sec == 0 && diff.tv_usec == 0) {
|
||||
drift.tv_sec = drift.tv_usec = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct timeval stop;
|
||||
gettimeofday(&stop, NULL);
|
||||
/* Hack to accumulate the drift */
|
||||
if ((diff.tv_sec == 0) && (diff.tv_usec == 0))
|
||||
{
|
||||
diff = timeval_diff(drift, diff); // diff = 0 - drift.
|
||||
}
|
||||
drift = timeval_diff(diff, timeval_diff(start, stop));
|
||||
drift = timeval_diff(diff, timeval_diff(start, stop));
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
double
|
||||
ttynowait (struct timeval prev, struct timeval cur, double speed)
|
||||
|
||||
double ttynowait(struct timeval prev, struct timeval cur, double speed)
|
||||
{
|
||||
/* do nothing */
|
||||
(void)prev;
|
||||
(void)cur;
|
||||
(void)speed;
|
||||
return 0; /* Speed isn't important. */
|
||||
}
|
||||
|
||||
int
|
||||
ttyread (FILE *fp, Header *h, char **buf)
|
||||
|
||||
int ttyread(FILE *fp, Header *h, char **buf)
|
||||
{
|
||||
if (read_header(fp, h) == 0) {
|
||||
return 0;
|
||||
if (read_header(fp, h) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*buf = malloc(h->len);
|
||||
if (*buf == NULL) {
|
||||
perror("malloc");
|
||||
if (*buf == NULL)
|
||||
{
|
||||
perror("malloc");
|
||||
}
|
||||
|
||||
if (fread(*buf, 1, h->len, fp) == 0) {
|
||||
perror("fread");
|
||||
|
||||
if (fread(*buf, 1, h->len, fp) == 0)
|
||||
{
|
||||
perror("fread");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ttypread (FILE *fp, Header *h, char **buf)
|
||||
|
||||
int ttypread(FILE *fp, Header *h, char **buf)
|
||||
{
|
||||
/*
|
||||
* Read persistently just like tail -f.
|
||||
*/
|
||||
while (ttyread(fp, h, buf) == 0) {
|
||||
struct timeval w = {0, 250000};
|
||||
select(0, NULL, NULL, NULL, &w);
|
||||
clearerr(fp);
|
||||
while (ttyread(fp, h, buf) == 0)
|
||||
{
|
||||
struct timeval w = { 0, 250000 };
|
||||
select(0, NULL, NULL, NULL, &w);
|
||||
clearerr(fp);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ttywrite (char *buf, int len)
|
||||
|
||||
void ttywrite(char *buf, int len)
|
||||
{
|
||||
fwrite(buf, 1, len, stdout);
|
||||
}
|
||||
|
||||
void
|
||||
ttynowrite (char *buf, int len)
|
||||
|
||||
void ttynowrite(char *buf, int len)
|
||||
{
|
||||
/* do nothing */
|
||||
(void)buf;
|
||||
(void)len;
|
||||
}
|
||||
|
||||
void
|
||||
ttyplay (FILE *fp, double speed, ReadFunc read_func,
|
||||
WriteFunc write_func, WaitFunc wait_func)
|
||||
|
||||
void ttyplay(FILE *fp, double speed, ReadFunc read_func, WriteFunc write_func, WaitFunc wait_func)
|
||||
{
|
||||
int first_time = 1;
|
||||
int first_time = 1;
|
||||
struct timeval prev;
|
||||
|
||||
setbuf(stdout, NULL);
|
||||
setbuf(fp, NULL);
|
||||
|
||||
while (1) {
|
||||
char *buf;
|
||||
Header h;
|
||||
while (1)
|
||||
{
|
||||
char *buf;
|
||||
Header h;
|
||||
|
||||
if (read_func(fp, &h, &buf) == 0) {
|
||||
break;
|
||||
}
|
||||
if (read_func(fp, &h, &buf) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!first_time) {
|
||||
speed = wait_func(prev, h.tv, speed);
|
||||
}
|
||||
first_time = 0;
|
||||
if (!first_time)
|
||||
{
|
||||
speed = wait_func(prev, h.tv, speed);
|
||||
}
|
||||
first_time = 0;
|
||||
|
||||
write_func(buf, h.len);
|
||||
prev = h.tv;
|
||||
free(buf);
|
||||
write_func(buf, h.len);
|
||||
prev = h.tv;
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ttyskipall (FILE *fp)
|
||||
|
||||
void ttyskipall(FILE *fp)
|
||||
{
|
||||
/*
|
||||
* Skip all records.
|
||||
@@ -221,22 +267,24 @@ ttyskipall (FILE *fp)
|
||||
ttyplay(fp, 0, ttyread, ttynowrite, ttynowait);
|
||||
}
|
||||
|
||||
void ttyplayback (FILE *fp, double speed,
|
||||
ReadFunc read_func, WaitFunc wait_func)
|
||||
|
||||
void ttyplayback(FILE *fp, double speed, ReadFunc read_func, WaitFunc wait_func)
|
||||
{
|
||||
(void)read_func;
|
||||
ttyplay(fp, speed, ttyread, ttywrite, wait_func);
|
||||
}
|
||||
|
||||
void ttypeek (FILE *fp, double speed,
|
||||
ReadFunc read_func, WaitFunc wait_func)
|
||||
|
||||
void ttypeek(FILE *fp, double speed, ReadFunc read_func, WaitFunc wait_func)
|
||||
{
|
||||
(void)read_func;
|
||||
(void)wait_func;
|
||||
ttyskipall(fp);
|
||||
ttyplay(fp, speed, ttypread, ttywrite, ttynowait);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
usage (void)
|
||||
void usage(void)
|
||||
{
|
||||
printf("Usage: ttyplay [OPTION] [FILE]\n");
|
||||
printf(" -s SPEED Set speed to SPEED [1.0]\n");
|
||||
@@ -245,68 +293,78 @@ usage (void)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We do some tricks so that select(2) properly works on
|
||||
* STDIN_FILENO in ttywait().
|
||||
*/
|
||||
FILE *
|
||||
input_from_stdin (void)
|
||||
FILE *input_from_stdin(void)
|
||||
{
|
||||
FILE *fp;
|
||||
int fd = edup(STDIN_FILENO);
|
||||
|
||||
edup2(STDOUT_FILENO, STDIN_FILENO);
|
||||
return efdopen(fd, "r");
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
double speed = 1.0;
|
||||
ReadFunc read_func = ttyread;
|
||||
WaitFunc wait_func = ttywait;
|
||||
ProcessFunc process = ttyplayback;
|
||||
FILE *input = NULL;
|
||||
double speed = 1.0;
|
||||
ReadFunc read_func = ttyread;
|
||||
WaitFunc wait_func = ttywait;
|
||||
ProcessFunc process = ttyplayback;
|
||||
FILE *input = NULL;
|
||||
struct termios old, new;
|
||||
|
||||
set_progname(argv[0]);
|
||||
while (1) {
|
||||
while (1)
|
||||
{
|
||||
int ch = getopt(argc, argv, "s:np");
|
||||
if (ch == EOF) {
|
||||
if (ch == EOF)
|
||||
{
|
||||
break;
|
||||
}
|
||||
switch (ch) {
|
||||
case 's':
|
||||
if (optarg == NULL) {
|
||||
perror("-s option requires an argument");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
sscanf(optarg, "%lf", &speed);
|
||||
break;
|
||||
case 'n':
|
||||
wait_func = ttynowait;
|
||||
break;
|
||||
case 'p':
|
||||
process = ttypeek;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
switch (ch)
|
||||
{
|
||||
case 's':
|
||||
if (optarg == NULL)
|
||||
{
|
||||
perror("-s option requires an argument");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
sscanf(optarg, "%lf", &speed);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
wait_func = ttynowait;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
process = ttypeek;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
input = efopen(argv[optind], "r");
|
||||
} else {
|
||||
if (optind < argc)
|
||||
{
|
||||
input = efopen(argv[optind], "r");
|
||||
}
|
||||
else
|
||||
{
|
||||
input = input_from_stdin();
|
||||
}
|
||||
assert(input != NULL);
|
||||
|
||||
tcgetattr(0, &old); /* Get current terminal state */
|
||||
new = old; /* Make a copy */
|
||||
tcgetattr(0, &old); /* Get current terminal state */
|
||||
new = old; /* Make a copy */
|
||||
new.c_lflag &= ~(ICANON | ECHO | ECHONL); /* unbuffered, no echo */
|
||||
tcsetattr(0, TCSANOW, &new); /* Make it current */
|
||||
tcsetattr(0, TCSANOW, &new); /* Make it current */
|
||||
|
||||
process(input, speed, read_func, wait_func);
|
||||
tcsetattr(0, TCSANOW, &old); /* Return terminal state */
|
||||
tcsetattr(0, TCSANOW, &old); /* Return terminal state */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
76
ttyrec.1
76
ttyrec.1
@@ -1,76 +0,0 @@
|
||||
.\"
|
||||
.\" This manual page is written by NAKANO Takeo <nakano@webmasters.gr.jp>
|
||||
.\"
|
||||
.TH TTYREC 1
|
||||
.SH NAME
|
||||
ttyrec \- a tty recorder
|
||||
.SH SYNOPSIS
|
||||
.br
|
||||
.B ttyrec
|
||||
.I "[\-a][\-u] [file]"
|
||||
.br
|
||||
.SH DESCRIPTION
|
||||
.B Ttyrec
|
||||
is a tty recorder.
|
||||
It is a derivative of
|
||||
.BR script (1)
|
||||
command for recording timing information with microsecond accuracy as well.
|
||||
It can record emacs -nw, vi, lynx, or any programs running on tty.
|
||||
.PP
|
||||
.B Ttyrec
|
||||
invokes a shell and records the session until the shell exits.
|
||||
Recorded data can be played back with
|
||||
.BR ttyplay (1).
|
||||
If the argument
|
||||
.I file
|
||||
is given, the session will be recorded in that file.
|
||||
Otherwise,
|
||||
.I ttyrecord
|
||||
is used as default.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-a
|
||||
Append the output to
|
||||
.I file
|
||||
or
|
||||
.IR ttyrecord ,
|
||||
rather than overwriting it.
|
||||
.TP
|
||||
.B \-u
|
||||
With this option,
|
||||
.B ttyrec
|
||||
automatically calls
|
||||
.BR uudecode (1)
|
||||
and saves its output when uuencoded data appear on the session.
|
||||
It allow you to transfer files from remote host.
|
||||
You can call
|
||||
.B ttyrec
|
||||
with this option, login to the remote host
|
||||
and invoke
|
||||
.BR uuencode (1)
|
||||
on it for the file you want to transfer.
|
||||
.TP
|
||||
.BI \-e " command"
|
||||
Invoke
|
||||
.I command
|
||||
when ttyrec starts.
|
||||
|
||||
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
.I SHELL
|
||||
If the variable
|
||||
.I SHELL
|
||||
exists, the shell forked by
|
||||
.B ttyrec
|
||||
will be that shell.
|
||||
If it's not set,
|
||||
the Bourne shell is assumed.
|
||||
(Most shells set this variable automatically).
|
||||
.SH "SEE ALSO"
|
||||
.BR script (1),
|
||||
.BR ttyplay (1),
|
||||
.BR ttytime (1),
|
||||
.BR uuencode (1),
|
||||
.BR uudecode (1)
|
||||
|
||||
7
ttyrec.h
7
ttyrec.h
@@ -1,11 +1,12 @@
|
||||
#ifndef __TTYREC_H__
|
||||
#define __TTYREC_H__
|
||||
|
||||
#include "sys/time.h"
|
||||
#include <sys/time.h>
|
||||
|
||||
typedef struct header {
|
||||
typedef struct header
|
||||
{
|
||||
struct timeval tv;
|
||||
int len;
|
||||
int len;
|
||||
} Header;
|
||||
|
||||
|
||||
|
||||
44
ttytime.c
44
ttytime.c
@@ -1,4 +1,10 @@
|
||||
/*
|
||||
/* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
* Copyright 2001-2019 The ovh-ttyrec Authors. All rights reserved.
|
||||
*
|
||||
* This work is based on the original ttyrec, whose license text
|
||||
* can be found below unmodified.
|
||||
*
|
||||
* Copyright (c) 1980 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -38,33 +44,39 @@
|
||||
#include "io.h"
|
||||
#include "ttyrec.h"
|
||||
|
||||
int
|
||||
calc_time (const char *filename)
|
||||
int calc_time(const char *filename);
|
||||
|
||||
int calc_time(const char *filename)
|
||||
{
|
||||
Header start, end;
|
||||
FILE *fp = efopen(filename, "r");
|
||||
FILE *fp = efopen(filename, "r");
|
||||
|
||||
read_header(fp, &start);
|
||||
end.tv.tv_sec = start.tv.tv_sec; // to avoid can-be-uninit warning
|
||||
fseek(fp, start.len, SEEK_CUR);
|
||||
while (1) {
|
||||
Header h;
|
||||
if (read_header(fp, &h) == 0) {
|
||||
break;
|
||||
}
|
||||
end = h;
|
||||
fseek(fp, h.len, SEEK_CUR);
|
||||
while (1)
|
||||
{
|
||||
Header h;
|
||||
if (read_header(fp, &h) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
end = h;
|
||||
fseek(fp, h.len, SEEK_CUR);
|
||||
}
|
||||
return end.tv.tv_sec - start.tv.tv_sec;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_progname(argv[0]);
|
||||
for (i = 1; i < argc; i++) {
|
||||
char *filename = argv[i];
|
||||
printf("%7d %s\n", calc_time(filename), filename);
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
char *filename = argv[i];
|
||||
printf("%7d %s\n", calc_time(filename), filename);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
1768
uncrustify.cfg
Normal file
1768
uncrustify.cfg
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user